{
  "name": "use-active-element",
  "author": "Brendan Dash (https://shadcn-hooks.com)",
  "description": "A hook to track the currently focused element in the document",
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/hooks/use-active-element.ts",
      "content": "import { useCallback, useSyncExternalStore } from 'react'\n\nexport interface UseActiveElementOptions {\n  /**\n   * Whether to resolve the deepest focused node inside open shadow roots.\n   * @default true\n   */\n  deep?: boolean\n  /**\n   * Whether to re-check active element when DOM nodes are removed.\n   * @default false\n   */\n  triggerOnRemoval?: boolean\n}\n\nfunction resolveActiveElement(deep: boolean): Element | null {\n  if (typeof document === 'undefined') {\n    return null\n  }\n\n  let activeElement: Element | null = document.activeElement\n\n  if (!deep) {\n    return activeElement\n  }\n\n  while (activeElement?.shadowRoot?.activeElement) {\n    activeElement = activeElement.shadowRoot.activeElement\n  }\n\n  return activeElement\n}\n\nexport function useActiveElement<T extends Element = HTMLElement>(\n  options: UseActiveElementOptions = {},\n): T | null {\n  const { deep = true, triggerOnRemoval = false } = options\n\n  const subscribe = useCallback(\n    (onStoreChange: () => void) => {\n      if (typeof window === 'undefined') {\n        return () => {}\n      }\n\n      const onFocus = () => {\n        onStoreChange()\n      }\n      const onBlur = (event: FocusEvent) => {\n        if (event.relatedTarget !== null) {\n          return\n        }\n        onStoreChange()\n      }\n\n      window.addEventListener('focus', onFocus, true)\n      window.addEventListener('blur', onBlur, true)\n\n      const observer =\n        triggerOnRemoval && typeof MutationObserver !== 'undefined'\n          ? new MutationObserver(() => {\n              onStoreChange()\n            })\n          : null\n\n      observer?.observe(document, {\n        childList: true,\n        subtree: true,\n      })\n\n      return () => {\n        window.removeEventListener('focus', onFocus, true)\n        window.removeEventListener('blur', onBlur, true)\n        observer?.disconnect()\n      }\n    },\n    [triggerOnRemoval],\n  )\n\n  const getSnapshot = useCallback(() => {\n    return resolveActiveElement(deep) as T | null\n  }, [deep])\n\n  const getServerSnapshot = useCallback(() => {\n    return null as T | null\n  }, [])\n\n  return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot)\n}\n",
      "type": "registry:hook"
    }
  ],
  "type": "registry:hook"
}
