UNPKG

@mantine/spotlight

Version:

Command center components for react and Mantine

139 lines (136 loc) 4.75 kB
'use client'; import { clamp } from '@mantine/hooks'; import { createStore, useStore } from '@mantine/store'; const createSpotlightStore = () => createStore({ opened: false, empty: false, selected: -1, listId: "", query: "", registeredActions: /* @__PURE__ */ new Set() }); const useSpotlight = (store) => useStore(store); function updateSpotlightStateAction(update, store) { const state = store.getState(); store.setState({ ...state, ...update(store.getState()) }); } function openSpotlightAction(store) { updateSpotlightStateAction(() => ({ opened: true, selected: -1 }), store); } function closeSpotlightAction(store) { updateSpotlightStateAction(() => ({ opened: false }), store); } function toggleSpotlightAction(store) { updateSpotlightStateAction( (state) => ({ opened: !state.opened, selected: state.opened ? state.selected : -1 }), store ); } function setSelectedAction(index, store) { store.updateState((state) => ({ ...state, selected: index })); } function setListId(id, store) { store.updateState((state) => ({ ...state, listId: id })); } function findElementByQuerySelector(selector, root = document) { const element = root.querySelector(selector); if (element) { return element; } const children = root instanceof ShadowRoot ? root.host.children : root.children; for (let i = 0; i < children.length; i += 1) { const child = children[i]; if (child.shadowRoot) { const shadowElement = findElementByQuerySelector(selector, child.shadowRoot); if (shadowElement) { return shadowElement; } } const nestedElement = findElementByQuerySelector(selector, child); if (nestedElement) { return nestedElement; } } return null; } function selectAction(index, store) { const state = store.getState(); const actionsList = state.listId ? findElementByQuerySelector(`#${state.listId}`) : null; const selected = actionsList?.querySelector("[data-selected]"); const actions = actionsList?.querySelectorAll("[data-action]") ?? []; const nextIndex = index === -1 ? actions.length - 1 : index === actions.length ? 0 : index; const selectedIndex = clamp(nextIndex, 0, actions.length - 1); selected?.removeAttribute("data-selected"); actions[selectedIndex]?.scrollIntoView({ block: "nearest" }); actions[selectedIndex]?.setAttribute("data-selected", "true"); setSelectedAction(selectedIndex, store); return selectedIndex; } function selectNextAction(store) { return selectAction(store.getState().selected + 1, store); } function selectPreviousAction(store) { return selectAction(store.getState().selected - 1, store); } function triggerSelectedAction(store) { const state = store.getState(); const selected = findElementByQuerySelector( `#${state.listId} [data-selected]` ); selected?.click(); } function registerAction(id, store) { const state = store.getState(); state.registeredActions.add(id); return () => { state.registeredActions.delete(id); }; } function setQuery(query, store) { updateSpotlightStateAction(() => ({ query }), store); Promise.resolve().then(() => { selectAction(0, store); updateSpotlightStateAction( (state) => ({ empty: state.query.trim().length > 0 && state.registeredActions.size === 0 || false }), store ); }); } function clearSpotlightState({ clearQuery }, store) { store.updateState((state) => ({ ...state, selected: -1, query: clearQuery ? "" : state.query, empty: clearQuery ? false : state.empty })); } const spotlightActions = { open: openSpotlightAction, close: closeSpotlightAction, toggle: toggleSpotlightAction, updateState: updateSpotlightStateAction, setSelectedAction, setListId, selectAction, selectNextAction, selectPreviousAction, triggerSelectedAction, registerAction, setQuery, clearSpotlightState }; function createSpotlight() { const store = createSpotlightStore(); const actions = { open: () => openSpotlightAction(store), close: () => closeSpotlightAction(store), toggle: () => toggleSpotlightAction(store) }; return [store, actions]; } const [spotlightStore, spotlight] = createSpotlight(); const { open: openSpotlight, close: closeSpotlight, toggle: toggleSpotlight } = spotlight; export { clearSpotlightState, closeSpotlight, closeSpotlightAction, createSpotlight, createSpotlightStore, openSpotlight, openSpotlightAction, registerAction, selectAction, selectNextAction, selectPreviousAction, setListId, setQuery, setSelectedAction, spotlight, spotlightActions, spotlightStore, toggleSpotlight, toggleSpotlightAction, triggerSelectedAction, updateSpotlightStateAction, useSpotlight }; //# sourceMappingURL=spotlight.store.mjs.map