import React from 'react'; import { Link } from '../link'; import { Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from './breadcrumb'; export interface BreadcrumbItem { label: string; href?: string; /** * Force render as current page (non-interactive, aria-current="page"). * By default only the last item without href is treated as current page. */ isCurrentPage?: boolean; icon?: React.ReactNode; } export interface BreadcrumbNavigationProps { items: BreadcrumbItem[]; separator?: React.ReactNode; /** * Max visible items (excluding the ellipsis slot) before collapsing. * Must be >= 2. Defaults to 5. */ maxItems?: number; className?: string; } type DisplayEntry = | { type: 'item'; item: BreadcrumbItem; originalIndex: number } | { type: 'ellipsis' }; export const BreadcrumbNavigation: React.FC = ({ items, separator, maxItems = 5, className, }) => { if (!items || items.length === 0) return null; const clampedMax = Math.max(2, maxItems); const entries: DisplayEntry[] = (() => { if (items.length <= clampedMax) { return items.map((item, i) => ({ type: 'item' as const, item, originalIndex: i })); } const tailCount = Math.max(1, clampedMax - 2); const tail = items.slice(-tailCount).map((item, i) => ({ type: 'item' as const, item, originalIndex: items.length - tailCount + i, })); return [ { type: 'item' as const, item: items[0]!, originalIndex: 0 }, { type: 'ellipsis' as const }, ...tail, ]; })(); const resolveIsCurrentPage = (item: BreadcrumbItem, originalIndex: number): boolean => { if (item.isCurrentPage !== undefined) return item.isCurrentPage; return originalIndex === items.length - 1; }; const renderItem = (item: BreadcrumbItem, originalIndex: number) => { const current = resolveIsCurrentPage(item, originalIndex); const content = ( <> {item.icon && {item.icon}} {item.label} ); if (current) { return ( {content} ); } return ( {item.href ? ( {content} ) : ( {content} )} ); }; return ( {entries.map((entry, displayIndex) => { const isFirst = displayIndex === 0; if (entry.type === 'ellipsis') { return ( {separator} ); } return ( {!isFirst && {separator}} {renderItem(entry.item, entry.originalIndex)} ); })} ); }; BreadcrumbNavigation.displayName = 'BreadcrumbNavigation';