{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "extends": "none",
  "name": "scroll-area",
  "title": "scroll-area",
  "description": "scroll-area",
  "dependencies": [
    "cn"
  ],
  "files": [
    {
      "path": "src/components/ui/scroll-area.tsx",
      "content": "\"use client\"\n\nimport { useLayoutEffect, useRef } from \"react\"\nimport { twJoin, cn } from \"cn\"\n\nexport type ScrollAreaOrientation = \"vertical\" | \"horizontal\" | \"both\"\n\nexport interface ScrollAreaProps extends React.ComponentPropsWithRef<\"div\"> {\n  scrollFade?: boolean\n  scrollbarGutter?: boolean\n  orientation?: ScrollAreaOrientation\n}\n\nexport function ScrollArea({\n  ref: forwardedRef,\n  className,\n  children,\n  scrollFade = false,\n  scrollbarGutter = false,\n  orientation = \"both\",\n  ...props\n}: ScrollAreaProps) {\n  const viewportRef = useRef<HTMLDivElement>(null)\n  const rafRef = useRef<number | null>(null)\n  const isThrottledRef = useRef(false)\n\n  const allowY = orientation === \"vertical\" || orientation === \"both\"\n  const allowX = orientation === \"horizontal\" || orientation === \"both\"\n\n  useLayoutEffect(() => {\n    const el = viewportRef.current\n    if (!el) return\n\n    const update = () => {\n      const rawHasY = el.scrollHeight > el.clientHeight + 1\n      const rawHasX = el.scrollWidth > el.clientWidth + 1\n\n      const hasY = allowY && rawHasY\n      const hasX = allowX && rawHasX\n\n      el.toggleAttribute(\"data-has-overflow-y\", hasY)\n      el.toggleAttribute(\"data-has-overflow-x\", hasX)\n\n      const yStart = hasY ? Math.max(0, el.scrollTop) : 0\n      const yEnd = hasY ? Math.max(0, el.scrollHeight - el.clientHeight - el.scrollTop) : 0\n      const xStart = hasX ? Math.max(0, el.scrollLeft) : 0\n      const xEnd = hasX ? Math.max(0, el.scrollWidth - el.clientWidth - el.scrollLeft) : 0\n\n      el.style.setProperty(\"--scroll-area-overflow-y-start\", `${yStart}px`)\n      el.style.setProperty(\"--scroll-area-overflow-y-end\", `${yEnd}px`)\n      el.style.setProperty(\"--scroll-area-overflow-x-start\", `${xStart}px`)\n      el.style.setProperty(\"--scroll-area-overflow-x-end\", `${xEnd}px`)\n    }\n\n    const scheduleUpdate = () => {\n      if (rafRef.current) cancelAnimationFrame(rafRef.current)\n      rafRef.current = requestAnimationFrame(update)\n    }\n\n    const throttledScrollUpdate = () => {\n      if (isThrottledRef.current) return\n      isThrottledRef.current = true\n      scheduleUpdate()\n      setTimeout(() => {\n        isThrottledRef.current = false\n      }, 16)\n    }\n\n    const ro = new ResizeObserver(scheduleUpdate)\n    ro.observe(el)\n\n    el.addEventListener(\"scroll\", throttledScrollUpdate, { passive: true })\n    update()\n\n    return () => {\n      el.removeEventListener(\"scroll\", throttledScrollUpdate)\n      ro.disconnect()\n      if (rafRef.current) cancelAnimationFrame(rafRef.current)\n    }\n  }, [allowX, allowY])\n\n  return (\n    <div ref={forwardedRef} className={cn(\"size-full min-h-0\", className)} {...props}>\n      <div\n        ref={viewportRef}\n        className={twJoin(\n          \"h-full overscroll-auto rounded-[inherit] outline-none transition-shadow data-has-overflow-y:overscroll-y-contain data-has-overflow-x:overscroll-x-contain\",\n\n          orientation === \"vertical\"\n            ? \"overflow-y-auto overflow-x-hidden\"\n            : orientation === \"horizontal\"\n              ? \"overflow-x-auto overflow-y-hidden\"\n              : \"overflow-auto\",\n          scrollFade\n            ? [\n                allowY &&\n                  \"mask-t-from-[calc(100%-min(var(--fade-size,--spacing(6)),var(--scroll-area-overflow-y-start,0)))] mask-b-from-[calc(100%-min(var(--fade-size,--spacing(6)),var(--scroll-area-overflow-y-end,0)))]\",\n                allowX &&\n                  \"mask-l-from-[calc(100%-min(var(--fade-size,--spacing(6)),var(--scroll-area-overflow-x-start,0)))] mask-r-from-[calc(100%-min(var(--fade-size,--spacing(6)),var(--scroll-area-overflow-x-end,0)))]\",\n              ]\n            : \"\",\n          scrollbarGutter\n            ? [allowY && \"data-has-overflow-y:pe-2.5\", allowX && \"data-has-overflow-x:pb-2.5\"]\n            : \"\"\n        )}\n        data-slot=\"scroll-area-viewport\"\n      >\n        {children}\n      </div>\n    </div>\n  )\n}\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}