{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "carousel-slider",
  "type": "registry:component",
  "title": "Carousel Slider",
  "description": "A playful, gesture-driven card carousel with spring-based rotation and smooth scaling.",
  "dependencies": [
    "@hugeicons/core-free-icons",
    "@hugeicons/react",
    "motion"
  ],
  "files": [
    {
      "path": "components/watermelon/carousel-slider.tsx",
      "type": "registry:component",
      "content": "\"use client\";\n\nimport React, { useState } from \"react\";\nimport {\n  motion,\n  AnimatePresence,\n  useMotionValue,\n  useTransform,\n  type PanInfo,\n  type Variants,\n} from \"motion/react\";\nimport { HugeiconsIcon } from \"@hugeicons/react\";\nimport { FavouriteIcon } from \"@hugeicons/core-free-icons\";\n\n/* ---------------- Types ---------------- */\n\nexport interface Slide {\n  id: number;\n  img: string;\n}\n\ntype IconRenderer = (props?: any) => React.ReactNode;\n\ninterface CarouselSliderProps {\n  slides?: Slide[];\n  favouriteIcon?: IconRenderer;\n}\n\n/* ---------------- Defaults ---------------- */\n\nconst DEFAULT_SLIDES: Slide[] = [\n  { id: 1, img: \"https://prourls.link/ORXBVr\" },\n  {\n    id: 2,\n    img: \"https://images.unsplash.com/photo-1518780664697-55e3ad937233?q=80&w=500&auto=format&fit=crop\",\n  },\n  {\n    id: 3,\n    img: \"https://images.unsplash.com/photo-1470770841072-f978cf4d019e?q=80&w=500&auto=format&fit=crop\",\n  },\n  {\n    id: 4,\n    img: \"https://images.unsplash.com/photo-1500382017468-9049fed747ef?q=80&w=500&auto=format&fit=crop\",\n  },\n  {\n    id: 5,\n    img: \"https://images.unsplash.com/photo-1464822759023-fed622ff2c3b?q=80&w=500&auto=format&fit=crop\",\n  },\n  {\n    id: 6,\n    img: \"https://images.unsplash.com/photo-1501785888041-af3ef285b470?q=80&w=500&auto=format&fit=crop\",\n  },\n];\n\n/* ---------------- Animation Variants ---------------- */\n\nconst variants: Variants = {\n  enter: (direction: number) => ({\n    x: direction > 0 ? 200 : -200,\n    filter: 'brightness(2)',\n    scale: 0.75,\n    opacity: 0,\n    rotate: direction > 0 ? 30 : -30,\n  }),\n  center: {\n    x: 0,\n    filter: 'brightness(1)',\n    scale: 1,\n    opacity: 1,\n    rotate: -3,\n    zIndex: 1,\n  },\n  exit: (direction: number) => ({\n    x: direction > 0 ? -200 : 200,\n    filter: 'brightness(2)',\n    scale: 0.75,\n    opacity: 0,\n    rotate: direction > 0 ? -30 : 30,\n    zIndex: 0,\n  }),\n};\n\n/* ---------------- Component ---------------- */\n\nexport const CarouselSlider: React.FC<CarouselSliderProps> = ({\n  slides = DEFAULT_SLIDES,\n  favouriteIcon = (props) => (\n    <HugeiconsIcon\n      icon={FavouriteIcon}\n      size={26}\n      strokeWidth={1.5}\n      {...props}\n    />\n  ),\n}) => {\n  const [index, setIndex] = useState(0);\n  const [direction, setDirection] = useState(1);\n\n  const dragX = useMotionValue(0);\n  const rotate = useTransform(dragX, [-200, 200], [-18, 18]);\n\n  const paginate = (newDirection: number) => {\n    setDirection(newDirection);\n    setIndex((prev) => (prev + newDirection + slides.length) % slides.length);\n  };\n\n  const handleDragEnd = (_: any, info: PanInfo) => {\n    if (info.offset.x < -120) paginate(1);\n    else if (info.offset.x > 120) paginate(-1);\n  };\n\n  return (\n    <div className=\"flex flex-col items-center justify-center\">\n      {/* Slider */}\n      <div className=\"relative w-40 sm:w-3xs aspect-square flex items-center justify-center -rotate-[6deg]\">\n        <AnimatePresence custom={direction} mode=\"wait\">\n          <motion.div\n            key={index}\n            custom={direction}\n            variants={variants}\n            initial=\"enter\"\n            animate=\"center\"\n            exit=\"exit\"\n            transition={{\n              x: { type: \"spring\", bounce: 0.2, duration: 0.5 },\n              scale: { duration: 0.35 },\n              opacity: { duration: 0.25 },\n            }}\n            drag=\"x\"\n            dragConstraints={{ left: 0, right: 0 }}\n            style={{ rotate, x: dragX }}\n            onDragEnd={handleDragEnd}\n            className=\"absolute w-full h-full bg-[#FDFDFD] dark:bg-zinc-900 rounded-[40px] p-2 shadow-md border-[1.2px] border-[#E6E6EA] dark:border-zinc-800 overflow-hidden\"\n          >\n            <div className=\"w-full h-full rounded-[32px] overflow-hidden bg-zinc-100 relative\">\n              <img\n                src={slides[index].img}\n                alt=\"\"\n                className=\"object-cover w-full h-full pointer-events-none\"\n              />\n\n              {/* Favourite Button */}\n              <button\n                type=\"button\"\n                title=\"Favourite\"\n                className=\"absolute top-4 right-4 w-10 h-10 bg-[#EDEDED] dark:bg-zinc-900/90 backdrop-blur-md rounded-full flex items-center justify-center shadow-md border border-white/20\"\n              >\n                {favouriteIcon({\n                  className: \"text-[#2b2b2b] dark:text-white/90\",\n                })}\n              </button>\n            </div>\n          </motion.div>\n        </AnimatePresence>\n\n        {/* Background Card */}\n        <div className=\"absolute -z-10 w-[95%] h-[95%] bg-white dark:bg-zinc-900 rounded-[40px] border-[6px] border-white dark:border-zinc-800 scale-95 opacity-50\" />\n      </div>\n\n      {/* Pagination */}\n      <div className=\"flex gap-2.5 mt-8 pl-8 -rotate-[6deg]\">\n        {slides.map((_, i) => (\n          <motion.div\n            key={i}\n            animate={{\n              scale: i === index ? 1.2 : 1,\n              opacity: i === index ? 1 : 0.4,\n            }}\n            transition={{\n              type: \"spring\",\n              stiffness: 300,\n              damping: 20,\n            }}\n            className=\"w-2.5 h-2.5 rounded-full bg-[#CCC7B8] cursor-pointer\"\n            onClick={() => {\n              setDirection(i > index ? 1 : -1);\n              setIndex(i);\n            }}\n          />\n        ))}\n      </div>\n    </div>\n  );\n};\n"
    }
  ]
}
