{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "before-after-wipe",
  "type": "registry:component",
  "title": "Before after wipe",
  "description": "A before and after comparison slider in React: drag the handle or use the labelled range input to wipe between two layouts across the full width.",
  "dependencies": [],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "registry/premium/before-after-wipe.tsx",
      "type": "registry:ui",
      "target": "components/ui/before-after-wipe.tsx",
      "content": "\"use client\"\nimport * as React from \"react\"\nimport { cn } from \"@/lib/utils\"\n\nfunction BeforeAfterWipe({\n  beforeLabel = \"Generic dashboard\",\n  afterLabel = \"Redesigned\",\n  className,\n}: {\n  beforeLabel?: string\n  afterLabel?: string\n  className?: string\n}) {\n  const [pct, setPct] = React.useState(50)\n  const ref = React.useRef<HTMLDivElement>(null)\n  const dragging = React.useRef(false)\n\n  const setFromClientX = (clientX: number) => {\n    const el = ref.current\n    if (!el) return\n    const r = el.getBoundingClientRect()\n    const next = ((clientX - r.left) / r.width) * 100\n    // Full travel — edge to edge, no fake inset dead zone\n    setPct(Math.min(100, Math.max(0, next)))\n  }\n\n  return (\n    <div\n      ref={ref}\n      data-slot=\"before-after-wipe\"\n      data-tier=\"premium\"\n      className={cn(\n        \"relative aspect-[16/10] overflow-hidden rounded-2xl border border-border bg-sunken select-none\",\n        className\n      )}\n      onPointerDown={(e) => {\n        dragging.current = true\n        ;(e.target as HTMLElement).setPointerCapture?.(e.pointerId)\n        setFromClientX(e.clientX)\n      }}\n      onPointerMove={(e) => {\n        if (!dragging.current) return\n        setFromClientX(e.clientX)\n      }}\n      onPointerUp={() => {\n        dragging.current = false\n      }}\n      onPointerCancel={() => {\n        dragging.current = false\n      }}\n    >\n      <div className=\"absolute inset-0 p-6\">\n        <p className=\"text-xs font-medium uppercase text-fg-muted\">{beforeLabel}</p>\n        <div className=\"mt-4 grid grid-cols-3 gap-2 opacity-60\">\n          {Array.from({ length: 6 }).map((_, i) => (\n            <div key={i} className=\"h-16 rounded-lg border border-border bg-surface\" />\n          ))}\n        </div>\n      </div>\n      <div\n        className=\"absolute inset-0 overflow-hidden\"\n        style={{ clipPath: `inset(0 0 0 ${pct}%)` }}\n      >\n        <div className=\"absolute inset-0 bg-bg p-6\">\n          <p className=\"text-xs font-medium uppercase text-fg-muted\">{afterLabel}</p>\n          <div className=\"mt-4 grid grid-cols-3 gap-2\">\n            {Array.from({ length: 6 }).map((_, i) => (\n              <div\n                key={i}\n                className={cn(\n                  \"h-16 rounded-lg border border-border bg-surface shadow-highlight\",\n                  i === 1 && \"border-accent/40 bg-accent/10\"\n                )}\n              />\n            ))}\n          </div>\n        </div>\n      </div>\n      <div\n        className=\"absolute inset-y-0 z-10 w-px bg-accent\"\n        style={{ left: `${pct}%` }}\n        aria-hidden\n      >\n        <div className=\"absolute top-1/2 left-1/2 flex size-8 -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-full border border-border bg-surface text-xs text-fg\">\n          ↔\n        </div>\n      </div>\n      <input\n        type=\"range\"\n        min={0}\n        max={100}\n        step={0.1}\n        value={pct}\n        aria-label={`Compare: ${beforeLabel} versus ${afterLabel}. Position ${Math.round(pct)} percent.`}\n        className=\"absolute inset-0 z-20 cursor-ew-resize opacity-0\"\n        onChange={(e) => setPct(Number(e.target.value))}\n      />\n    </div>\n  )\n}\nexport { BeforeAfterWipe }\n"
    }
  ]
}
