{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "ds-compare-slider",
  "title": "CompareSlider",
  "description": "Slider de comparação antes/depois com clip-path, arrastável ou via teclado (range input nativo).",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "components/ds/ds-compare-slider.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { ChevronsLeftRightIcon } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\n// ── Types ──\n\nexport interface CompareSliderProps extends Omit<\n  React.HTMLAttributes<HTMLDivElement>,\n  \"onChange\" | \"defaultValue\"\n> {\n  beforeSrc: string\n  beforeAlt: string\n  afterSrc: string\n  afterAlt: string\n  /** Initial handle position, 0-100. */\n  defaultValue?: number\n  /** Accessible label for the drag handle. */\n  label?: string\n}\n\n// ── Component ──\n\n/**\n * A before/after image comparison slider — drag the handle (or use the\n * native range input with arrow keys) to reveal more of either image. Uses\n * `clip-path` so neither image is stretched or squashed while dragging.\n */\nexport function CompareSlider({\n  beforeSrc,\n  beforeAlt,\n  afterSrc,\n  afterAlt,\n  defaultValue = 50,\n  label = \"Comparison slider\",\n  className,\n  ...props\n}: CompareSliderProps) {\n  const [value, setValue] = React.useState(defaultValue)\n\n  return (\n    <div\n      className={cn(\n        \"relative aspect-video w-full touch-none overflow-hidden rounded-2xl select-none\",\n        className\n      )}\n      data-slot=\"compare-slider\"\n      {...props}\n    >\n      {/* eslint-disable-next-line @next/next/no-img-element */}\n      <img\n        src={afterSrc}\n        alt={afterAlt}\n        loading=\"lazy\"\n        decoding=\"async\"\n        className=\"absolute inset-0 size-full object-cover\"\n      />\n\n      <div\n        className=\"absolute inset-0\"\n        style={{ clipPath: `inset(0 ${100 - value}% 0 0)` }}\n      >\n        {/* eslint-disable-next-line @next/next/no-img-element */}\n        <img\n          src={beforeSrc}\n          alt={beforeAlt}\n          loading=\"lazy\"\n          decoding=\"async\"\n          className=\"absolute inset-0 size-full object-cover\"\n        />\n      </div>\n\n      <div\n        className=\"pointer-events-none absolute inset-y-0 w-0.5 bg-card shadow-[0_0_0_1px_rgba(0,0,0,0.2)]\"\n        style={{ left: `${value}%` }}\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-card text-foreground shadow-lg\">\n          <ChevronsLeftRightIcon className=\"size-4\" aria-hidden=\"true\" />\n        </div>\n      </div>\n\n      <input\n        type=\"range\"\n        min={0}\n        max={100}\n        value={value}\n        onChange={(event) => setValue(Number(event.target.value))}\n        aria-label={label}\n        aria-valuenow={value}\n        aria-valuemin={0}\n        aria-valuemax={100}\n        className=\"peer absolute inset-0 h-full w-full cursor-ew-resize opacity-0 focus-visible:outline-none\"\n      />\n    </div>\n  )\n}\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}
