@box/blueprint-web 12.135.1 → 12.136.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,5 +6,5 @@ interface BreadcrumbDropdownProps {
6
6
  onPageLinkClick: (id: string) => void;
7
7
  size: 'xsmall' | 'small' | 'medium' | 'large';
8
8
  }
9
- export declare function BreadcrumbDropdown({ crumbsToRender, iconButton, onPageLinkClick, size, listRef, }: BreadcrumbDropdownProps): import("react/jsx-runtime").JSX.Element;
9
+ export declare function BreadcrumbDropdown({ crumbsToRender, iconButton, listRef, onPageLinkClick, size, }: BreadcrumbDropdownProps): import("react/jsx-runtime").JSX.Element;
10
10
  export {};
@@ -1,17 +1,17 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import { useCallback } from 'react';
3
3
  import { PointerRight } from '@box/blueprint-web-assets/icons/Fill';
4
+ import { EllipsizableText } from '../ellipsizable-text/ellipsizable-text.js';
4
5
  import { DropdownMenu } from '../primitives/dropdown-menu/index.js';
5
- import { Text } from '../text/text.js';
6
6
  import { getSeparatorSize } from './utils.js';
7
7
  import styles from './breadcrumb.module.js';
8
8
 
9
9
  function BreadcrumbDropdown({
10
10
  crumbsToRender,
11
11
  iconButton,
12
+ listRef,
12
13
  onPageLinkClick,
13
- size,
14
- listRef
14
+ size
15
15
  }) {
16
16
  const handlePageLinkClick = useCallback(crumbId => () => {
17
17
  onPageLinkClick(crumbId);
@@ -27,8 +27,10 @@ function BreadcrumbDropdown({
27
27
  className: styles.dropdownContent,
28
28
  children: crumbsToRender.map(crumb => jsx(DropdownMenu.Item, {
29
29
  onSelect: handlePageLinkClick(crumb.id),
30
- children: jsx(Text, {
30
+ children: jsx(EllipsizableText, {
31
31
  as: "span",
32
+ lineClamp: 1,
33
+ tooltipSide: "bottom",
32
34
  children: crumb.name
33
35
  })
34
36
  }, crumb.id))
@@ -1,50 +1,82 @@
1
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import noop from 'lodash/noop';
2
3
  import { forwardRef, useRef } from 'react';
3
4
  import { FolderTree, PointerRight } from '@box/blueprint-web-assets/icons/Fill';
4
- import { Ellipsis } from '@box/blueprint-web-assets/icons/Medium';
5
5
  import { Home } from '@box/blueprint-web-assets/icons/MediumFilled';
6
- import noop from 'lodash/noop';
7
- import { IconButton } from '../primitives/icon-button/icon-button.js';
8
6
  import { useBreakpoint, Breakpoint } from '../utils/useBreakpoint.js';
9
- import { BreadcrumbDropdown } from './breadcrumb-dropdown.js';
10
- import { PageLink } from './page-link.js';
7
+ import { EllipsisTruncationView } from './ellipsis-truncation-view.js';
8
+ import { FolderTreeTruncationView } from './folder-tree-truncation-view.js';
9
+ import { FullView } from './full-view.js';
10
+ import { MobileView } from './mobile-view.js';
11
11
  import { useFolderTreeTruncation } from './useFolderTreeTruncation.js';
12
12
  import { getSeparatorSize } from './utils.js';
13
13
  import styles from './breadcrumb.module.js';
14
14
 
15
+ const ELLIPSIS_TRUNCATION_THRESHOLD = 7;
15
16
  const Breadcrumb = /*#__PURE__*/forwardRef((props, forwardedRef) => {
16
17
  const {
17
18
  breadcrumbAriaLabel,
18
19
  crumbs,
19
- truncatedLinksIconAriaLabel,
20
- rootIconAriaLabel,
21
- rootIconVariant,
22
20
  isInteractive = true,
23
21
  isResponsiveEnabled,
22
+ onPageLinkClick = noop,
23
+ rootIconAriaLabel,
24
+ rootIconVariant,
24
25
  size = 'medium',
26
+ truncatedLinksIconAriaLabel,
25
27
  truncationMethod = 'ellipsis',
26
- onPageLinkClick = noop,
27
28
  ...rest
28
29
  } = props;
29
- // Responsive detection: mobile/tablet takes priority over consumer-controlled truncationMethod
30
30
  const breakpoint = useBreakpoint();
31
31
  const isMobile = isResponsiveEnabled || breakpoint <= Breakpoint.Medium;
32
- // If there are more than 7 crumbs, break up crumbs into first link, ellipsis icon button, and current page ancestor
33
- const shouldUseEllipsisTruncation = !isMobile && truncationMethod === 'ellipsis' && crumbs && crumbs.length > 7;
34
- // Get the current page (last crumb) and all ancestors (all crumbs except last)
35
- const currentPage = crumbs[crumbs.length - 1];
36
- const ancestorCrumbs = crumbs.slice(0, -1);
37
- // Folder-tree truncation: detect overflow and show up to 3 visible crumbs
38
32
  const breadcrumbListRef = useRef(null);
39
- const isFolderTreeTruncationEnabled = !isMobile && truncationMethod === 'folder-tree';
40
33
  const {
34
+ ellipsizeLastCrumb,
35
+ iconButtonRef,
41
36
  isTruncationRequired,
42
- visibleCrumbCount,
43
- iconButtonRef
44
- } = useFolderTreeTruncation(breadcrumbListRef, crumbs, isFolderTreeTruncationEnabled);
45
- const shouldUseFolderTreeTruncation = isFolderTreeTruncationEnabled && isTruncationRequired && crumbs;
46
- const visibleCrumbs = shouldUseFolderTreeTruncation ? crumbs.slice(-visibleCrumbCount) : [];
47
- const hiddenCrumbs = shouldUseFolderTreeTruncation ? crumbs.slice(0, -visibleCrumbCount) : [];
37
+ visibleCrumbCount
38
+ } = useFolderTreeTruncation(breadcrumbListRef, crumbs, isMobile);
39
+ if (!crumbs || crumbs.length === 0) {
40
+ return null;
41
+ }
42
+ // Responsive detection: mobile/tablet takes priority over consumer-controlled truncationMethod
43
+ let breadcrumbList;
44
+ if (isMobile) {
45
+ breadcrumbList = jsx(MobileView, {
46
+ crumbs: crumbs,
47
+ isInteractive: isInteractive,
48
+ onPageLinkClick: onPageLinkClick,
49
+ size: size,
50
+ truncatedLinksIconAriaLabel: truncatedLinksIconAriaLabel
51
+ });
52
+ } else if (truncationMethod === 'ellipsis' && crumbs.length > ELLIPSIS_TRUNCATION_THRESHOLD) {
53
+ breadcrumbList = jsx(EllipsisTruncationView, {
54
+ crumbs: crumbs,
55
+ isInteractive: isInteractive,
56
+ onPageLinkClick: onPageLinkClick,
57
+ size: size,
58
+ truncatedLinksIconAriaLabel: truncatedLinksIconAriaLabel
59
+ });
60
+ } else if (truncationMethod === 'folder-tree' && isTruncationRequired) {
61
+ breadcrumbList = jsx(FolderTreeTruncationView, {
62
+ crumbs: crumbs,
63
+ ellipsizeLastCrumb: ellipsizeLastCrumb,
64
+ iconButtonRef: iconButtonRef,
65
+ isInteractive: isInteractive,
66
+ onPageLinkClick: onPageLinkClick,
67
+ size: size,
68
+ truncatedLinksIconAriaLabel: truncatedLinksIconAriaLabel,
69
+ visibleCrumbCount: visibleCrumbCount
70
+ });
71
+ } else {
72
+ breadcrumbList = jsx(FullView, {
73
+ crumbs: crumbs,
74
+ ellipsizeLastCrumb: ellipsizeLastCrumb,
75
+ isInteractive: isInteractive,
76
+ onPageLinkClick: onPageLinkClick,
77
+ size: size
78
+ });
79
+ }
48
80
  return jsx("nav", {
49
81
  ref: forwardedRef,
50
82
  "aria-label": breadcrumbAriaLabel,
@@ -59,84 +91,12 @@ const Breadcrumb = /*#__PURE__*/forwardRef((props, forwardedRef) => {
59
91
  "aria-label": rootIconAriaLabel
60
92
  }) : jsx(FolderTree, {
61
93
  "aria-label": rootIconAriaLabel
62
- }), rootIconVariant && jsx(PointerRight, {
94
+ }), jsx(PointerRight, {
63
95
  height: getSeparatorSize(size),
64
96
  role: "presentation",
65
97
  width: getSeparatorSize(size)
66
98
  })]
67
- }), isMobile && crumbs && currentPage && jsxs(Fragment, {
68
- children: [ancestorCrumbs.length > 0 && jsx(BreadcrumbDropdown, {
69
- crumbsToRender: ancestorCrumbs,
70
- iconButton: jsx(IconButton, {
71
- "aria-label": truncatedLinksIconAriaLabel,
72
- icon: FolderTree,
73
- size: "small"
74
- }),
75
- onPageLinkClick: onPageLinkClick,
76
- size: size
77
- }), jsx(PageLink, {
78
- crumb: currentPage,
79
- isInteractive: isInteractive,
80
- isLast: true,
81
- onPageLinkClick: onPageLinkClick,
82
- size: size
83
- })]
84
- }), shouldUseEllipsisTruncation && jsxs(Fragment, {
85
- children: [jsx(PageLink, {
86
- crumb: crumbs[0],
87
- isInteractive: isInteractive,
88
- isLast: false,
89
- onPageLinkClick: onPageLinkClick,
90
- size: size
91
- }), jsx(BreadcrumbDropdown, {
92
- crumbsToRender: crumbs.slice(1, crumbs.length - 2),
93
- iconButton: jsx(IconButton, {
94
- "aria-label": truncatedLinksIconAriaLabel,
95
- icon: Ellipsis,
96
- size: "small"
97
- }),
98
- onPageLinkClick: onPageLinkClick,
99
- size: size
100
- }), jsx(PageLink, {
101
- crumb: crumbs[crumbs.length - 2],
102
- isInteractive: isInteractive,
103
- isLast: false,
104
- onPageLinkClick: onPageLinkClick,
105
- size: size
106
- }), jsx(PageLink, {
107
- crumb: currentPage,
108
- isInteractive: isInteractive,
109
- isLast: true,
110
- onPageLinkClick: onPageLinkClick,
111
- size: size
112
- })]
113
- }), shouldUseFolderTreeTruncation && jsxs(Fragment, {
114
- children: [jsx(BreadcrumbDropdown, {
115
- crumbsToRender: hiddenCrumbs,
116
- iconButton: jsx(IconButton, {
117
- "aria-label": truncatedLinksIconAriaLabel,
118
- icon: FolderTree,
119
- size: "small"
120
- }),
121
- listRef: iconButtonRef,
122
- onPageLinkClick: onPageLinkClick,
123
- size: size
124
- }), visibleCrumbs.map((crumb, index) => jsx(PageLink, {
125
- crumb: crumb,
126
- isInteractive: isInteractive,
127
- isLast: index === visibleCrumbs.length - 1,
128
- onPageLinkClick: onPageLinkClick,
129
- size: size
130
- }, crumb.id))]
131
- }), !isMobile && !shouldUseEllipsisTruncation && !shouldUseFolderTreeTruncation && crumbs?.map((crumb, index) => {
132
- return jsx(PageLink, {
133
- crumb: crumb,
134
- isInteractive: isInteractive,
135
- isLast: index === crumbs.length - 1,
136
- onPageLinkClick: onPageLinkClick,
137
- size: size
138
- }, crumb.id);
139
- })]
99
+ }), breadcrumbList]
140
100
  })
141
101
  });
142
102
  });
@@ -1,4 +1,4 @@
1
1
  import '../index.css';
2
- var styles = {"container":"bp_breadcrumb_module_container--ee92d","breadcrumb":"bp_breadcrumb_module_breadcrumb--ee92d","pageLink":"bp_breadcrumb_module_pageLink--ee92d","linkWithHover":"bp_breadcrumb_module_linkWithHover--ee92d","dropdownContent":"bp_breadcrumb_module_dropdownContent--ee92d"};
2
+ var styles = {"container":"bp_breadcrumb_module_container--335e0","breadcrumb":"bp_breadcrumb_module_breadcrumb--335e0","pageLink":"bp_breadcrumb_module_pageLink--335e0","linkWithHover":"bp_breadcrumb_module_linkWithHover--335e0","dropdownContent":"bp_breadcrumb_module_dropdownContent--335e0"};
3
3
 
4
4
  export { styles as default };
@@ -0,0 +1,2 @@
1
+ import { type BreadcrumbViewProps } from './types';
2
+ export declare const EllipsisTruncationView: ({ crumbs, isInteractive, onPageLinkClick, size, truncatedLinksIconAriaLabel, }: BreadcrumbViewProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,42 @@
1
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
+ import { Ellipsis } from '@box/blueprint-web-assets/icons/Medium';
3
+ import { IconButton } from '../primitives/icon-button/icon-button.js';
4
+ import { BreadcrumbDropdown } from './breadcrumb-dropdown.js';
5
+ import { PageLink } from './page-link.js';
6
+
7
+ const EllipsisTruncationView = ({
8
+ crumbs,
9
+ isInteractive,
10
+ onPageLinkClick,
11
+ size,
12
+ truncatedLinksIconAriaLabel
13
+ }) => {
14
+ const middleCrumbs = crumbs.slice(1, -2);
15
+ const lastTwoCrumbs = crumbs.slice(-2);
16
+ return jsxs(Fragment, {
17
+ children: [jsx(PageLink, {
18
+ crumb: crumbs[0],
19
+ isInteractive: isInteractive,
20
+ isLast: false,
21
+ onPageLinkClick: onPageLinkClick,
22
+ size: size
23
+ }), jsx(BreadcrumbDropdown, {
24
+ crumbsToRender: middleCrumbs,
25
+ iconButton: jsx(IconButton, {
26
+ "aria-label": truncatedLinksIconAriaLabel,
27
+ icon: Ellipsis,
28
+ size: "small"
29
+ }),
30
+ onPageLinkClick: onPageLinkClick,
31
+ size: size
32
+ }), lastTwoCrumbs.map((crumb, index) => jsx(PageLink, {
33
+ crumb: crumb,
34
+ isInteractive: isInteractive,
35
+ isLast: index === lastTwoCrumbs.length - 1,
36
+ onPageLinkClick: onPageLinkClick,
37
+ size: size
38
+ }, crumb.id))]
39
+ });
40
+ };
41
+
42
+ export { EllipsisTruncationView };
@@ -0,0 +1,2 @@
1
+ import { type FolderTreeTruncationViewProps } from './types';
2
+ export declare const FolderTreeTruncationView: ({ crumbs, ellipsizeLastCrumb, iconButtonRef, isInteractive, onPageLinkClick, size, truncatedLinksIconAriaLabel, visibleCrumbCount, }: FolderTreeTruncationViewProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,41 @@
1
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
+ import { FolderTree } from '@box/blueprint-web-assets/icons/Fill';
3
+ import { IconButton } from '../primitives/icon-button/icon-button.js';
4
+ import { BreadcrumbDropdown } from './breadcrumb-dropdown.js';
5
+ import { PageLink } from './page-link.js';
6
+
7
+ const FolderTreeTruncationView = ({
8
+ crumbs,
9
+ ellipsizeLastCrumb,
10
+ iconButtonRef,
11
+ isInteractive,
12
+ onPageLinkClick,
13
+ size,
14
+ truncatedLinksIconAriaLabel,
15
+ visibleCrumbCount
16
+ }) => {
17
+ const visibleCrumbs = crumbs.slice(-visibleCrumbCount);
18
+ const hiddenCrumbs = crumbs.slice(0, -visibleCrumbCount);
19
+ return jsxs(Fragment, {
20
+ children: [jsx(BreadcrumbDropdown, {
21
+ crumbsToRender: hiddenCrumbs,
22
+ iconButton: jsx(IconButton, {
23
+ "aria-label": truncatedLinksIconAriaLabel,
24
+ icon: FolderTree,
25
+ size: "small"
26
+ }),
27
+ listRef: iconButtonRef,
28
+ onPageLinkClick: onPageLinkClick,
29
+ size: size
30
+ }), visibleCrumbs.map((crumb, index) => jsx(PageLink, {
31
+ crumb: crumb,
32
+ ellipsizeLastCrumb: ellipsizeLastCrumb,
33
+ isInteractive: isInteractive,
34
+ isLast: index === visibleCrumbs.length - 1,
35
+ onPageLinkClick: onPageLinkClick,
36
+ size: size
37
+ }, crumb.id))]
38
+ });
39
+ };
40
+
41
+ export { FolderTreeTruncationView };
@@ -0,0 +1,2 @@
1
+ import { type BreadcrumbViewProps } from './types';
2
+ export declare const FullView: ({ crumbs, ellipsizeLastCrumb, isInteractive, onPageLinkClick, size, }: Omit<BreadcrumbViewProps, "truncatedLinksIconAriaLabel">) => import("react/jsx-runtime").JSX.Element[];
@@ -0,0 +1,19 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { PageLink } from './page-link.js';
3
+
4
+ const FullView = ({
5
+ crumbs,
6
+ ellipsizeLastCrumb,
7
+ isInteractive,
8
+ onPageLinkClick,
9
+ size
10
+ }) => crumbs.map((crumb, index) => jsx(PageLink, {
11
+ crumb: crumb,
12
+ ellipsizeLastCrumb: ellipsizeLastCrumb,
13
+ isInteractive: isInteractive,
14
+ isLast: index === crumbs.length - 1,
15
+ onPageLinkClick: onPageLinkClick,
16
+ size: size
17
+ }, crumb.id));
18
+
19
+ export { FullView };
@@ -0,0 +1,2 @@
1
+ import { type BreadcrumbViewProps } from './types';
2
+ export declare const MobileView: ({ crumbs, isInteractive, onPageLinkClick, size, truncatedLinksIconAriaLabel, }: BreadcrumbViewProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,37 @@
1
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
+ import { FolderTree } from '@box/blueprint-web-assets/icons/Fill';
3
+ import { IconButton } from '../primitives/icon-button/icon-button.js';
4
+ import { BreadcrumbDropdown } from './breadcrumb-dropdown.js';
5
+ import { PageLink } from './page-link.js';
6
+
7
+ const MobileView = ({
8
+ crumbs,
9
+ isInteractive,
10
+ onPageLinkClick,
11
+ size,
12
+ truncatedLinksIconAriaLabel
13
+ }) => {
14
+ const currentPage = crumbs[crumbs.length - 1];
15
+ const hiddenCrumbs = crumbs.slice(0, -1);
16
+ return jsxs(Fragment, {
17
+ children: [hiddenCrumbs.length > 0 && jsx(BreadcrumbDropdown, {
18
+ crumbsToRender: hiddenCrumbs,
19
+ iconButton: jsx(IconButton, {
20
+ "aria-label": truncatedLinksIconAriaLabel,
21
+ icon: FolderTree,
22
+ size: "small"
23
+ }),
24
+ onPageLinkClick: onPageLinkClick,
25
+ size: size
26
+ }), jsx(PageLink, {
27
+ crumb: currentPage,
28
+ ellipsizeLastCrumb: true,
29
+ isInteractive: isInteractive,
30
+ isLast: true,
31
+ onPageLinkClick: onPageLinkClick,
32
+ size: size
33
+ })]
34
+ });
35
+ };
36
+
37
+ export { MobileView };
@@ -1,17 +1,2 @@
1
- import { type Crumb } from './types';
2
- /**
3
- * A page link represents a combination of an optional folder icon, a single crumb, and a separator.
4
- */
5
- export interface PageLinkProps {
6
- /** The crumb to display in the page link. */
7
- crumb: Crumb;
8
- /** Whether the page link is the last crumb in the breadcrumb. */
9
- isLast: boolean;
10
- /** Whether the page link is interactive. */
11
- isInteractive: boolean;
12
- /** The callback to call when the page link is clicked. */
13
- onPageLinkClick: (id: string) => void;
14
- /** The text size of the page link. */
15
- size: 'xsmall' | 'small' | 'medium' | 'large';
16
- }
17
- export declare const PageLink: ({ crumb, isLast, isInteractive, onPageLinkClick, size }: PageLinkProps) => import("react/jsx-runtime").JSX.Element;
1
+ import { type PageLinkProps } from './types';
2
+ export declare const PageLink: ({ crumb, ellipsizeLastCrumb, isInteractive, isLast, onPageLinkClick, size, }: PageLinkProps) => import("react/jsx-runtime").JSX.Element;
@@ -1,25 +1,34 @@
1
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import { useCallback } from 'react';
3
3
  import { PointerRight } from '@box/blueprint-web-assets/icons/Fill';
4
+ import { EllipsizableText } from '../ellipsizable-text/ellipsizable-text.js';
4
5
  import { Link } from '../primitives/link/link.js';
5
6
  import { Text } from '../text/text.js';
6
- import styles from './breadcrumb.module.js';
7
7
  import { getBoldTextVariantFromSize, getTextVariantFromSize, getSeparatorSize } from './utils.js';
8
+ import styles from './breadcrumb.module.js';
8
9
 
9
10
  const PageLink = ({
10
11
  crumb,
11
- isLast,
12
+ ellipsizeLastCrumb = false,
12
13
  isInteractive,
14
+ isLast,
13
15
  onPageLinkClick,
14
16
  size
15
17
  }) => {
16
18
  const handlePageLinkClick = useCallback(() => {
17
19
  onPageLinkClick(crumb.id);
18
- }, [onPageLinkClick, crumb.id]);
20
+ }, [crumb.id, onPageLinkClick]);
19
21
  if (isLast) {
20
22
  return jsx("li", {
21
23
  className: styles.pageLink,
22
- children: jsx(Text, {
24
+ children: ellipsizeLastCrumb ? jsx(EllipsizableText, {
25
+ "aria-current": "page",
26
+ as: "span",
27
+ color: "textOnLightDefault",
28
+ lineClamp: 1,
29
+ variant: getBoldTextVariantFromSize(size),
30
+ children: crumb.name
31
+ }) : jsx(Text, {
23
32
  "aria-current": "page",
24
33
  as: "span",
25
34
  color: "textOnLightDefault",
@@ -23,7 +23,8 @@ export type BreadcrumbProps = {
23
23
  size?: 'xsmall' | 'small' | 'medium' | 'large';
24
24
  /** Aria label for the icon button when breadcrumb is truncated. */
25
25
  truncatedLinksIconAriaLabel: string;
26
- /** Controls behavior when there are too many crumbs to display.
26
+ /**
27
+ * Controls behavior when there are too many crumbs to display.
27
28
  * Ellipsis shows the crumbs at the beginning and end, with an ellipsis icon in between.
28
29
  * Folder-tree dynamically detects container overflow and shows up to 3 visible crumbs with a folder tree icon dropdown.
29
30
  */
@@ -36,3 +37,53 @@ export interface rootIconProps {
36
37
  /** Determines which icon is displayed at the root. */
37
38
  rootIconVariant: 'home' | 'folder-tree';
38
39
  }
40
+ export interface BreadcrumbViewProps {
41
+ crumbs: Crumb[];
42
+ ellipsizeLastCrumb?: boolean;
43
+ isInteractive: boolean;
44
+ onPageLinkClick: (id: string) => void;
45
+ size: NonNullable<BreadcrumbProps['size']>;
46
+ truncatedLinksIconAriaLabel: string;
47
+ }
48
+ export interface FolderTreeTruncationViewProps extends BreadcrumbViewProps {
49
+ iconButtonRef: React.RefObject<HTMLLIElement>;
50
+ visibleCrumbCount: number;
51
+ }
52
+ /**
53
+ * A page link represents a combination of an optional folder icon, a single crumb, and a separator.
54
+ */
55
+ export interface PageLinkProps {
56
+ /** The crumb to display in the page link. */
57
+ crumb: Crumb;
58
+ /** Whether the last crumb should be ellipsized. */
59
+ ellipsizeLastCrumb?: boolean;
60
+ /** Whether the page link is interactive. */
61
+ isInteractive: boolean;
62
+ /** Whether the page link is the last crumb in the breadcrumb. */
63
+ isLast: boolean;
64
+ /** The callback to call when the page link is clicked. */
65
+ onPageLinkClick: (id: string) => void;
66
+ /** The text size of the page link. */
67
+ size: 'xsmall' | 'small' | 'medium' | 'large';
68
+ }
69
+ export interface TruncationState {
70
+ /** Whether the last crumb should be ellipsized (when it doesn't fit even with truncation) */
71
+ ellipsizeLastCrumb: boolean;
72
+ /** Whether the breadcrumb content would exceed the container width IF no truncation was being applied */
73
+ isTruncationRequired: boolean;
74
+ /** Number of visible crumbs (not in dropdown) to show (1-3) */
75
+ visibleCrumbCount: number;
76
+ }
77
+ export interface FolderTreeTruncationResult extends TruncationState {
78
+ /** Ref to attach to the icon button container for width measurement */
79
+ iconButtonRef: React.RefObject<HTMLLIElement>;
80
+ }
81
+ export interface PerformTruncationParams {
82
+ container: HTMLOListElement;
83
+ crumbCount: number;
84
+ iconButtonRef: React.RefObject<HTMLLIElement>;
85
+ isTruncationRequired: boolean;
86
+ measuredIconButtonWidth: React.MutableRefObject<number>;
87
+ setState: React.Dispatch<React.SetStateAction<TruncationState>>;
88
+ storedCrumbWidths: React.MutableRefObject<number[]>;
89
+ }
@@ -1,25 +1,12 @@
1
- import { type Crumb } from './types';
2
- interface FolderTreeTruncationState {
3
- /** Whether the breadcrumb content would exceed the container width IF no truncation was being applied */
4
- isTruncationRequired: boolean;
5
- /** Number of visible crumbs (not in dropdown) to show (1-3) */
6
- visibleCrumbCount: number;
7
- }
8
- interface FolderTreeTruncationResult extends FolderTreeTruncationState {
9
- /** Ref to attach to the icon button container li element for width measurement */
10
- iconButtonRef: React.RefObject<HTMLLIElement>;
11
- }
1
+ import { type Crumb, type FolderTreeTruncationResult } from './types';
12
2
  /**
13
- * Hook which calculates how many crumbs can be displayed when folder-tree truncation is enabled.
3
+ * Hook that calculates optimal breadcrumb truncation for folder-tree display.
14
4
  *
15
- * ## Truncation Rules
16
- * - **≤3 crumbs**: Render all crumbs first, detect overflow, truncate only if needed
17
- * - **>3 crumbs**: Render truncated state immediately, show icon button + up to 3 crumbs
5
+ * Uses a cascading fallback strategy to show as many crumbs as possible without
6
+ * text ellipsis, falling back to ellipsis only as a last resort.
18
7
  *
19
- * @param containerRef - Ref to the main ol element
20
- * @param crumbs - Array of breadcrumb items
21
- * @param isEnabled - Whether folder-tree truncation is enabled. Can be false when responsive behavior is triggered
22
- * @returns Object containing wouldCrumbsOverflow, visibleCrumbCount, and iconButtonRef
8
+ * @param containerRef - Ref to the breadcrumb list container (ol element)
9
+ * @param crumbs - Array of breadcrumb items to display
10
+ * @param isMobile - Whether the breadcrumb is on a mobile device
23
11
  */
24
- export declare const useFolderTreeTruncation: (containerRef: React.RefObject<HTMLOListElement>, crumbs: Crumb[], isEnabled: boolean) => FolderTreeTruncationResult;
25
- export {};
12
+ export declare const useFolderTreeTruncation: (containerRef: React.RefObject<HTMLOListElement>, crumbs: Crumb[], isMobile: boolean) => FolderTreeTruncationResult;