{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "imagemodals",
  "dependencies": [
    "motion",
    "lucide-react"
  ],
  "devDependencies": [],
  "registryDependencies": [],
  "files": [
    {
      "path": "./registry/components/modal/image-modals.tsx",
      "content": "'use client';\nimport { transition } from '@/lib/utils';\nimport { XIcon } from 'lucide-react';\nimport { AnimatePresence, MotionConfig, motion } from 'motion/react';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\n\nexport default function Dialog() {\n  const [index, setIndex] = useState(5);\n  const [isOpen, setIsOpen] = useState(false);\n  useEffect(() => {\n    if (isOpen) {\n      document.body.classList.add('overflow-hidden');\n    } else {\n      document.body.classList.remove('overflow-hidden');\n    }\n\n    const handleKeyDown = (event: KeyboardEvent) => {\n      if (event.key === 'Escape') {\n        setIsOpen(false);\n      }\n    };\n\n    document.addEventListener('keydown', handleKeyDown);\n    return () => {\n      document.removeEventListener('keydown', handleKeyDown);\n    };\n  }, [isOpen]);\n  type Item = {\n    id: number;\n    imgSrc?: string;\n    videoSrc?: string;\n  };\n\n  const items: Item[] = [\n    {\n      id: 1,\n      imgSrc:\n        'https://images.unsplash.com/photo-1726824766931-4bd8b59af37c?q=80&w=1000&auto=format&fit=crop',\n    },\n    {\n      id: 2,\n      videoSrc: 'https://videos.pexels.com/video-files/7710243/7710243-uhd_2560_1440_30fps.mp4',\n    },\n  ];\n  const currentItem = items[index];\n  const [carouselWidth, setCarouselWidth] = useState(0);\n  const carousel = useRef(null);\n  useEffect(() => {\n    setCarouselWidth(\n      // @ts-expect-error\n      carousel.current.scrollWidth - carousel.current.offsetWidth\n    );\n  }, [carousel]);\n  return (\n    <div className='relative h-full'>\n      <MotionConfig transition={transition}>\n        <motion.div\n          ref={carousel}\n          drag='x'\n          dragElastic={0.2}\n          dragConstraints={{ right: 0, left: -carouselWidth }}\n          dragTransition={{ bounceDamping: 30 }}\n          transition={{ duration: 8, ease: 'easeInOut' }}\n          className='flex w-full  gap-4   py-10'\n        >\n          {items.map((item, i) => {\n            return (\n              <>\n                <motion.div\n                  // @ts-expect-error\n                  key={item}\n                  className='w-full flex relative  flex-col overflow-hidden border    dark:bg-black bg-neutral-300 hover:bg-neutral-200 dark:hover:bg-neutral-950'\n                  layoutId={`dialog-${item?.id}`}\n                  style={{\n                    borderRadius: '12px',\n                  }}\n                  tabIndex={i}\n                  onClick={() => {\n                    setIndex(i);\n                    setIsOpen(true);\n                  }}\n                >\n                  {item?.imgSrc && (\n                    <motion.div layoutId={`dialog-img-${item.id}`} className='w-full h-full'>\n                      <img\n                        src={item.imgSrc}\n                        alt='A desk lamp designed by Edouard Wilfrid Buquet in 1925. It features a double-arm design and is made from nickel-plated brass, aluminium and varnished wood.'\n                        className=' w-full object-cover'\n                      />\n                    </motion.div>\n                  )}\n                  {item?.videoSrc && (\n                    <motion.div layoutId={`dialog-video-${item.id}`} className='w-full h-full'>\n                      <video autoPlay muted loop className='h-full w-full object-cover  rounded-xs'>\n                        <source src={item.videoSrc!} type='video/mp4' />\n                      </video>\n                    </motion.div>\n                  )}\n                </motion.div>\n              </>\n            );\n          })}\n        </motion.div>\n        <AnimatePresence initial={false} mode='sync'>\n          {isOpen && (\n            <>\n              <motion.div\n                key={`backdrop-${currentItem.id}`}\n                className='fixed inset-0 h-full w-full dark:bg-black/25 bg-white/95 backdrop-blur-xs '\n                variants={{ open: { opacity: 1 }, closed: { opacity: 0 } }}\n                initial='closed'\n                animate='open'\n                exit='closed'\n                onClick={() => {\n                  setIsOpen(false);\n                }}\n              />\n              <motion.div\n                key='dialog'\n                className='pointer-events-none fixed inset-0 flex items-center justify-center z-50'\n              >\n                <motion.div\n                  className='pointer-events-auto relative flex flex-col overflow-hidden   dark:bg-neutral-950 bg-neutral-200 border w-[80%] h-[90%] '\n                  layoutId={`dialog-${currentItem.id}`}\n                  tabIndex={-1}\n                  style={{\n                    borderRadius: '24px',\n                  }}\n                >\n                  {items[index]?.imgSrc && (\n                    <motion.div layoutId={`dialog-img-${currentItem.id}`} className='w-full h-full'>\n                      <img src={currentItem.imgSrc} alt='' className='h-full w-full object-cover' />\n                    </motion.div>\n                  )}\n                  {items[index]?.videoSrc && (\n                    <motion.div\n                      layoutId={`dialog-video-${currentItem.id}`}\n                      className='w-full h-full'\n                    >\n                      <video\n                        autoPlay\n                        muted\n                        loop\n                        controls\n                        className='h-full w-full object-cover  rounded-xs'\n                      >\n                        <source src={currentItem.videoSrc!} type='video/mp4' />\n                      </video>\n                    </motion.div>\n                  )}\n\n                  <button\n                    onClick={() => setIsOpen(false)}\n                    className='absolute right-6 top-6 p-3 text-zinc-50 cursor-pointer dark:bg-neutral-900 bg-neutral-400 hover:bg-neutral-500 rounded-full dark:hover:bg-neutral-800'\n                    type='button'\n                    aria-label='Close dialog'\n                  >\n                    <XIcon size={24} />\n                  </button>\n                </motion.div>\n              </motion.div>\n            </>\n          )}\n        </AnimatePresence>\n      </MotionConfig>\n    </div>\n  );\n}\n",
      "type": "registry:component"
    },
    {
      "path": "./components/ui/media-modal.tsx",
      "content": "'use client';\nimport { useMediaQuery } from '@/hooks/use-media-query';\nimport { cn } from '@/lib/utils';\nimport { XIcon } from 'lucide-react';\nimport { AnimatePresence, MotionConfig, motion } from 'motion/react';\nimport React, { useEffect, useId, useState } from 'react';\n\nexport const transition = {\n  type: 'spring',\n  stiffness: 300, // Increased from 80\n  damping: 30, // Increased from 10\n  mass: 0.5, // Decreased from 0.9\n} as const;\n\ninterface IMediaModal {\n  imgSrc?: string;\n  videoSrc?: string;\n  className?: string;\n}\n\nexport function MediaModal({ imgSrc, videoSrc, className }: IMediaModal) {\n  const [isMediaModalOpen, setIsMediaModalOpen] = useState(false);\n  const uniqueId = useId();\n\n  useEffect(() => {\n    if (isMediaModalOpen) {\n      document.body.classList.add('overflow-hidden');\n    } else {\n      document.body.classList.remove('overflow-hidden');\n    }\n\n    const handleKeyDown = (event: KeyboardEvent) => {\n      if (event.key === 'Escape') {\n        setIsMediaModalOpen(false);\n      }\n    };\n\n    document.addEventListener('keydown', handleKeyDown);\n    return () => {\n      document.removeEventListener('keydown', handleKeyDown);\n    };\n  }, [isMediaModalOpen]);\n  return (\n    <>\n      <MotionConfig transition={transition}>\n        <>\n          <motion.div\n            className='w-full h-full flex relative flex-col overflow-hidden border cursor-zoom-in dark:bg-black bg-neutral-300 hover:bg-neutral-200 dark:hover:bg-neutral-950'\n            layoutId={`dialog-${uniqueId}`}\n            style={{\n              borderRadius: '12px',\n            }}\n            onClick={() => {\n              setIsMediaModalOpen(true);\n            }}\n          >\n            {imgSrc && (\n              <motion.div layoutId={`dialog-img-${uniqueId}`} className='w-full h-full'>\n                <img\n                  src={imgSrc}\n                  alt='A desk lamp designed by Edouard Wilfrid Buquet in 1925. It features a double-arm design and is made from nickel-plated brass, aluminium and varnished wood.'\n                  className=' w-full object-cover h-full'\n                />\n              </motion.div>\n            )}\n            {videoSrc && (\n              <motion.div layoutId={`dialog-video-${uniqueId}`} className='w-full h-full'>\n                <video autoPlay muted loop className='h-full w-full object-cover  rounded-xs'>\n                  <source src={videoSrc!} type='video/mp4' />\n                </video>\n              </motion.div>\n            )}\n          </motion.div>\n        </>\n        <AnimatePresence initial={false} mode='popLayout'>\n          {isMediaModalOpen && (\n            <>\n              <motion.div\n                key={`backdrop-${uniqueId}`}\n                className='fixed inset-0 h-full w-full z-50  dark:bg-black/25 bg-white/95 backdrop-blur-xs '\n                variants={{ open: { opacity: 1 }, closed: { opacity: 0 } }}\n                initial='closed'\n                animate='open'\n                exit='closed'\n                onClick={() => {\n                  setIsMediaModalOpen(false);\n                }}\n              />\n              <motion.div\n                key='dialog'\n                className='pointer-events-none fixed inset-0 flex items-center justify-center z-50'\n              >\n                <motion.div\n                  className={cn(\n                    'pointer-events-auto relative flex flex-col overflow-hidden dark:bg-neutral-950 bg-neutral-200 border w-[80%] h-[90%]',\n                    imgSrc && 'cursor-zoom-out'\n                  )}\n                  layoutId={`dialog-${uniqueId}`}\n                  layout={isMediaModalOpen}\n                  tabIndex={-1}\n                  style={{\n                    borderRadius: '24px',\n                  }}\n                >\n                  {imgSrc && (\n                    <motion.div\n                      layoutId={`dialog-img-${uniqueId}`}\n                      className='w-full h-full'\n                      onClick={() => setIsMediaModalOpen(false)}\n                    >\n                      <img src={imgSrc} alt='' className='h-full w-full object-cover' />\n                    </motion.div>\n                  )}\n                  {videoSrc && (\n                    <motion.div layoutId={`dialog-video-${uniqueId}`} className='w-full h-full'>\n                      <video\n                        autoPlay\n                        muted\n                        loop\n                        controls\n                        className='h-full w-full object-cover  rounded-xs'\n                      >\n                        <source src={videoSrc!} type='video/mp4' />\n                      </video>\n                    </motion.div>\n                  )}\n                  {videoSrc && (\n                    <button\n                      onClick={() => setIsMediaModalOpen(false)}\n                      className='absolute right-6 top-6 p-3 text-zinc-50 cursor-pointer dark:bg-neutral-900 bg-neutral-400 hover:bg-neutral-500 rounded-xl dark:hover:bg-neutral-800'\n                      type='button'\n                      aria-label='Close dialog'\n                    >\n                      <XIcon size={24} />\n                    </button>\n                  )}\n                </motion.div>\n              </motion.div>\n            </>\n          )}\n        </AnimatePresence>\n      </MotionConfig>\n    </>\n  );\n}\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:component"
}