{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "navbar",
  "type": "registry:ui",
  "title": "Navbar",
  "description": "نوار ناوبری",
  "registryDependencies": [
    "https://kashi.sepantapouya.com/r/cx.json",
    "https://kashi.sepantapouya.com/r/drawer.json",
    "https://kashi.sepantapouya.com/r/kashi-provider.json"
  ],
  "files": [
    {
      "path": "registry/kashi/Navbar.tsx",
      "type": "registry:ui",
      "target": "components/kashi/Navbar.tsx",
      "content": "\"use client\";\n\nimport { useEffect, useLayoutEffect, useRef, useState, type ElementType, type ReactNode } from \"react\";\nimport { cx } from \"./cx\";\nimport { Drawer } from \"./Drawer\";\nimport { useKashi } from \"./KashiProvider\";\n\nexport interface NavbarLink {\n  href: string;\n  label: ReactNode;\n  /** صفحهٔ فعلی؛ aria-current=\"page\" می‌گیرد */\n  current?: boolean;\n  icon?: ReactNode;\n  /** بج کنار عنوان، مثل «جدید» یا تعداد */\n  badge?: ReactNode;\n}\n\nexport interface NavbarProps {\n  /** لوگو و نام */\n  brand: ReactNode;\n  /** @default \"/\" */\n  brandHref?: string;\n  links?: NavbarLink[];\n  /** دکمه‌ها و آیکون‌های سمت چپ (در RTL)، مثل ورود یا جستجو */\n  actions?: ReactNode;\n  /** چسبیدن به بالای صفحه؛ با اسکرول سایه و پس‌زمینهٔ مات می‌گیرد @default true */\n  sticky?: boolean;\n  /** نشان صفحهٔ فعلی: «line» خط زیر پیوند، «pill» قرص رنگی @default \"line\" */\n  variant?: \"line\" | \"pill\";\n  /** پیوندها وسط نوار، لوگو و دکمه‌ها در دو طرف */\n  centered?: boolean;\n  /** نوار شناور: جدا از لبه‌ها با گوشهٔ گرد و سایه */\n  floating?: boolean;\n  /** بی‌رنگ روی تصویر یا هیرو؛ با sticky، پس از اسکرول پس‌زمینه می‌گیرد */\n  transparent?: boolean;\n  /** زیر این عرض پیوندها به منوی کشو می‌روند: sm ۶۴۰، md ۷۶۸، lg ۱۰۲۴ پیکسل @default \"md\" */\n  collapseBelow?: \"sm\" | \"md\" | \"lg\";\n  /** محتوای اضافهٔ پایین منوی گوشی، مثل دکمهٔ ورود */\n  menuFooter?: ReactNode;\n  /** کامپوننت پیوند، مثل Link در Next.js @default \"a\" */\n  linkAs?: ElementType;\n  /** @default \"ناوبری اصلی\" */\n  \"aria-label\"?: string;\n  className?: string;\n}\n\nconst useIsoLayout = typeof window === \"undefined\" ? useEffect : useLayoutEffect;\n\n/**\n * نوار ناوبری بالای سایت: لوگو، پیوندها با نشانگر لغزان، دکمه‌ها\n * و در گوشی منوی کشو با همان پیوندها. با اسکرول سایه می‌گیرد.\n */\nexport function Navbar({\n  brand, brandHref = \"/\", links = [], actions, sticky = true, variant = \"line\", centered, floating, transparent, collapseBelow = \"md\", menuFooter, linkAs, \"aria-label\": ariaLabel, className,\n}: NavbarProps) {\n  const { messages: M } = useKashi();\n  const label = ariaLabel ?? M.navbar.label;\n  const A = linkAs ?? \"a\";\n  const [open, setOpen] = useState(false);\n  const [scrolled, setScrolled] = useState(false);\n  const nav = useRef<HTMLElement>(null);\n\n  // نشانگر لغزان: روی پیوند زیر نشانگر یا پیوند فعلی\n  const place = (el: HTMLElement | null) => {\n    const n = nav.current;\n    if (!n) return;\n    if (!el) { n.style.setProperty(\"--_pill-o\", \"0\"); return; }\n    n.style.setProperty(\"--_pill-x\", `${el.offsetLeft}px`);\n    n.style.setProperty(\"--_pill-w\", `${el.offsetWidth}px`);\n    n.style.setProperty(\"--_pill-o\", \"1\");\n  };\n  const toCurrent = () => place(nav.current?.querySelector<HTMLElement>('[aria-current=\"page\"]') ?? null);\n  useIsoLayout(() => {\n    toCurrent();\n    const n = nav.current;\n    if (!n || typeof ResizeObserver === \"undefined\") return;\n    const ro = new ResizeObserver(toCurrent);\n    ro.observe(n);\n    return () => ro.disconnect();\n  }, [links]);\n\n  useEffect(() => {\n    // فقط نوار چسبیده با اسکرول صفحه تغییر می‌کند؛ نوار غیرچسبیده همراه محتوا بالا می‌رود\n    if (!sticky) return;\n    const on = () => setScrolled(window.scrollY > 4);\n    on();\n    window.addEventListener(\"scroll\", on, { passive: true });\n    return () => window.removeEventListener(\"scroll\", on);\n  }, [sticky]);\n\n  const item = (l: NavbarLink, i: number, cls: string, onClick?: () => void) => (\n    <A key={i} href={l.href} className={cls} aria-current={l.current ? \"page\" : undefined} onClick={onClick}>\n      {l.icon && <span className=\"k-navbar__icon\" aria-hidden=\"true\">{l.icon}</span>}\n      <span>{l.label}</span>\n      {l.badge && <span className=\"k-navbar__badge\">{l.badge}</span>}\n    </A>\n  );\n\n  return (\n    <header\n      className={cx(\"k-navbar\", sticky && \"k-navbar--sticky\", variant === \"pill\" && \"k-navbar--pill\", centered && \"k-navbar--centered\", floating && \"k-navbar--floating\", transparent && \"k-navbar--transparent\", `k-navbar--collapse-${collapseBelow}`, className)}\n      data-scrolled={scrolled || undefined}\n    >\n      <div className=\"k-navbar__inner\">\n        <A href={brandHref} className=\"k-navbar__brand\">{brand}</A>\n        {links.length > 0 && (\n          <nav ref={nav} className=\"k-navbar__nav\" aria-label={label} onPointerLeave={toCurrent}>\n            <span className=\"k-navbar__pill\" aria-hidden=\"true\" />\n            {links.map((l, i) => (\n              <A\n                key={i}\n                href={l.href}\n                className=\"k-navbar__link\"\n                aria-current={l.current ? \"page\" : undefined}\n                onPointerEnter={(e: { currentTarget: HTMLElement }) => place(e.currentTarget)}\n                onFocus={(e: { currentTarget: HTMLElement }) => place(e.currentTarget)}\n                onBlur={toCurrent}\n              >\n                {l.icon && <span className=\"k-navbar__icon\" aria-hidden=\"true\">{l.icon}</span>}\n                <span>{l.label}</span>\n                {l.badge && <span className=\"k-navbar__badge\">{l.badge}</span>}\n              </A>\n            ))}\n          </nav>\n        )}\n        <div className=\"k-navbar__actions\">\n          {actions}\n          {links.length > 0 && (\n            <button type=\"button\" className=\"k-btn k-btn--tertiary k-btn--icon k-btn--sm k-navbar__menu\" aria-label={M.navbar.menu} aria-haspopup=\"dialog\" aria-expanded={open} onClick={() => setOpen(true)}>\n              <svg viewBox=\"0 0 20 20\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.5} strokeLinecap=\"round\" aria-hidden=\"true\"><path d=\"M3.75 5.5h12.5M3.75 10h12.5M3.75 14.5h12.5\" /></svg>\n            </button>\n          )}\n        </div>\n      </div>\n      {links.length > 0 && (\n        <Drawer open={open} onOpenChange={setOpen} side=\"start\" size=\"sm\" title={M.navbar.menuTitle} footer={menuFooter} className=\"k-navbar__drawer\">\n          <nav className=\"k-navbar__mobile\" aria-label={label}>\n            {links.map((l, i) => item(l, i, \"k-navbar__mobile-link\", () => setOpen(false)))}\n          </nav>\n        </Drawer>\n      )}\n    </header>\n  );\n}\n"
    }
  ]
}