{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "code-tabs-mdx",
  "dependencies": [
    "shiki"
  ],
  "devDependencies": [],
  "registryDependencies": [],
  "files": [
    {
      "path": "./components/website/code-components/code-tabs-mdx.tsx",
      "content": "import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/website/ui/tabs';\nimport { highlightCode } from '@/lib/shiki-highlighter';\nimport { CopyButton } from './copy-button';\n\nexport default async function CodeTabsMdx({ children }: any) {\n  // console.log('children', children);\n\n  const blocks = Array.isArray(children) ? children : [children];\n  // console.log('blocks', blocks);\n\n  // Extract raw code + language\n  const parsed = blocks\n    // .filter((n: any) => n?.type === 'pre')\n    .map((node: any) => {\n      const codeNode = node.props.children;\n      return {\n        value: codeNode.props.children || '',\n        lang: codeNode.props.className?.replace('language-', '') || 'txt',\n      };\n    });\n\n  // console.log('parsed', parsed);\n\n  // Highlight everything\n  const highlighted = await Promise.all(parsed.map((t) => highlightCode(t.value, t.lang)));\n\n  // -------------------------\n  // CASE 1 — Only one block\n  // -------------------------\n  if (parsed.length === 1) {\n    return (\n      <div\n        className='rounded bg-zinc-900 p-4'\n        dangerouslySetInnerHTML={{ __html: highlighted[0] }}\n      />\n    );\n  }\n\n  // -------------------------\n  // CASE 2 — Always two blocks → fixed tabs\n  // -------------------------\n  const tabs = [\n    { meta: 'ui-layouts', html: highlighted[0], code: parsed[0].value },\n    { meta: 'shadcn', html: highlighted[1], code: parsed[1].value },\n  ];\n\n  return (\n    <Tabs\n      defaultValue='ui-layouts'\n      className='rounded-xl bg-codebg dark:border-neutral-800 backdrop-blur-md border relative p-1 my-5'\n    >\n      <TabsList className='rounded-lg mt-1 mx-1 dark:bg-transparent bg-transparent border-0'>\n        {tabs.map((tab) => (\n          <TabsTrigger\n            key={tab.meta}\n            value={tab.meta}\n            className='data-[state=active]:bg-white dark:data-[state=active]:bg-zinc-800 gap-1 data-[state=active]:border'\n          >\n            {tab.meta === 'ui-layouts' ? (\n              <>\n                <svg\n                  width='238'\n                  height='264'\n                  viewBox='0 0 238 264'\n                  fill='none'\n                  className='size-4'\n                  xmlns='http://www.w3.org/2000/svg'\n                >\n                  <path\n                    d='M130 0C146.292 0 159.5 13.2076 159.5 29.5V39.5C159.5 55.2401 172.26 68 188 68H208C224.292 68 237.5 81.2076 237.5 97.5V234.5C237.5 250.792 224.292 264 208 264H105C88.7076 264 75.5 250.792 75.5 234.5V226.5C75.5 210.76 62.7401 198 47 198H29.5C13.2076 198 0 184.792 0 168.5V29.5C0 13.2076 13.2076 0 29.5 0H130ZM86 78C81.5817 78 78 81.5817 78 86V191C78 195.418 81.5817 199 86 199H158C162.418 199 166 195.418 166 191V86C166 81.5817 162.418 78 158 78H86Z'\n                    fill='currentColor'\n                  />\n                </svg>\n                ui-layouts\n              </>\n            ) : (\n              <>\n                <svg viewBox='0 0 256 256' className='size-4' fill='none'>\n                  <line\n                    x1='208'\n                    y1='128'\n                    x2='128'\n                    y2='208'\n                    stroke='currentColor'\n                    strokeWidth='32'\n                  />\n                  <line x1='192' y1='40' x2='40' y2='192' stroke='currentColor' strokeWidth='32' />\n                </svg>\n                shadcn\n              </>\n            )}\n          </TabsTrigger>\n        ))}\n      </TabsList>\n\n      {tabs.map((tab) => (\n        <TabsContent key={tab.meta} value={tab.meta} className='mt-1 border-none'>\n          <CopyButton code={tab.code} classname='top-1.5 border bg-white absolute right-3' />\n          <div\n            className='cliblocks rounded-xl p-1 px-2 border-none'\n            dangerouslySetInnerHTML={{ __html: tab.html }}\n          />\n        </TabsContent>\n      ))}\n    </Tabs>\n  );\n}\n",
      "type": "registry:component"
    },
    {
      "path": "./lib/shiki-highlighter.ts",
      "content": "import { type Highlighter, createHighlighter } from 'shiki';\n\nconst SAFE_LANGS = new Set(['ts', 'tsx', 'js', 'jsx', 'json', 'css', 'html', 'bash']);\n\nfunction normalizeLang(lang?: string) {\n  if (!lang) return 'txt';\n  return SAFE_LANGS.has(lang) ? lang : 'txt';\n}\nlet highlighterPromise: Promise<Highlighter> | null = null;\n\nfunction getHighlighterInstance() {\n  if (!highlighterPromise) {\n    highlighterPromise = createHighlighter({\n      themes: ['github-dark', 'github-light', 'slack-dark'],\n      langs: ['ts', 'tsx', 'js', 'jsx', 'json', 'css', 'html', 'bash', 'txt'],\n    });\n  }\n\n  return highlighterPromise;\n}\nexport async function highlightCode(code: string, lang = 'ts') {\n  const highlighter = await getHighlighterInstance();\n  const safeLang = normalizeLang(lang);\n\n  try {\n    return highlighter.codeToHtml(code, {\n      lang: safeLang,\n      themes: {\n        light: 'github-light',\n        dark: 'slack-dark',\n      },\n    });\n  } catch (err) {\n    console.warn('[Shiki error – fallback]', err);\n\n    // Fallback: plain escaped code\n    return `<pre><code>${escapeHtml(code)}</code></pre>`;\n  }\n}\n\nfunction escapeHtml(str: unknown) {\n  if (typeof str !== 'string') {\n    console.warn('escapeHtml got non-string:', str);\n    return '';\n  }\n\n  return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n}\n",
      "type": "registry:component"
    },
    {
      "path": "./components/website/code-components/copy-button.tsx",
      "content": "'use client';\n\nimport { cn } from '@/lib/utils';\nimport { Check, CheckCheck, Copy } from 'lucide-react';\nimport { useState } from 'react';\n\nexport function CopyButton({ code, classname }: { code: string; classname?: string }) {\n  const [hasCheckIcon, setHasCheckIcon] = useState(false);\n\n  const onCopy = () => {\n    navigator.clipboard.writeText(code);\n    setHasCheckIcon(true);\n\n    setTimeout(() => {\n      setHasCheckIcon(false);\n    }, 1000);\n  };\n\n  return (\n    <>\n      <div\n        className={cn(\n          'absolute right-2 top-2 cursor-pointer dark:hover:shadow-[0px_1px_10px_5px_#3f7ef3] hover:shadow-[0px_1px_10px_5px_#9abaf7] dark:hover:border-blue-500 hover:border-blue-300  dark:bg-zinc-800 backdrop-blur-2xl bg-white rounded-md border-2',\n          classname\n        )}\n        onClick={onCopy}\n      >\n        <div\n          className={` inset-0 transform transition-all duration-300  w-9 h-8 grid place-content-center  ${\n            hasCheckIcon ? 'scale-0 opacity-0' : 'scale-100 opacity-100'\n          }`}\n        >\n          <Copy className='h-4 w-4 text-foreground/80' />\n        </div>\n        <div\n          className={`absolute inset-0 transform transition-all duration-300 w-8 h-8 grid place-content-center  ${\n            hasCheckIcon ? 'scale-100 opacity-100' : 'scale-0 opacity-0'\n          }`}\n        >\n          <CheckCheck className='h-4 w-4 text-foreground/80' />\n        </div>\n      </div>\n    </>\n  );\n}\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:component"
}