{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "scroll-area",
  "title": "Scroll Area",
  "description": "Augments native scroll functionality for custom, cross-browser styling.",
  "dependencies": [
    "clsx",
    "tailwind-merge"
  ],
  "registryDependencies": [
    "https://optics.agusmayol.com.ar/r/utils.json"
  ],
  "files": [
    {
      "path": "registry/optics/scroll-area.jsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"@/registry/optics/lib/utils\";\n\nconst ScrollArea = React.forwardRef(\n\t(\n\t\t{\n\t\t\tclassName = \"\",\n\t\t\tchildren = null,\n\t\t\tscrollHideDelay = 0,\n\t\t\tviewportClassName = \"\",\n\t\t\tmaskClassName = \"\",\n\t\t\tmaskHeight = 30,\n\t\t\tmaskColor = undefined,\n\t\t\t...props\n\t\t},\n\t\tref,\n\t) => {\n\t\tconst [showMask, setShowMask] = React.useState({\n\t\t\ttop: false,\n\t\t\tbottom: false,\n\t\t\tleft: false,\n\t\t\tright: false,\n\t\t});\n\t\tconst viewportRef = React.useRef(null);\n\n\t\tconst checkScrollability = React.useCallback(() => {\n\t\t\tconst element = viewportRef.current;\n\t\t\tif (!element) return;\n\n\t\t\tconst {\n\t\t\t\tscrollTop,\n\t\t\t\tscrollLeft,\n\t\t\t\tscrollWidth,\n\t\t\t\tclientWidth,\n\t\t\t\tscrollHeight,\n\t\t\t\tclientHeight,\n\t\t\t} = element;\n\t\t\tsetShowMask((prev) => ({\n\t\t\t\t...prev,\n\t\t\t\ttop: scrollTop > 0,\n\t\t\t\tbottom: scrollTop + clientHeight < scrollHeight - 1,\n\t\t\t\tleft: scrollLeft > 0,\n\t\t\t\tright: scrollLeft + clientWidth < scrollWidth - 1,\n\t\t\t}));\n\t\t}, []);\n\n\t\tReact.useEffect(() => {\n\t\t\tif (typeof window === \"undefined\") return;\n\n\t\t\tconst element = viewportRef.current;\n\t\t\tif (!element) return;\n\n\t\t\tconst controller = new AbortController();\n\t\t\tconst { signal } = controller;\n\n\t\t\tconst resizeObserver = new ResizeObserver(checkScrollability);\n\t\t\tresizeObserver.observe(element);\n\n\t\t\telement.addEventListener(\"scroll\", checkScrollability, { signal });\n\t\t\twindow.addEventListener(\"resize\", checkScrollability, { signal });\n\n\t\t\tcheckScrollability();\n\n\t\t\treturn () => {\n\t\t\t\tcontroller.abort();\n\t\t\t\tresizeObserver.disconnect();\n\t\t\t};\n\t\t}, [checkScrollability]);\n\n\t\treturn (\n\t\t\t<div\n\t\t\t\tref={ref}\n\t\t\t\trole=\"group\"\n\t\t\t\tdata-slot=\"scroll-area\"\n\t\t\t\taria-roledescription=\"scroll area\"\n\t\t\t\tclassName={cn(\"relative overflow-hidden\", className)}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t<div\n\t\t\t\t\tref={viewportRef}\n\t\t\t\t\tdata-slot=\"scroll-area-viewport\"\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"size-full overflow-auto rounded-[inherit] scrollbar-thin scrollbar-thumb-border scrollbar-track-transparent\",\n\t\t\t\t\t\tviewportClassName,\n\t\t\t\t\t)}\n\t\t\t\t\ttabIndex={0}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</div>\n\n\t\t\t\t{maskHeight > 0 && (\n\t\t\t\t\t<ScrollMask\n\t\t\t\t\t\tshowMask={showMask}\n\t\t\t\t\t\tclassName={maskClassName}\n\t\t\t\t\t\tmaskHeight={maskHeight}\n\t\t\t\t\t\tmaskColor={maskColor}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t);\n\t},\n);\n\nScrollArea.displayName = \"ScrollArea\";\n\nconst ScrollBar = () => null;\n\nconst ScrollMask = ({\n\tshowMask,\n\tmaskHeight,\n\tmaskColor = undefined,\n\tclassName = \"\",\n\t...props\n}) => {\n\t// Extract color name from maskColor (e.g., \"from-sidebar\" -> \"sidebar\", \"sidebar\" -> \"sidebar\")\n\tconst getColorVar = () => {\n\t\tif (!maskColor || maskColor === \"from-background\") {\n\t\t\treturn null; // Use default Tailwind classes\n\t\t}\n\t\tconst colorName = maskColor.startsWith(\"from-\")\n\t\t\t? maskColor.slice(5) // Remove \"from-\" prefix\n\t\t\t: maskColor;\n\t\t// Map color name to CSS variable\n\t\treturn `var(--${colorName})`;\n\t};\n\n\tconst colorVar = getColorVar();\n\tconst useCustomColor = colorVar !== null;\n\n\treturn (\n\t\t<>\n\t\t\t<div\n\t\t\t\t{...props}\n\t\t\t\taria-hidden=\"true\"\n\t\t\t\tclassName={cn(\"pointer-events-none absolute inset-0 z-10\", className)}\n\t\t\t>\n\t\t\t\t{useCustomColor ? (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName=\"absolute inset-x-0 top-0 transition-[height,opacity] duration-300\"\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\theight: showMask.top ? `${maskHeight}px` : \"0px\",\n\t\t\t\t\t\t\t\topacity: showMask.top ? 1 : 0,\n\t\t\t\t\t\t\t\tbackgroundImage: `linear-gradient(to bottom, ${colorVar}, transparent)`,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName=\"absolute inset-x-0 bottom-0 transition-[height,opacity] duration-300\"\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\theight: showMask.bottom ? `${maskHeight}px` : \"0px\",\n\t\t\t\t\t\t\t\topacity: showMask.bottom ? 1 : 0,\n\t\t\t\t\t\t\t\tbackgroundImage: `linear-gradient(to top, ${colorVar}, transparent)`,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</>\n\t\t\t\t) : (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\"absolute inset-x-0 top-0 transition-[height,opacity] duration-300 before:from-background before:bg-gradient-to-b before:to-transparent\",\n\t\t\t\t\t\t\t\t\"before:absolute before:inset-x-0 before:top-0 before:h-full before:content-['']\",\n\t\t\t\t\t\t\t\tshowMask.top ? \"before:opacity-100\" : \"before:opacity-0\",\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\theight: showMask.top ? `${maskHeight}px` : \"0px\",\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\"absolute inset-x-0 bottom-0 transition-[height,opacity] duration-300 after:from-background after:bg-gradient-to-t after:to-transparent\",\n\t\t\t\t\t\t\t\t\"after:absolute after:inset-x-0 after:bottom-0 after:h-full after:content-['']\",\n\t\t\t\t\t\t\t\tshowMask.bottom ? \"after:opacity-100\" : \"after:opacity-0\",\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\theight: showMask.bottom ? `${maskHeight}px` : \"0px\",\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t\t<div\n\t\t\t\t{...props}\n\t\t\t\taria-hidden=\"true\"\n\t\t\t\tclassName={cn(\"pointer-events-none absolute inset-0 z-10\", className)}\n\t\t\t>\n\t\t\t\t{useCustomColor ? (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName=\"absolute inset-y-0 left-0 transition-[width,opacity] duration-300\"\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\twidth: showMask.left ? `${maskHeight}px` : \"0px\",\n\t\t\t\t\t\t\t\topacity: showMask.left ? 1 : 0,\n\t\t\t\t\t\t\t\tbackgroundImage: `linear-gradient(to right, ${colorVar}, transparent)`,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName=\"absolute inset-y-0 right-0 transition-[width,opacity] duration-300\"\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\twidth: showMask.right ? `${maskHeight}px` : \"0px\",\n\t\t\t\t\t\t\t\topacity: showMask.right ? 1 : 0,\n\t\t\t\t\t\t\t\tbackgroundImage: `linear-gradient(to left, ${colorVar}, transparent)`,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</>\n\t\t\t\t) : (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\"absolute inset-y-0 left-0 transition-[width,opacity] duration-300 before:from-background before:bg-gradient-to-r before:to-transparent\",\n\t\t\t\t\t\t\t\t\"before:absolute before:inset-y-0 before:left-0 before:w-full before:content-['']\",\n\t\t\t\t\t\t\t\tshowMask.left ? \"before:opacity-100\" : \"before:opacity-0\",\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\twidth: showMask.left ? `${maskHeight}px` : \"0px\",\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\"absolute inset-y-0 right-0 transition-[width,opacity] duration-300 after:from-background after:bg-gradient-to-l after:to-transparent\",\n\t\t\t\t\t\t\t\t\"after:absolute after:inset-y-0 after:right-0 after:w-full after:content-['']\",\n\t\t\t\t\t\t\t\tshowMask.right ? \"after:opacity-100\" : \"after:opacity-0\",\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\twidth: showMask.right ? `${maskHeight}px` : \"0px\",\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</>\n\t);\n};\n\nScrollBar.displayName = \"ScrollBar\";\n\nexport { ScrollArea, ScrollBar };\n",
      "type": "registry:component",
      "target": "components/optics/scroll-area.jsx"
    }
  ],
  "type": "registry:component"
}