{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "hooks-use-auto-height",
  "title": "useAutoHeight",
  "description": "A hook that allows you to automatically adjust the height of an element based on its content.",
  "files": [
    {
      "path": "registry/hooks/use-auto-height/index.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\n\ninterface AutoHeightOptions {\n  includeParentBox?: boolean;\n  includeSelfBox?: boolean;\n}\n\nexport function useAutoHeight<T extends HTMLElement = HTMLDivElement>(\n  deps: React.DependencyList = [],\n  options: AutoHeightOptions = {\n    includeParentBox: true,\n    includeSelfBox: false,\n  }\n) {\n  const ref = React.useRef<T | null>(null);\n  const roRef = React.useRef<ResizeObserver | null>(null);\n  const rafRef = React.useRef<number | null>(null);\n  const [height, setHeight] = React.useState(0);\n\n  const scheduleHeight = React.useCallback((next: number) => {\n    if (rafRef.current !== null) {\n      cancelAnimationFrame(rafRef.current);\n    }\n    rafRef.current = requestAnimationFrame(() => {\n      rafRef.current = null;\n      setHeight(next);\n    });\n  }, []);\n\n  const measure = React.useCallback(() => {\n    const el = ref.current;\n    if (!el) {\n      return 0;\n    }\n\n    const base = el.getBoundingClientRect().height || 0;\n\n    let extra = 0;\n\n    if (options.includeParentBox && el.parentElement) {\n      const cs = getComputedStyle(el.parentElement);\n      const paddingY =\n        (Number.parseFloat(cs.paddingTop || \"0\") || 0) +\n        (Number.parseFloat(cs.paddingBottom || \"0\") || 0);\n      const borderY =\n        (Number.parseFloat(cs.borderTopWidth || \"0\") || 0) +\n        (Number.parseFloat(cs.borderBottomWidth || \"0\") || 0);\n      const isBorderBox = cs.boxSizing === \"border-box\";\n      if (isBorderBox) {\n        extra += paddingY + borderY;\n      }\n    }\n\n    if (options.includeSelfBox) {\n      const cs = getComputedStyle(el);\n      const paddingY =\n        (Number.parseFloat(cs.paddingTop || \"0\") || 0) +\n        (Number.parseFloat(cs.paddingBottom || \"0\") || 0);\n      const borderY =\n        (Number.parseFloat(cs.borderTopWidth || \"0\") || 0) +\n        (Number.parseFloat(cs.borderBottomWidth || \"0\") || 0);\n      const isBorderBox = cs.boxSizing === \"border-box\";\n      if (isBorderBox) {\n        extra += paddingY + borderY;\n      }\n    }\n\n    const dpr =\n      typeof window === \"undefined\" ? 1 : window.devicePixelRatio || 1;\n    const total = Math.ceil((base + extra) * dpr) / dpr;\n\n    return total;\n  }, [options.includeParentBox, options.includeSelfBox]);\n\n  React.useLayoutEffect(() => {\n    const el = ref.current;\n    if (!el) {\n      return;\n    }\n\n    setHeight(measure());\n\n    if (roRef.current) {\n      roRef.current.disconnect();\n      roRef.current = null;\n    }\n\n    const ro = new ResizeObserver(() => {\n      scheduleHeight(measure());\n    });\n\n    ro.observe(el);\n    if (options.includeParentBox && el.parentElement) {\n      ro.observe(el.parentElement);\n    }\n\n    roRef.current = ro;\n\n    return () => {\n      ro.disconnect();\n      roRef.current = null;\n      if (rafRef.current !== null) {\n        cancelAnimationFrame(rafRef.current);\n        rafRef.current = null;\n      }\n    };\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, deps);\n\n  React.useLayoutEffect(() => {\n    if (height === 0) {\n      const next = measure();\n      if (next !== 0) {\n        setHeight(next);\n      }\n    }\n  }, [height, measure]);\n\n  return { ref, height } as const;\n}\n",
      "type": "registry:hook",
      "target": "hooks/use-auto-height.tsx"
    }
  ],
  "type": "registry:hook"
}
