{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "before-after-slider",
  "title": "Before / After",
  "description": "Compare wireframe vs shipped UI mockups.",
  "registryDependencies": [
    "@atroui/utils",
    "@atroui/mockup-frame"
  ],
  "files": [
    {
      "path": "registry/default/blocks/before-after-slider.tsx",
      "content": "\"use client\";\n\nimport { useCallback, useRef, useState } from \"react\";\n\nimport { UiMockupFrame, type MockupVariant } from \"../ui/mockup-frame\";\nimport { cn } from \"@/lib/utils\";\n\ntype BeforeAfterSliderProps = {\n  variant?: MockupVariant;\n  beforeLabel?: string;\n  afterLabel?: string;\n  className?: string;\n};\n\nexport function BeforeAfterSlider({\n  variant = \"saas\",\n  beforeLabel = \"Before\",\n  afterLabel = \"After\",\n  className,\n}: BeforeAfterSliderProps) {\n  const [position, setPosition] = useState(50);\n  const containerRef = useRef<HTMLDivElement>(null);\n  const dragging = useRef(false);\n\n  const updatePosition = useCallback((clientX: number) => {\n    const el = containerRef.current;\n    if (!el) return;\n    const rect = el.getBoundingClientRect();\n    const pct = Math.min(100, Math.max(0, ((clientX - rect.left) / rect.width) * 100));\n    setPosition(pct);\n  }, []);\n\n  const onPointerDown = (e: React.PointerEvent) => {\n    dragging.current = true;\n    (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);\n    updatePosition(e.clientX);\n  };\n\n  const onPointerMove = (e: React.PointerEvent) => {\n    if (!dragging.current) return;\n    updatePosition(e.clientX);\n  };\n\n  const onPointerUp = () => {\n    dragging.current = false;\n  };\n\n  const onKeyDown = (e: React.KeyboardEvent) => {\n    if (e.key === \"ArrowLeft\") setPosition((p) => Math.max(0, p - 5));\n    if (e.key === \"ArrowRight\") setPosition((p) => Math.min(100, p + 5));\n  };\n\n  return (\n    <div\n      ref={containerRef}\n      className={cn(\n        \"relative aspect-[16/9] overflow-hidden rounded-2xl border border-border-subtle bg-muted p-3 sm:p-4 select-none touch-none\",\n        className\n      )}\n      onPointerMove={onPointerMove}\n      onPointerUp={onPointerUp}\n      onPointerLeave={onPointerUp}\n    >\n      <div className=\"absolute inset-3 sm:inset-4\" aria-hidden>\n        <UiMockupFrame variant={variant} state=\"shipped\" label={`${afterLabel} UI state`} className=\"h-full\" />\n      </div>\n\n      <div\n        className=\"absolute inset-3 sm:inset-4 overflow-hidden rounded-lg\"\n        style={{ clipPath: `inset(0 ${100 - position}% 0 0)` }}\n        aria-hidden\n      >\n        <UiMockupFrame variant={variant} state=\"wireframe\" label={`${beforeLabel} UI state`} className=\"h-full\" />\n      </div>\n\n      <div\n        className=\"absolute top-3 bottom-3 z-10 w-1 cursor-ew-resize bg-white shadow-lg sm:top-4 sm:bottom-4\"\n        style={{ left: `calc(${position}% * 0.92 + 4%)`, transform: \"translateX(-50%)\" }}\n        onPointerDown={onPointerDown}\n        onKeyDown={onKeyDown}\n        role=\"slider\"\n        tabIndex={0}\n        aria-valuenow={Math.round(position)}\n        aria-valuemin={0}\n        aria-valuemax={100}\n        aria-label={`Compare ${beforeLabel} and ${afterLabel}. Use arrow keys or drag.`}\n      >\n        <div className=\"absolute top-1/2 left-1/2 flex size-9 items-center justify-center border-2 border-white bg-brand shadow-md\">\n          <span className=\"text-[10px] font-bold text-white\" aria-hidden>\n            ||\n          </span>\n        </div>\n      </div>\n\n      <div className=\"pointer-events-none absolute bottom-6 left-6 border border-border-subtle bg-background/90 px-2.5 py-1 text-[10px] font-medium backdrop-blur-sm\">\n        {beforeLabel}\n      </div>\n      <div className=\"pointer-events-none absolute right-6 bottom-6 border border-border-subtle bg-background/90 px-2.5 py-1 text-[10px] font-medium backdrop-blur-sm\">\n        {afterLabel}\n      </div>\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/blocks/before-after-slider.tsx"
    }
  ],
  "type": "registry:block"
}