{
  "name": "use-element-size",
  "author": "Brendan Dash (https://shadcn-hooks.com)",
  "description": "A hook to track an element's width and height",
  "registryDependencies": [
    "@shadcnhooks/use-effect-with-target",
    "@shadcnhooks/create-effect-with-target"
  ],
  "files": [
    {
      "path": "registry/hooks/use-element-size.ts",
      "content": "import { useState } from 'react'\nimport { useEffectWithTarget } from '@/registry/hooks/use-effect-with-target'\nimport { getTargetElement } from '@/registry/lib/create-effect-with-target'\nimport type { BasicTarget } from '@/registry/lib/create-effect-with-target'\n\nexport interface ElementSize {\n  width: number\n  height: number\n}\n\nexport interface UseElementSizeOptions {\n  /**\n   * ResizeObserver box model to use for measuring.\n   *\n   * @default 'content-box'\n   */\n  box?: ResizeObserverBoxOptions\n}\n\nconst defaultInitialSize: ElementSize = {\n  width: 0,\n  height: 0,\n}\n\ntype ResizeObserverBoxSize =\n  | ResizeObserverSize\n  | ReadonlyArray<ResizeObserverSize>\n\nfunction toBoxSizeArray(\n  boxSize: ResizeObserverBoxSize | undefined,\n): readonly ResizeObserverSize[] {\n  if (!boxSize) {\n    return []\n  }\n\n  return Array.isArray(boxSize)\n    ? boxSize\n    : ([boxSize] as readonly ResizeObserverSize[])\n}\n\nfunction getSizeFromEntry(\n  entry: ResizeObserverEntry,\n  box: ResizeObserverBoxOptions,\n): ElementSize {\n  const boxSize =\n    box === 'border-box'\n      ? entry.borderBoxSize\n      : box === 'device-pixel-content-box'\n        ? entry.devicePixelContentBoxSize\n        : entry.contentBoxSize\n\n  const sizes = toBoxSizeArray(boxSize)\n\n  if (sizes.length > 0) {\n    return {\n      width: sizes.reduce((sum, size) => sum + size.inlineSize, 0),\n      height: sizes.reduce((sum, size) => sum + size.blockSize, 0),\n    }\n  }\n\n  return {\n    width: entry.contentRect.width,\n    height: entry.contentRect.height,\n  }\n}\n\nfunction isSvgElement(element: Element): element is SVGElement {\n  return typeof SVGElement !== 'undefined' && element instanceof SVGElement\n}\n\nexport function useElementSize(\n  target: BasicTarget<Element>,\n  initialSize: ElementSize = defaultInitialSize,\n  options: UseElementSizeOptions = {},\n): ElementSize {\n  const { box = 'content-box' } = options\n  const [size, setSize] = useState<ElementSize>(initialSize)\n\n  const updateSize = (nextSize: ElementSize) => {\n    setSize((currentSize) => {\n      if (\n        currentSize.width === nextSize.width &&\n        currentSize.height === nextSize.height\n      ) {\n        return currentSize\n      }\n\n      return nextSize\n    })\n  }\n\n  useEffectWithTarget(\n    () => {\n      const element = getTargetElement(target)\n\n      if (!element) {\n        updateSize({ width: 0, height: 0 })\n        return\n      }\n\n      updateSize(initialSize)\n\n      if (typeof ResizeObserver === 'undefined') {\n        const rect = element.getBoundingClientRect()\n        updateSize({\n          width: rect.width,\n          height: rect.height,\n        })\n\n        return\n      }\n\n      const observer = new ResizeObserver((entries) => {\n        const entry = entries[0]\n        if (!entry) {\n          return\n        }\n\n        if (isSvgElement(element)) {\n          const rect = element.getBoundingClientRect()\n          updateSize({\n            width: rect.width,\n            height: rect.height,\n          })\n          return\n        }\n\n        updateSize(getSizeFromEntry(entry, box))\n      })\n\n      try {\n        observer.observe(element, { box })\n      } catch {\n        observer.observe(element)\n      }\n\n      return () => {\n        observer.disconnect()\n      }\n    },\n    [box, initialSize.width, initialSize.height],\n    target,\n  )\n\n  return size\n}\n",
      "type": "registry:hook"
    }
  ],
  "type": "registry:hook"
}
