{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "code-block-animated",
  "type": "registry:block",
  "title": "Code block animated",
  "description": "Code block animated",
  "files": [
    {
      "path": "components/usages/codeblockanimatedusage.tsx",
      "content": "'use client';\r\n\r\nimport { CodeFrame } from \"@/registry/open-source/code-block-animated\";\r\n\r\n\r\ninterface CodeFrameDemoProps {\r\n    typeEffect: boolean;\r\n    duration: number;\r\n    delay: number;\r\n    theme: string;\r\n    language: string;\r\n}\r\n\r\nconst SNIPPETS: Record<string, string> = {\r\n    python: `from contextlib import contextmanager\r\nfrom typing import Generator\r\n\r\n@contextmanager\r\ndef safe_file_operation(filepath: str, mode: str = 'r') -> Generator:\r\n    \"\"\"Context manager for safe file operations.\"\"\"\r\n    file = None\r\n    try:\r\n        file = open(filepath, mode)\r\n        yield file\r\n    except FileNotFoundError:\r\n        print(f\"File {filepath} not found\")\r\n        raise\r\n    except IOError as e:\r\n        print(f\"IO error: {e}\")\r\n        raise\r\n    finally:\r\n        if file:\r\n            file.close()\r\n\r\n# Usage\r\nwith safe_file_operation('data.txt', 'r') as f:\r\n    content = f.read()\r\n    print(content)`,\r\n    javascript: `import { useState, useEffect } from 'react';\r\n\r\nfunction useFetch(url) {\r\n  const [data, setData] = useState(null);\r\n  const [loading, setLoading] = useState(true);\r\n  const [error, setError] = useState(null);\r\n\r\n  useEffect(() => {\r\n    const controller = new AbortController();\r\n    fetch(url, { signal: controller.signal })\r\n      .then((res) => res.json())\r\n      .then(setData)\r\n      .catch(setError)\r\n      .finally(() => setLoading(false));\r\n    return () => controller.abort();\r\n  }, [url]);\r\n\r\n  return { data, loading, error };\r\n}\r\n\r\nexport default useFetch;`,\r\n    react: `'use client';\r\n \r\nimport * as React from 'react';\r\n  \r\ntype MyComponentProps = {\r\n  myProps: string;\r\n} & React.ComponentProps<'div'>;\r\n  \r\nfunction MyComponent(props: MyComponentProps) {\r\n  return (\r\n    <div {...props}>\r\n      <p>My Component</p>\r\n    </div>\r\n  );\r\n}\r\n\r\nexport { MyComponent, type MyComponentProps };`,\r\n    java: `import java.util.Optional;\r\nimport java.util.function.Function;\r\n\r\npublic class Either<L, R> {\r\n    private final L left;\r\n    private final R right;\r\n\r\n    private Either(L left, R right) {\r\n        this.left = left;\r\n        this.right = right;\r\n    }\r\n\r\n    public static <L, R> Either<L, R> left(L value) {\r\n        return new Either<>(value, null);\r\n    }\r\n\r\n    public static <L, R> Either<L, R> right(R value) {\r\n        return new Either<>(null, value);\r\n    }\r\n\r\n    public boolean isRight() { return right != null; }\r\n\r\n    public <T> T fold(Function<L, T> leftFn, Function<R, T> rightFn) {\r\n        return isRight() ? rightFn.apply(right) : leftFn.apply(left);\r\n    }\r\n}`,\r\n};\r\n\r\nexport default function Usage({\r\n    typeEffect,\r\n    duration,\r\n    delay,\r\n    theme,\r\n    language,\r\n}: CodeFrameDemoProps) {\r\n    const code = SNIPPETS[language] ?? SNIPPETS['react'];\r\n    return (\r\n        <CodeFrame\r\n            key={`${typeEffect}-${duration}-${delay}-${language}-${theme}`}\r\n            code={code}\r\n            language={language}\r\n            typeEffect={typeEffect}\r\n            duration={duration}\r\n            delay={delay}\r\n            theme={theme}\r\n            className=\"w-125\"\r\n        />\r\n    );\r\n};",
      "type": "registry:block",
      "target": "~/example.tsx"
    },
    {
      "path": "components/usages/codeblockanimatedusage.tsx",
      "content": "'use client';\r\n\r\nimport { CodeFrame } from \"@/registry/open-source/code-block-animated\";\r\n\r\n\r\ninterface CodeFrameDemoProps {\r\n    typeEffect: boolean;\r\n    duration: number;\r\n    delay: number;\r\n    theme: string;\r\n    language: string;\r\n}\r\n\r\nconst SNIPPETS: Record<string, string> = {\r\n    python: `from contextlib import contextmanager\r\nfrom typing import Generator\r\n\r\n@contextmanager\r\ndef safe_file_operation(filepath: str, mode: str = 'r') -> Generator:\r\n    \"\"\"Context manager for safe file operations.\"\"\"\r\n    file = None\r\n    try:\r\n        file = open(filepath, mode)\r\n        yield file\r\n    except FileNotFoundError:\r\n        print(f\"File {filepath} not found\")\r\n        raise\r\n    except IOError as e:\r\n        print(f\"IO error: {e}\")\r\n        raise\r\n    finally:\r\n        if file:\r\n            file.close()\r\n\r\n# Usage\r\nwith safe_file_operation('data.txt', 'r') as f:\r\n    content = f.read()\r\n    print(content)`,\r\n    javascript: `import { useState, useEffect } from 'react';\r\n\r\nfunction useFetch(url) {\r\n  const [data, setData] = useState(null);\r\n  const [loading, setLoading] = useState(true);\r\n  const [error, setError] = useState(null);\r\n\r\n  useEffect(() => {\r\n    const controller = new AbortController();\r\n    fetch(url, { signal: controller.signal })\r\n      .then((res) => res.json())\r\n      .then(setData)\r\n      .catch(setError)\r\n      .finally(() => setLoading(false));\r\n    return () => controller.abort();\r\n  }, [url]);\r\n\r\n  return { data, loading, error };\r\n}\r\n\r\nexport default useFetch;`,\r\n    react: `'use client';\r\n \r\nimport * as React from 'react';\r\n  \r\ntype MyComponentProps = {\r\n  myProps: string;\r\n} & React.ComponentProps<'div'>;\r\n  \r\nfunction MyComponent(props: MyComponentProps) {\r\n  return (\r\n    <div {...props}>\r\n      <p>My Component</p>\r\n    </div>\r\n  );\r\n}\r\n\r\nexport { MyComponent, type MyComponentProps };`,\r\n    java: `import java.util.Optional;\r\nimport java.util.function.Function;\r\n\r\npublic class Either<L, R> {\r\n    private final L left;\r\n    private final R right;\r\n\r\n    private Either(L left, R right) {\r\n        this.left = left;\r\n        this.right = right;\r\n    }\r\n\r\n    public static <L, R> Either<L, R> left(L value) {\r\n        return new Either<>(value, null);\r\n    }\r\n\r\n    public static <L, R> Either<L, R> right(R value) {\r\n        return new Either<>(null, value);\r\n    }\r\n\r\n    public boolean isRight() { return right != null; }\r\n\r\n    public <T> T fold(Function<L, T> leftFn, Function<R, T> rightFn) {\r\n        return isRight() ? rightFn.apply(right) : leftFn.apply(left);\r\n    }\r\n}`,\r\n};\r\n\r\nexport default function Usage({\r\n    typeEffect,\r\n    duration,\r\n    delay,\r\n    theme,\r\n    language,\r\n}: CodeFrameDemoProps) {\r\n    const code = SNIPPETS[language] ?? SNIPPETS['react'];\r\n    return (\r\n        <CodeFrame\r\n            key={`${typeEffect}-${duration}-${delay}-${language}-${theme}`}\r\n            code={code}\r\n            language={language}\r\n            typeEffect={typeEffect}\r\n            duration={duration}\r\n            delay={delay}\r\n            theme={theme}\r\n            className=\"w-125\"\r\n        />\r\n    );\r\n};",
      "type": "registry:ui"
    },
    {
      "path": "registry/open-source/code-block-animated.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\nimport { cn } from '../utilities/cn';\n\n// Credit: \n// https://www.odysseyui.com/docs/components/animate/code-block\n\nconst LANG_SHIKI_MAP: Record<string, string> = {\n    react: 'tsx',\n};\n\nconst languageIcons: Record<string, React.ReactNode> = {\n    react: (\n        <svg\n            viewBox=\"0 0 569 512\"\n            className=\"w-4 h-4\"\n            xmlns=\"http://www.w3.org/2000/svg\"\n        >\n            <g fill=\"none\" fillRule=\"evenodd\">\n                <g transform=\"translate(-227, -256)\" fill=\"#58C4DC\" fillRule=\"nonzero\">\n                    <g transform=\"translate(227, 256)\">\n                        <path d=\"M285.5,201 C255.400481,201 231,225.400481 231,255.5 C231,285.599519 255.400481,310 285.5,310 C315.599519,310 340,285.599519 340,255.5 C340,225.400481 315.599519,201 285.5,201\" />\n                        <path d=\"M568.959856,255.99437 C568.959856,213.207656 529.337802,175.68144 466.251623,150.985214 C467.094645,145.423543 467.85738,139.922107 468.399323,134.521063 C474.621631,73.0415145 459.808523,28.6686204 426.709856,9.5541429 C389.677085,-11.8291748 337.36955,3.69129898 284.479928,46.0162134 C231.590306,3.69129898 179.282771,-11.8291748 142.25,9.5541429 C109.151333,28.6686204 94.3382249,73.0415145 100.560533,134.521063 C101.102476,139.922107 101.845139,145.443621 102.708233,151.02537 C97.4493791,153.033193 92.2908847,155.161486 87.3331099,157.39017 C31.0111824,182.708821 0,217.765415 0,255.99437 C0,298.781084 39.6220545,336.307301 102.708233,361.003527 C101.845139,366.565197 101.102476,372.066633 100.560533,377.467678 C94.3382249,438.947226 109.151333,483.32012 142.25,502.434597 C153.629683,508.887578 166.52439,512.186771 179.603923,511.991836 C210.956328,511.991836 247.567589,495.487529 284.479928,465.972527 C321.372196,495.487529 358.003528,511.991836 389.396077,511.991836 C402.475265,512.183856 415.36922,508.884856 426.75,502.434597 C459.848667,483.32012 474.661775,438.947226 468.439467,377.467678 C467.897524,372.066633 467.134789,366.565197 466.291767,361.003527 C529.377946,336.347457 569,298.761006 569,255.99437 M389.155214,27.1025182 C397.565154,26.899606 405.877839,28.9368502 413.241569,33.0055186 C436.223966,46.2772304 446.540955,82.2775015 441.522965,131.770345 C441.181741,135.143488 440.780302,138.556788 440.298575,141.990165 C414.066922,134.08804 387.205771,128.452154 360.010724,125.144528 C343.525021,103.224055 325.192524,82.7564475 305.214266,63.9661533 C336.586743,39.7116483 366.032313,27.1025182 389.135142,27.1025182 M378.356498,310.205598 C368.204912,327.830733 357.150626,344.919965 345.237759,361.405091 C325.045049,363.479997 304.758818,364.51205 284.459856,364.497299 C264.167589,364.51136 243.888075,363.479308 223.702025,361.405091 C211.820914,344.919381 200.80007,327.83006 190.683646,310.205598 C180.532593,292.629285 171.306974,274.534187 163.044553,255.99437 C171.306974,237.454554 180.532593,219.359455 190.683646,201.783142 C200.784121,184.229367 211.770999,167.201087 223.601665,150.764353 C243.824636,148.63809 264.145559,147.579168 284.479928,147.591877 C304.772146,147.579725 325.051559,148.611772 345.237759,150.68404 C357.109048,167.14607 368.136094,184.201112 378.27621,201.783142 C388.419418,219.363718 397.644825,237.458403 405.915303,255.99437 C397.644825,274.530337 388.419418,292.625022 378.27621,310.205598 M419.724813,290.127366 C426.09516,307.503536 431.324985,325.277083 435.380944,343.334682 C417.779633,348.823635 399.836793,353.149774 381.668372,356.285142 C388.573127,345.871232 395.263781,335.035679 401.740334,323.778483 C408.143291,312.655143 414.144807,301.431411 419.805101,290.207679 M246.363271,390.377981 C258.848032,391.140954 271.593728,391.582675 284.5,391.582675 C297.406272,391.582675 310.232256,391.140954 322.737089,390.377981 C310.880643,404.583418 298.10766,417.997563 284.5,430.534446 C270.921643,417.999548 258.18192,404.585125 246.363271,390.377981 Z M187.311556,356.244986 C169.137286,353.123646 151.187726,348.810918 133.578912,343.334682 C137.618549,325.305649 142.828222,307.559058 149.174827,290.207679 C154.754833,301.431411 160.736278,312.655143 167.239594,323.778483 C173.74291,334.901824 180.467017,345.864539 187.311556,356.285142 M149.174827,221.760984 C142.850954,204.473938 137.654787,186.794745 133.619056,168.834762 C151.18418,163.352378 169.085653,159.013101 187.211197,155.844146 C180.346585,166.224592 173.622478,176.986525 167.139234,188.210257 C160.65599,199.433989 154.734761,210.517173 149.074467,221.760984 M322.616657,121.590681 C310.131896,120.827708 297.3862,120.385987 284.379568,120.385987 C271.479987,120.385987 258.767744,120.787552 246.242839,121.590681 C258.061488,107.383537 270.801211,93.9691137 284.379568,81.4342157 C297.99241,93.9658277 310.765727,107.380324 322.616657,121.590681 Z M401.70019,188.210257 C395.196875,176.939676 388.472767,166.09743 381.527868,155.68352 C399.744224,158.819049 417.734224,163.151949 435.380944,168.654058 C431.331963,186.680673 426.122466,204.426664 419.785029,221.781062 C414.205023,210.55733 408.203506,199.333598 401.720262,188.230335 M127.517179,131.790423 C122.438973,82.3176579 132.816178,46.2973086 155.778503,33.0255968 C163.144699,28.9632474 171.455651,26.9264282 179.864858,27.1225964 C202.967687,27.1225964 232.413257,39.7317265 263.785734,63.9862316 C243.794133,82.7898734 225.448298,103.270812 208.949132,125.204763 C181.761691,128.528025 154.90355,134.14313 128.661281,141.990165 C128.199626,138.556788 127.778115,135.163566 127.456963,131.790423 M98.4529773,182.106474 C101.54406,180.767925 104.695358,179.429376 107.906872,178.090828 C114.220532,204.735668 122.781793,230.7969 133.498624,255.99437 C122.761529,281.241316 114.193296,307.357063 107.8868,334.058539 C56.7434387,313.076786 27.0971497,284.003505 27.0971497,255.99437 C27.0971497,229.450947 53.1907013,202.526037 98.4529773,182.106474 Z M155.778503,478.963143 C132.816178,465.691432 122.438973,429.671082 127.517179,380.198317 C127.838331,376.825174 128.259842,373.431953 128.721497,369.978497 C154.953686,377.878517 181.814655,383.514365 209.009348,386.824134 C225.500295,408.752719 243.832321,429.233234 263.805806,448.042665 C220.069,481.834331 180.105722,492.97775 155.838719,478.963143 M441.502893,380.198317 C446.520883,429.691161 436.203894,465.691432 413.221497,478.963143 C388.974566,493.017906 348.991216,481.834331 305.274481,448.042665 C325.241364,429.232737 343.566681,408.752215 360.050868,386.824134 C387.245915,383.516508 414.107066,377.880622 440.338719,369.978497 C440.820446,373.431953 441.221885,376.825174 441.563109,380.198317 M461.193488,334.018382 C454.869166,307.332523 446.294494,281.231049 435.561592,255.99437 C446.289797,230.744081 454.857778,204.629101 461.173416,177.930202 C512.216417,198.911955 541.942994,227.985236 541.942994,255.99437 C541.942994,284.003505 512.296705,313.076786 461.153344,334.058539\" />\n                    </g>\n                </g>\n            </g>\n        </svg>\n    ),\n    tsx: (\n        <svg\n            viewBox=\"0 0 569 512\"\n            className=\"w-4 h-4\"\n            xmlns=\"http://www.w3.org/2000/svg\"\n        >\n            <g fill=\"none\" fillRule=\"evenodd\">\n                <g transform=\"translate(-227, -256)\" fill=\"#58C4DC\" fillRule=\"nonzero\">\n                    <g transform=\"translate(227, 256)\">\n                        <path d=\"M285.5,201 C255.400481,201 231,225.400481 231,255.5 C231,285.599519 255.400481,310 285.5,310 C315.599519,310 340,285.599519 340,255.5 C340,225.400481 315.599519,201 285.5,201\" />\n                        <path d=\"M568.959856,255.99437 C568.959856,213.207656 529.337802,175.68144 466.251623,150.985214 C467.094645,145.423543 467.85738,139.922107 468.399323,134.521063 C474.621631,73.0415145 459.808523,28.6686204 426.709856,9.5541429 C389.677085,-11.8291748 337.36955,3.69129898 284.479928,46.0162134 C231.590306,3.69129898 179.282771,-11.8291748 142.25,9.5541429 C109.151333,28.6686204 94.3382249,73.0415145 100.560533,134.521063 C101.102476,139.922107 101.845139,145.443621 102.708233,151.02537 C97.4493791,153.033193 92.2908847,155.161486 87.3331099,157.39017 C31.0111824,182.708821 0,217.765415 0,255.99437 C0,298.781084 39.6220545,336.307301 102.708233,361.003527 C101.845139,366.565197 101.102476,372.066633 100.560533,377.467678 C94.3382249,438.947226 109.151333,483.32012 142.25,502.434597 C153.629683,508.887578 166.52439,512.186771 179.603923,511.991836 C210.956328,511.991836 247.567589,495.487529 284.479928,465.972527 C321.372196,495.487529 358.003528,511.991836 389.396077,511.991836 C402.475265,512.183856 415.36922,508.884856 426.75,502.434597 C459.848667,483.32012 474.661775,438.947226 468.439467,377.467678 C467.897524,372.066633 467.134789,366.565197 466.291767,361.003527 C529.377946,336.347457 569,298.761006 569,255.99437 M389.155214,27.1025182 C397.565154,26.899606 405.877839,28.9368502 413.241569,33.0055186 C436.223966,46.2772304 446.540955,82.2775015 441.522965,131.770345 C441.181741,135.143488 440.780302,138.556788 440.298575,141.990165 C414.066922,134.08804 387.205771,128.452154 360.010724,125.144528 C343.525021,103.224055 325.192524,82.7564475 305.214266,63.9661533 C336.586743,39.7116483 366.032313,27.1025182 389.135142,27.1025182 M378.356498,310.205598 C368.204912,327.830733 357.150626,344.919965 345.237759,361.405091 C325.045049,363.479997 304.758818,364.51205 284.459856,364.497299 C264.167589,364.51136 243.888075,363.479308 223.702025,361.405091 C211.820914,344.919381 200.80007,327.83006 190.683646,310.205598 C180.532593,292.629285 171.306974,274.534187 163.044553,255.99437 C171.306974,237.454554 180.532593,219.359455 190.683646,201.783142 C200.784121,184.229367 211.770999,167.201087 223.601665,150.764353 C243.824636,148.63809 264.145559,147.579168 284.479928,147.591877 C304.772146,147.579725 325.051559,148.611772 345.237759,150.68404 C357.109048,167.14607 368.136094,184.201112 378.27621,201.783142 C388.419418,219.363718 397.644825,237.458403 405.915303,255.99437 C397.644825,274.530337 388.419418,292.625022 378.27621,310.205598 M419.724813,290.127366 C426.09516,307.503536 431.324985,325.277083 435.380944,343.334682 C417.779633,348.823635 399.836793,353.149774 381.668372,356.285142 C388.573127,345.871232 395.263781,335.035679 401.740334,323.778483 C408.143291,312.655143 414.144807,301.431411 419.805101,290.207679 M246.363271,390.377981 C258.848032,391.140954 271.593728,391.582675 284.5,391.582675 C297.406272,391.582675 310.232256,391.140954 322.737089,390.377981 C310.880643,404.583418 298.10766,417.997563 284.5,430.534446 C270.921643,417.999548 258.18192,404.585125 246.363271,390.377981 Z M187.311556,356.244986 C169.137286,353.123646 151.187726,348.810918 133.578912,343.334682 C137.618549,325.305649 142.828222,307.559058 149.174827,290.207679 C154.754833,301.431411 160.736278,312.655143 167.239594,323.778483 C173.74291,334.901824 180.467017,345.864539 187.311556,356.285142 M149.174827,221.760984 C142.850954,204.473938 137.654787,186.794745 133.619056,168.834762 C151.18418,163.352378 169.085653,159.013101 187.211197,155.844146 C180.346585,166.224592 173.622478,176.986525 167.139234,188.210257 C160.65599,199.433989 154.734761,210.517173 149.074467,221.760984 M322.616657,121.590681 C310.131896,120.827708 297.3862,120.385987 284.379568,120.385987 C271.479987,120.385987 258.767744,120.787552 246.242839,121.590681 C258.061488,107.383537 270.801211,93.9691137 284.379568,81.4342157 C297.99241,93.9658277 310.765727,107.380324 322.616657,121.590681 Z M401.70019,188.210257 C395.196875,176.939676 388.472767,166.09743 381.527868,155.68352 C399.744224,158.819049 417.734224,163.151949 435.380944,168.654058 C431.331963,186.680673 426.122466,204.426664 419.785029,221.781062 C414.205023,210.55733 408.203506,199.333598 401.720262,188.230335 M127.517179,131.790423 C122.438973,82.3176579 132.816178,46.2973086 155.778503,33.0255968 C163.144699,28.9632474 171.455651,26.9264282 179.864858,27.1225964 C202.967687,27.1225964 232.413257,39.7317265 263.785734,63.9862316 C243.794133,82.7898734 225.448298,103.270812 208.949132,125.204763 C181.761691,128.528025 154.90355,134.14313 128.661281,141.990165 C128.199626,138.556788 127.778115,135.163566 127.456963,131.790423 M98.4529773,182.106474 C101.54406,180.767925 104.695358,179.429376 107.906872,178.090828 C114.220532,204.735668 122.781793,230.7969 133.498624,255.99437 C122.761529,281.241316 114.193296,307.357063 107.8868,334.058539 C56.7434387,313.076786 27.0971497,284.003505 27.0971497,255.99437 C27.0971497,229.450947 53.1907013,202.526037 98.4529773,182.106474 Z M155.778503,478.963143 C132.816178,465.691432 122.438973,429.671082 127.517179,380.198317 C127.838331,376.825174 128.259842,373.431953 128.721497,369.978497 C154.953686,377.878517 181.814655,383.514365 209.009348,386.824134 C225.500295,408.752719 243.832321,429.233234 263.805806,448.042665 C220.069,481.834331 180.105722,492.97775 155.838719,478.963143 M441.502893,380.198317 C446.520883,429.691161 436.203894,465.691432 413.221497,478.963143 C388.974566,493.017906 348.991216,481.834331 305.274481,448.042665 C325.241364,429.232737 343.566681,408.752215 360.050868,386.824134 C387.245915,383.516508 414.107066,377.880622 440.338719,369.978497 C440.820446,373.431953 441.221885,376.825174 441.563109,380.198317 M461.193488,334.018382 C454.869166,307.332523 446.294494,281.231049 435.561592,255.99437 C446.289797,230.744081 454.857778,204.629101 461.173416,177.930202 C512.216417,198.911955 541.942994,227.985236 541.942994,255.99437 C541.942994,284.003505 512.296705,313.076786 461.153344,334.058539\" />\n                    </g>\n                </g>\n            </g>\n        </svg>\n    ),\n    javascript: (\n        <svg viewBox=\"0 0 1052 1052\" className=\"w-4 h-4\">\n            <path fill=\"#f0db4f\" d=\"M0 0h1052v1052H0z\" />\n            <path\n                d=\"M965.9 801.1c-7.7-48-39-88.3-131.7-125.9-32.2-14.8-68.1-25.399-78.8-49.8-3.8-14.2-4.3-22.2-1.9-30.8 6.9-27.9 40.2-36.6 66.6-28.6 17 5.7 33.1 18.801 42.8 39.7 45.4-29.399 45.3-29.2 77-49.399-11.6-18-17.8-26.301-25.4-34-27.3-30.5-64.5-46.2-124-45-10.3 1.3-20.699 2.699-31 4-29.699 7.5-58 23.1-74.6 44-49.8 56.5-35.6 155.399 25 196.1 59.7 44.8 147.4 55 158.6 96.9 10.9 51.3-37.699 67.899-86 62-35.6-7.4-55.399-25.5-76.8-58.4-39.399 22.8-39.399 22.8-79.899 46.1 9.6 21 19.699 30.5 35.8 48.7 76.2 77.3 266.899 73.5 301.1-43.5 1.399-4.001 10.6-30.801 3.199-72.101zm-394-317.6h-98.4c0 85-.399 169.4-.399 254.4 0 54.1 2.8 103.7-6 118.9-14.4 29.899-51.7 26.2-68.7 20.399-17.3-8.5-26.1-20.6-36.3-37.699-2.8-4.9-4.9-8.7-5.601-9-26.699 16.3-53.3 32.699-80 49 13.301 27.3 32.9 51 58 66.399 37.5 22.5 87.9 29.4 140.601 17.3 34.3-10 63.899-30.699 79.399-62.199 22.4-41.3 17.6-91.3 17.4-146.6.5-90.2 0-180.4 0-270.9z\"\n                fill=\"#323330\"\n            />\n        </svg>\n    ),\n    js: (\n        <svg viewBox=\"0 0 1052 1052\" className=\"w-4 h-4\">\n            <path fill=\"#f0db4f\" d=\"M0 0h1052v1052H0z\" />\n            <path\n                d=\"M965.9 801.1c-7.7-48-39-88.3-131.7-125.9-32.2-14.8-68.1-25.399-78.8-49.8-3.8-14.2-4.3-22.2-1.9-30.8 6.9-27.9 40.2-36.6 66.6-28.6 17 5.7 33.1 18.801 42.8 39.7 45.4-29.399 45.3-29.2 77-49.399-11.6-18-17.8-26.301-25.4-34-27.3-30.5-64.5-46.2-124-45-10.3 1.3-20.699 2.699-31 4-29.699 7.5-58 23.1-74.6 44-49.8 56.5-35.6 155.399 25 196.1 59.7 44.8 147.4 55 158.6 96.9 10.9 51.3-37.699 67.899-86 62-35.6-7.4-55.399-25.5-76.8-58.4-39.399 22.8-39.399 22.8-79.899 46.1 9.6 21 19.699 30.5 35.8 48.7 76.2 77.3 266.899 73.5 301.1-43.5 1.399-4.001 10.6-30.801 3.199-72.101zm-394-317.6h-98.4c0 85-.399 169.4-.399 254.4 0 54.1 2.8 103.7-6 118.9-14.4 29.899-51.7 26.2-68.7 20.399-17.3-8.5-26.1-20.6-36.3-37.699-2.8-4.9-4.9-8.7-5.601-9-26.699 16.3-53.3 32.699-80 49 13.301 27.3 32.9 51 58 66.399 37.5 22.5 87.9 29.4 140.601 17.3 34.3-10 63.899-30.699 79.399-62.199 22.4-41.3 17.6-91.3 17.4-146.6.5-90.2 0-180.4 0-270.9z\"\n                fill=\"#323330\"\n            />\n        </svg>\n    ),\n    python: (\n        <svg fill=\"none\" viewBox=\"16 16 32 32\" className=\"w-4 h-4\">\n            <path\n                fill=\"url(#python__a)\"\n                d=\"M31.885 16c-8.124 0-7.617 3.523-7.617 3.523l.01 3.65h7.752v1.095H21.197S16 23.678 16 31.876c0 8.196 4.537 7.906 4.537 7.906h2.708v-3.804s-.146-4.537 4.465-4.537h7.688s4.32.07 4.32-4.175v-7.019S40.374 16 31.885 16zm-4.275 2.454a1.394 1.394 0 1 1 0 2.79 1.393 1.393 0 0 1-1.395-1.395c0-.771.624-1.395 1.395-1.395z\"\n            />\n            <path\n                fill=\"url(#python__b)\"\n                d=\"M32.115 47.833c8.124 0 7.617-3.523 7.617-3.523l-.01-3.65H31.97v-1.095h10.832S48 40.155 48 31.958c0-8.197-4.537-7.906-4.537-7.906h-2.708v3.803s.146 4.537-4.465 4.537h-7.688s-4.32-.07-4.32 4.175v7.019s-.656 4.247 7.833 4.247zm4.275-2.454a1.393 1.393 0 0 1-1.395-1.395 1.394 1.394 0 1 1 1.395 1.395z\"\n            />\n            <defs>\n                <linearGradient\n                    id=\"python__a\"\n                    x1=\"19.075\"\n                    x2=\"34.898\"\n                    y1=\"18.782\"\n                    y2=\"34.658\"\n                    gradientUnits=\"userSpaceOnUse\"\n                >\n                    <stop stopColor=\"#387EB8\" />\n                    <stop offset=\"1\" stopColor=\"#366994\" />\n                </linearGradient>\n                <linearGradient\n                    id=\"python__b\"\n                    x1=\"28.809\"\n                    x2=\"45.803\"\n                    y1=\"28.882\"\n                    y2=\"45.163\"\n                    gradientUnits=\"userSpaceOnUse\"\n                >\n                    <stop stopColor=\"#FFE052\" />\n                    <stop offset=\"1\" stopColor=\"#FFC331\" />\n                </linearGradient>\n            </defs>\n        </svg>\n    ),\n    java: (\n        <svg\n            preserveAspectRatio=\"xMidYMid\"\n            viewBox=\"0 0 256 346\"\n            className=\"w-4 h-4\"\n        >\n            <path\n                d=\"M83 267s-14 8 9 11c27 3 41 2 71-3 0 0 8 5 19 9-67 29-153-2-99-17M74 230s-15 11 8 13c29 3 52 3 92-4 0 0 6 5 15 8-82 24-173 2-115-17\"\n                fill=\"#5382A1\"\n            />\n            <path\n                d=\"M144 166c17 19-4 36-4 36s42-22 22-49c-18-26-32-38 44-82 0 0-119 29-62 95\"\n                fill=\"#E76F00\"\n            />\n            <path\n                d=\"M233 295s10 8-10 15c-39 12-163 15-197 0-12-5 11-13 18-14l12-2c-14-9-89 19-38 28 138 22 251-10 215-27M89 190s-63 15-22 21c17 2 51 2 83-1 26-2 52-7 52-7l-16 9c-64 16-187 8-151-9 30-14 54-13 54-13M202 253c64-33 34-66 13-61l-7 2s2-3 6-5c41-14 73 43-14 66l2-2\"\n                fill=\"#5382A1\"\n            />\n            <path\n                d=\"M162 0s36 36-34 91c-56 45-12 70 0 99-32-30-56-56-40-80 23-35 89-53 74-110\"\n                fill=\"#E76F00\"\n            />\n            <path\n                d=\"M95 345c62 4 158-3 160-32 0 0-4 11-51 20-53 10-119 9-158 2 0 0 8 7 49 10\"\n                fill=\"#5382A1\"\n            />\n        </svg>\n    ),\n};\n\nconst SHIKI_THEMES = {\n    'One Dark Pro': 'one-dark-pro',\n    'GitHub Dark': 'github-dark',\n    'GitHub Light': 'github-light',\n    Dracula: 'dracula',\n    Nord: 'nord',\n    Monokai: 'monokai',\n    'Tokyo Night': 'tokyo-night',\n    'Solarized Dark': 'solarized-dark',\n} as const;\n\ntype ShikiThemeName = (typeof SHIKI_THEMES)[keyof typeof SHIKI_THEMES];\n\ntype CodeFrameProps = {\n    code: string;\n    language?: string;\n    className?: string;\n    typeEffect?: boolean;\n    duration?: number;\n    delay?: number;\n    theme?: ShikiThemeName | string;\n};\n\nexport function CodeFrame({\n    code,\n    language = 'javascript',\n    className,\n    typeEffect = false,\n    duration = 5000,\n    delay = 0,\n    theme = 'one-dark-pro',\n}: CodeFrameProps) {\n    const [html, setHtml] = React.useState('');\n    const [visibleCode, setVisibleCode] = React.useState('');\n    const [isDone, setIsDone] = React.useState(false);\n    const containerRef = React.useRef<HTMLDivElement>(null);\n\n    // Typing effect animation\n    React.useEffect(() => {\n        setVisibleCode('');\n        setIsDone(false);\n\n        if (!typeEffect) {\n            setVisibleCode(code);\n            setIsDone(true);\n            return;\n        }\n\n        if (!code.length) return;\n\n        const characters = Array.from(code);\n        let index = 0;\n        const interval = duration / characters.length;\n        let intervalId: NodeJS.Timeout;\n\n        const timeout = setTimeout(() => {\n            intervalId = setInterval(() => {\n                if (index < characters.length) {\n                    setVisibleCode(characters.slice(0, index + 1).join(''));\n                    index++;\n                } else {\n                    clearInterval(intervalId);\n                    setIsDone(true);\n                }\n            }, interval);\n        }, delay);\n\n        return () => {\n            clearTimeout(timeout);\n            clearInterval(intervalId);\n        };\n    }, [code, typeEffect, duration, delay]);\n\n    // Syntax highlighting\n    React.useEffect(() => {\n        if (!visibleCode.length) return;\n\n        async function loadHighlightedCode() {\n            try {\n                const { codeToHtml } = await import('shiki');\n                const shikiLang = LANG_SHIKI_MAP[language] ?? language;\n                const highlighted = await codeToHtml(visibleCode, {\n                    lang: shikiLang,\n                    themes: {\n                        light: theme,\n                        dark: theme,\n                    },\n                });\n                setHtml(highlighted);\n            } catch (error) {\n                console.error('Error highlighting code:', error);\n            }\n        }\n        loadHighlightedCode();\n    }, [visibleCode, language, theme]);\n\n    // Auto-scroll during typing effect\n    React.useEffect(() => {\n        if (!typeEffect || !containerRef.current) return;\n        containerRef.current.scrollTo({\n            top: containerRef.current.scrollHeight,\n            behavior: 'smooth',\n        });\n    }, [html, typeEffect]);\n\n    const languageKey = language.toLowerCase();\n    const icon = languageIcons[languageKey];\n\n    return (\n        <div\n            className={cn(\n                'group bg-muted border border-border/60 max-w-full w-full rounded-2xl p-1 pt-0 relative',\n                className,\n            )}\n        >\n            <div className=\"flex items-center justify-between bg-transparent px-3 py-1\">\n                <div className=\"flex min-w-0 items-center gap-2\">\n                    {icon ? (\n                        <div className=\"inline-flex items-center justify-center rounded-sm px-1.5 py-1\">\n                            {icon}{' '}\n                            <span className=\"inline-flex items-center rounded-sm px-1.5 py-0.5 text-[12px] font-semibold leading-none text-muted-foreground capitalize\">\n                                {language === 'react' ? 'React' : language}\n                            </span>\n                        </div>\n                    ) : (\n                        <span className=\"inline-flex items-center rounded-sm border border-border/70 px-1.5 py-0.5 text-[10px] font-semibold leading-none text-muted-foreground\">\n                            {language.toUpperCase()}\n                        </span>\n                    )}\n                </div>\n\n                <CopyButton variant=\"secondary\" content={code} />\n            </div>\n\n            <div\n                ref={containerRef}\n                data-done={isDone}\n                className={cn(\n                    'relative bg-card border border-border/60 rounded-lg overflow-y-auto max-h-96 [&>pre]:m-0 [&>pre]:p-4 [&>pre]:bg-transparent',\n                    typeEffect &&\n                    !isDone &&\n                    \"[&_.line:last-of-type::after]:content-['|'] [&_.line:last-of-type::after]:inline-block [&_.line:last-of-type::after]:w-[1ch] [&_.line:last-of-type::after]:animate-pulse\",\n                )}\n                dangerouslySetInnerHTML={{ __html: html }}\n            />\n        </div>\n    );\n}\n\nexport { SHIKI_THEMES, type ShikiThemeName, type CodeFrameProps };",
      "type": "registry:ui"
    },
    {
      "path": "registry/utilities/cn.ts",
      "content": "import { ClassValue, clsx } from \"clsx\";\r\nimport { twMerge } from \"tailwind-merge\";\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n\treturn twMerge(clsx(inputs));\r\n}\r\n",
      "type": "registry:ui"
    }
  ]
}