Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[@mantine/spotlight] Search for the action item in the document or in ShadowDOMs #6400

Merged
merged 6 commits into from
Jun 28, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 32 additions & 2 deletions packages/@mantine/spotlight/src/spotlight.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,37 @@ export function setListId(id: string, store: SpotlightStore) {
store.updateState((state) => ({ ...state, listId: id }));
}

function findElementByQuerySelector<T extends HTMLElement>(
selector: string,
root: Document | Element | ShadowRoot = document
): T | null {
// Directly try to find the element in the current root.
const element = root.querySelector<T>(selector);
if (element) return element;

// Iterate through all children of the current root.
const children = root instanceof ShadowRoot ? root.host.children : root.children;
for (let i = 0; i < children.length; i += 1) {
const child = children[i];

// Recursively search in the child's shadow root if it exists.
if (child.shadowRoot) {
const shadowElement = findElementByQuerySelector<T>(selector, child.shadowRoot);
if (shadowElement) return shadowElement;
}

// 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.
const nestedElement = findElementByQuerySelector<T>(selector, child);
if (nestedElement) return nestedElement;
}

// Return null if the element isn't found in the current root or any of its shadow DOMs.
return null;
}

export function selectAction(index: number, store: SpotlightStore): number {
const state = store.getState();
const actionsList = document.getElementById(state.listId);
const actionsList = state.listId ? findElementByQuerySelector(`#${state.listId}`) : null;
const selected = actionsList?.querySelector<HTMLButtonElement>('[data-selected]');
const actions = actionsList?.querySelectorAll<HTMLButtonElement>('[data-action]') ?? [];
const nextIndex = index === -1 ? actions.length - 1 : index === actions.length ? 0 : index;
Expand All @@ -78,7 +106,9 @@ export function selectPreviousAction(store: SpotlightStore) {

export function triggerSelectedAction(store: SpotlightStore) {
const state = store.getState();
const selected = document.querySelector<HTMLButtonElement>(`#${state.listId} [data-selected]`);
const selected = findElementByQuerySelector<HTMLButtonElement>(
`#${state.listId} [data-selected]`
);
selected?.click();
}

Expand Down
Loading