{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "header-01",
  "description": "A simple header.",
  "dependencies": [
    "motion/react",
    "lucide-react",
    "next-themes"
  ],
  "registryDependencies": [
    "button",
    "utils"
  ],
  "files": [
    {
      "path": "registry/blocks/header-01/page.tsx",
      "content": "import { Navbar } from \"@/registry/blocks/header-01/components/navbar\"\n\nexport default function Page() {\n  return (\n    <div className=\"min-h-svh w-full\">\n      <Navbar />\n      <main className=\"flex-1\">\n        <section className=\"flex h-screen items-center justify-center\">\n          <h1 className=\"text-4xl font-bold\">Hero</h1>\n        </section>\n        <section className=\"flex h-screen items-center justify-center\">\n          <h1 className=\"text-4xl font-bold\">Section</h1>\n        </section>\n      </main>\n    </div>\n  )\n}\n",
      "type": "registry:page",
      "target": "app/header/page.tsx"
    },
    {
      "path": "registry/blocks/header-01/components/navbar.tsx",
      "content": "\"use client\"\n\nimport { useEffect, useState } from \"react\"\nimport Link from \"next/link\"\nimport { Menu, X } from \"lucide-react\"\nimport { AnimatePresence, motion, useScroll } from \"motion/react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Icons } from \"@/components/icons\"\nimport { NavMenu } from \"@/registry/blocks/header-01/components/nav-menu\"\nimport { ThemeToggle } from \"@/registry/blocks/header-01/components/theme-toggle\"\nimport { navLinks } from \"@/registry/blocks/header-01/lib/nav-links\"\n\nconst INITIAL_WIDTH = \"70rem\"\nconst MAX_WIDTH = \"800px\"\n\n// Animation variants\nconst overlayVariants = {\n  hidden: { opacity: 0 },\n  visible: { opacity: 1 },\n  exit: { opacity: 0 },\n}\n\nconst drawerVariants = {\n  hidden: { opacity: 0, y: 100 },\n  visible: {\n    opacity: 1,\n    y: 0,\n    rotate: 0,\n    transition: {\n      type: \"spring\" as const,\n      damping: 15,\n      stiffness: 200,\n      staggerChildren: 0.03,\n    },\n  },\n  exit: {\n    opacity: 0,\n    y: 100,\n    transition: { duration: 0.1 },\n  },\n}\n\nconst drawerMenuContainerVariants = {\n  hidden: { opacity: 0 },\n  visible: { opacity: 1 },\n}\n\nconst drawerMenuVariants = {\n  hidden: { opacity: 0 },\n  visible: { opacity: 1 },\n}\n\nexport function Navbar() {\n  const { scrollY } = useScroll()\n  const [hasScrolled, setHasScrolled] = useState(false)\n  const [isDrawerOpen, setIsDrawerOpen] = useState(false)\n  const [activeSection, setActiveSection] = useState(\"hero\")\n\n  useEffect(() => {\n    const handleScroll = () => {\n      const sections = navLinks.map((item) => item.href.substring(1))\n\n      for (const section of sections) {\n        const element = document.getElementById(section)\n        if (element) {\n          const rect = element.getBoundingClientRect()\n          if (rect.top <= 150 && rect.bottom >= 150) {\n            setActiveSection(section)\n            break\n          }\n        }\n      }\n    }\n\n    window.addEventListener(\"scroll\", handleScroll)\n    handleScroll()\n\n    return () => window.removeEventListener(\"scroll\", handleScroll)\n  }, [])\n\n  useEffect(() => {\n    const unsubscribe = scrollY.on(\"change\", (latest) => {\n      setHasScrolled(latest > 10)\n    })\n    return unsubscribe\n  }, [scrollY])\n\n  const toggleDrawer = () => setIsDrawerOpen((prev) => !prev)\n  const handleOverlayClick = () => setIsDrawerOpen(false)\n\n  return (\n    <header\n      className={cn(\n        \"sticky z-50 mx-4 flex justify-center transition-all duration-300 md:mx-0\",\n        hasScrolled ? \"top-6\" : \"top-4 mx-0\"\n      )}\n    >\n      <motion.div\n        initial={{ width: INITIAL_WIDTH }}\n        animate={{ width: hasScrolled ? MAX_WIDTH : INITIAL_WIDTH }}\n        transition={{ duration: 0.3, ease: [0.25, 0.1, 0.25, 1] }}\n      >\n        <div\n          className={cn(\n            \"mx-auto max-w-7xl rounded-2xl transition-all duration-300 xl:px-0\",\n            hasScrolled\n              ? \"border-border bg-background/75 border px-2 backdrop-blur-lg\"\n              : \"px-7 shadow-none\"\n          )}\n        >\n          <div className=\"flex h-[56px] items-center justify-between p-4\">\n            <Link href=\"/\" className=\"flex items-center gap-3\">\n              <Icons.logo className=\"-mt-1 size-4 md:size-6\" />\n              <p className=\"text-primary ml-1 text-lg font-semibold\">\n                EldoraUI\n              </p>\n            </Link>\n\n            <NavMenu />\n\n            <div className=\"flex shrink-0 flex-row items-center gap-1 md:gap-3\">\n              <div className=\"flex items-center space-x-6\">\n                <Link\n                  className=\"text-primary-foreground dark:text-cyan-500-foreground hidden h-8 w-fit items-center justify-center rounded-full border border-white/[0.12] bg-cyan-500 px-4 text-sm font-normal tracking-wide shadow-[inset_0_1px_2px_rgba(255,255,255,0.25),0_3px_3px_-1.5px_rgba(16,24,40,0.06),0_1px_1px_rgba(16,24,40,0.08)] md:flex\"\n                  href=\"#\"\n                >\n                  Try for free\n                </Link>\n              </div>\n              <ThemeToggle />\n              <button\n                className=\"border-border flex size-8 cursor-pointer items-center justify-center rounded-md border md:hidden\"\n                onClick={toggleDrawer}\n              >\n                {isDrawerOpen ? (\n                  <X className=\"size-5\" />\n                ) : (\n                  <Menu className=\"size-5\" />\n                )}\n              </button>\n            </div>\n          </div>\n        </div>\n      </motion.div>\n\n      {/* Mobile Drawer */}\n      <AnimatePresence>\n        {isDrawerOpen && (\n          <>\n            <motion.div\n              className=\"fixed inset-0 bg-black/50 backdrop-blur-sm\"\n              initial=\"hidden\"\n              animate=\"visible\"\n              exit=\"exit\"\n              variants={overlayVariants}\n              transition={{ duration: 0.2 }}\n              onClick={handleOverlayClick}\n            />\n\n            <motion.div\n              className=\"bg-background border-border fixed inset-x-0 bottom-3 mx-auto w-[95%] rounded-xl border p-4 shadow-lg\"\n              initial=\"hidden\"\n              animate=\"visible\"\n              exit=\"exit\"\n              variants={drawerVariants}\n            >\n              {/* Mobile menu content */}\n              <div className=\"flex flex-col gap-4\">\n                <div className=\"flex items-center justify-between\">\n                  <Link href=\"/\" className=\"flex items-center gap-3\">\n                    <Icons.logo className=\"size-7 md:size-10\" />\n                    <p className=\"text-primary text-lg font-semibold\">\n                      SkyAgent\n                    </p>\n                  </Link>\n                  <button\n                    onClick={toggleDrawer}\n                    className=\"border-border cursor-pointer rounded-md border p-1\"\n                  >\n                    <X className=\"size-5\" />\n                  </button>\n                </div>\n\n                <motion.ul\n                  className=\"border-border mb-4 flex flex-col rounded-md border text-sm\"\n                  variants={drawerMenuContainerVariants}\n                >\n                  <AnimatePresence>\n                    {navLinks.map((item) => (\n                      <motion.li\n                        key={item.id}\n                        className=\"border-border border-b p-2.5 last:border-b-0\"\n                        variants={drawerMenuVariants}\n                      >\n                        <a\n                          href={item.href}\n                          onClick={(e) => {\n                            e.preventDefault()\n                            const element = document.getElementById(\n                              item.href.substring(1)\n                            )\n                            element?.scrollIntoView({ behavior: \"smooth\" })\n                            setIsDrawerOpen(false)\n                          }}\n                          className={`hover:text-primary/80 underline-offset-4 transition-colors ${\n                            activeSection === item.href.substring(1)\n                              ? \"text-primary font-medium\"\n                              : \"text-primary/60\"\n                          }`}\n                        >\n                          {item.name}\n                        </a>\n                      </motion.li>\n                    ))}\n                  </AnimatePresence>\n                </motion.ul>\n\n                {/* Action buttons */}\n                <div className=\"flex flex-col gap-2\">\n                  <Link\n                    href=\"#\"\n                    className=\"text-primary-foreground dark:text-cyan-500-foreground flex h-8 w-full items-center justify-center rounded-full border border-white/[0.12] bg-cyan-500 px-4 text-sm font-normal tracking-wide shadow-[inset_0_1px_2px_rgba(255,255,255,0.25),0_3px_3px_-1.5px_rgba(16,24,40,0.06),0_1px_1px_rgba(16,24,40,0.08)] transition-all ease-out hover:bg-cyan-500/80 active:scale-95\"\n                  >\n                    Try for free\n                  </Link>\n                </div>\n              </div>\n            </motion.div>\n          </>\n        )}\n      </AnimatePresence>\n    </header>\n  )\n}\n",
      "type": "registry:component"
    },
    {
      "path": "registry/blocks/header-01/components/nav-menu.tsx",
      "content": "\"use client\"\n\nimport React, { useRef, useState } from \"react\"\nimport { motion } from \"motion/react\"\n\nimport { navLinks } from \"@/registry/blocks/header-01/lib/nav-links\"\n\ninterface NavItem {\n  id: number\n  name: string\n  href: string\n}\n\nconst navs: NavItem[] = [...navLinks]\n\nexport function NavMenu() {\n  const ref = useRef<HTMLUListElement>(null)\n  const [left, setLeft] = useState(0)\n  const [width, setWidth] = useState(0)\n  const [isReady, setIsReady] = useState(false)\n  const [activeSection, setActiveSection] = useState(\"hero\")\n  const [isManualScroll, setIsManualScroll] = useState(false)\n\n  React.useEffect(() => {\n    // Initialize with first nav item\n    const firstItem = ref.current?.querySelector(\n      `[href=\"#${navs[0].href.substring(1)}\"]`\n    )?.parentElement\n    if (firstItem) {\n      const rect = firstItem.getBoundingClientRect()\n      setLeft(firstItem.offsetLeft)\n      setWidth(rect.width)\n      setIsReady(true)\n    }\n  }, [])\n\n  React.useEffect(() => {\n    const handleScroll = () => {\n      // Skip scroll handling during manual click scrolling\n      if (isManualScroll) return\n\n      const sections = navs.map((item) => item.href.substring(1))\n\n      // Find the section closest to viewport top\n      let closestSection = sections[0]\n      let minDistance = Infinity\n\n      for (const section of sections) {\n        const element = document.getElementById(section)\n        if (element) {\n          const rect = element.getBoundingClientRect()\n          const distance = Math.abs(rect.top - 100) // Offset by 100px to trigger earlier\n          if (distance < minDistance) {\n            minDistance = distance\n            closestSection = section\n          }\n        }\n      }\n\n      // Update active section and nav indicator\n      setActiveSection(closestSection)\n      const navItem = ref.current?.querySelector(\n        `[href=\"#${closestSection}\"]`\n      )?.parentElement\n      if (navItem) {\n        const rect = navItem.getBoundingClientRect()\n        setLeft(navItem.offsetLeft)\n        setWidth(rect.width)\n      }\n    }\n\n    window.addEventListener(\"scroll\", handleScroll)\n    handleScroll() // Initial check\n    return () => window.removeEventListener(\"scroll\", handleScroll)\n  }, [isManualScroll])\n\n  const handleClick = (\n    e: React.MouseEvent<HTMLAnchorElement>,\n    item: NavItem\n  ) => {\n    e.preventDefault()\n\n    const targetId = item.href.substring(1)\n    const element = document.getElementById(targetId)\n\n    if (element) {\n      // Set manual scroll flag\n      setIsManualScroll(true)\n\n      // Immediately update nav state\n      setActiveSection(targetId)\n      const navItem = e.currentTarget.parentElement\n      if (navItem) {\n        const rect = navItem.getBoundingClientRect()\n        setLeft(navItem.offsetLeft)\n        setWidth(rect.width)\n      }\n\n      // Calculate exact scroll position\n      const elementPosition = element.getBoundingClientRect().top\n      const offsetPosition = elementPosition + window.pageYOffset - 100 // 100px offset\n\n      // Smooth scroll to exact position\n      window.scrollTo({\n        top: offsetPosition,\n        behavior: \"smooth\",\n      })\n\n      // Reset manual scroll flag after animation completes\n      setTimeout(() => {\n        setIsManualScroll(false)\n      }, 500) // Adjust timing to match scroll animation duration\n    }\n  }\n\n  return (\n    <div className=\"hidden w-full md:block\">\n      <ul\n        className=\"relative mx-auto flex h-11 w-fit items-center justify-center rounded-full px-2\"\n        ref={ref}\n      >\n        {navs.map((item) => (\n          <li\n            key={item.id}\n            className={`z-10 flex h-full cursor-pointer items-center justify-center px-4 py-2 text-sm font-medium transition-colors duration-200 ${\n              activeSection === item.href.substring(1)\n                ? \"text-primary\"\n                : \"text-primary/60 hover:text-primary\"\n            } tracking-tight`}\n          >\n            <a href={item.href} onClick={(e) => handleClick(e, item)}>\n              {item.name}\n            </a>\n          </li>\n        ))}\n        {isReady && (\n          <motion.li\n            animate={{ left, width }}\n            transition={{ type: \"spring\", stiffness: 400, damping: 30 }}\n            className=\"bg-accent/60 border-border absolute inset-0 my-1.5 rounded-full border\"\n          />\n        )}\n      </ul>\n    </div>\n  )\n}\n",
      "type": "registry:component"
    },
    {
      "path": "registry/blocks/header-01/components/theme-toggle.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Moon, Sun } from \"lucide-react\"\nimport { useTheme } from \"next-themes\"\n\nimport { Button } from \"@/components/ui/button\"\n\nexport function ThemeToggle() {\n  const { theme, setTheme } = useTheme()\n\n  return (\n    <Button\n      variant=\"outline\"\n      size=\"icon\"\n      onClick={() => setTheme(theme === \"light\" ? \"dark\" : \"light\")}\n      className=\"h-8 w-8 cursor-pointer rounded-full\"\n    >\n      <Sun className=\"text-primary h-[1.2rem] w-[1.2rem] scale-100 rotate-0 transition-all dark:scale-0 dark:-rotate-90\" />\n      <Moon className=\"text-primary absolute h-[1.2rem] w-[1.2rem] scale-0 rotate-90 transition-all dark:scale-100 dark:rotate-0\" />\n      <span className=\"sr-only\">Toggle theme</span>\n    </Button>\n  )\n}\n",
      "type": "registry:component"
    },
    {
      "path": "registry/blocks/header-01/lib/nav-links.ts",
      "content": "export const navLinks = [\n  { id: 1, name: \"Home\", href: \"/\" },\n  { id: 2, name: \"How it Works\", href: \"/\" },\n  { id: 3, name: \"Features\", href: \"/\" },\n  { id: 4, name: \"Pricing\", href: \"/\" },\n] as const\n",
      "type": "registry:lib"
    }
  ],
  "categories": [
    "header"
  ],
  "type": "registry:block"
}