Note
This is merely a convenience wrapper around @viselect/vanilla. The core API is fairly simple, if you want to have full control over it, you should roll out your own wrapper in your app.
Install using your package manager of choice:
npm install @viselect/preact
Last but not least, you'll need to add some basic styles to make your selection-area visible:
.selection-area {
background: rgba(46, 115, 252, 0.11);
border: 2px solid rgba(98, 155, 255, 0.81);
border-radius: 0.1em;
}
Additionally, to not interfere with text-selection, selection-js won't prevent any default events anymore (as of v2.0.3
).
This, however, can cause problems with the actual selection ("introduced" by #99, reported in #103).
If you don't care about text-selection, add the following to the container where all your selectables are located:
.container {
user-select: none;
}
Note
All options are exposed as props. They're a one-to-one mapping of the original options found in the vanilla version!
import SelectionArea, {SelectionEvent} from '@viselect/preact';
import {FunctionalComponent} from 'preact';
import {useState} from 'preact/hooks';
const App: FunctionComponent = () => {
const [selected, setSelected] = useState<Set<number>>(() => new Set());
const extractIds = (els: Element[]): number[] =>
els.map(v => v.getAttribute('data-key'))
.filter(Boolean)
.map(Number);
const onStart = ({event, selection}: SelectionEvent) => {
if (!event?.ctrlKey && !event?.metaKey) {
selection.clearSelection();
setSelected(() => new Set());
}
};
const onMove = ({store: {changed: {added, removed}}}: SelectionEvent) => {
setSelected(prev => {
const next = new Set(prev);
extractIds(added).forEach(id => next.add(id));
extractIds(removed).forEach(id => next.delete(id));
return next;
});
};
return (
<>
<SelectionArea className="container"
onStart={onStart}
onMove={onMove}
selectables=".selectable">
{new Array(42).fill(0).map((_, index) => (
<div className={selected.has(index) ? 'selected selectable' : 'selectable'}
data-key={index}
key={index}/>
))}
</SelectionArea>
</>
);
}