From 296dcc5e7e82f7baba90ee0fdd9a80b9fecf8dc1 Mon Sep 17 00:00:00 2001 From: duoduoObama <30836806+duoduoObama@users.noreply.github.com> Date: Sun, 30 Jul 2023 21:49:43 +0800 Subject: [PATCH] feat(useActiveElement): search deeply in shadow dom (#3208) Co-authored-by: Anthony Fu --- packages/core/useActiveElement/index.ts | 31 +++++++++++++++++++++---- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/packages/core/useActiveElement/index.ts b/packages/core/useActiveElement/index.ts index 4976bfb3448..5f9beeb3eff 100644 --- a/packages/core/useActiveElement/index.ts +++ b/packages/core/useActiveElement/index.ts @@ -3,7 +3,14 @@ import { useEventListener } from '../useEventListener' import type { ConfigurableDocumentOrShadowRoot, ConfigurableWindow } from '../_configurable' import { defaultWindow } from '../_configurable' -export interface UseActiveElementOptions extends ConfigurableWindow, ConfigurableDocumentOrShadowRoot {} +export interface UseActiveElementOptions extends ConfigurableWindow, ConfigurableDocumentOrShadowRoot { + /** + * Search active element deeply inside shadow dom + * + * @default true + */ + deep?: boolean +} /** * Reactive `document.activeElement` @@ -11,19 +18,33 @@ export interface UseActiveElementOptions extends ConfigurableWindow, Configurabl * @see https://vueuse.org/useActiveElement * @param options */ -export function useActiveElement(options: UseActiveElementOptions = {}) { - const { window = defaultWindow } = options +export function useActiveElement( + options: UseActiveElementOptions = {}, +) { + const { + window = defaultWindow, + deep = true, + } = options const document = options.document ?? window?.document + + const getDeepActiveElement = () => { + let element = document?.activeElement + if (deep) { + while (element?.shadowRoot) + element = element?.shadowRoot?.activeElement + } + return element + } + const activeElement = computedWithControl( () => null, - () => document?.activeElement as T | null | undefined, + () => getDeepActiveElement() as T | null | undefined, ) if (window) { useEventListener(window, 'blur', (event) => { if (event.relatedTarget !== null) return - activeElement.trigger() }, true) useEventListener(window, 'focus', activeElement.trigger, true)