{
  "name": "images-slider",
  "type": "registry:ui",
  "dependencies": [
    "motion"
  ],
  "files": [
    {
      "path": "components/ui/images-slider.tsx",
      "content": "\"use client\";\nimport { cn } from \"@/lib/utils\";\nimport { motion, AnimatePresence } from \"motion/react\";\nimport React, { useEffect, useState } from \"react\";\n\nexport const ImagesSlider = ({\n  images,\n  children,\n  overlay = true,\n  overlayClassName,\n  className,\n  autoplay = true,\n  direction = \"up\",\n}: {\n  images: string[];\n  children: React.ReactNode;\n  overlay?: React.ReactNode;\n  overlayClassName?: string;\n  className?: string;\n  autoplay?: boolean;\n  direction?: \"up\" | \"down\";\n}) => {\n  const [currentIndex, setCurrentIndex] = useState(0);\n  const [loading, setLoading] = useState(false);\n  const [loadedImages, setLoadedImages] = useState<string[]>([]);\n\n  const handleNext = () => {\n    setCurrentIndex((prevIndex) =>\n      prevIndex + 1 === images.length ? 0 : prevIndex + 1\n    );\n  };\n\n  const handlePrevious = () => {\n    setCurrentIndex((prevIndex) =>\n      prevIndex - 1 < 0 ? images.length - 1 : prevIndex - 1\n    );\n  };\n\n  useEffect(() => {\n    loadImages();\n  }, []);\n\n  const loadImages = () => {\n    setLoading(true);\n    const loadPromises = images.map((image) => {\n      return new Promise((resolve, reject) => {\n        const img = new Image();\n        img.src = image;\n        img.onload = () => resolve(image);\n        img.onerror = reject;\n      });\n    });\n\n    Promise.all(loadPromises)\n      .then((loadedImages) => {\n        setLoadedImages(loadedImages as string[]);\n        setLoading(false);\n      })\n      .catch((error) => console.error(\"Failed to load images\", error));\n  };\n  useEffect(() => {\n    const handleKeyDown = (event: KeyboardEvent) => {\n      if (event.key === \"ArrowRight\") {\n        handleNext();\n      } else if (event.key === \"ArrowLeft\") {\n        handlePrevious();\n      }\n    };\n\n    window.addEventListener(\"keydown\", handleKeyDown);\n\n    // autoplay\n    let interval: any;\n    if (autoplay) {\n      interval = setInterval(() => {\n        handleNext();\n      }, 5000);\n    }\n\n    return () => {\n      window.removeEventListener(\"keydown\", handleKeyDown);\n      clearInterval(interval);\n    };\n  }, []);\n\n  const slideVariants = {\n    initial: {\n      scale: 0,\n      opacity: 0,\n      rotateX: 45,\n    },\n    visible: {\n      scale: 1,\n      rotateX: 0,\n      opacity: 1,\n      transition: {\n        duration: 0.5,\n        ease: [0.645, 0.045, 0.355, 1.0] as const,\n      },\n    },\n    upExit: {\n      opacity: 1,\n      y: \"-150%\",\n      transition: {\n        duration: 1,\n      },\n    },\n    downExit: {\n      opacity: 1,\n      y: \"150%\",\n      transition: {\n        duration: 1,\n      },\n    },\n  };\n\n  const areImagesLoaded = loadedImages.length > 0;\n\n  return (\n    <div\n      className={cn(\n        \"overflow-hidden h-full w-full relative flex items-center justify-center\",\n        className\n      )}\n      style={{\n        perspective: \"1000px\",\n      }}\n    >\n      {areImagesLoaded && children}\n      {areImagesLoaded && overlay && (\n        <div\n          className={cn(\"absolute inset-0 bg-black/60 z-40\", overlayClassName)}\n        />\n      )}\n\n      {areImagesLoaded && (\n        <AnimatePresence>\n          <motion.img\n            key={currentIndex}\n            src={loadedImages[currentIndex]}\n            initial=\"initial\"\n            animate=\"visible\"\n            exit={direction === \"up\" ? \"upExit\" : \"downExit\"}\n            variants={slideVariants}\n            className=\"image h-full w-full absolute inset-0 object-cover object-center\"\n          />\n        </AnimatePresence>\n      )}\n    </div>\n  );\n};\n",
      "type": "registry:ui",
      "target": "components/ui/images-slider.tsx"
    }
  ],
  "author": "Manu Arora <hi@manuarora.in>",
  "title": "Images Slider"
}