import * as React from "react"; import { ChevronRight } from "lucide-react"; import { cn } from "@/lib/utils"; export function getValidChildren(children: React.ReactNode) { return React.Children.toArray(children).filter((child) => React.isValidElement(child), ) as React.ReactElement[]; } export interface BreadcrumbProps extends React.ComponentPropsWithoutRef<"nav"> { /* The visual separator between each breadcrumb item */ separator?: React.ReactNode; /** * If `true`, adds a separator between each breadcrumb item. * @default true */ addSeparator?: boolean; } export const Breadcrumb = React.forwardRef( ( { children, className, separator = , addSeparator = true, ...props }, forwardedRef, ) => { const validChildren = getValidChildren(children); const clones = validChildren.map((child, index) => { return React.cloneElement(child, { addSeparator, separator, isLastChild: validChildren.length === index + 1, }); }); return ( ); }, ); Breadcrumb.displayName = "Breadcrumb"; export interface BreadcrumbItemProps extends BreadcrumbProps { /** * If `true`, indicates that the breadcrumb item is active, adds * `aria-current=page` and renders a `span` */ isCurrentPage?: boolean; isLastChild?: boolean; } export const BreadcrumbItem = React.forwardRef< HTMLLIElement, BreadcrumbItemProps >( ( { children, className, isCurrentPage, isLastChild, separator, addSeparator, ...props }, forwardedRef, ) => { const validChildren = getValidChildren(children); const clones = validChildren.map((child) => { if (child.type === BreadcrumbLink) { return React.cloneElement(child, { isCurrentPage }); } if (child.type === BreadcrumbSeparator) { return React.cloneElement(child, { children: separator || child.props.children, }); } return child; }); return (
  • {clones} {!isLastChild && addSeparator && ( {separator} )}
  • ); }, ); BreadcrumbItem.displayName = "BreadcrumbItem"; export interface BreadcrumbLinkProps extends React.ComponentPropsWithoutRef<"a">, Pick { as?: React.ElementType; } export const BreadcrumbLink = React.forwardRef< HTMLAnchorElement, BreadcrumbLinkProps >(({ className, as: asComp, isCurrentPage, ...props }, forwardedRef) => { const Comp = (isCurrentPage ? "span" : asComp || "a") as "a"; return ( ); }); BreadcrumbLink.displayName = "BreadcrumbLink"; export type BreadcrumbSeparatorProps = React.ComponentPropsWithoutRef<"span">; export const BreadcrumbSeparator = React.forwardRef< HTMLSpanElement, BreadcrumbSeparatorProps >(({ className, ...props }, forwardedRef) => { return ( ); }); BreadcrumbSeparator.displayName = "BreadcrumbSeparator";