Skip to content

Commit

Permalink
[@mantine/spotlight] Fix spotlight not working correctly with shadow …
Browse files Browse the repository at this point in the history
…DOM (#6400)

* Search for the action item in the document or in ShadowDOMs.

* ESLint: Unary operator '++' used.(no-plusplus)

* Extend type instead of casting it

* Use `document` as default root, so we can omit it from the two method calls.

* Fix order of arguments

* Check if `state.listId` is truthy.
  • Loading branch information
gruschis authored Jun 28, 2024
1 parent cfd8b4e commit 898ab91
Showing 1 changed file with 32 additions and 2 deletions.
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

0 comments on commit 898ab91

Please sign in to comment.