{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "code-snippet-playground",
  "title": "Code Snippet Playground",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-react/blocks/code-snippet-playground/CodeSnippetPlayground.tsx",
      "content": "'use client'\n\nimport * as React from 'react'\nimport {\n  Braces,\n  Check,\n  CheckCircle2,\n  Code2,\n  Copy,\n  Eye,\n  FileCode,\n  Layers,\n  Loader2,\n  Play,\n  RotateCcw,\n  Terminal,\n  Zap,\n} from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'\nimport { Separator } from '@/components/ui/separator'\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'\n\ninterface CodeFile {\n  id: string\n  name: string\n  path: string\n  language: string\n  size: string\n  content: string\n}\n\ninterface TestLog {\n  id: string\n  name: string\n  duration: string\n  status: 'pass' | 'fail'\n}\n\nconst files: CodeFile[] = [\n  {\n    id: 'button-tsx',\n    name: 'Button.tsx',\n    path: 'packages/registry-react/components/button/Button.tsx',\n    language: 'typescript',\n    size: '1.1 KB',\n    content: `import * as React from 'react'\nimport { Slot } from '@radix-ui/react-slot'\nimport { cn } from '@/lib/utils'\nimport { buttonVariants, type ButtonVariants } from './button.variants'\n\nexport interface ButtonProps\n  extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n    ButtonVariants {\n  asChild?: boolean\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n  ({ className, variant, size, asChild = false, type = 'button', ...props }, ref) => {\n    const Comp = asChild ? Slot : 'button'\n    return (\n      <Comp\n        data-slot=\"button\"\n        data-variant={variant ?? undefined}\n        data-size={size ?? undefined}\n        className={cn(buttonVariants({ variant, size }), className)}\n        {...(asChild ? {} : { type })}\n        ref={ref}\n        {...props}\n      />\n    )\n  },\n)\nButton.displayName = 'Button'\n\nexport { Button }`,\n  },\n  {\n    id: 'button-variants',\n    name: 'button.variants.ts',\n    path: 'packages/registry-react/components/button/button.variants.ts',\n    language: 'typescript',\n    size: '1.4 KB',\n    content: `import type { VariantProps } from 'class-variance-authority'\nimport { cva } from 'class-variance-authority'\n\nexport const buttonVariants = cva(\n  'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*=\"size-\"])]:size-4 shrink-0',\n  {\n    variants: {\n      variant: {\n        default: 'bg-primary text-primary-foreground shadow-xs hover:bg-primary/90',\n        destructive: 'bg-destructive text-white shadow-xs hover:bg-destructive/90',\n        outline: 'border border-input bg-background shadow-xs hover:bg-accent hover:text-accent-foreground',\n        secondary: 'bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80',\n        ghost: 'hover:bg-accent hover:text-accent-foreground',\n        link: 'text-primary underline-offset-4 hover:underline',\n      },\n      size: {\n        default: 'h-9 px-4 py-2',\n        sm: 'h-8 rounded-md px-3 text-xs',\n        lg: 'h-10 rounded-md px-6',\n        icon: 'size-9',\n      },\n    },\n    defaultVariants: {\n      variant: 'default',\n      size: 'default',\n    },\n  },\n)\n\nexport type ButtonVariants = VariantProps<typeof buttonVariants>`,\n  },\n  {\n    id: 'index-ts',\n    name: 'index.ts',\n    path: 'packages/registry-react/components/button/index.ts',\n    language: 'typescript',\n    size: '220 B',\n    content: `export { Button, type ButtonProps } from './Button'\nexport { buttonVariants, type ButtonVariants } from './button.variants'`,\n  },\n  {\n    id: 'button-test',\n    name: 'button.test.tsx',\n    path: 'packages/registry-react/components/button/__tests__/button.spec.tsx',\n    language: 'typescript',\n    size: '1.7 KB',\n    content: `import { describe, it, expect, vi } from 'vitest'\nimport { render, screen, fireEvent } from '@testing-library/react'\nimport { Button } from '../Button'\n\ndescribe('Button Primitive', () => {\n  it('renders default button with children text', () => {\n    render(<Button>Submit</Button>)\n    const btn = screen.getByRole('button', { name: /submit/i })\n    expect(btn).toBeInTheDocument()\n    expect(btn).toHaveAttribute('data-slot', 'button')\n  })\n\n  it('applies variant classes correctly', () => {\n    render(<Button variant=\"destructive\">Delete</Button>)\n    const btn = screen.getByRole('button', { name: /delete/i })\n    expect(btn).toHaveAttribute('data-variant', 'destructive')\n    expect(btn.className).toContain('bg-destructive')\n  })\n\n  it('applies size styles correctly', () => {\n    render(<Button size=\"sm\">Small</Button>)\n    const btn = screen.getByRole('button', { name: /small/i })\n    expect(btn).toHaveAttribute('data-size', 'sm')\n    expect(btn.className).toContain('h-8')\n  })\n\n  it('handles click events when active', () => {\n    const handleClick = vi.fn()\n    render(<Button onClick={handleClick}>Trigger</Button>)\n    fireEvent.click(screen.getByRole('button', { name: /trigger/i }))\n    expect(handleClick).toHaveBeenCalledTimes(1)\n  })\n\n  it('respects disabled state attribute', () => {\n    render(<Button disabled>Disabled</Button>)\n    expect(screen.getByRole('button', { name: /disabled/i })).toBeDisabled()\n  })\n\n  it('forwards custom class names with cn()', () => {\n    render(<Button className=\"custom-btn\">Custom</Button>)\n    const btn = screen.getByRole('button', { name: /custom/i })\n    expect(btn.className).toContain('custom-btn')\n  })\n})`,\n  },\n]\n\nconst testLogs: TestLog[] = [\n  { id: '1', name: 'renders default button with children text', duration: '4ms', status: 'pass' },\n  { id: '2', name: 'applies variant classes correctly', duration: '7ms', status: 'pass' },\n  { id: '3', name: 'applies size styles correctly', duration: '5ms', status: 'pass' },\n  { id: '4', name: 'handles click events when active', duration: '8ms', status: 'pass' },\n  { id: '5', name: 'respects disabled state attribute', duration: '6ms', status: 'pass' },\n  { id: '6', name: 'forwards custom class names with cn()', duration: '12ms', status: 'pass' },\n]\n\ntype ButtonVariant = 'default' | 'secondary' | 'destructive' | 'outline' | 'ghost' | 'link'\ntype ButtonSize = 'default' | 'sm' | 'lg' | 'icon'\n\nexport interface CodeSnippetPlaygroundProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nfunction highlightSyntaxLine(line: string): string {\n  if (!line.trim()) return '&nbsp;'\n\n  const escaped = line.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')\n\n  // Single line comments\n  if (/^\\s*\\/\\//.test(escaped) || /^\\s*\\/\\*/.test(escaped) || /^\\s*\\*/.test(escaped) || /^\\s*&lt;!--/.test(escaped)) {\n    return `<span class=\"text-zinc-500 italic\">${escaped}</span>`\n  }\n\n  // Every emitted <span> is parked behind a letter-only placeholder so later\n  // passes cannot match inside the markup they already produced.\n  const parked: string[] = []\n  const park = (html: string) => {\n    const key = String(parked.length)\n      .split('')\n      .map((d) => String.fromCharCode(97 + Number(d)))\n      .join('')\n    parked.push(html)\n    return `\\u0000${key}\\u0000`\n  }\n\n  let out = escaped\n\n  // Strings\n  out = out.replace(/([\"'`])(?:(?=(\\\\?))\\2.)*?\\1/g, (m) => park(`<span class=\"text-success font-normal\">${m}</span>`))\n\n  // Trailing comments\n  out = out.replace(/(\\/\\/.*$)/, (m) => park(`<span class=\"text-zinc-500 italic\">${m}</span>`))\n\n  // Keywords\n  out = out.replace(\n    /\\b(import|export|from|const|let|var|function|return|interface|type|default|as|typeof|withDefaults|defineProps|defineEmits|describe|it|expect|test|async|await|extends|new|true|false|null|undefined)\\b/g,\n    (m) => park(`<span class=\"text-chart-1 font-semibold\">${m}</span>`),\n  )\n\n  // Types\n  out = out.replace(\n    /\\b(string|boolean|number|void|HTMLAttributes|VariantProps|ButtonVariants|ButtonProps|Props|Variant|Size|HTMLButtonElement|Record)\\b/g,\n    (m) => park(`<span class=\"text-warning font-medium\">${m}</span>`),\n  )\n\n  // Functions / methods\n  out = out.replace(\n    /\\b(cn|buttonVariants|cva|mount|render|screen|getByRole|fireEvent|vi|trigger|classes|attributes|emitted|toBe|toContain|toHaveProperty|toBeDefined|toBeInTheDocument|toHaveAttribute|toHaveBeenCalledTimes|toHaveBeenCalled|forwardRef|displayName|ref|computed|onMounted|onUnmounted|fn)\\b/g,\n    (m) => park(`<span class=\"text-info\">${m}</span>`),\n  )\n\n  // Vue/TSX tags\n  out = out.replace(\n    /(&lt;\\/?(?:template|script|Primitive|Button|Slot|Comp|slot|div|span|button)\\b(?:\\s|\\/|&gt;)?)/g,\n    (m) => park(`<span class=\"text-info font-medium\">${m}</span>`),\n  )\n\n  // Attributes / directives\n  out = out.replace(\n    /(\\b(?:data-slot|data-variant|data-size|className|variant|size|asChild|as|type|class|lang|setup|ref|onClick|disabled)\\b|:[a-zA-Z0-9_-]+)/g,\n    (m) => park(`<span class=\"text-chart-2\">${m}</span>`),\n  )\n\n  // Numbers\n  out = out.replace(/\\b(\\d+)\\b/g, (m) => park(`<span class=\"text-warning\">${m}</span>`))\n\n  // Restore every parked span\n  return out.replace(/\\u0000([a-j]+)\\u0000/g, (_, key: string) => {\n    const idx = Number(\n      key\n        .split('')\n        .map((c: string) => String(c.charCodeAt(0) - 97))\n        .join(''),\n    )\n    return parked[idx] ?? ''\n  })\n}\n\nexport function CodeSnippetPlayground({ className, ...props }: CodeSnippetPlaygroundProps) {\n  const [activeFileId, setActiveFileId] = React.useState('button-tsx')\n  const [activeRightTab, setActiveRightTab] = React.useState('preview')\n  const [hoveredLine, setHoveredLine] = React.useState<number | null>(null)\n  const [isCopied, setIsCopied] = React.useState(false)\n  const [isSnippetCopied, setIsSnippetCopied] = React.useState(false)\n  const [isRunning, setIsRunning] = React.useState(false)\n  const [lastRunTime, setLastRunTime] = React.useState('14:32:08')\n  const [executionCount, setExecutionCount] = React.useState(1)\n\n  // Interactive Workbench State\n  const [selectedVariant, setSelectedVariant] = React.useState<ButtonVariant>('default')\n  const [selectedSize, setSelectedSize] = React.useState<ButtonSize>('default')\n  const [isDisabled, setIsDisabled] = React.useState(false)\n  const [isLoading, setIsLoading] = React.useState(false)\n  const [withIcon, setWithIcon] = React.useState(true)\n  const [clickCount, setClickCount] = React.useState(0)\n  const [lastInteraction, setLastInteraction] = React.useState('Ready for test interactions')\n\n  const activeFile = React.useMemo(() => {\n    return files.find((f) => f.id === activeFileId) || files[0]\n  }, [activeFileId])\n\n  const activeFileLines = React.useMemo(() => {\n    return activeFile.content.split('\\n')\n  }, [activeFile])\n\n  const generatedSnippet = React.useMemo(() => {\n    const v = selectedVariant !== 'default' ? ` variant=\"${selectedVariant}\"` : ''\n    const s = selectedSize !== 'default' ? ` size=\"${selectedSize}\"` : ''\n    const d = isDisabled ? ' disabled' : ''\n\n    if (selectedSize === 'icon') {\n      return `<Button${v}${s}${d}>\\n  <Zap className=\"size-4\" />\\n</Button>`\n    }\n\n    if (isLoading) {\n      return `<Button${v}${s}${d}>\\n  <Loader2 className=\"size-4 animate-spin\" />\\n  Please wait\\n</Button>`\n    }\n\n    if (withIcon) {\n      return `<Button${v}${s}${d}>\\n  <Zap className=\"size-4\" />\\n  Interactive Button\\n</Button>`\n    }\n\n    return `<Button${v}${s}${d}>Interactive Button</Button>`\n  }, [selectedVariant, selectedSize, isDisabled, isLoading, withIcon])\n\n  const handleRunCode = React.useCallback(() => {\n    if (isRunning) return\n    setIsRunning(true)\n    setActiveRightTab('console')\n\n    setTimeout(() => {\n      setIsRunning(false)\n      setExecutionCount((prev) => prev + 1)\n      const now = new Date()\n      setLastRunTime(now.toTimeString().split(' ')[0])\n    }, 480)\n  }, [isRunning])\n\n  const handleCopyFile = React.useCallback(() => {\n    if (typeof navigator !== 'undefined' && navigator.clipboard) {\n      navigator.clipboard.writeText(activeFile.content)\n      setIsCopied(true)\n      setTimeout(() => setIsCopied(false), 2000)\n    }\n  }, [activeFile])\n\n  const handleCopySnippet = React.useCallback(() => {\n    if (typeof navigator !== 'undefined' && navigator.clipboard) {\n      navigator.clipboard.writeText(generatedSnippet)\n      setIsSnippetCopied(true)\n      setTimeout(() => setIsSnippetCopied(false), 2000)\n    }\n  }, [generatedSnippet])\n\n  const handleResetPlayground = React.useCallback(() => {\n    setActiveFileId('button-tsx')\n    setSelectedVariant('default')\n    setSelectedSize('default')\n    setIsDisabled(false)\n    setIsLoading(false)\n    setWithIcon(true)\n    setClickCount(0)\n    setLastInteraction('Playground reset to initial state')\n  }, [])\n\n  const handleButtonClick = React.useCallback(() => {\n    if (isDisabled || isLoading) return\n    setClickCount((prev) => {\n      const next = prev + 1\n      setLastInteraction(`Dispatched onClick event #${next} at ${new Date().toLocaleTimeString()}`)\n      return next\n    })\n  }, [isDisabled, isLoading])\n\n  React.useEffect(() => {\n    const handleKeyDown = (e: KeyboardEvent) => {\n      if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') {\n        e.preventDefault()\n        handleRunCode()\n      }\n    }\n    window.addEventListener('keydown', handleKeyDown)\n    return () => window.removeEventListener('keydown', handleKeyDown)\n  }, [handleRunCode])\n\n  return (\n    <Card\n      className={cn('border-border bg-card w-full overflow-hidden shadow-xs', className)}\n      data-slot=\"code-snippet-playground\"\n      {...props}\n    >\n      {/* Top Toolbar */}\n      <CardHeader className=\"border-border bg-muted/20 flex flex-col gap-3 border-b p-4 sm:flex-row sm:items-center sm:justify-between\">\n        <div className=\"flex items-center gap-3\">\n          <div className=\"bg-primary/10 text-primary flex size-9 items-center justify-center rounded-lg\">\n            <Code2 className=\"size-4.5\" />\n          </div>\n          <div>\n            <div className=\"flex items-center gap-2\">\n              <CardTitle className=\"text-base font-semibold tracking-tight\">Button.tsx · Radix UI Primitive</CardTitle>\n              <Badge variant=\"outline\" className=\"text-muted-foreground font-mono text-xs\">\n                React 19\n              </Badge>\n              <Badge variant=\"secondary\" className=\"font-mono text-xs\">\n                TypeScript 5.6\n              </Badge>\n            </div>\n            <CardDescription className=\"text-muted-foreground text-xs\">\n              Multi-file component studio with live preview, syntax engine, and Vitest suite\n            </CardDescription>\n          </div>\n        </div>\n\n        {/* Action Buttons */}\n        <div className=\"flex flex-wrap items-center gap-2\">\n          <div className=\"border-border/80 bg-background/80 flex items-center gap-1.5 rounded-md border px-2.5 py-1 text-xs\">\n            <span\n              className={cn(\n                'size-2 rounded-full transition-colors',\n                isRunning ? 'bg-warning animate-pulse' : 'bg-success',\n              )}\n            />\n            <span className=\"text-muted-foreground font-mono\">\n              {isRunning ? 'Running suite...' : '6 tests passing'}\n            </span>\n          </div>\n\n          <Button\n            variant=\"outline\"\n            size=\"sm\"\n            className=\"h-8 gap-1.5 text-xs shadow-none\"\n            title=\"Reset Playground\"\n            onClick={handleResetPlayground}\n          >\n            <RotateCcw className=\"size-3.5\" />\n            <span className=\"hidden sm:inline\">Reset</span>\n          </Button>\n\n          <Button\n            variant=\"outline\"\n            size=\"sm\"\n            className=\"h-8 gap-1.5 text-xs shadow-none\"\n            title=\"Copy active file contents\"\n            onClick={handleCopyFile}\n          >\n            {isCopied ? <Check className=\"text-success size-3.5\" /> : <Copy className=\"size-3.5\" />}\n            <span>{isCopied ? 'Copied!' : 'Copy File'}</span>\n          </Button>\n\n          <Button size=\"sm\" className=\"h-8 gap-1.5 text-xs font-medium\" disabled={isRunning} onClick={handleRunCode}>\n            {isRunning ? <Loader2 className=\"size-3.5 animate-spin\" /> : <Play className=\"size-3.5 fill-current\" />}\n            <span>Run Code</span>\n            <kbd className=\"border-primary-foreground/30 bg-primary-foreground/10 hidden rounded border px-1 font-mono text-xs sm:inline\">\n              ⌘↵\n            </kbd>\n          </Button>\n        </div>\n      </CardHeader>\n\n      {/* Main 2-Column Studio Grid */}\n      <div className=\"divide-border grid grid-cols-1 divide-y lg:grid-cols-12 lg:divide-x lg:divide-y-0\">\n        {/* Left Column: File Tabs & Dark Code Editor (7/12 cols) */}\n        <section className=\"flex min-h-[560px] flex-col bg-zinc-950 text-zinc-100 lg:col-span-7\">\n          {/* File Navigation Tabs */}\n          <div className=\"flex items-center justify-between border-b border-zinc-800/80 bg-zinc-900/70 px-2\">\n            <div className=\"flex scrollbar-none items-center gap-1 overflow-x-auto py-1.5\">\n              {files.map((file) => (\n                <button\n                  key={file.id}\n                  type=\"button\"\n                  className={cn(\n                    'group flex cursor-pointer items-center gap-2 rounded-md px-3 py-1.5 font-mono text-xs transition-colors',\n                    activeFileId === file.id\n                      ? 'border border-zinc-800 bg-zinc-950 text-zinc-100 shadow-xs'\n                      : 'text-zinc-400 hover:bg-zinc-800/50 hover:text-zinc-200',\n                  )}\n                  onClick={() => setActiveFileId(file.id)}\n                >\n                  {file.name.endsWith('.tsx') ? (\n                    <FileCode\n                      className={cn(\n                        'size-3.5 transition-colors',\n                        activeFileId === file.id ? 'text-info' : 'text-zinc-500',\n                      )}\n                    />\n                  ) : file.name.endsWith('.variants.ts') ? (\n                    <Braces\n                      className={cn(\n                        'size-3.5 transition-colors',\n                        activeFileId === file.id ? 'text-chart-1' : 'text-zinc-500',\n                      )}\n                    />\n                  ) : file.name === 'index.ts' ? (\n                    <Layers\n                      className={cn(\n                        'size-3.5 transition-colors',\n                        activeFileId === file.id ? 'text-warning' : 'text-zinc-500',\n                      )}\n                    />\n                  ) : (\n                    <CheckCircle2\n                      className={cn(\n                        'size-3.5 transition-colors',\n                        activeFileId === file.id ? 'text-success' : 'text-zinc-500',\n                      )}\n                    />\n                  )}\n                  <span>{file.name}</span>\n                </button>\n              ))}\n            </div>\n\n            <span className=\"hidden font-mono text-xs text-zinc-500 xl:inline\">{activeFile.size}</span>\n          </div>\n\n          {/* Breadcrumb / Path Info */}\n          <div className=\"flex items-center justify-between border-b border-zinc-800/60 bg-zinc-950/80 px-4 py-1.5 font-mono text-xs text-zinc-400\">\n            <div className=\"flex items-center gap-1.5 overflow-hidden text-ellipsis whitespace-nowrap\">\n              <span className=\"text-zinc-600\">src /</span>\n              <span>{activeFile.path}</span>\n            </div>\n            <span className=\"text-zinc-500\">{activeFileLines.length} lines</span>\n          </div>\n\n          {/* Code Editor Body */}\n          <div className=\"relative flex flex-1 overflow-x-auto bg-zinc-950 py-3 font-mono text-xs leading-relaxed select-text\">\n            {/* Gutter Line Numbers */}\n            <div className=\"flex flex-col border-r border-zinc-800/60 px-3 text-right text-zinc-600 select-none\">\n              {activeFileLines.map((_, index) => (\n                <span\n                  key={index}\n                  className={cn(\n                    'h-5 leading-5 transition-colors',\n                    hoveredLine === index + 1 ? 'font-semibold text-zinc-300' : '',\n                  )}\n                >\n                  {index + 1}\n                </span>\n              ))}\n            </div>\n\n            {/* Code Lines with Syntax Coloring */}\n            <div className=\"flex-1 px-4 whitespace-pre\">\n              {activeFileLines.map((line, index) => (\n                <div\n                  key={index}\n                  className={cn(\n                    'group flex h-5 items-center rounded-xs px-1 leading-5 transition-colors',\n                    hoveredLine === index + 1 ? 'bg-zinc-800/40' : '',\n                  )}\n                  onMouseEnter={() => setHoveredLine(index + 1)}\n                  onMouseLeave={() => setHoveredLine(null)}\n                >\n                  <span dangerouslySetInnerHTML={{ __html: highlightSyntaxLine(line) }} />\n                </div>\n              ))}\n            </div>\n          </div>\n\n          {/* Editor Status Bar */}\n          <div className=\"flex items-center justify-between border-t border-zinc-800/60 bg-zinc-900/90 px-3 py-1 font-mono text-xs text-zinc-400\">\n            <div className=\"flex items-center gap-3\">\n              <span>UTF-8</span>\n              <span>2 Spaces</span>\n              <span className=\"text-zinc-500\">React TSX</span>\n            </div>\n            <div className=\"flex items-center gap-3\">\n              <span>Ln {hoveredLine ?? 1}, Col 1</span>\n              <span className=\"text-success\">Prettier ✓</span>\n            </div>\n          </div>\n        </section>\n\n        {/* Right Column: Live Sandbox & Terminal Console (5/12 cols) */}\n        <section className=\"bg-background flex min-h-[560px] flex-col lg:col-span-5\">\n          <Tabs value={activeRightTab} onValueChange={setActiveRightTab} className=\"flex h-full flex-col\">\n            {/* Right Tab Header */}\n            <div className=\"border-border bg-muted/30 border-b px-3 py-2\">\n              <TabsList className=\"grid w-full grid-cols-2\">\n                <TabsTrigger value=\"preview\" className=\"gap-1.5 text-xs\">\n                  <Eye className=\"size-3.5\" />\n                  <span>Live Preview</span>\n                </TabsTrigger>\n                <TabsTrigger value=\"console\" className=\"gap-1.5 text-xs\">\n                  <Terminal className=\"size-3.5\" />\n                  <span>Terminal</span>\n                  <Badge variant=\"secondary\" className=\"text-success ml-1 px-1 py-0 font-mono text-xs\">\n                    PASS\n                  </Badge>\n                </TabsTrigger>\n              </TabsList>\n            </div>\n\n            {/* TAB 1: Live Component Sandbox */}\n            <TabsContent value=\"preview\" className=\"m-0 flex flex-1 flex-col gap-4 p-4\">\n              {/* Variant & Style Controls */}\n              <div className=\"border-border bg-card space-y-3 rounded-lg border p-3 shadow-xs\">\n                <div className=\"flex items-center justify-between\">\n                  <span className=\"text-foreground text-xs font-semibold\">Variant</span>\n                  <span className=\"text-muted-foreground font-mono text-xs\">{selectedVariant}</span>\n                </div>\n                <div className=\"flex flex-wrap gap-1.5\">\n                  {(['default', 'secondary', 'destructive', 'outline', 'ghost', 'link'] as ButtonVariant[]).map((v) => (\n                    <button\n                      key={v}\n                      type=\"button\"\n                      className={cn(\n                        'min-h-6 cursor-pointer rounded-md px-2.5 py-1 font-mono text-xs capitalize transition-colors',\n                        selectedVariant === v\n                          ? 'bg-primary text-primary-foreground font-medium shadow-xs'\n                          : 'bg-muted/60 text-muted-foreground hover:bg-muted hover:text-foreground',\n                      )}\n                      onClick={() => setSelectedVariant(v)}\n                    >\n                      {v}\n                    </button>\n                  ))}\n                </div>\n\n                <Separator className=\"my-2\" />\n\n                <div className=\"flex items-center justify-between\">\n                  <span className=\"text-foreground text-xs font-semibold\">Size & Options</span>\n                </div>\n                <div className=\"flex flex-wrap items-center gap-1.5\">\n                  {(['sm', 'default', 'lg', 'icon'] as ButtonSize[]).map((s) => (\n                    <button\n                      key={s}\n                      type=\"button\"\n                      className={cn(\n                        'min-h-6 cursor-pointer rounded-md px-2 py-0.5 font-mono text-xs uppercase transition-colors',\n                        selectedSize === s\n                          ? 'bg-secondary text-secondary-foreground font-semibold'\n                          : 'bg-muted/40 text-muted-foreground hover:bg-muted',\n                      )}\n                      onClick={() => setSelectedSize(s)}\n                    >\n                      {s}\n                    </button>\n                  ))}\n\n                  <div className=\"ml-auto flex items-center gap-2\">\n                    <label className=\"text-muted-foreground flex cursor-pointer items-center gap-1.5 text-xs select-none\">\n                      <input\n                        type=\"checkbox\"\n                        checked={isDisabled}\n                        onChange={(e) => setIsDisabled(e.target.checked)}\n                        className=\"accent-primary\"\n                      />\n                      <span>Disabled</span>\n                    </label>\n                    <label className=\"text-muted-foreground flex cursor-pointer items-center gap-1.5 text-xs select-none\">\n                      <input\n                        type=\"checkbox\"\n                        checked={isLoading}\n                        onChange={(e) => setIsLoading(e.target.checked)}\n                        className=\"accent-primary\"\n                      />\n                      <span>Loading</span>\n                    </label>\n                    <label className=\"text-muted-foreground flex cursor-pointer items-center gap-1.5 text-xs select-none\">\n                      <input\n                        type=\"checkbox\"\n                        checked={withIcon}\n                        onChange={(e) => setWithIcon(e.target.checked)}\n                        className=\"accent-primary\"\n                      />\n                      <span>Icon</span>\n                    </label>\n                  </div>\n                </div>\n              </div>\n\n              {/* Render Stage Canvas */}\n              <div className=\"border-border bg-muted/20 relative flex min-h-[160px] flex-1 flex-col items-center justify-center rounded-lg border border-dashed p-6\">\n                <div className=\"flex flex-col items-center gap-3\">\n                  <Button\n                    variant={selectedVariant}\n                    size={selectedSize}\n                    disabled={isDisabled || isLoading}\n                    className=\"transition-[color,background-color,border-color,box-shadow,opacity,transform,scale,translate,rotate] active:scale-95\"\n                    onClick={handleButtonClick}\n                  >\n                    {isLoading ? (\n                      <Loader2 className=\"size-4 animate-spin\" />\n                    ) : withIcon || selectedSize === 'icon' ? (\n                      <Zap className=\"size-4\" />\n                    ) : null}\n                    {selectedSize !== 'icon' && <span>Interactive Button</span>}\n                  </Button>\n\n                  <p className=\"text-muted-foreground font-mono text-xs\">\n                    Clicks: <span className=\"text-foreground font-semibold\">{clickCount}</span>\n                  </p>\n                </div>\n\n                {/* Last Interaction Status */}\n                <div className=\"bg-background/80 text-muted-foreground absolute right-2 bottom-2 left-2 flex items-center justify-between rounded-md px-2 py-1 text-xs backdrop-blur-xs\">\n                  <span className=\"truncate font-mono\">{lastInteraction}</span>\n                  <span className=\"text-success shrink-0 font-medium\">Rendered OK</span>\n                </div>\n              </div>\n\n              {/* Dynamic Snippet Output */}\n              <div className=\"space-y-1.5\">\n                <div className=\"flex items-center justify-between text-xs\">\n                  <span className=\"text-foreground font-medium\">Usage Code</span>\n                  <button\n                    type=\"button\"\n                    className=\"text-muted-foreground hover:text-foreground flex min-h-6 cursor-pointer items-center gap-1\"\n                    onClick={handleCopySnippet}\n                  >\n                    {isSnippetCopied ? <Check className=\"text-success size-3\" /> : <Copy className=\"size-3\" />}\n                    <span>{isSnippetCopied ? 'Copied' : 'Copy'}</span>\n                  </button>\n                </div>\n                <pre className=\"border-border bg-muted/40 text-foreground overflow-x-auto rounded-md border p-2.5 font-mono text-xs leading-relaxed\">\n                  <code>{generatedSnippet}</code>\n                </pre>\n              </div>\n            </TabsContent>\n\n            {/* TAB 2: Terminal Console Execution Output */}\n            <TabsContent\n              value=\"console\"\n              className=\"m-0 flex flex-1 flex-col bg-zinc-950 p-4 font-mono text-xs text-zinc-300\"\n            >\n              {/* Console Toolbar */}\n              <div className=\"mb-3 flex items-center justify-between border-b border-zinc-800 pb-2 text-zinc-400\">\n                <div className=\"flex items-center gap-2\">\n                  <span className=\"font-semibold text-zinc-200\">Vitest Test Runner</span>\n                  <Badge variant=\"outline\" className=\"border-zinc-700 bg-zinc-900 font-mono text-xs text-zinc-300\">\n                    v2.1.8\n                  </Badge>\n                </div>\n                <div className=\"flex items-center gap-3\">\n                  <span className=\"text-zinc-500\">\n                    Run #{executionCount} ({lastRunTime})\n                  </span>\n                  <button\n                    type=\"button\"\n                    className=\"cursor-pointer text-zinc-400 hover:text-zinc-100\"\n                    title=\"Re-run tests\"\n                    onClick={handleRunCode}\n                  >\n                    <RotateCcw className=\"size-3.5\" />\n                  </button>\n                </div>\n              </div>\n\n              {/* Terminal Execution Logs */}\n              <div className=\"flex-1 space-y-2 overflow-y-auto pr-1\">\n                <div className=\"text-zinc-500\">\n                  $ vitest run packages/registry-react/components/button/__tests__/button.spec.tsx\n                </div>\n\n                <div className=\"text-success flex items-center gap-2 font-semibold\">\n                  <CheckCircle2 className=\"size-3.5 shrink-0\" />\n                  <span>PASS packages/registry-react/components/button/__tests__/button.spec.tsx (6 tests)</span>\n                  <span className=\"font-normal text-zinc-500\">42ms</span>\n                </div>\n\n                <div className=\"ml-4 space-y-1.5 border-l border-zinc-800 pl-3\">\n                  {testLogs.map((log) => (\n                    <div key={log.id} className=\"flex items-center justify-between text-zinc-300\">\n                      <div className=\"flex items-center gap-2\">\n                        <Check className=\"text-success size-3\" />\n                        <span>{log.name}</span>\n                      </div>\n                      <span className=\"text-zinc-500\">{log.duration}</span>\n                    </div>\n                  ))}\n                </div>\n\n                {/* Summary Card */}\n                <div className=\"mt-4 space-y-1 rounded-md border border-zinc-800/80 bg-zinc-900/60 p-2.5 text-zinc-400\">\n                  <div className=\"flex justify-between\">\n                    <span>Test Files</span>\n                    <span className=\"text-success font-medium\">1 passed (1)</span>\n                  </div>\n                  <div className=\"flex justify-between\">\n                    <span>Tests</span>\n                    <span className=\"text-success font-medium\">6 passed (6)</span>\n                  </div>\n                  <div className=\"flex justify-between\">\n                    <span>Start at</span>\n                    <span className=\"text-zinc-300\">{lastRunTime}</span>\n                  </div>\n                  <div className=\"flex justify-between\">\n                    <span>Duration</span>\n                    <span className=\"text-zinc-300\">42ms (transform 12ms, setup 0ms, collect 8ms, tests 42ms)</span>\n                  </div>\n                </div>\n              </div>\n\n              {/* Bottom Console Status Banner */}\n              <div className=\"border-success/30 bg-success/10 text-success mt-3 flex items-center justify-between rounded-md border px-3 py-2\">\n                <div className=\"flex items-center gap-2 font-semibold\">\n                  <CheckCircle2 className=\"size-4\" />\n                  <span>PASS · 6 passed, 0 failed in 42ms</span>\n                </div>\n                <span className=\"text-success/80 text-xs\">Exit code: 0</span>\n              </div>\n            </TabsContent>\n          </Tabs>\n        </section>\n      </div>\n    </Card>\n  )\n}\n\nexport default CodeSnippetPlayground\n",
      "type": "registry:block",
      "target": "~/components/blocks/CodeSnippetPlayground.tsx"
    }
  ],
  "dependencies": [
    "lucide-react"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/react/badge.json",
    "https://uipkge.dev/r/react/button.json",
    "https://uipkge.dev/r/react/card.json",
    "https://uipkge.dev/r/react/separator.json",
    "https://uipkge.dev/r/react/tabs.json"
  ],
  "description": "Multi-file interactive code runner, editor tabs, and terminal console output for components with live render sandbox, syntax highlighting, and test execution.",
  "categories": [
    "devops",
    "app",
    "developer",
    "education"
  ]
}