{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "code-block",
  "title": "Code Block",
  "description": "The code block from the Notra dashboard: a dualtone panel with a filename or tabs on the shell, syntax-highlighted code on the card and a copy button, plus a one-line command variant.",
  "dependencies": [
    "@base-ui/react",
    "@hugeicons/core-free-icons",
    "@hugeicons/react",
    "cn",
    "sugar-high"
  ],
  "files": [
    {
      "path": "registry/notra/code-block/components/code-block.tsx",
      "content": "\"use client\";\n\nimport { Tabs } from \"@base-ui/react/tabs\";\nimport {\n  Alert02Icon,\n  Copy01Icon,\n  Tick02Icon,\n} from \"@hugeicons/core-free-icons\";\nimport { HugeiconsIcon } from \"@hugeicons/react\";\nimport { cn } from \"cn\";\nimport { useMemo, useRef, useState } from \"react\";\nimport { highlight } from \"sugar-high\";\n\nimport {\n  CODE_BLOCK_COPIED_MS,\n  CODE_BLOCK_COPY_LABELS,\n  CODE_BLOCK_LABELS,\n} from \"../constants/code-block\";\nimport type {\n  CodeBlockCopyButtonProps,\n  CodeBlockProps,\n  CodeBlockTabsProps,\n  CopyStatus,\n} from \"../types/code-block\";\n\nfunction CodeBlockCopyButton({\n  code,\n  label,\n  onCopy,\n}: CodeBlockCopyButtonProps) {\n  const [status, setStatus] = useState<CopyStatus>(\"idle\");\n  const resetRef = useRef(0);\n\n  const copy = async () => {\n    window.clearTimeout(resetRef.current);\n    try {\n      await navigator.clipboard.writeText(code);\n      onCopy?.();\n      setStatus(\"copied\");\n    } catch {\n      setStatus(\"failed\");\n    }\n    resetRef.current = window.setTimeout(\n      () => setStatus(\"idle\"),\n      CODE_BLOCK_COPIED_MS\n    );\n  };\n\n  return (\n    <button\n      aria-label={CODE_BLOCK_COPY_LABELS[status](label)}\n      className=\"text-muted-foreground hover:bg-muted hover:text-foreground focus-visible:outline-ring relative inline-flex size-7 shrink-0 cursor-pointer items-center justify-center rounded-lg outline-2 outline-transparent transition-colors\"\n      onClick={copy}\n      type=\"button\"\n    >\n      <HugeiconsIcon\n        className={cn(\n          \"transition-[opacity,scale] duration-150\",\n          status !== \"idle\" && \"scale-50 opacity-0\"\n        )}\n        icon={Copy01Icon}\n        size={14}\n      />\n      <HugeiconsIcon\n        className={cn(\n          \"absolute transition-[opacity,scale] duration-150\",\n          status !== \"copied\" && \"scale-50 opacity-0\"\n        )}\n        icon={Tick02Icon}\n        size={14}\n      />\n      <HugeiconsIcon\n        className={cn(\n          \"text-destructive absolute transition-[opacity,scale] duration-150\",\n          status !== \"failed\" && \"scale-50 opacity-0\"\n        )}\n        icon={Alert02Icon}\n        size={14}\n      />\n    </button>\n  );\n}\n\nfunction CommandBlock({\n  code,\n  className,\n  label = CODE_BLOCK_LABELS.command,\n  onCopy,\n}: Pick<CodeBlockProps, \"code\" | \"className\" | \"label\" | \"onCopy\">) {\n  return (\n    <div\n      className={cn(\n        \"border-border/60 bg-muted/40 flex h-9 min-w-0 items-center rounded-lg border ps-3 pe-1\",\n        className\n      )}\n      data-slot=\"code-block\"\n    >\n      <input\n        aria-label={label}\n        className=\"text-foreground h-full min-w-0 flex-1 cursor-text appearance-none border-0 bg-transparent p-0 font-mono text-xs leading-none shadow-none outline-none\"\n        onFocus={(event) => event.currentTarget.select()}\n        readOnly\n        value={code}\n      />\n      <CodeBlockCopyButton code={code} label={label} onCopy={onCopy} />\n    </div>\n  );\n}\n\nexport function CodeBlockTabs({\n  label,\n  value,\n  options,\n  onValueChange,\n}: CodeBlockTabsProps) {\n  return (\n    <Tabs.Root\n      onValueChange={(next) => {\n        const option = options.find((item) => item.value === next);\n        if (option) {\n          onValueChange(option.value);\n        }\n      }}\n      value={value}\n    >\n      <Tabs.List\n        aria-label={label}\n        className=\"relative flex h-9 items-stretch gap-3.5\"\n      >\n        {options.map((option) => (\n          <Tabs.Tab\n            className=\"text-muted-foreground hover:text-foreground data-active:text-foreground focus-visible:outline-ring flex shrink-0 cursor-pointer items-center gap-1.5 rounded-sm text-xs whitespace-nowrap outline-2 -outline-offset-2 outline-transparent transition-colors\"\n            key={option.value}\n            value={option.value}\n          >\n            {option.icon}\n            {option.label}\n          </Tabs.Tab>\n        ))}\n        <Tabs.Indicator className=\"bg-foreground absolute bottom-1 left-(--active-tab-left) h-0.5 w-(--active-tab-width) rounded-full transition-[left,width] duration-200 ease-[cubic-bezier(0.22,1,0.36,1)] motion-reduce:transition-none\" />\n      </Tabs.List>\n    </Tabs.Root>\n  );\n}\n\nexport function CodeBlock({\n  code,\n  className,\n  filename,\n  headerEnd,\n  tabs,\n  variant = \"panel\",\n  label,\n  wrap = false,\n  onCopy,\n}: CodeBlockProps) {\n  const html = useMemo(() => highlight(code), [code]);\n\n  if (variant === \"command\") {\n    return (\n      <CommandBlock\n        className={className}\n        code={code}\n        label={label}\n        onCopy={onCopy}\n      />\n    );\n  }\n\n  return (\n    <div\n      className={cn(\n        \"border-shell-border bg-shell min-w-0 rounded-2xl border p-0.5 pt-0\",\n        className\n      )}\n      data-slot=\"code-block\"\n    >\n      <div className=\"flex h-9 min-w-0 items-center gap-3 ps-2.5 pe-1\">\n        {tabs ? (\n          <div className=\"min-w-0 flex-1 overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden\">\n            {tabs}\n          </div>\n        ) : null}\n        {filename ? (\n          <p\n            className={cn(\n              \"text-muted-foreground truncate font-mono text-xs\",\n              tabs ? \"shrink-0 pe-2\" : \"min-w-0 flex-1\"\n            )}\n          >\n            {filename}\n          </p>\n        ) : null}\n        {tabs || filename ? null : <span className=\"min-w-0 flex-1\" />}\n        {headerEnd}\n      </div>\n      <div className=\"group/code border-table-card-border bg-table-card shadow-table-card relative min-w-0 rounded-[14px] border\">\n        <div className=\"bg-table-card absolute end-1 top-1 z-10 rounded-lg opacity-0 transition-opacity duration-150 group-hover/code:opacity-100 focus-within:opacity-100 [@media(hover:none)]:opacity-100\">\n          <CodeBlockCopyButton\n            code={code}\n            label={label ?? CODE_BLOCK_LABELS.snippet}\n            onCopy={onCopy}\n          />\n        </div>\n        <pre\n          className={cn(\n            \"m-0 overflow-x-auto bg-transparent p-3 pe-10 font-mono text-xs leading-relaxed [scrollbar-width:thin]\",\n            wrap && \"wrap-anywhere whitespace-pre-wrap\"\n          )}\n          // biome-ignore lint/security/noDangerouslySetInnerHtml: sugar-high escapes the source before tokenizing\n          dangerouslySetInnerHTML={{ __html: html }}\n        />\n      </div>\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/code-block/components/code-block.tsx"
    },
    {
      "path": "registry/notra/code-block/constants/code-block.ts",
      "content": "export const CODE_BLOCK_COPIED_MS = 1500;\n\nexport const CODE_BLOCK_LABELS = {\n  command: \"Command\",\n  snippet: \"Snippet\",\n} as const;\n\nexport const CODE_BLOCK_COPY_LABELS = {\n  idle: (label: string) => `Copy ${label}`,\n  copied: (label: string) => `${label} copied`,\n  failed: (label: string) => `Copying ${label} failed`,\n} as const;\n",
      "type": "registry:lib",
      "target": "components/code-block/constants/code-block.ts"
    },
    {
      "path": "registry/notra/code-block/types/code-block.ts",
      "content": "import type { ReactNode } from \"react\";\n\nexport interface CodeBlockProps {\n  code: string;\n  className?: string;\n  filename?: string;\n  headerEnd?: ReactNode;\n  tabs?: ReactNode;\n  variant?: \"command\" | \"panel\";\n  label?: string;\n  wrap?: boolean;\n  onCopy?: () => void;\n}\n\nexport interface CodeBlockTabOption {\n  value: string;\n  label: string;\n  icon?: ReactNode;\n}\n\nexport interface CodeBlockTabsProps {\n  label: string;\n  value: string;\n  options: readonly CodeBlockTabOption[];\n  onValueChange: (value: string) => void;\n}\n\nexport interface CodeBlockCopyButtonProps {\n  code: string;\n  label: string;\n  onCopy?: () => void;\n}\n\nexport type CopyStatus = \"idle\" | \"copied\" | \"failed\";\n",
      "type": "registry:lib",
      "target": "components/code-block/types/code-block.ts"
    }
  ],
  "cssVars": {
    "theme": {
      "color-shell": "var(--shell)",
      "color-shell-border": "var(--shell-border)",
      "color-table-card": "var(--table-card)",
      "color-table-card-border": "var(--table-card-border)",
      "shadow-table-card": "var(--table-card-shadow)"
    },
    "light": {
      "shell": "var(--table-shell)",
      "shell-border": "var(--table-shell-border)",
      "table-shell": "#f3f3f2",
      "table-shell-border": "#e7e7e5",
      "table-card": "#ffffff",
      "table-card-border": "#e5e5e5",
      "table-card-shadow": "0 1px 2px hsl(240 10% 10% / 0.06), 0 2px 8px -2px hsl(240 10% 10% / 0.06)",
      "sh-class": "oklch(0.55 0.13 265)",
      "sh-identifier": "oklch(0.42 0.02 265)",
      "sh-sign": "oklch(0.62 0.01 265)",
      "sh-property": "oklch(0.55 0.15 25)",
      "sh-entity": "oklch(0.55 0.13 265)",
      "sh-jsxliterals": "oklch(0.52 0.16 300)",
      "sh-string": "oklch(0.52 0.12 155)",
      "sh-keyword": "oklch(0.55 0.19 320)",
      "sh-comment": "oklch(0.65 0.02 265)"
    },
    "dark": {
      "shell": "var(--table-shell)",
      "shell-border": "var(--table-shell-border)",
      "table-shell": "#161616",
      "table-shell-border": "#232323",
      "table-card": "#1f1f1f",
      "table-card-border": "#333333",
      "table-card-shadow": "inset 0 1px 0 hsl(0 0% 100% / 0.05), inset 0 0 0 1px hsl(0 0% 100% / 0.015), inset 0 12px 18px -16px hsl(0 0% 100% / 0.035)",
      "sh-class": "oklch(0.78 0.11 255)",
      "sh-identifier": "oklch(0.86 0.01 265)",
      "sh-sign": "oklch(0.66 0.01 265)",
      "sh-property": "oklch(0.76 0.12 30)",
      "sh-entity": "oklch(0.78 0.11 255)",
      "sh-jsxliterals": "oklch(0.78 0.13 300)",
      "sh-string": "oklch(0.79 0.13 150)",
      "sh-keyword": "oklch(0.76 0.15 330)",
      "sh-comment": "oklch(0.6 0.02 265)"
    }
  },
  "type": "registry:component"
}