{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "breadcrumb-separator",
  "type": "registry:ui",
  "title": "Breadcrumb Separator",
  "description": "Breadcrumb navigation with customizable separators (chevron, slash, dot, arrow, dash).",
  "dependencies": [
    "lucide-react"
  ],
  "files": [
    {
      "path": "registry/ruixenui/breadcrumb-separator.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\n/* ═══════════════════════════════════════════════════════════\n   Breadcrumb Separator — Reactive hover-cascade breadcrumb.\n\n   The separator isn't decoration — it's a directional cue.\n   When you hover a parent item, you're expressing intent to\n   \"go back.\" Items after the hovered one fade and shift right,\n   as if they'd be popped from the navigation stack. The\n   separator adjacent to the hovered item scales with a spring\n   overshoot, reinforcing the spatial metaphor.\n\n   Two transition curves:\n     • Separator scale: cubic-bezier(0.34, 1.56, 0.64, 1) — spring\n     • Fade cascade: cubic-bezier(0.16, 1, 0.3, 1) — smooth ease-out\n   ═══════════════════════════════════════════════════════════ */\n\ntype SeparatorType = \"chevron\" | \"slash\" | \"dot\" | \"arrow\" | \"dash\";\n\ninterface BreadcrumbItem {\n  label: string;\n  href?: string;\n}\n\ninterface BreadcrumbSeparatorProps {\n  items: BreadcrumbItem[];\n  separator?: SeparatorType;\n  className?: string;\n}\n\nfunction renderSeparator(type: SeparatorType) {\n  if (type === \"chevron\") {\n    return (\n      <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\n        <path\n          d=\"M5.25 3.5L8.75 7L5.25 10.5\"\n          stroke=\"currentColor\"\n          strokeWidth=\"1.5\"\n          strokeLinecap=\"round\"\n          strokeLinejoin=\"round\"\n        />\n      </svg>\n    );\n  }\n\n  const chars: Record<string, string> = {\n    slash: \"/\",\n    dot: \"·\",\n    arrow: \"→\",\n    dash: \"—\",\n  };\n\n  return <span className=\"text-xs leading-none\">{chars[type]}</span>;\n}\n\nexport default function BreadcrumbSeparator({\n  items,\n  separator = \"chevron\",\n  className,\n}: BreadcrumbSeparatorProps) {\n  const [hoveredIndex, setHoveredIndex] = React.useState<number | null>(null);\n\n  if (items.length === 0) return null;\n\n  return (\n    <nav aria-label=\"Breadcrumb\" className={cn(\"\", className)}>\n      <ol\n        className=\"flex flex-wrap items-center gap-1\"\n        onMouseLeave={() => setHoveredIndex(null)}\n      >\n        {items.map((item, index) => {\n          const isLast = index === items.length - 1;\n          const isLink = !!item.href && !isLast;\n          const isHovered = hoveredIndex === index;\n          const isFaded = hoveredIndex !== null && index > hoveredIndex;\n          const isSeparatorActive = hoveredIndex === index;\n\n          return (\n            <li\n              key={index}\n              className=\"inline-flex items-center\"\n              onMouseEnter={() => {\n                if (isLink) {\n                  setHoveredIndex(index);\n                } else {\n                  setHoveredIndex(null);\n                }\n              }}\n              style={{\n                opacity: isFaded ? 0.4 : 1,\n                transform: isFaded ? \"translateX(2px)\" : \"translateX(0)\",\n                transition:\n                  \"opacity 0.2s cubic-bezier(0.16, 1, 0.3, 1), transform 0.25s cubic-bezier(0.16, 1, 0.3, 1)\",\n              }}\n            >\n              {isLink ? (\n                <a\n                  href={item.href}\n                  className={cn(\n                    \"rounded-md px-1.5 py-0.5 text-sm transition-colors duration-200\",\n                    isHovered\n                      ? \"text-foreground\"\n                      : \"text-muted-foreground hover:text-foreground\",\n                  )}\n                >\n                  {item.label}\n                </a>\n              ) : (\n                <span\n                  className={cn(\n                    \"rounded-md px-1.5 py-0.5 text-sm\",\n                    isLast\n                      ? \"font-medium text-foreground\"\n                      : \"text-muted-foreground\",\n                  )}\n                  {...(isLast ? { \"aria-current\": \"page\" as const } : {})}\n                >\n                  {item.label}\n                </span>\n              )}\n              {!isLast && (\n                <span\n                  className=\"ml-1 mr-0.5 inline-flex items-center text-muted-foreground\"\n                  aria-hidden=\"true\"\n                  style={{\n                    transform: isSeparatorActive ? \"scale(1.2)\" : \"scale(1)\",\n                    transition:\n                      \"transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.2s ease\",\n                  }}\n                >\n                  {renderSeparator(separator)}\n                </span>\n              )}\n            </li>\n          );\n        })}\n      </ol>\n    </nav>\n  );\n}\n\nexport {\n  BreadcrumbSeparator as BreadcrumbSeparatorComponent,\n  type BreadcrumbSeparatorProps,\n};\n",
      "type": "registry:ui",
      "target": "components/ruixen/breadcrumb-separator.tsx"
    }
  ]
}