{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "code-block",
  "title": "Code Block",
  "description": "A syntax-highlighted code block component with copy functionality.",
  "dependencies": [
    "@base-ui/react",
    "@shikijs/transformers",
    "shiki",
    "lucide-react",
    "motion",
    "react-icons",
    "clsx",
    "tailwind-merge"
  ],
  "registryDependencies": [
    "https://optics.agusmayol.com.ar/r/button.json",
    "https://optics.agusmayol.com.ar/r/select.json",
    "https://optics.agusmayol.com.ar/r/sonner.json",
    "https://optics.agusmayol.com.ar/r/scroll-area.json",
    "https://optics.agusmayol.com.ar/r/use-controlled-state.json",
    "https://optics.agusmayol.com.ar/r/utils.json"
  ],
  "files": [
    {
      "path": "registry/optics/code-block.jsx",
      "content": "\"use client\";\n\nimport { useControlledState } from \"@/registry/optics/hooks/use-controlled-state\";\nimport {\n\ttransformerNotationDiff,\n\ttransformerNotationErrorLevel,\n\ttransformerNotationFocus,\n\ttransformerNotationHighlight,\n\ttransformerNotationWordHighlight,\n} from \"@shikijs/transformers\";\nimport { CheckIcon, CopyIcon, Loader2 } from \"lucide-react\";\nimport {\n\tcreateContext,\n\tuseContext,\n\tuseEffect,\n\tuseState,\n\tuseLayoutEffect,\n\tuseRef,\n} from \"react\";\nimport { useRender } from \"@base-ui/react/use-render\";\nimport { mergeProps } from \"@base-ui/react/merge-props\";\nimport { motion, AnimatePresence } from \"motion/react\";\nimport {\n\tSiAstro,\n\tSiBiome,\n\tSiBower,\n\tSiBun,\n\tSiC,\n\tSiCircleci,\n\tSiCoffeescript,\n\tSiCplusplus,\n\tSiCss3,\n\tSiCssmodules,\n\tSiDart,\n\tSiDocker,\n\tSiDocusaurus,\n\tSiDotenv,\n\tSiEditorconfig,\n\tSiEslint,\n\tSiGatsby,\n\tSiGitignoredotio,\n\tSiGnubash,\n\tSiGo,\n\tSiGraphql,\n\tSiGrunt,\n\tSiGulp,\n\tSiHandlebarsdotjs,\n\tSiHtml5,\n\tSiJavascript,\n\tSiJest,\n\tSiJson,\n\tSiLess,\n\tSiMarkdown,\n\tSiMdx,\n\tSiMintlify,\n\tSiMocha,\n\tSiMysql,\n\tSiNextdotjs,\n\tSiPerl,\n\tSiPhp,\n\tSiPostcss,\n\tSiPrettier,\n\tSiPrisma,\n\tSiPug,\n\tSiPython,\n\tSiR,\n\tSiReact,\n\tSiReadme,\n\tSiRedis,\n\tSiRemix,\n\tSiRive,\n\tSiRollupdotjs,\n\tSiRuby,\n\tSiSanity,\n\tSiSass,\n\tSiScala,\n\tSiSentry,\n\tSiShadcnui,\n\tSiStorybook,\n\tSiStylelint,\n\tSiSublimetext,\n\tSiSvelte,\n\tSiSvg,\n\tSiSwift,\n\tSiTailwindcss,\n\tSiToml,\n\tSiTypescript,\n\tSiVercel,\n\tSiVite,\n\tSiVuedotjs,\n\tSiWebassembly,\n} from \"react-icons/si\";\nimport { codeToHtml } from \"shiki\";\nimport { Button } from \"@/registry/optics/button\";\nimport {\n\tSelect,\n\tSelectContent,\n\tSelectItem,\n\tSelectTrigger,\n\tSelectValue,\n} from \"@/registry/optics/select\";\nimport { toast } from \"@/registry/optics/sonner\";\nimport { ScrollArea, ScrollBar } from \"@/registry/optics/scroll-area\";\nimport { cn } from \"@/registry/optics/lib/utils\";\n\nconst filenameIconMap = {\n\t\".env\": SiDotenv,\n\t\"*.astro\": SiAstro,\n\t\"biome.json\": SiBiome,\n\t\".bowerrc\": SiBower,\n\t\"bun.lockb\": SiBun,\n\t\"*.c\": SiC,\n\t\"*.cpp\": SiCplusplus,\n\t\".circleci/config.yml\": SiCircleci,\n\t\"*.coffee\": SiCoffeescript,\n\t\"*.module.css\": SiCssmodules,\n\t\"*.css\": SiCss3,\n\t\"*.dart\": SiDart,\n\tDockerfile: SiDocker,\n\t\"docusaurus.config.js\": SiDocusaurus,\n\t\".editorconfig\": SiEditorconfig,\n\t\".eslintrc\": SiEslint,\n\t\"eslint.config.*\": SiEslint,\n\t\"gatsby-config.*\": SiGatsby,\n\t\".gitignore\": SiGitignoredotio,\n\t\"*.go\": SiGo,\n\t\"*.graphql\": SiGraphql,\n\t\"*.sh\": SiGnubash,\n\t\"Gruntfile.*\": SiGrunt,\n\t\"gulpfile.*\": SiGulp,\n\t\"*.hbs\": SiHandlebarsdotjs,\n\t\"*.html\": SiHtml5,\n\t\"*.js\": SiJavascript,\n\t\"*.json\": SiJson,\n\t\"*.test.js\": SiJest,\n\t\"*.less\": SiLess,\n\t\"*.md\": SiMarkdown,\n\t\"*.mdx\": SiMdx,\n\t\"mintlify.json\": SiMintlify,\n\t\"mocha.opts\": SiMocha,\n\t\"*.mustache\": SiHandlebarsdotjs,\n\t\"*.sql\": SiMysql,\n\t\"next.config.*\": SiNextdotjs,\n\t\"*.pl\": SiPerl,\n\t\"*.php\": SiPhp,\n\t\"postcss.config.*\": SiPostcss,\n\t\"prettier.config.*\": SiPrettier,\n\t\"*.prisma\": SiPrisma,\n\t\"*.pug\": SiPug,\n\t\"*.py\": SiPython,\n\t\"*.r\": SiR,\n\t\"*.rb\": SiRuby,\n\t\"*.jsx\": SiReact,\n\t\"*.tsx\": SiReact,\n\t\"readme.md\": SiReadme,\n\t\"*.rdb\": SiRedis,\n\t\"remix.config.*\": SiRemix,\n\t\"*.riv\": SiRive,\n\t\"rollup.config.*\": SiRollupdotjs,\n\t\"sanity.config.*\": SiSanity,\n\t\"*.sass\": SiSass,\n\t\"*.scss\": SiSass,\n\t\"*.sc\": SiScala,\n\t\"*.scala\": SiScala,\n\t\"sentry.client.config.*\": SiSentry,\n\t\"components.json\": SiShadcnui,\n\t\"storybook.config.*\": SiStorybook,\n\t\"stylelint.config.*\": SiStylelint,\n\t\".sublime-settings\": SiSublimetext,\n\t\"*.svelte\": SiSvelte,\n\t\"*.svg\": SiSvg,\n\t\"*.swift\": SiSwift,\n\t\"tailwind.config.*\": SiTailwindcss,\n\t\"*.toml\": SiToml,\n\t\"*.ts\": SiTypescript,\n\t\"vercel.json\": SiVercel,\n\t\"vite.config.*\": SiVite,\n\t\"*.vue\": SiVuedotjs,\n\t\"*.wasm\": SiWebassembly,\n};\n\nconst lineNumberClassNames = cn(\n\t\"[&_code]:[counter-reset:line]\",\n\t\"[&_code]:[counter-increment:line_0]\",\n\t\"[&_.line]:before:content-[counter(line)]\",\n\t\"[&_.line]:before:inline-block\",\n\t\"[&_.line]:before:[counter-increment:line]\",\n\t\"[&_.line]:before:w-4\",\n\t\"[&_.line]:before:mr-4\",\n\t\"[&_.line]:before:text-[13px]\",\n\t\"[&_.line]:before:text-right\",\n\t\"[&_.line]:before:text-muted-foreground/50\",\n\t\"[&_.line]:before:font-mono\",\n\t\"[&_.line]:before:select-none\",\n);\n\nconst darkModeClassNames = cn(\n\t\"dark:[&_.shiki]:!text-[var(--shiki-dark)]\",\n\t// \"dark:[&_.shiki]:!bg-[var(--shiki-dark-bg)]\",\n\t\"dark:[&_.shiki]:![font-style:var(--shiki-dark-font-style)]\",\n\t\"dark:[&_.shiki]:![font-weight:var(--shiki-dark-font-weight)]\",\n\t\"dark:[&_.shiki]:![text-decoration:var(--shiki-dark-text-decoration)]\",\n\t\"dark:[&_.shiki_span]:!text-[var(--shiki-dark)]\",\n\t\"dark:[&_.shiki_span]:![font-style:var(--shiki-dark-font-style)]\",\n\t\"dark:[&_.shiki_span]:![font-weight:var(--shiki-dark-font-weight)]\",\n\t\"dark:[&_.shiki_span]:![text-decoration:var(--shiki-dark-text-decoration)]\",\n);\n\nconst lineHighlightClassNames = cn(\n\t\"[&_.line.highlighted]:bg-blue-50\",\n\t\"[&_.line.highlighted]:after:bg-blue-500\",\n\t\"[&_.line.highlighted]:after:absolute\",\n\t\"[&_.line.highlighted]:after:left-0\",\n\t\"[&_.line.highlighted]:after:top-0\",\n\t\"[&_.line.highlighted]:after:bottom-0\",\n\t\"[&_.line.highlighted]:after:w-0.5\",\n\t\"dark:[&_.line.highlighted]:!bg-blue-500/10\",\n);\n\nconst lineDiffClassNames = cn(\n\t\"[&_.line.diff]:after:absolute\",\n\t\"[&_.line.diff]:after:left-0\",\n\t\"[&_.line.diff]:after:top-0\",\n\t\"[&_.line.diff]:after:bottom-0\",\n\t\"[&_.line.diff]:after:w-0.5\",\n\t\"[&_.line.diff.add]:bg-emerald-50\",\n\t\"[&_.line.diff.add]:after:bg-emerald-500\",\n\t\"[&_.line.diff.remove]:bg-rose-50\",\n\t\"[&_.line.diff.remove]:after:bg-rose-500\",\n\t\"dark:[&_.line.diff.add]:!bg-emerald-500/10\",\n\t\"dark:[&_.line.diff.remove]:!bg-rose-500/10\",\n);\n\nconst lineFocusedClassNames = cn(\n\t\"[&_code:has(.focused)_.line]:blur-[2px]\",\n\t\"[&_code:has(.focused)_.line.focused]:blur-none\",\n);\n\nconst wordHighlightClassNames = cn(\n\t\"[&_.highlighted-word]:bg-blue-50\",\n\t\"dark:[&_.highlighted-word]:!bg-blue-500/10\",\n);\n\nconst codeBlockClassName = cn(\n\t\"mt-0 bg-card text-sm\",\n\t\"[&_pre]:py-4\",\n\t// \"[&_.shiki]:!bg-[var(--shiki-bg)]\",\n\t\"[&_.shiki]:!bg-transparent\",\n\t\"[&_code]:w-full\",\n\t\"[&_code]:grid\",\n\t\"[&_code]:bg-transparent\",\n\t\"[&_code]:min-w-0\",\n\t\"[&_.line]:px-4\",\n\t\"[&_.line]:w-full\",\n\t\"[&_.line]:relative\",\n\t\"[&_.line]:min-w-0\",\n);\n\nconst highlight = (html, language, themes) =>\n\tcodeToHtml(html, {\n\t\tlang: language ?? \"typescript\",\n\t\tthemes: themes ?? {\n\t\t\tlight: \"github-light\",\n\t\t\tdark: \"github-dark-default\",\n\t\t},\n\t\ttransformers: [\n\t\t\ttransformerNotationDiff({\n\t\t\t\tmatchAlgorithm: \"v3\",\n\t\t\t}),\n\t\t\ttransformerNotationHighlight({\n\t\t\t\tmatchAlgorithm: \"v3\",\n\t\t\t}),\n\t\t\ttransformerNotationWordHighlight({\n\t\t\t\tmatchAlgorithm: \"v3\",\n\t\t\t}),\n\t\t\ttransformerNotationFocus({\n\t\t\t\tmatchAlgorithm: \"v3\",\n\t\t\t}),\n\t\t\ttransformerNotationErrorLevel({\n\t\t\t\tmatchAlgorithm: \"v3\",\n\t\t\t}),\n\t\t],\n\t});\n\nconst CodeBlockContext = createContext({\n\tvalue: undefined,\n\tonValueChange: undefined,\n\tdata: [],\n});\n\nexport const CodeBlock = ({\n\tvalue: controlledValue = undefined,\n\tonValueChange: controlledOnValueChange = undefined,\n\tdefaultValue = \"\",\n\tclassName = \"\",\n\tdata = [],\n\t...props\n}) => {\n\tconst [value, onValueChange] = useControlledState({\n\t\tdefaultValue: defaultValue ?? \"\",\n\t\tvalue: controlledValue,\n\t\tonChange: controlledOnValueChange,\n\t});\n\n\treturn (\n\t\t<CodeBlockContext.Provider value={{ value, onValueChange, data }}>\n\t\t\t<div\n\t\t\t\tclassName={cn(\"w-full overflow-hidden rounded-md border\", className)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t</CodeBlockContext.Provider>\n\t);\n};\n\nexport const CodeBlockHeader = ({ className = \"\", ...props }) => (\n\t<div\n\t\tclassName={cn(\n\t\t\t\"flex flex-row items-center border-b bg-secondary p-1\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t/>\n);\n\nexport const CodeBlockFiles = ({\n\tclassName = \"\",\n\tchildren = null,\n\t...props\n}) => {\n\tconst { data } = useContext(CodeBlockContext);\n\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\"flex grow flex-row items-center gap-2\", className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{data.map(children)}\n\t\t</div>\n\t);\n};\n\nexport const CodeBlockFilename = ({\n\tclassName = \"\",\n\ticon = undefined,\n\tvalue = undefined,\n\tchildren = null,\n\t...props\n}) => {\n\tconst { value: activeValue } = useContext(CodeBlockContext);\n\tconst defaultIcon = Object.entries(filenameIconMap).find(([pattern]) => {\n\t\tconst regex = new RegExp(\n\t\t\t`^${pattern.replace(/\\\\/g, \"\\\\\\\\\").replace(/\\./g, \"\\\\.\").replace(/\\*/g, \".*\")}$`,\n\t\t);\n\t\treturn regex.test(children);\n\t})?.[1];\n\tconst Icon = icon ?? defaultIcon;\n\n\tif (value !== activeValue) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<div\n\t\t\tclassName=\"flex items-center gap-2 bg-secondary px-4 py-1.5 text-muted-foreground text-xs\"\n\t\t\t{...props}\n\t\t>\n\t\t\t{Icon && <Icon className=\"h-4 w-4 shrink-0\" />}\n\t\t\t<span className=\"flex-1 truncate\">{children}</span>\n\t\t</div>\n\t);\n};\n\nexport const CodeBlockSelect = (props = {}) => {\n\tconst { value, onValueChange } = useContext(CodeBlockContext);\n\n\treturn <Select onValueChange={onValueChange} value={value} {...props} />;\n};\n\nexport const CodeBlockSelectTrigger = ({ className = \"\", ...props }) => (\n\t<SelectTrigger\n\t\tclassName={cn(\n\t\t\t\"w-fit border-none text-muted-foreground text-xs shadow-none\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t/>\n);\n\nexport const CodeBlockSelectValue = (props = {}) => <SelectValue {...props} />;\n\nexport const CodeBlockSelectContent = ({\n\tchildren = null,\n\tclassName = \"\",\n\t...props\n}) => {\n\tconst { data } = useContext(CodeBlockContext);\n\n\treturn (\n\t\t<SelectContent className={cn(\"w-[calc(100%+2rem)]\", className)} {...props}>\n\t\t\t{data.map(children)}\n\t\t</SelectContent>\n\t);\n};\n\nexport const CodeBlockSelectItem = ({ className = \"\", ...props }) => (\n\t<SelectItem className={cn(\"text-sm\", className)} {...props} />\n);\n\nexport const CodeBlockCopyButton = ({\n\trender = undefined,\n\tonCopy = undefined,\n\tonError = undefined,\n\ttimeout = 2000,\n\tclassName = \"\",\n\tvariant = \"outline\",\n\tsize = \"icon\",\n\t...props\n}) => {\n\tconst [isCopied, setIsCopied] = useState(false);\n\tconst [isLoading, setIsLoading] = useState(false);\n\tconst { data, value } = useContext(CodeBlockContext);\n\tconst code = data.find((item) => item.filename === value)?.code;\n\n\tconst copyToClipboard = async () => {\n\t\tif (isLoading) return;\n\n\t\tsetIsLoading(true);\n\n\t\tif (typeof window === \"undefined\") {\n\t\t\tonError?.(new Error(\"Window is not available\"));\n\t\t\tsetIsLoading(false);\n\t\t\treturn;\n\t\t}\n\n\t\tif (typeof navigator === \"undefined\") {\n\t\t\tonError?.(new Error(\"Navigator is not available\"));\n\t\t\tsetIsLoading(false);\n\t\t\treturn;\n\t\t}\n\n\t\tif (!code) {\n\t\t\tonError?.(new Error(\"No code to copy\"));\n\t\t\tsetIsLoading(false);\n\t\t\treturn;\n\t\t}\n\n\t\tif (navigator?.clipboard?.writeText) {\n\t\t\ttry {\n\t\t\t\tawait navigator.clipboard.writeText(code);\n\t\t\t\tsetIsCopied(true);\n\t\t\t\tonCopy?.();\n\n\t\t\t\tsetTimeout(() => setIsCopied(false), timeout);\n\t\t\t\tsetIsLoading(false);\n\t\t\t\treturn;\n\t\t\t} catch (error) {\n\t\t\t\t// fallthrough to fallback\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tconst textArea = document.createElement(\"textarea\");\n\t\t\ttextArea.value = code;\n\t\t\ttextArea.style.position = \"fixed\";\n\t\t\ttextArea.style.left = \"-999999px\";\n\t\t\ttextArea.style.top = \"-999999px\";\n\t\t\ttextArea.style.opacity = \"0\";\n\t\t\ttextArea.setAttribute(\"readonly\", \"\");\n\t\t\tdocument.body.appendChild(textArea);\n\n\t\t\ttextArea.select();\n\t\t\ttextArea.setSelectionRange(0, 99999);\n\n\t\t\tconst successful = document.execCommand(\"copy\");\n\t\t\tdocument.body.removeChild(textArea);\n\n\t\t\tif (successful) {\n\t\t\t\tsetIsCopied(true);\n\t\t\t\tonCopy?.();\n\n\t\t\t\tsetTimeout(() => setIsCopied(false), timeout);\n\t\t\t} else {\n\t\t\t\tthrow new Error(\"execCommand('copy') returned false\");\n\t\t\t}\n\t\t} catch (fallbackError) {\n\t\t\ttoast({\n\t\t\t\ttype: \"error\",\n\t\t\t\ttitle: \"Copy Failed\",\n\t\t\t\tdescription:\n\t\t\t\t\t\"Unable to copy code to clipboard. Please try manually selecting and copying the text.\",\n\t\t\t\tduration: 4000,\n\t\t\t});\n\n\t\t\tonError?.(fallbackError);\n\t\t} finally {\n\t\t\tsetIsLoading(false);\n\t\t}\n\t};\n\n\tconst buttonContent = (\n\t\t<>\n\t\t\t<div className=\"relative\">\n\t\t\t\t<div\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"absolute inset-0 flex items-center justify-center transition-all duration-300 ease-in-out will-change-[transform,opacity,filter]\",\n\t\t\t\t\t\tisCopied\n\t\t\t\t\t\t\t? \"scale-100 opacity-100 blur-0\"\n\t\t\t\t\t\t\t: \"blur-xs scale-[0.25] opacity-0\",\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<CheckIcon className=\"text-muted-foreground\" size={14} />\n\t\t\t\t</div>\n\t\t\t\t<div\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"absolute inset-0 flex items-center justify-center transition-all duration-300 ease-in-out will-change-[transform,opacity,filter]\",\n\t\t\t\t\t\tisLoading\n\t\t\t\t\t\t\t? \"scale-100 opacity-100 blur-0\"\n\t\t\t\t\t\t\t: \"blur-xs scale-[0.25] opacity-0\",\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<Loader2 className=\"text-muted-foreground animate-spin\" size={14} />\n\t\t\t\t</div>\n\t\t\t\t<div\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"transition-[transform, opacity, filter] duration-300 ease-in-out will-change-[transform,opacity,filter]\",\n\t\t\t\t\t\tisCopied || isLoading\n\t\t\t\t\t\t\t? \"blur-xs scale-[0.25] opacity-0\"\n\t\t\t\t\t\t\t: \"scale-100 opacity-100 blur-0\",\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<CopyIcon className=\"text-muted-foreground\" size={14} />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<span className=\"sr-only\">Copy to clipboard</span>\n\t\t</>\n\t);\n\n\tconst defaultProps = {\n\t\trole: \"button\",\n\t\t\"aria-label\": isCopied ? \"Copied!\" : \"Copy to clipboard\",\n\t\tdisabled: isLoading,\n\t\tclassName: cn(\"shrink-0 z-50 pointer-events-auto selection-all\", className),\n\t\tonClick: copyToClipboard,\n\t\tvariant,\n\t\tsize,\n\t\tchildren: buttonContent,\n\t};\n\n\tif (render) {\n\t\tconst element = useRender({\n\t\t\tdefaultTagName: \"button\",\n\t\t\trender:\n\t\t\t\ttypeof render === \"function\"\n\t\t\t\t\t? (props, state) => {\n\t\t\t\t\t\t\tconst mergedProps = mergeProps(\"button\", defaultProps, props);\n\t\t\t\t\t\t\treturn render(mergedProps, { isCopied, isLoading, ...state });\n\t\t\t\t\t\t}\n\t\t\t\t\t: render,\n\t\t\tprops: mergeProps(\"button\", defaultProps, props),\n\t\t\tstate: {\n\t\t\t\tisCopied,\n\t\t\t\tisLoading,\n\t\t\t},\n\t\t});\n\t\treturn element;\n\t}\n\n\treturn <Button {...defaultProps} {...props} />;\n};\n\nconst CodeBlockFallback = ({ children = null, ...props } = {}) => (\n\t<div {...props}>\n\t\t<pre className=\"w-full\">\n\t\t\t<code>\n\t\t\t\t{children\n\t\t\t\t\t?.toString()\n\t\t\t\t\t.split(\"\\n\")\n\t\t\t\t\t.map((line, i) => (\n\t\t\t\t\t\t<span className=\"line\" key={i}>\n\t\t\t\t\t\t\t{line}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t))}\n\t\t\t</code>\n\t\t</pre>\n\t</div>\n);\n\nexport const CodeBlockBody = ({ children = null, ...props }) => {\n\tconst { data } = useContext(CodeBlockContext);\n\n\treturn <div {...props}>{data.map(children)}</div>;\n};\n\nexport const CodeBlockItem = ({\n\tchildren = null,\n\tlineNumbers = true,\n\tclassName = \"\",\n\tvalue = undefined,\n\t...props\n}) => {\n\tconst { value: activeValue } = useContext(CodeBlockContext);\n\n\tif (value !== activeValue) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t// ScrollArea viene de un .jsx, no hay tipos\n\t\t<ScrollArea\n\t\t\tmaskColor=\"from-sidebar\"\n\t\t\tclassName={cn(\n\t\t\t\tcodeBlockClassName,\n\t\t\t\tlineHighlightClassNames,\n\t\t\t\tlineDiffClassNames,\n\t\t\t\tlineFocusedClassNames,\n\t\t\t\twordHighlightClassNames,\n\t\t\t\tdarkModeClassNames,\n\t\t\t\tlineNumbers && lineNumberClassNames,\n\t\t\t\t\"min-w-0\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\tviewportClassName=\"[&_code]:min-w-full overflow-x-auto [&_code]:max-w-full\"\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t\t<ScrollBar orientation=\"horizontal\" />\n\t\t</ScrollArea>\n\t);\n};\n\nexport const CodeBlockContent = ({\n\tchildren = \"\",\n\tthemes = undefined,\n\tlanguage = undefined,\n\tsyntaxHighlighting = true,\n\t...props\n}) => {\n\tconst [html, setHtml] = useState(null);\n\tconst [isExpanded, setIsExpanded] = useState(false);\n\tconst [fullHeight, setFullHeight] = useState(null);\n\tconst [isReady, setIsReady] = useState(false);\n\tconst codeLines = children.split(\"\\n\");\n\tconst hasMoreThan10Lines = codeLines.length > 10;\n\tconst measureRef = useRef(null);\n\tconst contentRef = useRef(null);\n\n\tuseEffect(() => {\n\t\tif (!syntaxHighlighting) {\n\t\t\treturn;\n\t\t}\n\n\t\thighlight(children, language, themes)\n\t\t\t.then(setHtml)\n\t\t\t// biome-ignore lint/suspicious/noConsole: \"it's fine\"\n\t\t\t.catch(console.error);\n\t}, [children, themes, syntaxHighlighting, language]);\n\n\tuseLayoutEffect(() => {\n\t\tif (!measureRef.current) return;\n\n\t\tconst measureHeight = () => {\n\t\t\tif (measureRef.current) {\n\t\t\t\tconst height = measureRef.current.getBoundingClientRect().height;\n\t\t\t\tsetFullHeight(height);\n\t\t\t\tsetIsReady(true);\n\t\t\t}\n\t\t};\n\n\t\tconst timeoutId = setTimeout(measureHeight, 0);\n\n\t\tconst resizeObserver = new ResizeObserver(() => {\n\t\t\tmeasureHeight();\n\t\t});\n\n\t\tif (measureRef.current) {\n\t\t\tresizeObserver.observe(measureRef.current);\n\t\t}\n\n\t\treturn () => {\n\t\t\tclearTimeout(timeoutId);\n\t\t\tresizeObserver.disconnect();\n\t\t};\n\t}, [html, children, syntaxHighlighting]);\n\n\tconst collapsedHeight = 240;\n\n\tconst transition = {\n\t\ttype: \"spring\",\n\t\tstiffness: 200,\n\t\tdamping: 25,\n\t};\n\n\tconst shouldCollapse =\n\t\thasMoreThan10Lines && (fullHeight ? fullHeight > collapsedHeight : true);\n\tconst targetHeight = !isReady\n\t\t? collapsedHeight\n\t\t: shouldCollapse && !isExpanded\n\t\t\t? collapsedHeight\n\t\t\t: fullHeight || \"auto\";\n\tconst shouldShowExpand = isReady && shouldCollapse && !isExpanded;\n\tconst motionTransition = isReady ? transition : { duration: 0 };\n\n\treturn (\n\t\t<div className=\"relative w-full flex flex-col min-h-0 min-w-0\" {...props}>\n\t\t\t<div\n\t\t\t\tref={measureRef}\n\t\t\t\tclassName=\"invisible pointer-events-none absolute -z-50 w-full\"\n\t\t\t\tstyle={{ visibility: \"hidden\" }}\n\t\t\t>\n\t\t\t\t{!(syntaxHighlighting && html) ? (\n\t\t\t\t\t<CodeBlockFallback>{children}</CodeBlockFallback>\n\t\t\t\t) : (\n\t\t\t\t\t<div\n\t\t\t\t\t\t// Shiki\n\t\t\t\t\t\tdangerouslySetInnerHTML={{ __html: html }}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t\t<motion.div\n\t\t\t\tclassName=\"relative overflow-hidden w-full min-h-0 min-w-0\"\n\t\t\t\tstyle={{ maxHeight: \"100%\" }}\n\t\t\t\tanimate={{ height: targetHeight }}\n\t\t\t\ttransition={motionTransition}\n\t\t\t>\n\t\t\t\t<ScrollArea\n\t\t\t\t\tmaskColor=\"from-sidebar\"\n\t\t\t\t\tclassName=\"w-full min-w-0\"\n\t\t\t\t\tviewportClassName=\"[&_code]:min-w-full overflow-x-auto [&_code]:max-w-full\"\n\t\t\t\t>\n\t\t\t\t\t<div ref={contentRef}>\n\t\t\t\t\t\t{!(syntaxHighlighting && html) ? (\n\t\t\t\t\t\t\t<CodeBlockFallback>{children}</CodeBlockFallback>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t// Shiki\n\t\t\t\t\t\t\t\tdangerouslySetInnerHTML={{ __html: html }}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t\t<ScrollBar orientation=\"horizontal\" />\n\t\t\t\t</ScrollArea>\n\t\t\t</motion.div>\n\t\t\t<AnimatePresence>\n\t\t\t\t{shouldShowExpand && (\n\t\t\t\t\t<motion.div\n\t\t\t\t\t\tinitial={{ opacity: 0 }}\n\t\t\t\t\t\tanimate={{ opacity: 1 }}\n\t\t\t\t\t\texit={{ opacity: 0 }}\n\t\t\t\t\t\ttransition={{ duration: 0.2 }}\n\t\t\t\t\t\tclassName=\"absolute bottom-0 left-0 right-0 flex items-center justify-center bg-gradient-to-t from-card via-card/95 to-transparent pb-4 pt-12 pointer-events-none z-30\"\n\t\t\t\t\t\tstyle={{ width: \"100%\" }}\n\t\t\t\t\t>\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\tonClick={() => setIsExpanded(true)}\n\t\t\t\t\t\t\tclassName=\"z-10 text-muted-foreground hover:bg-transparent hover:text-foreground transition-colors duration-500 ease-in-out pointer-events-auto\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tExpand\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</motion.div>\n\t\t\t\t)}\n\t\t\t</AnimatePresence>\n\t\t</div>\n\t);\n};\n\nCodeBlock.displayName = \"CodeBlock\";\nCodeBlockHeader.displayName = \"CodeBlockHeader\";\nCodeBlockFiles.displayName = \"CodeBlockFiles\";\nCodeBlockFilename.displayName = \"CodeBlockFilename\";\nCodeBlockSelect.displayName = \"CodeBlockSelect\";\nCodeBlockSelectTrigger.displayName = \"CodeBlockSelectTrigger\";\nCodeBlockSelectValue.displayName = \"CodeBlockSelectValue\";\nCodeBlockSelectContent.displayName = \"CodeBlockSelectContent\";\nCodeBlockSelectItem.displayName = \"CodeBlockSelectItem\";\nCodeBlockCopyButton.displayName = \"CodeBlockCopyButton\";\nCodeBlockBody.displayName = \"CodeBlockBody\";\nCodeBlockItem.displayName = \"CodeBlockItem\";\nCodeBlockContent.displayName = \"CodeBlockContent\";\n",
      "type": "registry:component",
      "target": "components/optics/code-block.jsx"
    }
  ],
  "type": "registry:component"
}