{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "hero-bento-preview-grid",
  "title": "Hero Bento Preview Grid",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/hero-bento-preview-grid/hero-bento-preview-grid.component.ts",
      "content": "// Asymmetric 3-column bento hero with an interactive OKLCH palette customizer,\n// a dual-framework parity toggle, a bundle bloat calculator, and edge latency\n// telemetry. Port of the React block 1:1.\nimport { ChangeDetectionStrategy, Component, DestroyRef, Input, computed, inject, signal } from '@angular/core'\nimport {\n  Activity,\n  ArrowRight,\n  CheckCircle2,\n  Code2,\n  Cpu,\n  Layers,\n  LucideAngularModule,\n  Moon,\n  Palette,\n  Play,\n  Sun,\n  Zap,\n} 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\ninterface ColorTheme {\n  name: string\n  hue: string\n  hex: string\n}\n\nconst colorThemes: ColorTheme[] = [\n  { name: 'Emerald', hue: 'oklch(0.65 0.22 145)', hex: '#10b981' },\n  { name: 'Indigo', hue: 'oklch(0.60 0.24 275)', hex: '#6366f1' },\n  { name: 'Amber', hue: 'oklch(0.75 0.18 70)', hex: '#f59e0b' },\n  { name: 'Rose', hue: 'oklch(0.65 0.24 15)', hex: '#f43f5e' },\n]\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-hero-bento-preview-grid, [ui-hero-bento-preview-grid]',\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=\"hero-bento-preview-grid\" [class]=\"rootClass\">\n      <!-- Center Ambient Glow -->\n      <div\n        class=\"bg-primary/10 pointer-events-none absolute top-1/4 left-1/2 -z-10 h-96 w-full max-w-5xl -translate-x-1/2 -translate-y-1/2 rounded-full blur-xl\"\n      ></div>\n\n      <div class=\"mx-auto max-w-7xl space-y-12 text-center\">\n        <!-- Headline & Subtitle -->\n        <div class=\"mx-auto max-w-3xl space-y-5\">\n          <span ui-badge variant=\"secondary\" class=\"gap-1.5 px-3 py-1 font-mono text-xs shadow-xs\">\n            <lucide-icon [img]=\"Layers\" class=\"text-primary size-3.5\" />\n            The Unbundled Design Engineering Platform\n          </span>\n\n          <h1 class=\"text-foreground text-4xl leading-[1.12] font-bold tracking-tight sm:text-5xl lg:text-6xl\">\n            Everything design engineers need to build at lightspeed.\n          </h1>\n\n          <p class=\"text-muted-foreground text-base leading-relaxed sm:text-lg\">\n            Tactile workbenches, OKLCH fluid color palettes, and guaranteed cross-framework parity—composed right in\n            your hero.\n          </p>\n\n          <!-- CTA Buttons -->\n          <div class=\"flex flex-wrap items-center justify-center gap-3 pt-2\">\n            <a ui-button size=\"lg\" href=\"#explore\" class=\"gap-2 font-semibold shadow-xs\">\n              <span>Explore 300+ Workbenches</span>\n              <lucide-icon [img]=\"ArrowRight\" class=\"size-4\" />\n            </a>\n\n            <a ui-button variant=\"outline\" size=\"lg\" href=\"#docs\" class=\"gap-2 font-medium\">\n              <lucide-icon [img]=\"Code2\" class=\"text-muted-foreground size-4\" />\n              <span>View Architecture</span>\n            </a>\n          </div>\n        </div>\n\n        <!-- 3-Column Asymmetric Bento Hero Grid -->\n        <div class=\"mx-auto grid max-w-6xl grid-cols-1 gap-4 pt-4 text-left sm:gap-6 md:grid-cols-3\">\n          <!-- Tile 1: OKLCH Theme Customizer (2 Cols) -->\n          <div\n            ui-card\n            class=\"border-border bg-card flex flex-col justify-between space-y-6 rounded-2xl p-6 shadow-sm md:col-span-2\"\n          >\n            <div class=\"space-y-2\">\n              <div class=\"flex items-center justify-between\">\n                <span class=\"text-primary inline-flex items-center gap-1.5 font-mono text-xs font-semibold\">\n                  <lucide-icon [img]=\"Palette\" class=\"size-3.5\" /> OKLCH Dynamic Theme Engine\n                </span>\n                <span ui-badge variant=\"outline\" class=\"font-mono text-xs\">Zero Runtime CSS</span>\n              </div>\n              <h3 class=\"text-foreground text-lg font-bold\">Interactive Palette &amp; Contrast Synthesizer</h3>\n              <p class=\"text-muted-foreground text-xs\">\n                Select a brand accent and watch UI components dynamically adjust perceptual contrast.\n              </p>\n            </div>\n\n            <!-- Color Buttons & Live Preview -->\n            <div class=\"border-border bg-background/60 space-y-4 rounded-xl border p-4\">\n              <div class=\"flex items-center justify-between\">\n                <div class=\"flex items-center gap-2\">\n                  @for (c of themes; track c.name; let idx = $index) {\n                    <button\n                      type=\"button\"\n                      [class]=\"colorDotClass(idx)\"\n                      [style.backgroundColor]=\"c.hex\"\n                      [attr.aria-label]=\"'Select ' + c.name + ' theme'\"\n                      (click)=\"activeColorIndex.set(idx)\"\n                    ></button>\n                  }\n                </div>\n\n                <div class=\"text-muted-foreground flex items-center gap-1 font-mono text-xs\">\n                  <span>Mode:</span>\n                  <button\n                    type=\"button\"\n                    class=\"border-border hover:bg-muted rounded border p-1 transition-[colors,transform] duration-150 active:scale-90\"\n                    [attr.aria-label]=\"isDarkPreview() ? 'Switch to light preview' : 'Switch to dark preview'\"\n                    (click)=\"isDarkPreview.set(!isDarkPreview())\"\n                  >\n                    @if (!isDarkPreview()) {\n                      <lucide-icon [img]=\"Sun\" class=\"text-warning size-3.5\" />\n                    } @else {\n                      <lucide-icon [img]=\"Moon\" class=\"text-muted-foreground size-3.5\" />\n                    }\n                  </button>\n                </div>\n              </div>\n\n              <!-- Live Button Demo with Active Hue -->\n              <div class=\"flex flex-wrap items-center gap-3 pt-2\">\n                <button\n                  type=\"button\"\n                  class=\"rounded-lg px-4 py-2 text-xs font-semibold text-white shadow-xs transition-transform active:scale-95\"\n                  [style.backgroundColor]=\"themes[activeColorIndex()].hex\"\n                >\n                  Synthesized Action Button\n                </button>\n                <button\n                  type=\"button\"\n                  class=\"border-border bg-background text-foreground hover:bg-muted rounded-lg border px-4 py-2 text-xs font-medium transition-[colors,transform] duration-150 active:scale-95\"\n                >\n                  Secondary Token\n                </button>\n              </div>\n            </div>\n          </div>\n\n          <!-- Tile 2: Dual Framework Parity (1 Col) -->\n          <div ui-card class=\"border-border bg-card flex flex-col justify-between space-y-4 rounded-2xl p-6 shadow-sm\">\n            <div class=\"space-y-2\">\n              <div class=\"flex items-center justify-between\">\n                <span class=\"text-success inline-flex items-center gap-1.5 font-mono text-xs font-semibold\">\n                  <lucide-icon [img]=\"CheckCircle2\" class=\"size-3.5\" /> 100% Mirror Parity\n                </span>\n              </div>\n              <h3 class=\"text-foreground text-lg font-bold\">Vue 3.5 &amp; React 19</h3>\n              <p class=\"text-muted-foreground text-xs\">\n                Identical CVA variant matrix and AST output across both frameworks.\n              </p>\n            </div>\n\n            <!-- Framework Toggle -->\n            <div class=\"space-y-3\">\n              <div class=\"bg-muted/40 border-border grid grid-cols-2 gap-1 rounded-lg border p-1\">\n                <button type=\"button\" [class]=\"frameworkTabClass('vue')\" (click)=\"activeFramework.set('vue')\">\n                  Vue 3.5 SFC\n                </button>\n                <button type=\"button\" [class]=\"frameworkTabClass('react')\" (click)=\"activeFramework.set('react')\">\n                  React 19 TSX\n                </button>\n              </div>\n\n              <!-- Code snippet snippet -->\n              <div class=\"bg-muted/30 border-border/80 text-muted-foreground rounded-lg border p-3 font-mono text-xs\">\n                <span class=\"text-primary font-bold\">&gt;</span>\n                <span> &lt;Button variant=\"primary\"&gt;</span>\n                <div class=\"text-success mt-0.5 font-medium\">&check; CVA Type Contract Validated</div>\n              </div>\n            </div>\n          </div>\n\n          <!-- Tile 3: Zero Bundle Bloat Calculator (1 Col) -->\n          <div ui-card class=\"border-border bg-card flex flex-col justify-between space-y-4 rounded-2xl p-6 shadow-sm\">\n            <div class=\"space-y-2\">\n              <span class=\"text-warning inline-flex items-center gap-1.5 font-mono text-xs font-semibold\">\n                <lucide-icon [img]=\"Cpu\" class=\"size-3.5\" /> Zero NPM Overhead\n              </span>\n              <h3 class=\"text-foreground text-lg font-bold\">Own Your Source Code</h3>\n              <p class=\"text-muted-foreground text-xs\">\n                Slide to calculate bundle weight saved compared to monolithic packages.\n              </p>\n            </div>\n\n            <!-- Slider Widget -->\n            <div class=\"border-border bg-background/60 space-y-3 rounded-xl border p-4\">\n              <div class=\"flex items-center justify-between font-mono text-xs\">\n                <span class=\"text-muted-foreground\">Installed Blocks:</span>\n                <span class=\"text-foreground font-bold\">{{ componentCount() }}</span>\n              </div>\n              <input\n                [value]=\"componentCount()\"\n                (input)=\"setComponentCount($event)\"\n                type=\"range\"\n                min=\"1\"\n                max=\"50\"\n                aria-label=\"Installed blocks\"\n                class=\"accent-primary w-full cursor-pointer\"\n              />\n              <div class=\"border-border/60 flex items-center justify-between border-t pt-1 font-mono text-xs\">\n                <span class=\"text-muted-foreground\">Bundle Saved:</span>\n                <span class=\"text-success font-mono font-bold\">~{{ estimatedSavings() }} kB</span>\n              </div>\n            </div>\n          </div>\n\n          <!-- Tile 4: Sub-millisecond Execution Speed (2 Cols) -->\n          <div\n            ui-card\n            class=\"border-border bg-card flex flex-col justify-between space-y-4 rounded-2xl p-6 shadow-sm md:col-span-2\"\n          >\n            <div class=\"flex items-center justify-between\">\n              <div class=\"space-y-1\">\n                <span class=\"text-primary inline-flex items-center gap-1.5 font-mono text-xs font-semibold\">\n                  <lucide-icon [img]=\"Zap\" class=\"size-3.5\" /> Instant Hydration &amp; Zero Latency\n                </span>\n                <h3 class=\"text-foreground text-lg font-bold\">Edge Optimized Architecture</h3>\n              </div>\n              <button\n                ui-button\n                size=\"sm\"\n                variant=\"outline\"\n                type=\"button\"\n                class=\"gap-1.5 font-mono text-xs active:scale-95\"\n                (click)=\"triggerQuery()\"\n              >\n                @if (!isRunningQuery()) {\n                  <lucide-icon [img]=\"Play\" class=\"size-3 fill-current\" />\n                } @else {\n                  <lucide-icon [img]=\"Activity\" class=\"size-3 animate-spin\" />\n                }\n                <span>Ping Edge</span>\n              </button>\n            </div>\n\n            <!-- Latency Telemetry Row -->\n            <div class=\"grid grid-cols-3 gap-3\">\n              <div class=\"border-border bg-background/50 space-y-0.5 rounded-lg border p-3\">\n                <p class=\"text-muted-foreground font-mono text-xs\">Round-Trip Latency</p>\n                <p class=\"text-success font-mono text-xl font-bold\">{{ queryLatency() }}</p>\n              </div>\n              <div class=\"border-border bg-background/50 space-y-0.5 rounded-lg border p-3\">\n                <p class=\"text-muted-foreground font-mono text-xs\">DOM Mutation Time</p>\n                <p class=\"text-foreground font-mono text-xl font-bold\">&lt; 1.2ms</p>\n              </div>\n              <div class=\"border-border bg-background/50 space-y-0.5 rounded-lg border p-3\">\n                <p class=\"text-muted-foreground font-mono text-xs\">Accessibility Score</p>\n                <p class=\"text-primary font-mono text-xl font-bold\">100 / 100</p>\n              </div>\n            </div>\n          </div>\n        </div>\n      </div>\n    </section>\n  `,\n})\nexport class UiHeroBentoPreviewGridComponent {\n  protected readonly Activity = Activity\n  protected readonly ArrowRight = ArrowRight\n  protected readonly CheckCircle2 = CheckCircle2\n  protected readonly Code2 = Code2\n  protected readonly Cpu = Cpu\n  protected readonly Layers = Layers\n  protected readonly Moon = Moon\n  protected readonly Palette = Palette\n  protected readonly Play = Play\n  protected readonly Sun = Sun\n  protected readonly Zap = Zap\n\n  protected readonly themes = colorThemes\n\n  @Input('class') className?: string\n\n  readonly activeColorIndex = signal(0)\n  readonly isDarkPreview = signal(true)\n  readonly activeFramework = signal<'vue' | 'react'>('vue')\n  readonly componentCount = signal(12)\n  readonly isRunningQuery = signal(false)\n  readonly queryLatency = signal('12ms')\n\n  private queryTimer: ReturnType<typeof setTimeout> | undefined\n\n  constructor() {\n    inject(DestroyRef).onDestroy(() => clearTimeout(this.queryTimer))\n  }\n\n  readonly estimatedSavings = computed(() => (this.componentCount() * 42).toFixed(0))\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  colorDotClass(idx: number): string {\n    return cn(\n      'size-6 rounded-full border-2 transition-transform active:scale-90',\n      this.activeColorIndex() === idx\n        ? 'border-foreground scale-125 shadow-xs'\n        : 'border-transparent opacity-70 hover:opacity-100',\n    )\n  }\n\n  frameworkTabClass(framework: 'vue' | 'react'): string {\n    const active = framework === 'vue' ? 'text-success' : 'text-info'\n    return cn(\n      'rounded-md py-1.5 font-mono text-xs font-semibold transition-[color,background-color,transform] duration-150 active:scale-95',\n      this.activeFramework() === framework ? `bg-background shadow-xs ${active}` : 'text-muted-foreground',\n    )\n  }\n\n  setComponentCount(event: Event): void {\n    const value = Number((event.target as HTMLInputElement).value)\n    if (!Number.isNaN(value)) this.componentCount.set(value)\n  }\n\n  triggerQuery(): void {\n    this.isRunningQuery.set(true)\n    clearTimeout(this.queryTimer)\n    this.queryTimer = setTimeout(() => {\n      this.queryLatency.set(`${Math.floor(Math.random() * 8) + 8}ms`)\n      this.isRunningQuery.set(false)\n    }, 400)\n  }\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/hero-bento-preview-grid/hero-bento-preview-grid.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/hero-bento-preview-grid/index.ts",
      "content": "export { UiHeroBentoPreviewGridComponent } from './hero-bento-preview-grid.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/hero-bento-preview-grid/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": "Asymmetric 3-column bento hero section with interactive OKLCH palette customizer, dual-framework parity toggle, bundle bloat calculator, and edge latency telemetry.",
  "categories": [
    "marketing"
  ],
  "deprecated": true,
  "replacedBy": "hero"
}