{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "expandable-bento-grid",
  "type": "registry:ui",
  "dependencies": [
    "framer-motion",
    "lucide-react"
  ],
  "files": [
    {
      "path": "components/ui/expandable-bento-grid.tsx",
      "content": "'use client'\n\nimport React, { useEffect, useId, useRef, useState } from 'react'\nimport { AnimatePresence, motion } from 'framer-motion'\nimport { useOutsideClick } from '@/hooks/use-outside-click'\nimport { X } from 'lucide-react'\n\nexport interface BentoGridProps {\n    items: {\n        id: string | number\n        title: string\n        subtitle?: string\n        description?: string\n        content: React.ReactNode\n        icon?: React.ReactNode\n        className?: string\n    }[]\n}\n\nexport default function ExpandableBentoGrid({ items }: BentoGridProps) {\n    const [active, setActive] = useState<(typeof items)[number] | boolean | null>(null)\n    const ref = useRef<HTMLDivElement>(null)\n    const id = useId()\n\n    useEffect(() => {\n        function onKeyDown(event: KeyboardEvent) {\n            if (event.key === 'Escape') {\n                setActive(false)\n            }\n        }\n\n        if (active && typeof active === 'object') {\n            document.body.style.overflow = 'hidden'\n        } else {\n            document.body.style.overflow = 'auto'\n        }\n\n        window.addEventListener('keydown', onKeyDown)\n        return () => window.removeEventListener('keydown', onKeyDown)\n    }, [active])\n\n    useOutsideClick(ref, () => setActive(null))\n\n    return (\n        <>\n            <AnimatePresence>\n                {active && typeof active === 'object' && (\n                    <motion.div\n                        initial={{ opacity: 0 }}\n                        animate={{ opacity: 1 }}\n                        exit={{ opacity: 0 }}\n                        className=\"fixed inset-0 bg-black/20 h-full w-full z-[10000]\"\n                    />\n                )}\n            </AnimatePresence>\n            <AnimatePresence>\n                {active && typeof active === 'object' ? (\n                    <div className=\" fixed inset-0 top-16 grid place-items-center z-[10001] \">\n                        <motion.button\n                            key={`button-${active.title}-${id}`}\n                            layout\n                            initial={{ opacity: 0 }}\n                            animate={{ opacity: 1 }}\n                            exit={{ opacity: 0, transition: { duration: 0.05 } }}\n                            className=\"flex absolute top-2 right-2 md:right-10 lg:hidden items-center justify-center bg-white rounded-full h-6 w-6\"\n                            onClick={() => setActive(null)}\n                        >\n                            <X className=\"h-4 w-4 dark:text-white text-black\" />\n                            \n                        </motion.button>\n                        <motion.div\n                            layoutId={`card-${active.title}-${id}`}\n                            ref={ref}\n                            className=\"w-full max-w-[500px] h-full md:h-fit md:max-h-[90%] flex flex-col bg-white dark:bg-neutral-900 sm:rounded-3xl overflow-hidden\"\n                        >\n                            <motion.div layoutId={`image-${active.title}-${id}`}>\n                                <div className=\"w-full h-40 md:h-50 lg:h-60 bg-blue-100 dark:bg-blue-900/20 flex items-center justify-center perspective-distant transform-3d\">\n                                    {active.icon ? (\n                                        <div className=\"scale-[2] text-blue-500\">{active.icon}</div>\n                                    ) : (\n                                        <div className=\"w-full h-full bg-gray-200\" />\n                                    )}\n                                </div>\n                            </motion.div>\n\n                            <div >\n                                <div className=\"flex justify-between p-4  items-center\">\n                                    <div className=\"\">\n                                        <motion.h3\n                                            layoutId={`title-${active.title}-${id}`}\n                                            className=\"font-bold text-neutral-700 dark:text-neutral-200 md:text-sm \"\n                                        >\n                                            {active.title}\n                                        </motion.h3>\n                                        <motion.p\n                                            layoutId={`description-${active.title}-${id}`}\n                                            className=\"text-neutral-600 dark:text-neutral-400 text-[14px] text-balance\"\n                                        >\n                                            {active.description}\n                                        </motion.p>\n                                    </div>\n\n                                    <motion.a\n                                        layoutId={`button-${active.title}-${id}`}\n                                        href=\"#\"\n                                        target=\"_blank\"\n                                        className=\"px-4 py-3 text-sm rounded-2xl font-bold bg-blue-100 dark:bg-blue-900/30 text-white\"\n                                    >\n                                        Visit\n                                    </motion.a>\n                                </div>\n\n\n                             \n                                  <div className=\"pt-4  px-4  flex justify-center mx-auto overflow-auto\">\n                                    <motion.div\n                                        layout\n                                        initial={{ opacity: 0 }}\n                                        animate={{ opacity: 1 }}\n                                        exit={{ opacity: 0 }}\n                                        className=\"text-neutral-600 text-xs md:text-sm lg:text-base h-40 md:h-fit pb-5 flex flex-col items-start gap-4  dark:text-neutral-400 [mask:linear-gradient(to_bottom,white,white,transparent)] [scrollbar-width:none] [-ms-overflow-style:none] [-webkit-overflow-scrolling:touch]\"\n                                    >\n                                        {active.content}\n                                    </motion.div>\n                                </div>\n                              </div>\n                          \n                        </motion.div>\n                    </div>\n                ) : null}\n            </AnimatePresence>\n            <ul className=\"max-w-4xl mx-auto w-full gap-2 lg:gap-4 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3  items-start \">\n                {items.map((item) => (\n                    <motion.div\n                        layoutId={`card-${item.title}-${id}`}\n                        key={item.id}\n                        onClick={() => setActive(item)}\n                        className=\"p-4 flex flex-col md:flex-row justify-between items-center hover:bg-neutral-50 dark:hover:bg-neutral-800 rounded-xl cursor-pointer bg-blue-50/60 dark:bg-blue-900/10 border border-blue-100 dark:border-blue-800 transition-colors\"\n                    >\n                        <div className=\"flex gap-3 flex-row items-center justify-center mx-auto \">\n                            <motion.div layoutId={`image-${item.title}-${id}`}>\n                                <div className=\"h-14 w-14 rounded-lg bg-blue-100 dark:bg-blue-900/30 flex items-center justify-center text-blue-500 p-1\">\n                                    {item.icon}\n                                </div>\n                            </motion.div>\n                            <div className=\"\">\n                                <motion.h3\n                                    layoutId={`title-${item.title}-${id}`}\n                                    className=\"font-medium  text-neutral-800 dark:text-neutral-200  text-left\"\n                                >\n                                    {item.title}\n                                </motion.h3>\n                                <motion.p\n                                    layoutId={`description-${item.title}-${id}`}\n                                    className=\"text-neutral-600 dark:text-neutral-400 text-left  text-xs md:text-[14px]\"\n                                >\n                                    {item.subtitle}\n                                </motion.p>\n                            </div>\n                        </div>\n                    </motion.div>\n                ))}\n            </ul>\n        </>\n    )\n}\n",
      "type": "registry:ui",
      "target": "components/ui/expandable-bento-grid.tsx"
    }
  ]
}