UNPKG

@mantine/spotlight

Version:

Command center components for react and Mantine

1 lines 8.58 kB
{"version":3,"file":"spotlight.store.cjs","names":[],"sources":["../src/spotlight.store.ts"],"sourcesContent":["import { clamp } from '@mantine/hooks';\nimport { createStore, MantineStore, useStore } from '@mantine/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 = MantineStore<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 = state.listId\n ? findElementByQuerySelector<HTMLButtonElement>(`#${state.listId} [data-selected]`)\n : null;\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"],"mappings":"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"}