{"version":3,"file":"breadcrumb.mjs","names":[],"sources":["../../../../package/common/breadcrumb/breadcrumb.tsx"],"sourcesContent":["import { useState } from 'react';\nimport type { MouseEvent, ReactElement } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faChevronRight, faEllipsis } from '@fortawesome/free-solid-svg-icons';\n\nimport InteractableDiv from '../interactableDiv';\nimport ActionIcon from '../actionIcon';\nimport Popover from '../popover';\nimport { PopoverAlign, PopoverPlacement } from '../popover/popover.types';\nimport { useComponentDefaults, useLabels } from '../configProvider';\nimport type { BreadcrumbItem, BreadcrumbLabels, BreadcrumbProps } from './breadcrumb.types';\n\nimport styles from './breadcrumb.module.pcss';\nimport { renderIcon } from '../utils/renderIcon';\nimport { useLinkClick } from '../utils/navigation';\n\ninterface IndexedItem {\n  item: BreadcrumbItem;\n  index: number;\n}\n\nconst DEFAULT_LABELS: Required<BreadcrumbLabels> = {\n  showHidden: 'Show hidden breadcrumbs',\n};\n\nfunction getGroups(items: BreadcrumbItem[], maxItems?: number) {\n  const indexed = items.map((item, index) => ({ item, index }));\n  if (!maxItems || items.length <= maxItems) {\n    return { leading: indexed, hidden: [] as IndexedItem[], trailing: [] as IndexedItem[] };\n  }\n\n  const trailingCount = Math.max(1, maxItems - 2);\n  const hiddenCount = items.length - 1 - trailingCount;\n  if (hiddenCount <= 0) {\n    return { leading: indexed, hidden: [] as IndexedItem[], trailing: [] as IndexedItem[] };\n  }\n\n  return {\n    leading: indexed.slice(0, 1),\n    hidden: indexed.slice(1, 1 + hiddenCount),\n    trailing: indexed.slice(1 + hiddenCount),\n  };\n}\n\nfunction Breadcrumb(props: BreadcrumbProps): ReactElement {\n  const {\n    items = [],\n    separator,\n    maxItems,\n    'aria-label': ariaLabel = 'Breadcrumb',\n    className,\n    style,\n    classNames,\n    styles: slotStyles,\n    labels,\n    ...rest\n  } = useComponentDefaults('Breadcrumb', props);\n  const text = useLabels('Breadcrumb', labels, DEFAULT_LABELS);\n  const followLink = useLinkClick();\n\n  const [isHiddenMenuOpen, setIsHiddenMenuOpen] = useState(false);\n  const { leading, hidden, trailing } = getGroups(items, maxItems);\n  const lastIndex = items.length - 1;\n\n  function renderSeparatorAfter(index: number) {\n    if (index === lastIndex) return null;\n    return (\n      <span className={cx(styles.breadcrumbSeparator, classNames?.separator)} style={slotStyles?.separator}>\n        {separator ?? <FontAwesomeIcon icon={faChevronRight} />}\n      </span>\n    );\n  }\n\n  function renderItem({ item, index }: IndexedItem) {\n    return (\n      <li key={item.id ?? index} className={cx(styles.breadcrumbItem, classNames?.item)} style={slotStyles?.item}>\n        {renderCrumb(item, index === lastIndex, styles, classNames, slotStyles, followLink)}\n        {renderSeparatorAfter(index)}\n      </li>\n    );\n  }\n\n  return (\n    <nav\n      {...rest}\n      aria-label={ariaLabel}\n      className={cx(styles.breadcrumb, classNames?.root, className)}\n      style={{ ...style, ...slotStyles?.root }}\n    >\n      <ol className={cx(styles.breadcrumbList, classNames?.list)} style={slotStyles?.list}>\n        {leading.map(renderItem)}\n\n        {hidden.length > 0 && (\n          <li className={cx(styles.breadcrumbItem, classNames?.item)} style={slotStyles?.item}>\n            <Popover\n              isOpen={isHiddenMenuOpen}\n              onOpenChange={setIsHiddenMenuOpen}\n              placement={PopoverPlacement.Bottom}\n              align={PopoverAlign.Start}\n              // The list brings its own padding and width.\n              constrainWidth={false}\n              classNames={{ panel: styles.breadcrumbHiddenPanel }}\n              content={\n                <ul className={cx(styles.breadcrumbHiddenList, classNames?.hiddenList)} style={slotStyles?.hiddenList}>\n                  {hidden.map(({ item, index }) => (\n                    <li\n                      key={item.id ?? index}\n                      className={cx(styles.breadcrumbHiddenItem, classNames?.hiddenItem)}\n                      style={slotStyles?.hiddenItem}\n                    >\n                      {renderCrumb(\n                        {\n                          ...item,\n                          onClick: (event) => {\n                            item.onClick?.(event);\n                            setIsHiddenMenuOpen(false);\n                          },\n                        },\n                        false,\n                        styles,\n                        classNames,\n                        slotStyles,\n                        followLink,\n                      )}\n                    </li>\n                  ))}\n                </ul>\n              }\n            >\n              <ActionIcon\n                icon={faEllipsis}\n                color='var(--text-dark)'\n                title={text.showHidden}\n                aria-label={text.showHidden}\n                aria-expanded={isHiddenMenuOpen}\n                className={cx(styles.breadcrumbEllipsis, classNames?.ellipsis)}\n                style={slotStyles?.ellipsis}\n              />\n            </Popover>\n            {renderSeparatorAfter(hidden[hidden.length - 1].index)}\n          </li>\n        )}\n\n        {trailing.map(renderItem)}\n      </ol>\n    </nav>\n  );\n}\n\nfunction renderCrumb(\n  item: BreadcrumbItem,\n  isCurrent: boolean,\n  styles: Record<string, string>,\n  classNames: BreadcrumbProps['classNames'],\n  slotStyles: BreadcrumbProps['styles'],\n  followLink: (event: MouseEvent<HTMLAnchorElement>) => void,\n) {\n  const content = (\n    <>\n      {item.icon\n        ? renderIcon(item.icon, {\n            className: cx(styles.breadcrumbIcon, classNames?.icon),\n            style: slotStyles?.icon,\n          })\n        : null}\n      {item.label}\n    </>\n  );\n\n  if (isCurrent) {\n    return (\n      <span\n        aria-current='page'\n        className={cx(styles.breadcrumbCurrent, classNames?.current)}\n        style={slotStyles?.current}\n      >\n        {content}\n      </span>\n    );\n  }\n\n  if (item.disabled) {\n    return (\n      <span\n        className={cx(styles.breadcrumbLink, styles.breadcrumbLinkDisabled, classNames?.link)}\n        style={slotStyles?.link}\n      >\n        {content}\n      </span>\n    );\n  }\n\n  if (item.href) {\n    return (\n      <a\n        href={item.href}\n        onClick={(event) => {\n          item.onClick?.(event);\n          followLink(event);\n        }}\n        className={cx(styles.breadcrumbLink, classNames?.link)}\n        style={slotStyles?.link}\n      >\n        {content}\n      </a>\n    );\n  }\n\n  if (item.onClick) {\n    return (\n      <InteractableDiv\n        onClick={item.onClick}\n        className={cx(styles.breadcrumbLink, classNames?.link)}\n        style={slotStyles?.link}\n      >\n        {content}\n      </InteractableDiv>\n    );\n  }\n\n  return (\n    <span\n      className={cx(styles.breadcrumbLink, styles.breadcrumbLinkDisabled, classNames?.link)}\n      style={slotStyles?.link}\n    >\n      {content}\n    </span>\n  );\n}\n\nexport default Breadcrumb;\n"],"mappings":"6wBAsBA,IAAM,EAA6C,CACjD,WAAY,yBACd,EAEA,SAAS,EAAU,EAAyB,EAAmB,CAC7D,IAAM,EAAU,EAAM,KAAK,EAAM,KAAW,CAAE,OAAM,OAAM,EAAE,EAC5D,GAAI,CAAC,GAAY,EAAM,QAAU,EAC/B,MAAO,CAAE,QAAS,EAAS,OAAQ,CAAC,EAAoB,SAAU,CAAC,CAAmB,EAGxF,IAAM,EAAgB,KAAK,IAAI,EAAG,EAAW,CAAC,EACxC,EAAc,EAAM,OAAS,EAAI,EAKvC,OAJI,GAAe,EACV,CAAE,QAAS,EAAS,OAAQ,CAAC,EAAoB,SAAU,CAAC,CAAmB,EAGjF,CACL,QAAS,EAAQ,MAAM,EAAG,CAAC,EAC3B,OAAQ,EAAQ,MAAM,EAAG,EAAI,CAAW,EACxC,SAAU,EAAQ,MAAM,EAAI,CAAW,CACzC,CACF,CAEA,SAAS,EAAW,EAAsC,CACxD,GAAM,CACJ,QAAQ,CAAC,EACT,YACA,WACA,aAAc,EAAY,aAC1B,YACA,QACA,aACA,OAAQ,EACR,SACA,GAAG,GACD,EAAqB,aAAc,CAAK,EACtC,EAAO,EAAU,aAAc,EAAQ,CAAc,EACrD,EAAa,EAAa,EAE1B,CAAC,EAAkB,GAAuB,EAAS,EAAK,EACxD,CAAE,UAAS,SAAQ,YAAa,EAAU,EAAO,CAAQ,EACzD,EAAY,EAAM,OAAS,EAEjC,SAAS,EAAqB,EAAe,CAE3C,OADI,IAAU,EAAkB,KAE9B,EAAC,OAAD,CAAM,UAAW,EAAG,EAAO,oBAAqB,GAAY,SAAS,EAAG,MAAO,GAAY,UACxF,SAAA,GAAa,EAAC,EAAD,CAAiB,KAAM,CAAiB,CAAA,CAClD,CAAA,CAEV,CAEA,SAAS,EAAW,CAAE,OAAM,SAAsB,CAChD,OACE,EAAC,KAAD,CAA2B,UAAW,EAAG,EAAO,eAAgB,GAAY,IAAI,EAAG,MAAO,GAAY,KAAtG,SAAA,CACG,EAAY,EAAM,IAAU,EAAW,EAAQ,EAAY,EAAY,CAAU,EACjF,EAAqB,CAAK,CACzB,CAHK,EAAA,EAAK,IAAM,CAGhB,CAER,CAEA,OACE,EAAC,MAAD,CACE,GAAI,EACJ,aAAY,EACZ,UAAW,EAAG,EAAO,WAAY,GAAY,KAAM,CAAS,EAC5D,MAAO,CAAE,GAAG,EAAO,GAAG,GAAY,IAAK,EAEvC,SAAA,EAAC,KAAD,CAAI,UAAW,EAAG,EAAO,eAAgB,GAAY,IAAI,EAAG,MAAO,GAAY,KAA/E,SAAA,CACG,EAAQ,IAAI,CAAU,EAEtB,EAAO,OAAS,GACf,EAAC,KAAD,CAAI,UAAW,EAAG,EAAO,eAAgB,GAAY,IAAI,EAAG,MAAO,GAAY,KAA/E,SAAA,CACE,EAAC,EAAD,CACE,OAAQ,EACR,aAAc,EACd,UAAW,EAAiB,OAC5B,MAAO,EAAa,MAEpB,eAAgB,GAChB,WAAY,CAAE,MAAO,EAAO,qBAAsB,EAClD,QACE,EAAC,KAAD,CAAI,UAAW,EAAG,EAAO,qBAAsB,GAAY,UAAU,EAAG,MAAO,GAAY,WACxF,SAAA,EAAO,KAAK,CAAE,OAAM,WACnB,EAAC,KAAD,CAEE,UAAW,EAAG,EAAO,qBAAsB,GAAY,UAAU,EACjE,MAAO,GAAY,WAElB,SAAA,EACC,CACE,GAAG,EACH,QAAU,GAAU,CAClB,EAAK,UAAU,CAAK,EACpB,EAAoB,EAAK,CAC3B,CACF,EACA,GACA,EACA,EACA,EACA,CACF,CACE,EAlBG,EAAK,IAAM,CAkBd,CACL,CACC,CAAA,EAGN,SAAA,EAAC,EAAD,CACE,KAAM,EACN,MAAM,mBACN,MAAO,EAAK,WACZ,aAAY,EAAK,WACjB,gBAAe,EACf,UAAW,EAAG,EAAO,mBAAoB,GAAY,QAAQ,EAC7D,MAAO,GAAY,QACpB,CAAA,CACM,CAAA,EACR,EAAqB,EAAO,EAAO,OAAS,EAAE,CAAC,KAAK,CACnD,IAGL,EAAS,IAAI,CAAU,CACtB,GACD,CAAA,CAET,CAEA,SAAS,EACP,EACA,EACA,EACA,EACA,EACA,EACA,CACA,IAAM,EACJ,EAAA,EAAA,CAAA,SAAA,CACG,EAAK,KACF,EAAW,EAAK,KAAM,CACpB,UAAW,EAAG,EAAO,eAAgB,GAAY,IAAI,EACrD,MAAO,GAAY,IACrB,CAAC,EACD,KACH,EAAK,KACN,CAAA,CAAA,EAsDJ,OAnDI,EAEA,EAAC,OAAD,CACE,eAAa,OACb,UAAW,EAAG,EAAO,kBAAmB,GAAY,OAAO,EAC3D,MAAO,GAAY,QAElB,SAAA,CACG,CAAA,EAIN,EAAK,SAEL,EAAC,OAAD,CACE,UAAW,EAAG,EAAO,eAAgB,EAAO,uBAAwB,GAAY,IAAI,EACpF,MAAO,GAAY,KAElB,SAAA,CACG,CAAA,EAIN,EAAK,KAEL,EAAC,IAAD,CACE,KAAM,EAAK,KACX,QAAU,GAAU,CAClB,EAAK,UAAU,CAAK,EACpB,EAAW,CAAK,CAClB,EACA,UAAW,EAAG,EAAO,eAAgB,GAAY,IAAI,EACrD,MAAO,GAAY,KAElB,SAAA,CACA,CAAA,EAIH,EAAK,QAEL,EAAC,EAAD,CACE,QAAS,EAAK,QACd,UAAW,EAAG,EAAO,eAAgB,GAAY,IAAI,EACrD,MAAO,GAAY,KAElB,SAAA,CACc,CAAA,EAKnB,EAAC,OAAD,CACE,UAAW,EAAG,EAAO,eAAgB,EAAO,uBAAwB,GAAY,IAAI,EACpF,MAAO,GAAY,KAElB,SAAA,CACG,CAAA,CAEV"}