{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "feature-hover-tilt-cards",
  "title": "Feature Hover Tilt Cards",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/feature-hover-tilt-cards/feature-hover-tilt-cards.component.ts",
      "content": "// Tactile 3D perspective tilt workbench: each card tracks the pointer for a hardware-accelerated\n// rotateX/rotateY depth effect, plus live interactives (token efficiency slider, spring impulse\n// trigger, dual-framework mirror switcher). Port of the React block 1:1.\nimport { ChangeDetectionStrategy, Component, Input, signal } from '@angular/core'\nimport { Cpu, Eye, Layers, LayoutGrid, 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 interface CardRotation {\n  rx: number\n  ry: number\n}\n\nconst NEUTRAL_ROTATIONS: Record<number, CardRotation> = {\n  0: { rx: 0, ry: 0 },\n  1: { rx: 0, ry: 0 },\n  2: { rx: 0, ry: 0 },\n}\n\n// Kept out of the template: a literal `<script` inside an interpolation trips\n// prettier's HTML parser (it looks like a real tag open).\nconst MIRROR_BADGES = {\n  vue: '<script setup lang=\"ts\"> + Reka UI',\n  react: \"'use client' + Radix UI\",\n} as const\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-feature-hover-tilt-cards, [ui-feature-hover-tilt-cards]',\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-hover-tilt-cards\" [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]=\"Eye\" class=\"text-primary size-3.5\" />\n            Tactile Physics &amp; Surface Depth\n          </span>\n          <h2 class=\"text-foreground text-3xl font-bold tracking-tight sm:text-4xl\">\n            Engineered for tactile feedback &amp; micro-interactions.\n          </h2>\n          <p class=\"text-muted-foreground text-base\">\n            Hover over each workbench card to experience hardware-accelerated 3D depth and live interactive physics.\n          </p>\n        </div>\n\n        <!-- 3D Perspective Tilt Cards Grid -->\n        <div class=\"grid grid-cols-1 gap-6 [perspective:1200px] lg:grid-cols-3\">\n          <!-- Card 1: Unbundled Token Inspector -->\n          <div\n            class=\"transition-transform duration-200 ease-out will-change-transform\"\n            [style.transform]=\"tiltTransform(0)\"\n            (mousemove)=\"handleMouseMove($event, 0)\"\n            (mouseleave)=\"handleMouseLeave(0)\"\n          >\n            <div\n              ui-card\n              class=\"border-border bg-card/95 hover:border-primary/50 relative flex h-full flex-col justify-between space-y-6 overflow-hidden rounded-2xl p-6 text-left shadow-xl transition-[color,background-color,border-color,box-shadow] hover:shadow-sm\"\n            >\n              <div class=\"space-y-3\">\n                <div class=\"flex items-center justify-between\">\n                  <div class=\"bg-primary/10 text-primary flex size-9 items-center justify-center rounded-xl font-mono\">\n                    <lucide-icon [img]=\"Layers\" class=\"size-4\" />\n                  </div>\n                  <span ui-badge variant=\"outline\" class=\"font-mono text-xs\">Zero Bloat</span>\n                </div>\n\n                <h3 class=\"text-foreground font-mono text-lg font-bold\">Unbundled Code Ownership</h3>\n                <p class=\"text-muted-foreground text-xs leading-relaxed\">\n                  AST-level code generation puts pristine component source directly in your repository.\n                </p>\n\n                <!-- Interactive Token Scale Slider -->\n                <div class=\"border-border bg-muted/30 mt-4 space-y-2 rounded-xl border p-3.5\">\n                  <div class=\"flex items-center justify-between font-mono text-xs\">\n                    <span class=\"text-muted-foreground\">Tree-Shake Efficiency:</span>\n                    <span class=\"text-success font-bold\">{{ tokenScale() }}%</span>\n                  </div>\n                  <input\n                    type=\"range\"\n                    min=\"50\"\n                    max=\"100\"\n                    [value]=\"tokenScale()\"\n                    (input)=\"onTokenScaleInput($event)\"\n                    aria-label=\"Tree-shake efficiency\"\n                    class=\"accent-primary bg-border h-1.5 w-full cursor-pointer rounded-lg\"\n                  />\n                  <p class=\"text-muted-foreground font-mono text-xs\">\n                    Unused variants automatically pruned at compile time.\n                  </p>\n                </div>\n              </div>\n\n              <div\n                class=\"border-border/60 text-muted-foreground flex items-center justify-between border-t pt-4 font-mono text-xs\"\n              >\n                <span>0 dependencies added</span>\n                <span class=\"text-primary font-semibold\">&check; Pure Source</span>\n              </div>\n            </div>\n          </div>\n\n          <!-- Card 2: Spring Velocity Simulator -->\n          <div\n            class=\"transition-transform duration-200 ease-out will-change-transform\"\n            [style.transform]=\"tiltTransform(1)\"\n            (mousemove)=\"handleMouseMove($event, 1)\"\n            (mouseleave)=\"handleMouseLeave(1)\"\n          >\n            <div\n              ui-card\n              class=\"border-border bg-card/95 hover:border-primary/50 relative flex h-full flex-col justify-between space-y-6 overflow-hidden rounded-2xl p-6 text-left shadow-xl transition-[color,background-color,border-color,box-shadow] hover:shadow-sm\"\n            >\n              <div class=\"space-y-3\">\n                <div class=\"flex items-center justify-between\">\n                  <div class=\"bg-warning/10 text-warning flex size-9 items-center justify-center rounded-xl font-mono\">\n                    <lucide-icon [img]=\"Zap\" class=\"size-4\" />\n                  </div>\n                  <span\n                    ui-badge\n                    variant=\"outline\"\n                    class=\"border-warning/20 bg-warning/10 text-warning font-mono text-xs\"\n                  >\n                    Fluid Motion\n                  </span>\n                </div>\n\n                <h3 class=\"text-foreground font-mono text-lg font-bold\">Spring Physics Engine</h3>\n                <p class=\"text-muted-foreground text-xs leading-relaxed\">\n                  Calibrated cubic-bezier curves for tactile, zero-overshoot micro-interactions.\n                </p>\n\n                <!-- Interactive Spring Trigger Box -->\n                <div class=\"border-border bg-muted/30 mt-4 space-y-3 rounded-xl border p-3.5 text-center\">\n                  <div\n                    [class]=\"springCubeClass\"\n                    class=\"bg-primary text-primary-foreground mx-auto flex size-12 items-center justify-center rounded-2xl font-mono text-sm font-bold shadow-md transition-colors duration-300\"\n                  >\n                    <lucide-icon [img]=\"Cpu\" class=\"size-5\" />\n                  </div>\n\n                  <button\n                    ui-button\n                    size=\"sm\"\n                    variant=\"outline\"\n                    class=\"h-8 w-full font-mono text-xs\"\n                    (click)=\"triggerSpringTest()\"\n                  >\n                    Trigger Spring Impulse\n                  </button>\n                </div>\n              </div>\n\n              <div\n                class=\"border-border/60 text-muted-foreground flex items-center justify-between border-t pt-4 font-mono text-xs\"\n              >\n                <span>Duration: 180ms</span>\n                <span class=\"text-success font-semibold\">&check; 60fps Native</span>\n              </div>\n            </div>\n          </div>\n\n          <!-- Card 3: Dual-Framework Mirror Comparator -->\n          <div\n            class=\"transition-transform duration-200 ease-out will-change-transform\"\n            [style.transform]=\"tiltTransform(2)\"\n            (mousemove)=\"handleMouseMove($event, 2)\"\n            (mouseleave)=\"handleMouseLeave(2)\"\n          >\n            <div\n              ui-card\n              class=\"border-border bg-card/95 hover:border-primary/50 relative flex h-full flex-col justify-between space-y-6 overflow-hidden rounded-2xl p-6 text-left shadow-xl transition-[color,background-color,border-color,box-shadow] hover:shadow-sm\"\n            >\n              <div class=\"space-y-3\">\n                <div class=\"flex items-center justify-between\">\n                  <div class=\"bg-info/10 text-info flex size-9 items-center justify-center rounded-xl font-mono\">\n                    <lucide-icon [img]=\"LayoutGrid\" class=\"size-4\" />\n                  </div>\n                  <span ui-badge variant=\"outline\" class=\"border-info/20 bg-info/10 text-info font-mono text-xs\">\n                    1:1 Parity\n                  </span>\n                </div>\n\n                <h3 class=\"text-foreground font-mono text-lg font-bold\">Dual-Framework Compiler</h3>\n                <p class=\"text-muted-foreground text-xs leading-relaxed\">\n                  Identical DOM attributes, variants, and keyboard ergonomics across Vue 3.5 &amp; React 19.\n                </p>\n\n                <!-- Interactive Framework Switcher -->\n                <div class=\"border-border bg-muted/30 mt-4 space-y-2 rounded-xl border p-3 font-mono text-xs\">\n                  <div class=\"bg-background border-border flex items-center gap-1 rounded-lg border p-1\">\n                    <button\n                      type=\"button\"\n                      [class]=\"mirrorTabClass('vue')\"\n                      class=\"flex-1 rounded py-1 text-center transition-colors\"\n                      (click)=\"setActiveMirror('vue')\"\n                    >\n                      Vue 3.5 SFC\n                    </button>\n                    <button\n                      type=\"button\"\n                      [class]=\"mirrorTabClass('react')\"\n                      class=\"flex-1 rounded py-1 text-center transition-colors\"\n                      (click)=\"setActiveMirror('react')\"\n                    >\n                      React 19 JSX\n                    </button>\n                  </div>\n                  <p class=\"text-muted-foreground pt-1 text-xs\">{{ mirrorBadge }}</p>\n                </div>\n              </div>\n\n              <div\n                class=\"border-border/60 text-muted-foreground flex items-center justify-between border-t pt-4 font-mono text-xs\"\n              >\n                <span>AST Verified</span>\n                <span class=\"text-primary font-semibold\">&check; 100% Match</span>\n              </div>\n            </div>\n          </div>\n        </div>\n      </div>\n    </section>\n  `,\n})\nexport class UiFeatureHoverTiltCardsComponent {\n  protected readonly Cpu = Cpu\n  protected readonly Eye = Eye\n  protected readonly Layers = Layers\n  protected readonly LayoutGrid = LayoutGrid\n  protected readonly Zap = Zap\n\n  @Input('class') className?: string\n\n  readonly rotations = signal<Record<number, CardRotation>>({ ...NEUTRAL_ROTATIONS })\n  readonly tokenScale = signal(100)\n  readonly isPulsing = signal(false)\n  readonly activeMirror = signal<'vue' | 'react'>('vue')\n  private pulseTimer: ReturnType<typeof setTimeout> | undefined\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 mirrorBadge(): string {\n    return MIRROR_BADGES[this.activeMirror()]\n  }\n\n  get springCubeClass(): string {\n    return cn(this.isPulsing() ? 'bg-success ring-success/30 scale-125 rotate-12 ring-4' : 'scale-100')\n  }\n\n  tiltTransform(index: number): string {\n    const r = this.rotations()[index] ?? { rx: 0, ry: 0 }\n    return `perspective(1000px) rotateX(${r.rx}deg) rotateY(${r.ry}deg)`\n  }\n\n  mirrorTabClass(mirror: 'vue' | 'react'): string {\n    return cn(\n      this.activeMirror() === mirror\n        ? 'bg-primary text-primary-foreground font-semibold shadow-xs'\n        : 'text-muted-foreground',\n    )\n  }\n\n  handleMouseMove(event: MouseEvent, index: number): void {\n    const card = event.currentTarget as HTMLElement | null\n    const rect = card?.getBoundingClientRect()\n    if (!rect || rect.width === 0 || rect.height === 0) return\n    const x = event.clientX - rect.left\n    const y = event.clientY - rect.top\n    const centerX = rect.width / 2\n    const centerY = rect.height / 2\n    const rotateX = ((y - centerY) / centerY) * -7\n    const rotateY = ((x - centerX) / centerX) * 7\n    this.rotations.update((prev) => ({ ...prev, [index]: { rx: rotateX, ry: rotateY } }))\n  }\n\n  handleMouseLeave(index: number): void {\n    this.rotations.update((prev) => ({ ...prev, [index]: { rx: 0, ry: 0 } }))\n  }\n\n  onTokenScaleInput(event: Event): void {\n    this.tokenScale.set(Number((event.target as HTMLInputElement).value))\n  }\n\n  triggerSpringTest(): void {\n    this.isPulsing.set(true)\n    clearTimeout(this.pulseTimer)\n    this.pulseTimer = setTimeout(() => this.isPulsing.set(false), 600)\n  }\n\n  setActiveMirror(mirror: 'vue' | 'react'): void {\n    this.activeMirror.set(mirror)\n  }\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/feature-hover-tilt-cards/feature-hover-tilt-cards.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/feature-hover-tilt-cards/index.ts",
      "content": "export { UiFeatureHoverTiltCardsComponent, type CardRotation } from './feature-hover-tilt-cards.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/feature-hover-tilt-cards/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": "3D perspective tilt workbench cards with dynamic mouse tracking, interactive token efficiency sliders, spring impulse testing, and dual-framework parity inspect.",
  "categories": [
    "marketing"
  ]
}