UNPKG

@empoleon/spotlight

Version:

Command center components for react and Empoleon

1 lines 11.9 kB
{"version":3,"file":"spotlight.store.cjs","sources":["../src/spotlight.store.ts"],"sourcesContent":["import { clamp } from '@empoleon/hooks';\nimport { createStore, EmpoleonStore, useStore } from '@empoleon/store';\n\nexport interface SpotlightState {\n opened: boolean;\n selected: number;\n listId: string;\n query: string;\n empty: boolean;\n registeredActions: Set<string>;\n}\n\nexport type SpotlightStore = EmpoleonStore<SpotlightState>;\n\nexport const createSpotlightStore = () =>\n createStore<SpotlightState>({\n opened: false,\n empty: false,\n selected: -1,\n listId: '',\n query: '',\n registeredActions: new Set(),\n });\n\nexport const useSpotlight = (store: SpotlightStore) => useStore(store);\n\nexport function updateSpotlightStateAction(\n update: (state: SpotlightState) => Partial<SpotlightState>,\n store: SpotlightStore\n) {\n const state = store.getState();\n store.setState({ ...state, ...update(store.getState()) });\n}\n\nexport function openSpotlightAction(store: SpotlightStore) {\n updateSpotlightStateAction(() => ({ opened: true, selected: -1 }), store);\n}\n\nexport function closeSpotlightAction(store: SpotlightStore) {\n updateSpotlightStateAction(() => ({ opened: false }), store);\n}\n\nexport function toggleSpotlightAction(store: SpotlightStore) {\n updateSpotlightStateAction(\n (state) => ({ opened: !state.opened, selected: state.opened ? state.selected : -1 }),\n store\n );\n}\n\nexport function setSelectedAction(index: number, store: SpotlightStore) {\n store.updateState((state) => ({ ...state, selected: index }));\n}\n\nexport function setListId(id: string, store: SpotlightStore) {\n store.updateState((state) => ({ ...state, listId: id }));\n}\n\nfunction findElementByQuerySelector<T extends HTMLElement>(\n selector: string,\n root: Document | Element | ShadowRoot = document\n): T | null {\n // Directly try to find the element in the current root.\n const element = root.querySelector<T>(selector);\n if (element) {\n return element;\n }\n\n // Iterate through all children of the current root.\n const children = root instanceof ShadowRoot ? root.host.children : root.children;\n for (let i = 0; i < children.length; i += 1) {\n const child = children[i];\n\n // Recursively search in the child's shadow root if it exists.\n if (child.shadowRoot) {\n const shadowElement = findElementByQuerySelector<T>(selector, child.shadowRoot);\n if (shadowElement) {\n return shadowElement;\n }\n }\n\n // Also, search recursively in the child itself if it does not have a shadow root or the element wasn't found in its shadow root.\n const nestedElement = findElementByQuerySelector<T>(selector, child);\n if (nestedElement) {\n return nestedElement;\n }\n }\n\n // Return null if the element isn't found in the current root or any of its shadow DOMs.\n return null;\n}\n\nexport function selectAction(index: number, store: SpotlightStore): number {\n const state = store.getState();\n const actionsList = state.listId ? findElementByQuerySelector(`#${state.listId}`) : null;\n const selected = actionsList?.querySelector<HTMLButtonElement>('[data-selected]');\n const actions = actionsList?.querySelectorAll<HTMLButtonElement>('[data-action]') ?? [];\n const nextIndex = index === -1 ? actions.length - 1 : index === actions.length ? 0 : index;\n\n const selectedIndex = clamp(nextIndex, 0, actions.length - 1);\n selected?.removeAttribute('data-selected');\n actions[selectedIndex]?.scrollIntoView({ block: 'nearest' });\n actions[selectedIndex]?.setAttribute('data-selected', 'true');\n setSelectedAction(selectedIndex, store);\n\n return selectedIndex;\n}\n\nexport function selectNextAction(store: SpotlightStore) {\n return selectAction(store.getState().selected + 1, store);\n}\n\nexport function selectPreviousAction(store: SpotlightStore) {\n return selectAction(store.getState().selected - 1, store);\n}\n\nexport function triggerSelectedAction(store: SpotlightStore) {\n const state = store.getState();\n const selected = findElementByQuerySelector<HTMLButtonElement>(\n `#${state.listId} [data-selected]`\n );\n selected?.click();\n}\n\nexport function registerAction(id: string, store: SpotlightStore) {\n const state = store.getState();\n state.registeredActions.add(id);\n return () => {\n state.registeredActions.delete(id);\n };\n}\n\nexport function setQuery(query: string, store: SpotlightStore) {\n updateSpotlightStateAction(() => ({ query }), store);\n Promise.resolve().then(() => {\n selectAction(0, store);\n updateSpotlightStateAction(\n (state) => ({\n empty: (state.query.trim().length > 0 && state.registeredActions.size === 0) || false,\n }),\n store\n );\n });\n}\n\nexport function clearSpotlightState(\n { clearQuery }: { clearQuery: boolean | undefined },\n store: SpotlightStore\n) {\n store.updateState((state) => ({\n ...state,\n selected: -1,\n query: clearQuery ? '' : state.query,\n empty: clearQuery ? false : state.empty,\n }));\n}\n\nexport const spotlightActions = {\n open: openSpotlightAction,\n close: closeSpotlightAction,\n toggle: toggleSpotlightAction,\n updateState: updateSpotlightStateAction,\n setSelectedAction,\n setListId,\n selectAction,\n selectNextAction,\n selectPreviousAction,\n triggerSelectedAction,\n registerAction,\n setQuery,\n clearSpotlightState,\n};\n\nexport function createSpotlight() {\n const store = createSpotlightStore();\n const actions = {\n open: () => openSpotlightAction(store),\n close: () => closeSpotlightAction(store),\n toggle: () => toggleSpotlightAction(store),\n };\n\n return [store, actions] as const;\n}\n\nexport const [spotlightStore, spotlight] = createSpotlight();\nexport const { open: openSpotlight, close: closeSpotlight, toggle: toggleSpotlight } = spotlight;\n"],"names":["createSpotlightStore","createStore","opened","empty","selected","listId","query","registeredActions","Set","useSpotlight","store","useStore","updateSpotlightStateAction","update","state","getState","setState","openSpotlightAction","closeSpotlightAction","toggleSpotlightAction","setSelectedAction","index","updateState","setListId","id","findElementByQuerySelector","selector","root","arguments","length","undefined","document","element","querySelector","children","ShadowRoot","host","i","child","shadowRoot","shadowElement","nestedElement","selectAction","actionsList","actions","querySelectorAll","nextIndex","selectedIndex","clamp","removeAttribute","scrollIntoView","block","setAttribute","selectNextAction","selectPreviousAction","triggerSelectedAction","click","registerAction","add","delete","setQuery","Promise","resolve","then","trim","size","clearSpotlightState","_ref","clearQuery","spotlightActions","open","close","toggle","createSpotlight","spotlightStore","spotlight","openSpotlight","closeSpotlight","toggleSpotlight"],"mappings":"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"}