import React, { forwardRef, isValidElement, useState } from 'react'; import { Pressable, Text, View } from 'react-native'; import { breadcrumbStyles } from './Breadcrumb.styles'; import type { BreadcrumbProps, BreadcrumbItem as BreadcrumbItemType } from './types'; import Icon from '../Icon'; import type { IconName } from '../Icon/icon-types'; import Menu from '../Menu/Menu.native'; import type { MenuItem } from '../Menu/types'; import type { IdealystElement } from '../utils/refTypes'; interface BreadcrumbItemProps { item: BreadcrumbItemType; isLast: boolean; size: BreadcrumbProps['size']; intent: BreadcrumbProps['intent']; itemStyle?: BreadcrumbProps['itemStyle']; } const BreadcrumbItem: React.FC = ({ item, isLast, size, intent, itemStyle }) => { const isDisabled = item.disabled || false; breadcrumbStyles.useVariants({ size, intent, active: isLast, disabled: isDisabled, }); const iconSize = (breadcrumbStyles.icon as any).width || 16; const renderIcon = () => { if (!item.icon) return null; if (typeof item.icon === 'string') { return ( ); } else if (isValidElement(item.icon)) { return item.icon; } return null; }; const content = ( {item.icon && {renderIcon()}} {item.label} ); if (!!item.onPress && !item.disabled) { return ( {content} ); } return {content}; }; interface BreadcrumbSeparatorProps { separator: React.ReactNode; size: BreadcrumbProps['size']; separatorStyle?: BreadcrumbProps['separatorStyle']; } const BreadcrumbSeparator: React.FC = ({ separator, size, separatorStyle }) => { breadcrumbStyles.useVariants({ size }); if (typeof separator === 'string') { return {separator}; } return {separator}; }; interface BreadcrumbEllipsisProps { size: BreadcrumbProps['size']; intent: BreadcrumbProps['intent']; } const BreadcrumbEllipsis: React.FC = ({ size, intent }) => { breadcrumbStyles.useVariants({ size, intent }); return ( ); }; const Breadcrumb = forwardRef(({ items, separator = '/', maxItems, intent = 'primary', size = 'md', style, itemStyle, separatorStyle, testID, responsive = false, minVisibleItems = 3, id, }, ref) => { const [menuOpen, setMenuOpen] = useState(false); breadcrumbStyles.useVariants({ size, intent }); // Handle responsive collapsing let displayItems = items; let collapsedItems: BreadcrumbItemType[] = []; let showMenu = false; let showEllipsis = false; if (responsive && items.length > minVisibleItems) { // Responsive mode: show first item + menu + last (minVisibleItems - 2) items showMenu = true; const lastItemCount = Math.max(1, minVisibleItems - 2); displayItems = [ items[0], ...items.slice(-lastItemCount), ]; collapsedItems = items.slice(1, -(lastItemCount)); } else if (maxItems && items.length > maxItems) { // Legacy truncation mode showEllipsis = true; const firstItems = items.slice(0, 1); const lastItems = items.slice(-(maxItems - 1)); displayItems = [...firstItems, ...lastItems]; } // Convert collapsed breadcrumb items to menu items const menuItems: MenuItem[] = collapsedItems.map((item, index) => ({ id: `collapsed-${index}`, label: item.label, onClick: item.onPress, disabled: item.disabled, icon: typeof item.icon === 'string' ? (item.icon as IconName) : undefined, })); return ( {displayItems.map((item, index) => { const isLast = index === displayItems.length - 1; const shouldShowEllipsis = showEllipsis && index === 1; const shouldShowMenu = showMenu && index === 1; return ( {shouldShowEllipsis && ( <> )} {shouldShowMenu && ( <> )} {!isLast && ( )} ); })} ); }); Breadcrumb.displayName = 'Breadcrumb'; export default Breadcrumb;