{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "lamphome",
  "type": "registry:block",
  "title": "Lamphome",
  "description": "Lamphome",
  "files": [
    {
      "path": "components/usages/lamphomeusage.tsx",
      "content": "import { Button } from '@/components/ui/button';\nimport { Lamphome } from '@/registry/open-source/lamphome';\nimport Link from 'next/link';\n\nexport default function LamphomeDemo() {\n    return (\n        <Lamphome\n            title='SCROLLX UI'\n            description='An open-source collection of animated, interactive & fully customizable components for building stunning, memorable user interfaces.'\n            logoSrc='/favicon.ico'\n            logoAlt='My Logo'\n            navItems={[\n                { href: '/', label: 'Home' },\n                { href: '/docs', label: 'Docs' },\n                { href: '/templates', label: 'Templates' },\n                { href: '/showcase', label: 'Showcase' },\n            ]}\n            className='my-custom-class'\n        >\n            <div className='mt-12'>\n                <div className='mt-6 flex flex-col items-center gap-4'>\n                    <Button\n                        asChild\n                        size='sm'\n                        className='w-full md:w-auto bg-black dark:bg-linear-to-r from-violet-500 to-purple-600 text-white hover:from-violet-600 hover:to-purple-700 border-0'\n                    >\n                        <Link href='https://scrollxui.dev/docs/components'>\n                            View Components\n                        </Link>\n                    </Button>\n                </div>\n            </div>\n        </Lamphome>\n    );\n}\n",
      "type": "registry:block",
      "target": "~/example.tsx"
    },
    {
      "path": "components/usages/lamphomeusage.tsx",
      "content": "import { Button } from '@/components/ui/button';\nimport { Lamphome } from '@/registry/open-source/lamphome';\nimport Link from 'next/link';\n\nexport default function LamphomeDemo() {\n    return (\n        <Lamphome\n            title='SCROLLX UI'\n            description='An open-source collection of animated, interactive & fully customizable components for building stunning, memorable user interfaces.'\n            logoSrc='/favicon.ico'\n            logoAlt='My Logo'\n            navItems={[\n                { href: '/', label: 'Home' },\n                { href: '/docs', label: 'Docs' },\n                { href: '/templates', label: 'Templates' },\n                { href: '/showcase', label: 'Showcase' },\n            ]}\n            className='my-custom-class'\n        >\n            <div className='mt-12'>\n                <div className='mt-6 flex flex-col items-center gap-4'>\n                    <Button\n                        asChild\n                        size='sm'\n                        className='w-full md:w-auto bg-black dark:bg-linear-to-r from-violet-500 to-purple-600 text-white hover:from-violet-600 hover:to-purple-700 border-0'\n                    >\n                        <Link href='https://scrollxui.dev/docs/components'>\n                            View Components\n                        </Link>\n                    </Button>\n                </div>\n            </div>\n        </Lamphome>\n    );\n}\n",
      "type": "registry:ui"
    },
    {
      "path": "components/ui/button.tsx",
      "content": "import * as React from \"react\";\r\n\r\nimport { cn } from \"@/registry/utilities/cn\";\r\nimport { Slot } from \"@radix-ui/react-slot\";\r\nimport { cva, type VariantProps } from \"class-variance-authority\";\r\n\r\nconst buttonVariants = cva(\r\n\t\"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm text-white hover:text-gray-400 font-medium ring-offset-background transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50\",\r\n\t{\r\n\t\tvariants: {\r\n\t\t\tvariant: {\r\n\t\t\t\tsimple:\r\n\t\t\t\t\t\"bg-secondary relative z-10 bg-transparent hover:border-secondary hover:bg-secondary/50  border border-transparent dark:text-white text-sm md:text-sm transition font-medium duration-200  rounded-md px-4 py-2  flex items-center justify-center\",\r\n\t\t\t\tdefault: \"bg-primary text-primary-foreground hover:bg-primary/90\",\r\n\t\t\t\tdestructive:\r\n\t\t\t\t\t\"bg-destructive text-destructive-foreground hover:bg-destructive/90\",\r\n\t\t\t\toutline:\r\n\t\t\t\t\t\"border border-input bg-background hover:bg-accent hover:text-accent-foreground\",\r\n\t\t\t\tsecondary:\r\n\t\t\t\t\t\"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\r\n\t\t\t\tghost: \"hover:bg-accent hover:text-black hover:stroke-black dark:text-white text-black\",\r\n\t\t\t\tlink: \"text-primary underline-offset-4 hover:underline\",\r\n\t\t\t},\r\n\t\t\tsize: {\r\n\t\t\t\tdefault: \"h-10 px-4 py-2\",\r\n\t\t\t\tsm: \"h-9 rounded-md px-3\",\r\n\t\t\t\tlg: \"h-11 rounded-md px-8\",\r\n\t\t\t\ticon: \"h-10 w-10\",\r\n\t\t\t},\r\n\t\t},\r\n\t\tdefaultVariants: {\r\n\t\t\tvariant: \"default\",\r\n\t\t\tsize: \"default\",\r\n\t\t},\r\n\t}\r\n);\r\n\r\nexport interface ButtonProps\r\n\textends React.ButtonHTMLAttributes<HTMLButtonElement>,\r\n\t\tVariantProps<typeof buttonVariants> {\r\n\tasChild?: boolean;\r\n}\r\n\r\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\r\n\t({ className, variant, size, asChild = false, ...props }, ref) => {\r\n\t\tconst Comp = asChild ? Slot : \"button\";\r\n\t\treturn (\r\n\t\t\t<Comp\r\n\t\t\t\tclassName={cn(buttonVariants({ variant, size, className }))}\r\n\t\t\t\tref={ref}\r\n\t\t\t\t{...props}\r\n\t\t\t/>\r\n\t\t);\r\n\t}\r\n);\r\nButton.displayName = \"Button\";\r\n\r\nexport { Button, buttonVariants };\r\n",
      "type": "registry:ui"
    },
    {
      "path": "registry/utilities/cn.ts",
      "content": "import { ClassValue, clsx } from \"clsx\";\r\nimport { twMerge } from \"tailwind-merge\";\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n\treturn twMerge(clsx(inputs));\r\n}\r\n",
      "type": "registry:ui"
    },
    {
      "path": "registry/open-source/lamphome.tsx",
      "content": "'use client';\n\nimport { motion, AnimatePresence, PanInfo } from 'motion/react';\nimport Image from 'next/image';\nimport Link from 'next/link';\nimport React, { useState, useRef, useMemo } from 'react';\nimport { useTheme } from 'next-themes';\n\n// Credit:\n// https://scrollxui.dev/docs/components/lamphome\n\ninterface NavItem {\n    href: string;\n    label: string;\n}\n\ninterface LamphomeProps {\n    title?: string;\n    description?: string;\n    logoSrc?: string;\n    logoAlt?: string;\n    navItems?: NavItem[];\n    children?: React.ReactNode;\n    className?: string;\n}\n\nexport function Lamphome({\n    title,\n    description,\n    logoSrc,\n    logoAlt,\n    navItems = [],\n    children,\n    className = '',\n}: LamphomeProps) {\n    const { theme, setTheme, resolvedTheme } = useTheme();\n    const isDarkMode = resolvedTheme === 'dark';\n\n    const chainPulled = useMemo(() => isDarkMode, [isDarkMode]);\n    const chainLength = useMemo(() => (isDarkMode ? 72 : 48), [isDarkMode]);\n    const showGlow = useMemo(() => isDarkMode, [isDarkMode]);\n    const glowPosition = useMemo<'above' | 'below'>(\n        () => (isDarkMode ? 'above' : 'below'),\n        [isDarkMode],\n    );\n\n    const [mobileMenuOpen, setMobileMenuOpen] = useState(false);\n    const [dragY, setDragY] = useState(0);\n    const [isDragging, setIsDragging] = useState(false);\n    const [dynamicGlowPosition, setDynamicGlowPosition] = useState<\n        'above' | 'below'\n    >('below');\n\n    const titleRef = useRef<HTMLHeadingElement>(null);\n    const navBarRef = useRef<HTMLDivElement>(null);\n\n    const calculateGlowPosition = (currentDragY: number) => {\n        if (!titleRef.current || !navBarRef.current) return 'below';\n        const navBarRect = navBarRef.current.getBoundingClientRect();\n        const titleRect = titleRef.current.getBoundingClientRect();\n        const chainEndY = navBarRect.bottom + chainLength + currentDragY;\n        const titleCenterY = titleRect.top + titleRect.height / 2;\n        return chainEndY < titleCenterY ? 'above' : 'below';\n    };\n\n    const handleDragStart = () => {\n        setIsDragging(true);\n    };\n\n    const handleDragEnd = (\n        event: MouseEvent | TouchEvent | PointerEvent,\n        info: PanInfo,\n    ) => {\n        setIsDragging(false);\n        const finalDragY = Math.max(0, info.offset.y);\n        if (finalDragY > 8) {\n            const newTheme = theme === 'dark' ? 'light' : 'dark';\n            setTheme(newTheme);\n        }\n        setTimeout(() => {\n            setDragY(0);\n        }, 100);\n    };\n\n    const toggleMobileMenu = () => {\n        setMobileMenuOpen(!mobileMenuOpen);\n    };\n\n    const currentGlowPosition = isDragging ? dynamicGlowPosition : glowPosition;\n\n    return (\n        <div\n            className={`min-h-full w-full flex flex-col items-center justify-start pt-2 [@media(min-width:480px)]:pt-4 [@media(min-width:768px)]:pt-6 [@media(min-width:1024px)]:pt-8 transition-all duration-500 text-gray-900 dark:text-white ${className}`}\n        >\n            <motion.div\n                ref={navBarRef}\n                initial={{ width: '95%' }}\n                animate={{ width: '95%' }}\n                transition={{ duration: 0.8, ease: 'easeOut' }}\n                className='relative flex items-center justify-between w-full max-w-4xl h-auto py-3 px-3 [@media(min-width:768px)]:px-6 bg-white/80 dark:bg-neutral-950 backdrop-blur-xs border border-gray-200 dark:border-gray-700 rounded-2xl shadow-lg hover:shadow-xl transition-all duration-300'\n            >\n                {logoSrc && (\n                    <div className='shrink-0'>\n                        <Image\n                            src={logoSrc}\n                            alt={logoAlt || 'Logo'}\n                            width={28}\n                            height={28}\n                            className='cursor-pointer hover:scale-110 transition-transform duration-200'\n                        />\n                    </div>\n                )}\n\n                <nav className='hidden [@media(min-width:640px)]:flex items-center space-x-4 [@media(min-width:768px)]:space-x-6'>\n                    {navItems.map((item, index) => (\n                        <Link\n                            key={index}\n                            href={item.href}\n                            className='text-sm [@media(min-width:768px)]:text-base font-medium text-gray-700 dark:text-gray-200 hover:text-gray-900 dark:hover:text-white transition-colors duration-200 relative group'\n                        >\n                            {item.label}\n                            <span className='absolute -bottom-1 left-0 w-0 h-0.5 bg-linear-to-r from-blue-500 to-purple-500 group-hover:w-full transition-all duration-300'></span>\n                        </Link>\n                    ))}\n                </nav>\n\n                <div className='flex items-center space-x-2'>\n                    <button\n                        onClick={toggleMobileMenu}\n                        className='[@media(min-width:640px)]:hidden flex justify-center items-center p-2 bg-gray-100 dark:bg-neutral-900 rounded-lg hover:bg-gray-200 dark:hover:bg-slate-600 transition-colors duration-200'\n                    >\n                        <motion.svg\n                            width='18'\n                            height='18'\n                            viewBox='0 0 24 24'\n                            fill='none'\n                            stroke='currentColor'\n                            strokeWidth='2'\n                            strokeLinecap='round'\n                            strokeLinejoin='round'\n                            animate={{ rotate: mobileMenuOpen ? 90 : 0 }}\n                            transition={{ duration: 0.2 }}\n                        >\n                            <line x1='3' y1='6' x2='21' y2='6' />\n                            <line x1='3' y1='12' x2='21' y2='12' />\n                            <line x1='3' y1='18' x2='21' y2='18' />\n                        </motion.svg>\n                    </button>\n                </div>\n\n                <div className='absolute right-3 top-full mt-2 flex flex-col items-center group z-10'>\n                    <motion.div\n                        className='w-1 bg-linear-to-b from-gray-400 to-gray-600 dark:from-gray-500 dark:to-gray-300 rounded-full shadow-2xs relative'\n                        animate={{\n                            height: chainLength + dragY,\n                            scaleY: 1,\n                        }}\n                        transition={{\n                            duration: isDragging ? 0.05 : 0.6,\n                            ease: isDragging ? 'linear' : 'easeOut',\n                            type: isDragging ? 'tween' : 'spring',\n                            stiffness: isDragging ? undefined : 200,\n                            damping: isDragging ? undefined : 20,\n                        }}\n                        style={{\n                            height: `${chainLength + dragY}px`,\n                            transformOrigin: 'top center',\n                        }}\n                    >\n                        {dragY > 4 && (\n                            <div className='absolute inset-0 flex flex-col justify-evenly'>\n                                {Array.from({\n                                    length: Math.floor((chainLength + dragY) / 8),\n                                }).map((_, i) => (\n                                    <div\n                                        key={i}\n                                        className='w-full h-0.5 bg-gray-500 dark:bg-gray-400 rounded-full opacity-40'\n                                    />\n                                ))}\n                            </div>\n                        )}\n                    </motion.div>\n                    <motion.div\n                        drag='y'\n                        dragConstraints={{ top: 0, bottom: 12 }}\n                        dragElastic={0}\n                        onDragStart={handleDragStart}\n                        onDragEnd={handleDragEnd}\n                        onDrag={(\n                            event: MouseEvent | TouchEvent | PointerEvent,\n                            info: PanInfo,\n                        ) => {\n                            const newDragY = Math.max(0, info.offset.y);\n                            setDragY(newDragY);\n                            if (newDragY > 4) {\n                                const position = calculateGlowPosition(newDragY);\n                                setDynamicGlowPosition(position);\n                            }\n                        }}\n                        whileHover={{ scale: 1.05 }}\n                        whileDrag={{\n                            scale: 1.12,\n                            boxShadow: `0 ${6 + dragY * 0.3}px ${14 + dragY * 0.3\n                                }px rgba(0,0,0,0.3)`,\n                        }}\n                        className='w-6 h-6 bg-linear-to-br from-yellow-400 to-yellow-600 dark:from-yellow-300 dark:to-yellow-500 rounded-full shadow-lg border-2 border-yellow-500 dark:border-yellow-400 transition-shadow duration-200 relative overflow-hidden cursor-grab active:cursor-grabbing'\n                        animate={{\n                            rotateZ: chainPulled ? 180 : 0,\n                        }}\n                        transition={{\n                            duration: 0.5,\n                            ease: 'easeInOut',\n                        }}\n                        style={{ position: 'relative', top: -20, y: 0 }}\n                    >\n                        <div className='w-full h-full rounded-full bg-linear-to-br from-yellow-300 to-transparent opacity-60'></div>\n                        <div className='absolute inset-0 flex items-center justify-center'>\n                            <div className='flex flex-col space-y-0.5'>\n                                <motion.div\n                                    className='w-3 h-0.5 bg-yellow-700 dark:bg-yellow-200 rounded-full opacity-60'\n                                    animate={{ scaleX: 1 + dragY * 0.02 }}\n                                />\n                                <motion.div\n                                    className='w-3 h-0.5 bg-yellow-700 dark:bg-yellow-200 rounded-full opacity-60'\n                                    animate={{ scaleX: 1 + dragY * 0.02 }}\n                                />\n                                <motion.div\n                                    className='w-3 h-0.5 bg-yellow-700 dark:bg-yellow-200 rounded-full opacity-60'\n                                    animate={{ scaleX: 1 + dragY * 0.02 }}\n                                />\n                            </div>\n                        </div>\n                        {isDarkMode && (\n                            <motion.div\n                                initial={{ opacity: 0 }}\n                                animate={{ opacity: 1 }}\n                                className='absolute inset-0 flex items-center justify-center bg-yellow-500/90 dark:bg-yellow-400/90 rounded-full backdrop-blur-xs'\n                            >\n                                <svg\n                                    width='12'\n                                    height='12'\n                                    viewBox='0 0 24 24'\n                                    fill='none'\n                                    stroke='currentColor'\n                                    strokeWidth='2'\n                                    className='text-gray-800'\n                                >\n                                    <circle cx='12' cy='12' r='5' />\n                                    <line x1='12' y1='1' x2='12' y2='3' />\n                                    <line x1='12' y1='21' x2='12' y2='23' />\n                                    <line x1='4.22' y1='4.22' x2='5.64' y2='5.64' />\n                                    <line x1='18.36' y1='18.36' x2='19.78' y2='19.78' />\n                                    <line x1='1' y1='12' x2='3' y2='12' />\n                                    <line x1='21' y1='12' x2='23' y2='12' />\n                                    <line x1='4.22' y1='19.78' x2='5.64' y2='18.36' />\n                                    <line x1='18.36' y1='5.64' x2='19.78' y2='4.22' />\n                                </svg>\n                            </motion.div>\n                        )}\n                        {!isDragging && !chainPulled && (\n                            <motion.div\n                                className='absolute -bottom-10 left-1/2 transform -translate-x-1/2 text-xs text-gray-500 dark:text-gray-400 whitespace-nowrap pointer-events-none bg-white/80 dark:bg-slate-800/80 px-2 py-1 rounded-full'\n                                initial={{ opacity: 0, y: -5 }}\n                                animate={{\n                                    opacity: [0, 1, 1, 0],\n                                    y: [0, -2, -2, 0],\n                                }}\n                                transition={{\n                                    duration: 3,\n                                    repeat: Infinity,\n                                    repeatDelay: 2,\n                                    ease: 'easeInOut',\n                                }}\n                            >\n                                Pull to toggle theme!\n                            </motion.div>\n                        )}\n                        {isDragging && dragY > 4 && (\n                            <motion.div\n                                initial={{ opacity: 0, scale: 0.8 }}\n                                animate={{\n                                    opacity: dragY > 8 ? 1 : 0.7,\n                                    scale: dragY > 8 ? 1.1 : 1,\n                                }}\n                                className={`absolute -bottom-12 left-1/2 transform -translate-x-1/2 text-xs text-white px-3 py-1.5 rounded-full whitespace-nowrap pointer-events-none font-medium transition-all duration-200 ${currentGlowPosition === 'above'\n                                    ? 'bg-purple-600'\n                                    : 'bg-amber-600'\n                                    }`}\n                            >\n                                {dragY > 8\n                                    ? `🌟 Release for ${currentGlowPosition === 'above' ? 'Dark' : 'Light'\n                                    } Mode!`\n                                    : `Pull ${Math.round(8 - dragY)}px more`}\n                            </motion.div>\n                        )}\n                        {!isDragging && dragY > 0 && (\n                            <motion.div\n                                className='absolute inset-0 rounded-full bg-yellow-300 opacity-30'\n                                initial={{ scale: 1.2, opacity: 0.5 }}\n                                animate={{ scale: 1, opacity: 0 }}\n                                transition={{ duration: 0.3, ease: 'easeOut' }}\n                            />\n                        )}\n                    </motion.div>\n                </div>\n\n                <AnimatePresence>\n                    {mobileMenuOpen && (\n                        <motion.div\n                            initial={{ opacity: 0, y: -10 }}\n                            animate={{ opacity: 1, y: 0 }}\n                            exit={{ opacity: 0, y: -10 }}\n                            transition={{ duration: 0.2 }}\n                            className='absolute top-full left-0 right-0 mt-2 [@media(min-width:640px)]:hidden bg-white dark:bg-neutral-950 border border-gray-200 dark:border-gray-700 rounded-xl shadow-lg backdrop-blur-xs z-50'\n                        >\n                            <nav className='flex flex-col py-2'>\n                                {navItems.map((item, index) => (\n                                    <Link\n                                        key={index}\n                                        href={item.href}\n                                        onClick={() => setMobileMenuOpen(false)}\n                                        className='px-4 py-3 text-sm font-medium text-gray-700 dark:text-gray-200 hover:text-gray-900 dark:hover:text-white hover:bg-gray-50 dark:hover:bg-slate-700 transition-colors duration-200'\n                                    >\n                                        {item.label}\n                                    </Link>\n                                ))}\n                            </nav>\n                        </motion.div>\n                    )}\n                </AnimatePresence>\n            </motion.div>\n\n            {isDarkMode && (\n                <motion.div\n                    initial={{ width: 0, opacity: 0 }}\n                    animate={{\n                        width: showGlow ? '80%' : 0,\n                        opacity: showGlow ? 1 : 0,\n                    }}\n                    transition={{ duration: 0.8, delay: 0.2 }}\n                    className='relative max-w-3xl mt-6 h-0.5 bg-linear-to-r from-transparent via-purple-400 to-transparent'\n                    style={{\n                        boxShadow: showGlow\n                            ? '0 0 20px #A855F7, 0 0 40px rgba(168, 85, 247, 0.6), 0 0 60px rgba(168, 85, 247, 0.4)'\n                            : 'none',\n                    }}\n                >\n                    <motion.div\n                        initial={{ opacity: 0 }}\n                        animate={{ opacity: showGlow ? 1 : 0 }}\n                        transition={{ duration: 0.8, delay: 0.3 }}\n                        className='absolute top-full left-1/2 transform -translate-x-1/2 w-full h-20 pointer-events-none'\n                        style={{\n                            background: showGlow\n                                ? 'radial-gradient(ellipse, rgba(168, 85, 247, 0.3) 0%, rgba(168, 85, 247, 0.1) 50%, transparent 100%)'\n                                : 'none',\n                            filter: showGlow ? 'blur(15px)' : 'none',\n                        }}\n                    />\n                </motion.div>\n            )}\n            {title && (\n                <motion.h1\n                    ref={titleRef}\n                    className='mt-6 [@media(min-width:480px)]:mt-8 text-xl [@media(min-width:480px)]:text-2xl [@media(min-width:640px)]:text-3xl [@media(min-width:768px)]:text-4xl [@media(min-width:1024px)]:text-5xl [@media(min-width:1280px)]:text-6xl font-bold bg-linear-to-r from-gray-900 via-gray-700 to-gray-900 dark:from-white dark:via-gray-200 dark:to-white bg-clip-text text-transparent text-center px-4 max-w-4xl'\n                    initial={{ opacity: 0, y: 20 }}\n                    animate={{ opacity: 1, y: 0 }}\n                    transition={{ duration: 0.8, delay: 0.4 }}\n                >\n                    {title}\n                </motion.h1>\n            )}\n            {!isDarkMode && (\n                <motion.div\n                    initial={{ width: '60%', opacity: 1 }}\n                    animate={{\n                        width: '60%',\n                        opacity: 1,\n                    }}\n                    transition={{ duration: 0.8 }}\n                    className='border-t mt-4 max-w-2xl border-gray-300'\n                />\n            )}\n            {description && (\n                <motion.p\n                    className='mt-4 [@media(min-width:480px)]:mt-6 text-center text-xs [@media(min-width:480px)]:text-sm [@media(min-width:640px)]:text-base [@media(min-width:768px)]:text-lg text-gray-600 dark:text-gray-300 max-w-xs [@media(min-width:480px)]:max-w-md [@media(min-width:768px)]:max-w-2xl px-4 leading-relaxed'\n                    initial={{ opacity: 0, y: 20 }}\n                    animate={{ opacity: 1, y: 0 }}\n                    transition={{ duration: 0.8, delay: 0.6 }}\n                >\n                    {description}\n                </motion.p>\n            )}\n            {children && (\n                <motion.div\n                    className='mt-6 [@media(min-width:480px)]:mt-8 w-full flex justify-center'\n                    initial={{ opacity: 0, y: 30 }}\n                    animate={{ opacity: 1, y: 0 }}\n                    transition={{ duration: 0.8, delay: 0.8 }}\n                >\n                    {children}\n                </motion.div>\n            )}\n        </div>\n    );\n}\n",
      "type": "registry:ui"
    }
  ]
}