@furystack/shades-common-components
Version:
140 lines • 5.95 kB
JavaScript
import { ObservableValue } from '@furystack/utils';
export class CollectionService {
options;
[Symbol.dispose]() {
this.data[Symbol.dispose]();
this.selection[Symbol.dispose]();
this.searchTerm[Symbol.dispose]();
this.hasFocus[Symbol.dispose]();
this.focusedEntry[Symbol.dispose]();
}
isSelected = (entry) => this.selection.getValue().includes(entry);
addToSelection = (entry) => {
this.selection.setValue([...this.selection.getValue(), entry]);
};
removeFromSelection = (entry) => {
this.selection.setValue(this.selection.getValue().filter((e) => e !== entry));
};
toggleSelection = (entry) => {
if (this.isSelected(entry)) {
this.removeFromSelection(entry);
}
else {
this.addToSelection(entry);
}
};
data = new ObservableValue({ count: 0, entries: [] });
focusedEntry = new ObservableValue(undefined);
selection = new ObservableValue([]);
searchTerm = new ObservableValue('');
hasFocus = new ObservableValue(false);
handleKeyDown(ev) {
const { entries } = this.data.getValue();
const hasFocus = this.hasFocus.getValue();
const selectedEntries = this.selection.getValue();
const focusedEntry = this.focusedEntry.getValue();
const searchTerm = this.searchTerm.getValue();
if (hasFocus) {
switch (ev.key) {
case ' ':
ev.preventDefault();
if (focusedEntry) {
this.selection.setValue(selectedEntries.includes(focusedEntry)
? selectedEntries.filter((e) => e !== focusedEntry)
: [...selectedEntries, focusedEntry]);
}
break;
case '*':
this.selection.setValue(entries.filter((e) => !selectedEntries.includes(e)));
break;
case '+':
this.selection.setValue(entries);
break;
case '-':
this.selection.setValue([]);
break;
case 'Insert':
if (focusedEntry) {
if (this.selection.getValue().includes(focusedEntry)) {
this.selection.setValue([...this.selection.getValue().filter((e) => e !== focusedEntry)]);
}
else {
this.selection.setValue([...this.selection.getValue(), focusedEntry]);
}
this.focusedEntry.setValue(entries[entries.findIndex((e) => e === this.focusedEntry.getValue()) + 1]);
}
break;
case 'ArrowUp':
ev.preventDefault();
this.focusedEntry.setValue(entries[Math.max(0, entries.findIndex((e) => e === focusedEntry) - 1)]);
break;
case 'ArrowDown':
ev.preventDefault();
this.focusedEntry.setValue(entries[Math.min(entries.length - 1, entries.findIndex((e) => e === focusedEntry) + 1)]);
break;
case 'Home': {
this.focusedEntry.setValue(entries[0]);
break;
}
case 'End': {
this.focusedEntry.setValue(entries[entries.length - 1]);
break;
}
case 'Tab': {
this.hasFocus.setValue(!hasFocus);
break;
}
case 'Escape': {
this.searchTerm.setValue('');
this.selection.setValue([]);
break;
}
default:
if (this.options.searchField && ev.key.length === 1) {
const newSearchExpression = searchTerm + ev.key;
const newFocusedEntry = entries.find((e) => this.options.searchField &&
e[this.options.searchField]?.toString().startsWith(newSearchExpression));
this.focusedEntry.setValue(newFocusedEntry);
this.searchTerm.setValue(newSearchExpression);
}
}
}
}
handleRowClick(entry, ev) {
this.options.onRowClick?.(entry);
const currentSelectionValue = this.selection.getValue();
const lastFocused = this.focusedEntry.getValue();
if (ev.ctrlKey) {
if (currentSelectionValue.includes(entry)) {
this.selection.setValue(currentSelectionValue.filter((s) => s !== entry));
}
else {
this.selection.setValue([...currentSelectionValue, entry]);
}
}
if (ev.shiftKey) {
const lastFocusedIndex = this.data.getValue().entries.findIndex((e) => e === lastFocused);
const entryIndex = this.data.getValue().entries.findIndex((e) => e === entry);
const selection = [...currentSelectionValue];
if (lastFocusedIndex > entryIndex) {
for (let i = entryIndex; i <= lastFocusedIndex; i++) {
selection.push(this.data.getValue().entries[i]);
}
}
else {
for (let i = lastFocusedIndex; i <= entryIndex; i++) {
selection.push(this.data.getValue().entries[i]);
}
}
this.selection.setValue(selection);
}
this.focusedEntry.setValue(entry);
}
constructor(options = {}) {
this.options = options;
}
handleRowDoubleClick(entry) {
this.options.onRowDoubleClick?.(entry);
}
}
//# sourceMappingURL=collection-service.js.map