UNPKG

@furystack/shades-common-components

Version:

Common UI components for FuryStack Shades

64 lines (57 loc) 2.31 kB
import type { Injector } from '@furystack/inject' import { debounce, ObservableValue } from '@furystack/utils' import type { CommandPaletteSuggestionResult, CommandProvider } from './command-provider.js' export class CommandPaletteManager { public isOpened = new ObservableValue(false) public isLoading = new ObservableValue(false) public term = new ObservableValue('') public selectedIndex = new ObservableValue(0) public currentSuggestions = new ObservableValue<CommandPaletteSuggestionResult[]>([]) public keyPressListener = ((ev: KeyboardEvent) => { if (ev.key && ev.key.toLowerCase() === 'p' && ev.ctrlKey) { this.isOpened.setValue(true) this.currentSuggestions.setValue([]) } if (ev.key === 'Escape') { this.isOpened.setValue(false) } }).bind(this) public [Symbol.dispose]() { window.removeEventListener('keyup', this.keyPressListener) this.isOpened[Symbol.dispose]() this.isLoading[Symbol.dispose]() this.term[Symbol.dispose]() this.selectedIndex[Symbol.dispose]() this.currentSuggestions[Symbol.dispose]() } public selectSuggestion(injector: Injector, index: number = this.selectedIndex.getValue()) { const selectedSuggestion = this.currentSuggestions.getValue()[index] this.isOpened.setValue(false) selectedSuggestion.onSelected({ injector }) } private lastGetSuggestionOptions?: { injector: Injector; term: string } public getSuggestion = debounce(async (options: { injector: Injector; term: string }) => { try { if (this.lastGetSuggestionOptions?.term === options.term) { return } this.isLoading.setValue(true) this.lastGetSuggestionOptions = options this.currentSuggestions.setValue([]) this.selectedIndex.setValue(0) await Promise.all( this.commandProviders.map(async (cp) => { const value = await cp(options) if (this.lastGetSuggestionOptions === options) { this.currentSuggestions.setValue([...this.currentSuggestions.getValue(), ...value].sortBy('score')) } }), ) } finally { this.isLoading.setValue(false) } }, 250) constructor(private readonly commandProviders: CommandProvider[]) { window.addEventListener('keyup', this.keyPressListener, true) } }