{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "feature-code-preview-split",
  "title": "Feature Code Preview Split",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/feature-code-preview-split/feature-code-preview-split.component.ts",
      "content": "// Split-pane developer workbench featuring live code generation across Vue 3.5,\n// React 19, and Tailwind v4 tokens synchronized with an interactive component canvas.\n// Port of the React block 1:1.\nimport { ChangeDetectionStrategy, Component, DestroyRef, Input, computed, inject, signal } from '@angular/core'\nimport { Check, Code2, Copy, Eye, LucideAngularModule, Zap } from 'lucide-angular'\nimport { cn } from '@/lib/utils'\nimport { UiBadgeComponent } from '@/ui/badge/badge.component'\nimport { UiButtonComponent } from '@/ui/button/button.component'\nimport { UiCardComponent } from '@/ui/card/card.component'\n\nexport type FrameworkTab = 'vue' | 'react' | 'tailwind'\nexport type PreviewButtonVariant = 'default' | 'secondary' | 'outline' | 'destructive'\nexport type PreviewButtonSize = 'sm' | 'default' | 'lg'\n\nconst frameworkTabs: { id: FrameworkTab; label: string }[] = [\n  { id: 'vue', label: 'Vue 3.5 SFC' },\n  { id: 'react', label: 'React 19 JSX' },\n  { id: 'tailwind', label: 'Tailwind Tokens' },\n]\n\nconst variantOptions: PreviewButtonVariant[] = ['default', 'secondary', 'outline', 'destructive']\nconst sizeOptions: PreviewButtonSize[] = ['sm', 'default', 'lg']\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-feature-code-preview-split, [ui-feature-code-preview-split]',\n  standalone: true,\n  // React renders the root <section> itself: the host stays out of layout and `class` goes to the root.\n  host: { '[attr.class]': '\"contents\"' },\n  imports: [LucideAngularModule, UiBadgeComponent, UiButtonComponent, UiCardComponent],\n  template: `\n    <section data-slot=\"feature-code-preview-split\" [class]=\"rootClass\">\n      <div class=\"mx-auto max-w-7xl space-y-12\">\n        <!-- Section Header -->\n        <div class=\"mx-auto max-w-3xl space-y-4 text-center\">\n          <span ui-badge variant=\"secondary\" class=\"gap-1.5 px-3 py-1 font-mono text-xs shadow-xs\">\n            <lucide-icon [img]=\"Code2\" class=\"text-primary size-3.5\" />\n            Interactive DX Playground\n          </span>\n          <h2 class=\"text-foreground text-3xl font-bold tracking-tight sm:text-4xl\">\n            Real-time code generation with instant live preview.\n          </h2>\n          <p class=\"text-muted-foreground text-base\">\n            Modify the interactive controls on the right to see the AST code synchronize live across Vue 3.5, React 19,\n            and Tailwind v4.\n          </p>\n        </div>\n\n        <!-- Split-Pane DX Workbench -->\n        <div class=\"grid grid-cols-1 items-stretch gap-6 lg:grid-cols-12\">\n          <!-- Left Pane: Interactive Code Sandbox Editor (7 Cols) -->\n          <div\n            ui-card\n            class=\"border-border bg-card/95 flex flex-col justify-between space-y-4 rounded-2xl p-6 text-left shadow-sm lg:col-span-7\"\n          >\n            <!-- Editor Top Bar -->\n            <div class=\"border-border flex items-center justify-between border-b pb-3\">\n              <!-- Framework Selector Tabs -->\n              <div class=\"bg-muted/60 border-border flex items-center gap-1 rounded-lg border p-1\">\n                @for (tab of frameworkTabs; track tab.id) {\n                  <button type=\"button\" [class]=\"frameworkTabClass(tab.id)\" (click)=\"activeFramework.set(tab.id)\">\n                    {{ tab.label }}\n                  </button>\n                }\n              </div>\n\n              <!-- Copy Code Button -->\n              <button\n                ui-button\n                size=\"sm\"\n                variant=\"ghost\"\n                class=\"h-8 gap-1.5 px-2 font-mono text-xs\"\n                (click)=\"copyCode()\"\n              >\n                @if (isCopied()) {\n                  <lucide-icon [img]=\"Check\" class=\"text-success size-3.5\" />\n                } @else {\n                  <lucide-icon [img]=\"Copy\" class=\"text-muted-foreground size-3.5\" />\n                }\n                <span>{{ isCopied() ? 'Copied' : 'Copy' }}</span>\n              </button>\n            </div>\n\n            <!-- Code Viewport -->\n            <pre\n              class=\"border-border bg-muted/40 text-foreground my-2 flex-1 overflow-x-auto rounded-xl border p-4 font-mono text-xs leading-relaxed\"\n            ><code>{{ dynamicCode() }}</code></pre>\n\n            <!-- Footer Metadata -->\n            <div\n              class=\"text-muted-foreground border-border flex items-center justify-between border-t pt-3 font-mono text-xs\"\n            >\n              <span>Syntax: {{ syntaxLabel() }}</span>\n              <span class=\"text-success font-semibold\">&#10003; 100% Tree-Shakeable</span>\n            </div>\n          </div>\n\n          <!-- Right Pane: Live Component Render & Controls (5 Cols) -->\n          <div\n            ui-card\n            class=\"border-border bg-card/95 flex flex-col justify-between space-y-6 rounded-2xl p-6 text-left shadow-sm lg:col-span-5\"\n          >\n            <div class=\"space-y-4\">\n              <div class=\"border-border flex items-center justify-between border-b pb-3\">\n                <div class=\"flex items-center gap-2\">\n                  <lucide-icon [img]=\"Eye\" class=\"text-primary size-4\" />\n                  <h3 class=\"text-foreground font-mono text-xs font-bold\">Interactive Component Canvas</h3>\n                </div>\n                <span ui-badge variant=\"outline\" class=\"border-success/20 bg-success/10 text-success font-mono text-xs\">\n                  Live Render\n                </span>\n              </div>\n\n              <!-- Live Rendered Component Center Stage -->\n              <div\n                class=\"border-border bg-background/50 flex h-44 items-center justify-center rounded-xl border border-dashed p-6 transition-colors\"\n              >\n                <button ui-button [variant]=\"activeVariant()\" [size]=\"activeSize()\" class=\"gap-2 font-mono shadow-sm\">\n                  @if (showIcon()) {\n                    <lucide-icon [img]=\"Zap\" class=\"size-4\" />\n                  }\n                  <span>Deploy Application</span>\n                </button>\n              </div>\n            </div>\n\n            <!-- Component Controls Box -->\n            <div class=\"border-border space-y-4 border-t pt-2\">\n              <p class=\"text-muted-foreground font-mono text-xs tracking-wider uppercase\">Interactive Prop Controls</p>\n\n              <!-- Variant Selector -->\n              <div class=\"space-y-1.5\">\n                <span class=\"text-muted-foreground font-mono text-xs\">Variant:</span>\n                <div class=\"grid grid-cols-2 gap-1.5\">\n                  @for (v of variantOptions; track v) {\n                    <button type=\"button\" [class]=\"variantButtonClass(v)\" (click)=\"activeVariant.set(v)\">\n                      {{ v }}\n                    </button>\n                  }\n                </div>\n              </div>\n\n              <!-- Size Selector & Icon Toggle -->\n              <div class=\"grid grid-cols-2 gap-4\">\n                <div class=\"space-y-1.5\">\n                  <span class=\"text-muted-foreground font-mono text-xs\">Size:</span>\n                  <div class=\"flex items-center gap-1\">\n                    @for (s of sizeOptions; track s) {\n                      <button type=\"button\" [class]=\"sizeButtonClass(s)\" (click)=\"activeSize.set(s)\">\n                        {{ s === 'default' ? 'md' : s }}\n                      </button>\n                    }\n                  </div>\n                </div>\n\n                <div class=\"space-y-1.5\">\n                  <span class=\"text-muted-foreground font-mono text-xs\">Leading Icon:</span>\n                  <button\n                    ui-button\n                    size=\"sm\"\n                    variant=\"outline\"\n                    [class]=\"iconToggleClass\"\n                    (click)=\"showIcon.set(!showIcon())\"\n                  >\n                    {{ showIcon() ? 'Enabled' : 'Disabled' }}\n                  </button>\n                </div>\n              </div>\n            </div>\n          </div>\n        </div>\n      </div>\n    </section>\n  `,\n})\nexport class UiFeatureCodePreviewSplitComponent {\n  protected readonly Check = Check\n  protected readonly Code2 = Code2\n  protected readonly Copy = Copy\n  protected readonly Eye = Eye\n  protected readonly Zap = Zap\n\n  protected readonly frameworkTabs = frameworkTabs\n  protected readonly variantOptions = variantOptions\n  protected readonly sizeOptions = sizeOptions\n\n  @Input('class') className?: string\n\n  readonly activeFramework = signal<FrameworkTab>('vue')\n  readonly activeVariant = signal<PreviewButtonVariant>('default')\n  readonly activeSize = signal<PreviewButtonSize>('default')\n  readonly showIcon = signal(true)\n  readonly isCopied = signal(false)\n\n  private copyTimer: ReturnType<typeof setTimeout> | undefined\n\n  constructor() {\n    inject(DestroyRef).onDestroy(() => clearTimeout(this.copyTimer))\n  }\n\n  readonly dynamicCode = computed(() => {\n    const variant = this.activeVariant()\n    const size = this.activeSize()\n    const showIcon = this.showIcon()\n    if (this.activeFramework() === 'vue') {\n      const iconImport = showIcon ? \"\\nimport { Zap } from 'lucide-vue-next'\" : ''\n      const iconElement = showIcon ? '\\n    <Zap class=\"size-4\" />' : ''\n      return `<script setup lang=\"ts\">\\nimport { Button } from '@/components/ui/button'${iconImport}\\n</scr${'ipt'}>\\n\\n<template>\\n  <Button\\n    variant=\"${variant}\"\\n    size=\"${size}\"\\n    class=\"font-mono\"\\n  >${iconElement}\\n    <span>Deploy Application</span>\\n  </Button>\\n</template>`\n    }\n\n    if (this.activeFramework() === 'react') {\n      const iconImport = showIcon ? \"\\nimport { Zap } from 'lucide-react'\" : ''\n      const iconElement = showIcon ? '\\n      <Zap className=\"size-4\" />' : ''\n      return `'use client'\\n\\nimport { Button } from '@/components/ui/button'${iconImport}\\n\\nexport function DeployTrigger() {\\n  return (\\n    <Button\\n      variant=\"${variant}\"\\n      size=\"${size}\"\\n      className=\"font-mono\"\\n    >${iconElement}\\n      <span>Deploy Application</span>\\n    </Button>\\n  )\\n}`\n    }\n\n    return `@theme inline {\\n  --color-primary: oklch(0.205 0 0);\\n  --color-primary-foreground: oklch(0.985 0 0);\\n  --color-destructive: oklch(0.577 0.245 27.325);\\n  --radius-lg: 0.625rem;\\n  --ease-spring: cubic-bezier(0.16, 1, 0.3, 1);\\n}`\n  })\n\n  readonly syntaxLabel = computed(() =>\n    this.activeFramework() === 'vue'\n      ? 'Vue SFC + TS'\n      : this.activeFramework() === 'react'\n        ? 'TypeScript TSX'\n        : 'CSS @theme',\n  )\n\n  get rootClass(): string {\n    return cn('bg-background relative overflow-hidden px-4 py-16 sm:px-6 sm:py-24 lg:px-8', this.className)\n  }\n\n  get iconToggleClass(): string {\n    return cn('h-7 w-full font-mono text-xs', this.showIcon() ? 'border-primary text-primary' : 'text-muted-foreground')\n  }\n\n  frameworkTabClass(id: FrameworkTab): string {\n    return cn(\n      'rounded-md px-2.5 py-1 font-mono text-xs transition-colors',\n      this.activeFramework() === id\n        ? 'bg-primary text-primary-foreground font-semibold shadow-xs'\n        : 'text-muted-foreground hover:text-foreground',\n    )\n  }\n\n  variantButtonClass(v: PreviewButtonVariant): string {\n    return cn(\n      'rounded-lg border px-2.5 py-1 text-center font-mono text-xs capitalize transition-colors',\n      this.activeVariant() === v\n        ? 'border-primary bg-primary text-primary-foreground font-semibold shadow-xs'\n        : 'border-border bg-card text-muted-foreground hover:text-foreground',\n    )\n  }\n\n  sizeButtonClass(s: PreviewButtonSize): string {\n    return cn(\n      'flex-1 rounded-lg border py-1 text-center font-mono text-xs uppercase transition-colors',\n      this.activeSize() === s\n        ? 'border-primary bg-primary text-primary-foreground font-semibold shadow-xs'\n        : 'border-border bg-card text-muted-foreground',\n    )\n  }\n\n  copyCode(): void {\n    try {\n      void navigator.clipboard?.writeText(this.dynamicCode())\n    } catch {\n      // fallback\n    }\n    this.isCopied.set(true)\n    clearTimeout(this.copyTimer)\n    this.copyTimer = setTimeout(() => this.isCopied.set(false), 2000)\n  }\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/feature-code-preview-split/feature-code-preview-split.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/feature-code-preview-split/index.ts",
      "content": "export {\n  UiFeatureCodePreviewSplitComponent,\n  type FrameworkTab,\n  type PreviewButtonVariant,\n  type PreviewButtonSize,\n} from './feature-code-preview-split.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/feature-code-preview-split/index.ts"
    }
  ],
  "dependencies": [
    "lucide-angular"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/angular/badge.json",
    "https://uipkge.dev/r/angular/button.json",
    "https://uipkge.dev/r/angular/card.json"
  ],
  "description": "Split-pane developer workbench featuring live code generation across Vue 3.5, React 19, and Tailwind v4 tokens synchronized with an interactive component canvas.",
  "categories": [
    "marketing"
  ]
}