UNPKG

@furystack/shades-common-components

Version:

140 lines 5.95 kB
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