{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "extends": "none",
  "name": "scroll-area",
  "title": "scroll-area",
  "description": "scroll-area",
  "dependencies": [
    "tailwind-merge"
  ],
  "files": [
    {
      "path": "src/components/ui/scroll-area.tsx",
      "content": "'use client'\n\nimport { useLayoutEffect, useRef } from 'react'\nimport { twJoin, twMerge } from 'tailwind-merge'\n\ntype 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={twMerge('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"
}