@carbon/ibm-products 2.71.1 → 2.72.0-rc.0
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.
- package/css/carbon.css +50 -0
- package/css/carbon.css.map +1 -1
- package/css/index-full-carbon.css +560 -185
- package/css/index-full-carbon.css.map +1 -1
- package/css/index-full-carbon.min.css +1 -1
- package/css/index-full-carbon.min.css.map +1 -1
- package/css/index-without-carbon-released-only.css +132 -1
- package/css/index-without-carbon-released-only.css.map +1 -1
- package/css/index-without-carbon-released-only.min.css +1 -1
- package/css/index-without-carbon-released-only.min.css.map +1 -1
- package/css/index-without-carbon.css +570 -245
- package/css/index-without-carbon.css.map +1 -1
- package/css/index-without-carbon.min.css +1 -1
- package/css/index-without-carbon.min.css.map +1 -1
- package/css/index.css +358 -33
- package/css/index.css.map +1 -1
- package/css/index.min.css +1 -1
- package/css/index.min.css.map +1 -1
- package/es/components/{BigNumbers/BigNumbers.d.ts → BigNumber/BigNumber.d.ts} +5 -5
- package/es/components/{BigNumbers/BigNumbers.js → BigNumber/BigNumber.js} +12 -12
- package/es/components/BigNumber/BigNumberSkeleton.d.ts +17 -0
- package/es/components/{BigNumbers/BigNumbersSkeleton.js → BigNumber/BigNumberSkeleton.js} +16 -16
- package/es/components/{BigNumbers → BigNumber}/constants.d.ts +3 -3
- package/es/components/{BigNumbers → BigNumber}/constants.js +6 -6
- package/es/components/{BigNumbers → BigNumber}/index.d.ts +2 -2
- package/es/components/Coachmark/next/Coachmark/Coachmark.d.ts +72 -0
- package/es/components/Coachmark/next/Coachmark/Coachmark.js +185 -0
- package/es/components/Coachmark/next/Coachmark/CoachmarkBeacon/CoachmarkBeacon.d.ts +44 -0
- package/es/components/Coachmark/next/Coachmark/CoachmarkBeacon/index.d.ts +8 -0
- package/es/components/Coachmark/next/Coachmark/CoachmarkBubble/CoachmarkBubble.d.ts +38 -0
- package/es/components/Coachmark/next/Coachmark/CoachmarkBubble/CoachmarkBubble.js +125 -0
- package/es/components/Coachmark/next/Coachmark/CoachmarkBubble/CoachmarkBubbleHeader.d.ts +24 -0
- package/es/components/Coachmark/next/Coachmark/CoachmarkBubble/CoachmarkBubbleHeader.js +25 -0
- package/es/components/Coachmark/next/Coachmark/CoachmarkBubble/index.d.ts +10 -0
- package/es/components/Coachmark/next/Coachmark/CoachmarkContent.d.ts +34 -0
- package/es/components/Coachmark/next/Coachmark/CoachmarkContent.js +118 -0
- package/es/components/Coachmark/next/Coachmark/ContentBody.d.ts +23 -0
- package/es/components/Coachmark/next/Coachmark/ContentBody.js +37 -0
- package/es/components/Coachmark/next/Coachmark/ContentHeader.d.ts +21 -0
- package/es/components/Coachmark/next/Coachmark/ContentHeader.js +89 -0
- package/{lib/components/BigNumbers → es/components/Coachmark/next/Coachmark}/index.d.ts +2 -2
- package/es/components/CoachmarkBeacon/CoachmarkBeacon.js +0 -1
- package/es/components/ConditionBuilder/ConditionBuilderContent/ConditionBuilderContent.js +2 -1
- package/es/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItem.js +11 -5
- package/es/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemDate/ConditionBuilderItemDate.js +1 -1
- package/es/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemNumber/ConditionBuilderItemNumber.js +11 -4
- package/es/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemOption/ItemOption.js +2 -2
- package/es/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemOption/ItemOptionForValueField.js +1 -1
- package/es/components/ConditionBuilder/ConditionGroupBuilder/ConditionGroupBuilder.js +42 -3
- package/es/components/ConditionBuilder/ConditionPreview/ConditionPreview.d.ts +3 -1
- package/es/components/ConditionBuilder/ConditionPreview/ConditionPreview.js +5 -3
- package/es/components/ConditionBuilder/utils/useTranslations.js +1 -1
- package/es/components/EditInPlace/EditInPlace.js +0 -3
- package/es/components/EmptyStates/EmptyState.d.ts +2 -2
- package/es/components/EmptyStates/EmptyState.js +2 -8
- package/es/components/FilterPanel/FilterPanelGroup/index.d.ts +1 -0
- package/es/components/InterstitialScreen/InterstitialScreen.d.ts +1 -25
- package/es/components/InterstitialScreen/InterstitialScreen.js +3 -19
- package/es/components/InterstitialScreen/InterstitialScreenBody.d.ts +1 -1
- package/es/components/InterstitialScreen/InterstitialScreenBody.js +1 -1
- package/es/components/InterstitialScreen/InterstitialScreenFooter.d.ts +1 -1
- package/es/components/InterstitialScreen/InterstitialScreenFooter.js +1 -1
- package/es/components/InterstitialScreen/InterstitialScreenHeader.d.ts +6 -0
- package/es/components/InterstitialScreen/InterstitialScreenHeader.js +1 -1
- package/es/components/InterstitialScreen/_story-assets/InterstitialScreenViewModule/InterstitialScreenViewModule.d.ts +1 -1
- package/es/components/InterstitialScreen/context.d.ts +31 -0
- package/es/components/InterstitialScreen/context.js +18 -0
- package/es/components/InterstitialScreen/index.d.ts +3 -2
- package/es/components/NotificationsPanel/NotificationsPanel.js +36 -13
- package/es/components/PageHeader/PageHeader.d.ts +2 -1
- package/es/components/PageHeader/PageHeader.js +2 -1
- package/es/components/PageHeader/next/PageHeader.d.ts +18 -3
- package/es/components/PageHeader/next/PageHeader.js +260 -12
- package/es/components/PageHeader/next/context.d.ts +25 -0
- package/es/components/PageHeader/next/context.js +30 -0
- package/es/components/PageHeader/next/index.d.ts +3 -3
- package/es/components/PageHeader/next/overflowHandler.d.ts +95 -0
- package/es/components/PageHeader/next/overflowHandler.js +162 -0
- package/es/components/PageHeader/next/utils.d.ts +19 -0
- package/es/components/PageHeader/next/utils.js +68 -0
- package/es/components/ProductiveCard/ProductiveCard.js +2 -1
- package/es/components/ScrollGradient/ScrollGradient.js +1 -2
- package/es/components/SidePanel/SidePanel.d.ts +4 -0
- package/es/components/SidePanel/SidePanel.js +8 -2
- package/es/components/Tearsheet/TearsheetShell.js +8 -5
- package/es/components/TruncatedText/TruncatedText.d.ts +48 -0
- package/es/components/TruncatedText/TruncatedText.js +86 -0
- package/es/components/TruncatedText/index.d.ts +7 -0
- package/es/components/TruncatedText/useTruncatedText.d.ts +16 -0
- package/es/components/TruncatedText/useTruncatedText.js +41 -0
- package/es/components/index.d.ts +3 -1
- package/es/global/js/hooks/useOverflowString.d.ts +2 -2
- package/es/global/js/hooks/useResizeObserver.d.ts +1 -1
- package/es/global/js/package-settings.d.ts +2 -1
- package/es/global/js/package-settings.js +3 -2
- package/es/global/js/utils/checkForOverflow.js +21 -0
- package/es/global/js/utils/makeDraggable/index.d.ts +1 -0
- package/es/global/js/utils/makeDraggable/makeDraggable.d.ts +19 -0
- package/es/global/js/utils/makeDraggable/makeDraggable.js +91 -0
- package/es/global/js/utils/makeDraggable/makeDraggable.stories.d.ts +22 -0
- package/es/index.js +3 -1
- package/es/node_modules/@floating-ui/core/dist/floating-ui.core.js +592 -0
- package/es/node_modules/@floating-ui/dom/dist/floating-ui.dom.js +713 -0
- package/es/node_modules/@floating-ui/react-dom/dist/floating-ui.react-dom.js +95 -0
- package/es/node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.js +161 -0
- package/es/node_modules/@floating-ui/utils/dist/floating-ui.utils.js +142 -0
- package/es/settings.d.ts +2 -1
- package/lib/components/{BigNumbers/BigNumbers.d.ts → BigNumber/BigNumber.d.ts} +5 -5
- package/lib/components/{BigNumbers/BigNumbers.js → BigNumber/BigNumber.js} +11 -11
- package/lib/components/BigNumber/BigNumberSkeleton.d.ts +17 -0
- package/lib/components/{BigNumbers/BigNumbersSkeleton.js → BigNumber/BigNumberSkeleton.js} +15 -15
- package/lib/components/{BigNumbers → BigNumber}/constants.d.ts +3 -3
- package/lib/components/{BigNumbers → BigNumber}/constants.js +6 -6
- package/lib/components/BigNumber/index.d.ts +7 -0
- package/lib/components/Coachmark/Coachmark.js +2 -2
- package/lib/components/Coachmark/next/Coachmark/Coachmark.d.ts +72 -0
- package/lib/components/Coachmark/next/Coachmark/Coachmark.js +189 -0
- package/lib/components/Coachmark/next/Coachmark/CoachmarkBeacon/CoachmarkBeacon.d.ts +44 -0
- package/lib/components/Coachmark/next/Coachmark/CoachmarkBeacon/index.d.ts +8 -0
- package/lib/components/Coachmark/next/Coachmark/CoachmarkBubble/CoachmarkBubble.d.ts +38 -0
- package/lib/components/Coachmark/next/Coachmark/CoachmarkBubble/CoachmarkBubble.js +127 -0
- package/lib/components/Coachmark/next/Coachmark/CoachmarkBubble/CoachmarkBubbleHeader.d.ts +24 -0
- package/lib/components/Coachmark/next/Coachmark/CoachmarkBubble/CoachmarkBubbleHeader.js +27 -0
- package/lib/components/Coachmark/next/Coachmark/CoachmarkBubble/index.d.ts +10 -0
- package/lib/components/Coachmark/next/Coachmark/CoachmarkContent.d.ts +34 -0
- package/lib/components/Coachmark/next/Coachmark/CoachmarkContent.js +122 -0
- package/lib/components/Coachmark/next/Coachmark/ContentBody.d.ts +23 -0
- package/lib/components/Coachmark/next/Coachmark/ContentBody.js +41 -0
- package/lib/components/Coachmark/next/Coachmark/ContentHeader.d.ts +21 -0
- package/lib/components/Coachmark/next/Coachmark/ContentHeader.js +93 -0
- package/lib/components/Coachmark/next/Coachmark/index.d.ts +7 -0
- package/lib/components/CoachmarkBeacon/CoachmarkBeacon.js +0 -1
- package/lib/components/CoachmarkFixed/CoachmarkFixed.js +2 -2
- package/lib/components/CoachmarkStack/CoachmarkStack.js +2 -2
- package/lib/components/CoachmarkStack/CoachmarkStackHome.js +2 -2
- package/lib/components/ConditionBuilder/ConditionBuilderContent/ConditionBuilderContent.js +2 -1
- package/lib/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItem.js +11 -5
- package/lib/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemDate/ConditionBuilderItemDate.js +1 -1
- package/lib/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemNumber/ConditionBuilderItemNumber.js +11 -4
- package/lib/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemOption/ItemOption.js +2 -2
- package/lib/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemOption/ItemOptionForValueField.js +1 -1
- package/lib/components/ConditionBuilder/ConditionGroupBuilder/ConditionGroupBuilder.js +41 -2
- package/lib/components/ConditionBuilder/ConditionPreview/ConditionPreview.d.ts +3 -1
- package/lib/components/ConditionBuilder/ConditionPreview/ConditionPreview.js +5 -3
- package/lib/components/ConditionBuilder/utils/useTranslations.js +1 -1
- package/lib/components/EditInPlace/EditInPlace.js +0 -3
- package/lib/components/EmptyStates/EmptyState.d.ts +2 -2
- package/lib/components/EmptyStates/EmptyState.js +2 -8
- package/lib/components/FilterPanel/FilterPanelGroup/index.d.ts +1 -0
- package/lib/components/InterstitialScreen/InterstitialScreen.d.ts +1 -25
- package/lib/components/InterstitialScreen/InterstitialScreen.js +6 -25
- package/lib/components/InterstitialScreen/InterstitialScreenBody.d.ts +1 -1
- package/lib/components/InterstitialScreen/InterstitialScreenBody.js +6 -6
- package/lib/components/InterstitialScreen/InterstitialScreenFooter.d.ts +1 -1
- package/lib/components/InterstitialScreen/InterstitialScreenFooter.js +9 -9
- package/lib/components/InterstitialScreen/InterstitialScreenHeader.d.ts +6 -0
- package/lib/components/InterstitialScreen/InterstitialScreenHeader.js +5 -5
- package/lib/components/InterstitialScreen/_story-assets/InterstitialScreenViewModule/InterstitialScreenViewModule.d.ts +1 -1
- package/lib/components/InterstitialScreen/context.d.ts +31 -0
- package/lib/components/InterstitialScreen/context.js +21 -0
- package/lib/components/InterstitialScreen/index.d.ts +3 -2
- package/lib/components/NotificationsPanel/NotificationsPanel.js +36 -13
- package/lib/components/PageHeader/PageHeader.d.ts +2 -1
- package/lib/components/PageHeader/PageHeader.js +2 -1
- package/lib/components/PageHeader/next/PageHeader.d.ts +18 -3
- package/lib/components/PageHeader/next/PageHeader.js +261 -7
- package/lib/components/PageHeader/next/context.d.ts +25 -0
- package/lib/components/PageHeader/next/context.js +33 -0
- package/lib/components/PageHeader/next/index.d.ts +3 -3
- package/lib/components/PageHeader/next/overflowHandler.d.ts +95 -0
- package/lib/components/PageHeader/next/overflowHandler.js +166 -0
- package/lib/components/PageHeader/next/utils.d.ts +19 -0
- package/lib/components/PageHeader/next/utils.js +71 -0
- package/lib/components/ProductiveCard/ProductiveCard.js +2 -1
- package/lib/components/ScrollGradient/ScrollGradient.js +1 -2
- package/lib/components/SidePanel/SidePanel.d.ts +4 -0
- package/lib/components/SidePanel/SidePanel.js +8 -2
- package/lib/components/Tearsheet/TearsheetShell.js +8 -5
- package/lib/components/TruncatedText/TruncatedText.d.ts +48 -0
- package/lib/components/TruncatedText/TruncatedText.js +86 -0
- package/lib/components/TruncatedText/index.d.ts +7 -0
- package/lib/components/TruncatedText/useTruncatedText.d.ts +16 -0
- package/lib/components/TruncatedText/useTruncatedText.js +45 -0
- package/lib/components/index.d.ts +3 -1
- package/lib/global/js/hooks/useOverflowString.d.ts +2 -2
- package/lib/global/js/hooks/usePortalTarget.js +2 -2
- package/lib/global/js/hooks/useResizeObserver.d.ts +1 -1
- package/lib/global/js/package-settings.d.ts +2 -1
- package/lib/global/js/package-settings.js +3 -2
- package/lib/global/js/utils/checkForOverflow.js +23 -0
- package/lib/global/js/utils/makeDraggable/index.d.ts +1 -0
- package/lib/global/js/utils/makeDraggable/makeDraggable.d.ts +19 -0
- package/lib/global/js/utils/makeDraggable/makeDraggable.js +93 -0
- package/lib/global/js/utils/makeDraggable/makeDraggable.stories.d.ts +22 -0
- package/lib/index.js +10 -3
- package/lib/node_modules/@floating-ui/core/dist/floating-ui.core.js +600 -0
- package/lib/node_modules/@floating-ui/dom/dist/floating-ui.dom.js +722 -0
- package/lib/node_modules/@floating-ui/react-dom/dist/floating-ui.react-dom.js +102 -0
- package/lib/node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.js +182 -0
- package/lib/node_modules/@floating-ui/utils/dist/floating-ui.utils.js +164 -0
- package/lib/settings.d.ts +2 -1
- package/package.json +9 -10
- package/scss/components/{BigNumbers/_big-numbers.scss → BigNumber/_big-number.scss} +5 -5
- package/scss/components/{BigNumbers → BigNumber}/_carbon-imports.scss +3 -3
- package/scss/components/{BigNumbers → BigNumber}/_index-with-carbon.scss +2 -2
- package/scss/components/{BigNumbers → BigNumber}/_index.scss +2 -2
- package/scss/components/Card/_card.scss +2 -0
- package/scss/components/Coachmark/_bubble.scss +62 -0
- package/scss/components/Coachmark/_coachmark-beacon.scss +164 -0
- package/scss/components/Coachmark/_coachmark.scss +15 -0
- package/scss/components/ConditionBuilder/_condition-builder.scss +8 -0
- package/scss/components/PageHeader/_page-header.scss +144 -1
- package/scss/components/Tearsheet/_tearsheet.scss +6 -0
- package/scss/components/TruncatedText/_carbon-imports.scss +6 -0
- package/scss/components/TruncatedText/_index-with-carbon.scss +9 -0
- package/scss/components/TruncatedText/_index.scss +8 -0
- package/scss/components/TruncatedText/_truncated-text.scss +26 -0
- package/scss/components/_index-with-carbon.scss +3 -2
- package/scss/components/_index.scss +3 -2
- package/telemetry.yml +24 -5
- package/es/components/BigNumbers/BigNumbersSkeleton.d.ts +0 -17
- package/lib/components/BigNumbers/BigNumbersSkeleton.d.ts +0 -17
@@ -14,9 +14,15 @@ var cx = require('classnames');
|
|
14
14
|
var react = require('@carbon/react');
|
15
15
|
var layout = require('@carbon/layout');
|
16
16
|
var PageHeaderUtils = require('../PageHeaderUtils.js');
|
17
|
+
var overflowHandler = require('./overflowHandler.js');
|
17
18
|
var utilities = require('@carbon/utilities');
|
18
19
|
var useOverflowItems = require('../../../global/js/hooks/useOverflowItems/useOverflowItems.js');
|
19
20
|
var useId = require('../../../global/js/utils/useId.js');
|
21
|
+
var icons = require('@carbon/react/icons');
|
22
|
+
var context = require('./context.js');
|
23
|
+
var utils = require('./utils.js');
|
24
|
+
var settings = require('../../../settings.js');
|
25
|
+
var useResizeObserver = require('../../../global/js/hooks/useResizeObserver.js');
|
20
26
|
|
21
27
|
/**
|
22
28
|
* ----------
|
@@ -30,14 +36,91 @@ const PageHeader = /*#__PURE__*/React.forwardRef(function PageHeader(_ref, ref)
|
|
30
36
|
children,
|
31
37
|
...other
|
32
38
|
} = _ref;
|
39
|
+
const [refs, setRefs] = React.useState({});
|
40
|
+
const tempRef = React.useRef(null);
|
41
|
+
const componentRef = ref ?? tempRef;
|
33
42
|
const classNames = cx({
|
34
43
|
[`${PageHeaderUtils.blockClass}`]: true,
|
35
44
|
[`${PageHeaderUtils.blockClass}__next`]: true
|
36
45
|
}, className);
|
37
|
-
|
46
|
+
|
47
|
+
// Used to set CSS custom property with PageHeaderContent height to be used
|
48
|
+
// for sticky positioning
|
49
|
+
useResizeObserver.useResizeObserver(componentRef, () => {
|
50
|
+
if (componentRef?.current && refs?.contentRef?.current) {
|
51
|
+
const pageHeaderContentHeight = refs?.contentRef?.current?.offsetHeight;
|
52
|
+
const totalHeaderOffset = utils.getHeaderOffset(componentRef?.current);
|
53
|
+
componentRef?.current.style.setProperty(`--${settings.pkg.prefix}-page-header-header-top`, `${(Math.round(pageHeaderContentHeight) - totalHeaderOffset) * -1}px`);
|
54
|
+
componentRef?.current.style.setProperty(`--${settings.pkg.prefix}-page-header-breadcrumb-top`, `${totalHeaderOffset}px`);
|
55
|
+
}
|
56
|
+
});
|
57
|
+
const [fullyCollapsed, setFullyCollapsed] = React.useState(false);
|
58
|
+
const [titleClipped, setTitleClipped] = React.useState(false);
|
59
|
+
|
60
|
+
// Intersection Observer setup, tracks if the PageHeaderContent is visible on page.
|
61
|
+
// If it is not visible, we should set fully collapsed to true so that the
|
62
|
+
// scroller button will know if it is clicked to expand rather than
|
63
|
+
// collapse the header.
|
64
|
+
React.useEffect(() => {
|
65
|
+
if (!refs?.contentRef || !componentRef?.current) {
|
66
|
+
return;
|
67
|
+
}
|
68
|
+
const totalHeaderOffset = utils.getHeaderOffset(componentRef?.current);
|
69
|
+
const predefinedContentPadding = 24;
|
70
|
+
const contentObserver = new IntersectionObserver(entries => {
|
71
|
+
entries.forEach(entry => {
|
72
|
+
if (entry.target === refs?.contentRef.current) {
|
73
|
+
setFullyCollapsed(!entry.isIntersecting);
|
74
|
+
}
|
75
|
+
});
|
76
|
+
}, {
|
77
|
+
root: null,
|
78
|
+
rootMargin: `${(predefinedContentPadding + totalHeaderOffset + 40) * -1}px 0px 0px 0px`,
|
79
|
+
threshold: 0.1
|
80
|
+
});
|
81
|
+
if (!refs?.titleRef?.current) {
|
82
|
+
return;
|
83
|
+
}
|
84
|
+
const totalTitleHeight = refs?.titleRef.current.offsetHeight;
|
85
|
+
const titleObserver = new IntersectionObserver(entries => {
|
86
|
+
entries.forEach(entry => {
|
87
|
+
if (entry.target === refs?.titleRef.current) {
|
88
|
+
setTitleClipped(!entry.isIntersecting);
|
89
|
+
}
|
90
|
+
});
|
91
|
+
}, {
|
92
|
+
root: null,
|
93
|
+
rootMargin: `${(predefinedContentPadding + totalTitleHeight + totalHeaderOffset + 24) * -1}px 0px 0px 0px`,
|
94
|
+
threshold: 0.1
|
95
|
+
});
|
96
|
+
if (refs?.contentRef.current) {
|
97
|
+
contentObserver.observe(refs?.contentRef.current);
|
98
|
+
}
|
99
|
+
if (refs?.titleRef.current) {
|
100
|
+
titleObserver.observe(refs?.titleRef.current);
|
101
|
+
}
|
102
|
+
return () => {
|
103
|
+
if (!refs?.contentRef?.current) {
|
104
|
+
return;
|
105
|
+
}
|
106
|
+
contentObserver.unobserve(refs?.contentRef.current);
|
107
|
+
if (!refs?.titleRef?.current) {
|
108
|
+
return;
|
109
|
+
}
|
110
|
+
contentObserver.unobserve(refs?.titleRef.current);
|
111
|
+
};
|
112
|
+
}, [refs, componentRef]);
|
113
|
+
return /*#__PURE__*/React.createElement(context.PageHeaderContext.Provider, {
|
114
|
+
value: {
|
115
|
+
refs,
|
116
|
+
setRefs,
|
117
|
+
fullyCollapsed,
|
118
|
+
titleClipped
|
119
|
+
}
|
120
|
+
}, /*#__PURE__*/React.createElement("div", _rollupPluginBabelHelpers.extends({
|
38
121
|
className: classNames,
|
39
|
-
ref:
|
40
|
-
}, other), children);
|
122
|
+
ref: componentRef
|
123
|
+
}, other), children));
|
41
124
|
});
|
42
125
|
PageHeader.displayName = 'PageHeader';
|
43
126
|
|
@@ -104,10 +187,25 @@ const PageHeaderContent = /*#__PURE__*/React.forwardRef(function PageHeaderConte
|
|
104
187
|
pageActions,
|
105
188
|
...other
|
106
189
|
} = _ref3;
|
190
|
+
const contentRef = React.useRef(null);
|
191
|
+
const componentRef = ref ?? contentRef;
|
192
|
+
const {
|
193
|
+
setRefs
|
194
|
+
} = context.usePageHeader();
|
107
195
|
const classNames = cx({
|
108
196
|
[`${PageHeaderUtils.blockClass}__content`]: true
|
109
197
|
}, className);
|
110
198
|
const titleRef = React.useRef(null);
|
199
|
+
React.useEffect(() => {
|
200
|
+
if (componentRef?.current) {
|
201
|
+
setRefs(prev => ({
|
202
|
+
...prev,
|
203
|
+
contentRef: componentRef,
|
204
|
+
titleRef
|
205
|
+
}));
|
206
|
+
}
|
207
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
208
|
+
}, []);
|
111
209
|
const [isEllipsisApplied, setIsEllipsisApplied] = React.useState(false);
|
112
210
|
const isEllipsisActive = element => {
|
113
211
|
setIsEllipsisApplied(element.offsetHeight < element.scrollHeight);
|
@@ -118,7 +216,7 @@ const PageHeaderContent = /*#__PURE__*/React.forwardRef(function PageHeaderConte
|
|
118
216
|
}, [title]);
|
119
217
|
return /*#__PURE__*/React.createElement("div", _rollupPluginBabelHelpers.extends({
|
120
218
|
className: classNames,
|
121
|
-
ref:
|
219
|
+
ref: componentRef
|
122
220
|
}, other), /*#__PURE__*/React.createElement(react.Grid, null, /*#__PURE__*/React.createElement(react.Column, {
|
123
221
|
lg: 16,
|
124
222
|
md: 8,
|
@@ -360,11 +458,16 @@ const PageHeaderTabBar = /*#__PURE__*/React.forwardRef(function PageHeaderTabBar
|
|
360
458
|
className,
|
361
459
|
children,
|
362
460
|
tags = [],
|
461
|
+
scroller,
|
363
462
|
...other
|
364
463
|
} = _ref7;
|
365
464
|
const classNames = cx({
|
366
465
|
[`${PageHeaderUtils.blockClass}__tab-bar`]: true
|
367
466
|
}, className);
|
467
|
+
const renderScroller = () => scroller && /*#__PURE__*/React.createElement("div", {
|
468
|
+
className: `${settings.pkg.prefix}--page-header--scroller-button-container`
|
469
|
+
}, scroller);
|
470
|
+
|
368
471
|
// Early return if no tags are provided
|
369
472
|
if (!tags.length) {
|
370
473
|
return /*#__PURE__*/React.createElement("div", _rollupPluginBabelHelpers.extends({
|
@@ -374,7 +477,7 @@ const PageHeaderTabBar = /*#__PURE__*/React.forwardRef(function PageHeaderTabBar
|
|
374
477
|
lg: 16,
|
375
478
|
md: 8,
|
376
479
|
sm: 4
|
377
|
-
}, children)));
|
480
|
+
}, children, renderScroller())));
|
378
481
|
}
|
379
482
|
const [openPopover, setOpenPopover] = React.useState(false);
|
380
483
|
const tagSize = tags[0]?.size || 'md';
|
@@ -449,10 +552,149 @@ const PageHeaderTabBar = /*#__PURE__*/React.forwardRef(function PageHeaderTabBar
|
|
449
552
|
md: 8,
|
450
553
|
sm: 4
|
451
554
|
}, /*#__PURE__*/React.createElement("div", {
|
452
|
-
className: `${PageHeaderUtils.blockClass}__tab-bar--tablist
|
453
|
-
|
555
|
+
className: cx(`${PageHeaderUtils.blockClass}__tab-bar--tablist`, {
|
556
|
+
[`${settings.pkg.prefix}--page-header__tab-bar--with-scroller`]: !!scroller
|
557
|
+
})
|
558
|
+
}, children, tags.length > 0 && renderTags(), renderScroller()))));
|
454
559
|
});
|
455
560
|
PageHeaderTabBar.displayName = 'PageHeaderTabBar';
|
561
|
+
const PageHeaderScrollButton = /*#__PURE__*/React.forwardRef(function PageHeaderExpander(_ref8, ref) {
|
562
|
+
let {
|
563
|
+
className,
|
564
|
+
children,
|
565
|
+
label,
|
566
|
+
onClick,
|
567
|
+
collapseText = 'Collapse',
|
568
|
+
expandText = 'Expand',
|
569
|
+
...other
|
570
|
+
} = _ref8;
|
571
|
+
const {
|
572
|
+
refs,
|
573
|
+
fullyCollapsed
|
574
|
+
} = context.usePageHeader();
|
575
|
+
const handleScroller = isFullyCollapsed => {
|
576
|
+
if (!refs?.contentRef?.current) {
|
577
|
+
return;
|
578
|
+
}
|
579
|
+
const scrollableTarget = utils.scrollableAncestor(refs?.contentRef.current);
|
580
|
+
|
581
|
+
// Page header content is not fully collapsed
|
582
|
+
if (!isFullyCollapsed) {
|
583
|
+
const pageHeaderContentHeight = refs?.contentRef.current.offsetHeight;
|
584
|
+
scrollableTarget?.scrollTo({
|
585
|
+
top: pageHeaderContentHeight,
|
586
|
+
// headerTopValue, check if breadcrumb bar is included
|
587
|
+
behavior: 'smooth'
|
588
|
+
});
|
589
|
+
} else {
|
590
|
+
// Page header content is fully collapsed
|
591
|
+
scrollableTarget?.scrollTo({
|
592
|
+
top: 0,
|
593
|
+
behavior: 'smooth'
|
594
|
+
});
|
595
|
+
}
|
596
|
+
};
|
597
|
+
return /*#__PURE__*/React.createElement(react.IconButton, _rollupPluginBabelHelpers.extends({
|
598
|
+
ref: ref,
|
599
|
+
label: fullyCollapsed ? expandText : collapseText,
|
600
|
+
size: "md",
|
601
|
+
kind: "ghost",
|
602
|
+
autoAlign: true
|
603
|
+
}, other, {
|
604
|
+
onClick: event => {
|
605
|
+
onClick?.(event);
|
606
|
+
handleScroller(!!fullyCollapsed);
|
607
|
+
},
|
608
|
+
className: cx(className, `${settings.pkg.prefix}--page-header--scroller-button`)
|
609
|
+
}), /*#__PURE__*/React.createElement(icons.ChevronUp, {
|
610
|
+
className: cx(`${settings.pkg.prefix}--page-header--scroller-button-icon`, {
|
611
|
+
[`${settings.pkg.prefix}--page-header--scroller-button-icon-collapsed`]: fullyCollapsed
|
612
|
+
})
|
613
|
+
}));
|
614
|
+
});
|
615
|
+
const PageHeaderTitleBreadcrumb = /*#__PURE__*/React.forwardRef((_ref9, ref) => {
|
616
|
+
let {
|
617
|
+
className,
|
618
|
+
children,
|
619
|
+
...other
|
620
|
+
} = _ref9;
|
621
|
+
const {
|
622
|
+
titleClipped,
|
623
|
+
refs
|
624
|
+
} = context.usePageHeader();
|
625
|
+
return /*#__PURE__*/React.createElement(react.BreadcrumbItem, _rollupPluginBabelHelpers.extends({
|
626
|
+
ref: ref,
|
627
|
+
isCurrentPage: true
|
628
|
+
}, other, {
|
629
|
+
className: cx(className, `${settings.pkg.prefix}--page-header-title-breadcrumb`, {
|
630
|
+
[`${settings.pkg.prefix}--page-header-title-breadcrumb-show`]: titleClipped && refs?.titleRef
|
631
|
+
})
|
632
|
+
}), children);
|
633
|
+
});
|
634
|
+
// This component is a wrapper for the Breadcrumb, and renders breadcrumb items as children
|
635
|
+
// including the overflow breadcrumb item. The overflowHandler determines what elements
|
636
|
+
// are visible and hidden and passes the hidden elements back to the render prop used
|
637
|
+
// to display the overflow breadcrumb
|
638
|
+
const PageHeaderBreadcrumbOverflow = /*#__PURE__*/React.forwardRef((_ref10, ref) => {
|
639
|
+
let {
|
640
|
+
renderOverflowBreadcrumb,
|
641
|
+
className,
|
642
|
+
children,
|
643
|
+
...other
|
644
|
+
} = _ref10;
|
645
|
+
const [hiddenBreadcrumbs, setHiddenBreadcrumbs] = React.useState([]);
|
646
|
+
const fallbackRef = React.useRef(null);
|
647
|
+
const componentRef = ref ?? fallbackRef;
|
648
|
+
|
649
|
+
// Initialize overflow resize handler
|
650
|
+
const carbonPrefix = react.usePrefix();
|
651
|
+
React.useEffect(() => {
|
652
|
+
if (!componentRef) {
|
653
|
+
return;
|
654
|
+
}
|
655
|
+
const breadcrumbList = componentRef?.current.querySelector(`.${carbonPrefix}--breadcrumb`);
|
656
|
+
overflowHandler.createOverflowHandler({
|
657
|
+
container: breadcrumbList,
|
658
|
+
onChange: (_, hidden) => {
|
659
|
+
setHiddenBreadcrumbs(hidden);
|
660
|
+
}
|
661
|
+
});
|
662
|
+
// Don't want ref or carbon prefix in dependency array
|
663
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
664
|
+
}, []);
|
665
|
+
const renderChildren = () => {
|
666
|
+
// Only BreadcrumbItems and TitleBreadcrumbs are valid children
|
667
|
+
const filteredBreadcrumbs = React.Children.toArray(children).filter(child => {
|
668
|
+
if (/*#__PURE__*/React.isValidElement(child)) {
|
669
|
+
return child.type === react.BreadcrumbItem || PageHeaderTitleBreadcrumb;
|
670
|
+
}
|
671
|
+
});
|
672
|
+
// We need to clone the renderProp for the overflow breadcrumb item
|
673
|
+
// to place it before the title breadcrumb according to the design
|
674
|
+
if (filteredBreadcrumbs) {
|
675
|
+
const overflowBreadcrumb = renderOverflowBreadcrumb?.(hiddenBreadcrumbs);
|
676
|
+
// If no overflow breadcrumb provided, return here with the rest of the children
|
677
|
+
if (!overflowBreadcrumb) {
|
678
|
+
return children;
|
679
|
+
}
|
680
|
+
const clonedTitleBreadcrumb = /*#__PURE__*/React.cloneElement(overflowBreadcrumb, {
|
681
|
+
key: 'cloned overflow breadcrumb item',
|
682
|
+
'data-fixed': true,
|
683
|
+
className: cx(`${settings.pkg.prefix}--page-header-breadcrumb-overflow-item`, {
|
684
|
+
[`${settings.pkg.prefix}--page-header-overflow-breadcrumb-item-with-items`]: hiddenBreadcrumbs.length
|
685
|
+
})
|
686
|
+
});
|
687
|
+
const clonedChildren = [...filteredBreadcrumbs];
|
688
|
+
clonedChildren.splice(filteredBreadcrumbs.length - 1, 0, clonedTitleBreadcrumb); // second to last position
|
689
|
+
return clonedChildren;
|
690
|
+
}
|
691
|
+
return children;
|
692
|
+
};
|
693
|
+
return /*#__PURE__*/React.createElement(react.Breadcrumb, _rollupPluginBabelHelpers.extends({
|
694
|
+
className: cx(className, `${settings.pkg.prefix}--page-header-breadcrumb-overflow`),
|
695
|
+
ref: componentRef
|
696
|
+
}, other), renderChildren());
|
697
|
+
});
|
456
698
|
|
457
699
|
/**
|
458
700
|
* -------
|
@@ -473,18 +715,30 @@ const HeroImage = PageHeaderHeroImage;
|
|
473
715
|
HeroImage.displayName = 'PageHeaderHeroImage';
|
474
716
|
const TabBar = PageHeaderTabBar;
|
475
717
|
TabBar.displayName = 'PageHeaderTabBar';
|
718
|
+
const ScrollButton = PageHeaderScrollButton;
|
719
|
+
ScrollButton.displayName = 'PageHeaderScrollButton';
|
720
|
+
const TitleBreadcrumb = PageHeaderTitleBreadcrumb;
|
721
|
+
TitleBreadcrumb.displayName = 'PageHeaderTitleBreadcrumb';
|
722
|
+
const BreadcrumbOverflow = PageHeaderBreadcrumbOverflow;
|
723
|
+
BreadcrumbOverflow.displayName = 'PageHeaderBreadcrumbOverflow';
|
476
724
|
|
477
725
|
exports.BreadcrumbBar = BreadcrumbBar;
|
726
|
+
exports.BreadcrumbOverflow = BreadcrumbOverflow;
|
478
727
|
exports.Content = Content;
|
479
728
|
exports.ContentPageActions = ContentPageActions;
|
480
729
|
exports.ContentText = ContentText;
|
481
730
|
exports.HeroImage = HeroImage;
|
482
731
|
exports.PageHeader = PageHeader;
|
483
732
|
exports.PageHeaderBreadcrumbBar = PageHeaderBreadcrumbBar;
|
733
|
+
exports.PageHeaderBreadcrumbOverflow = PageHeaderBreadcrumbOverflow;
|
484
734
|
exports.PageHeaderContent = PageHeaderContent;
|
485
735
|
exports.PageHeaderContentPageActions = PageHeaderContentPageActions;
|
486
736
|
exports.PageHeaderContentText = PageHeaderContentText;
|
487
737
|
exports.PageHeaderHeroImage = PageHeaderHeroImage;
|
738
|
+
exports.PageHeaderScrollButton = PageHeaderScrollButton;
|
488
739
|
exports.PageHeaderTabBar = PageHeaderTabBar;
|
740
|
+
exports.PageHeaderTitleBreadcrumb = PageHeaderTitleBreadcrumb;
|
489
741
|
exports.Root = Root;
|
742
|
+
exports.ScrollButton = ScrollButton;
|
490
743
|
exports.TabBar = TabBar;
|
744
|
+
exports.TitleBreadcrumb = TitleBreadcrumb;
|
@@ -0,0 +1,25 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright IBM Corp. 2025, 2025
|
3
|
+
*
|
4
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
6
|
+
*/
|
7
|
+
import { RefObject } from 'react';
|
8
|
+
/**
|
9
|
+
* -------------
|
10
|
+
* Context setup
|
11
|
+
* -------------
|
12
|
+
*/
|
13
|
+
export type PageHeaderRefs = {
|
14
|
+
contentRef?: RefObject<HTMLDivElement | null>;
|
15
|
+
titleRef?: RefObject<HTMLHeadingElement | null>;
|
16
|
+
};
|
17
|
+
type PageHeaderContextType = {
|
18
|
+
refs?: PageHeaderRefs;
|
19
|
+
setRefs: React.Dispatch<React.SetStateAction<PageHeaderRefs>>;
|
20
|
+
fullyCollapsed?: boolean;
|
21
|
+
titleClipped?: boolean;
|
22
|
+
};
|
23
|
+
export declare const PageHeaderContext: import("react").Context<PageHeaderContextType | undefined>;
|
24
|
+
export declare function usePageHeader(): PageHeaderContextType;
|
25
|
+
export {};
|
@@ -0,0 +1,33 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright IBM Corp. 2020, 2025
|
3
|
+
*
|
4
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
6
|
+
*/
|
7
|
+
|
8
|
+
'use strict';
|
9
|
+
|
10
|
+
var React = require('react');
|
11
|
+
|
12
|
+
/**
|
13
|
+
* -------------
|
14
|
+
* Context setup
|
15
|
+
* -------------
|
16
|
+
*/
|
17
|
+
|
18
|
+
const PageHeaderContext = /*#__PURE__*/React.createContext({
|
19
|
+
fullyCollapsed: false,
|
20
|
+
setRefs: () => {},
|
21
|
+
refs: {},
|
22
|
+
titleClipped: false
|
23
|
+
});
|
24
|
+
function usePageHeader() {
|
25
|
+
const context = React.useContext(PageHeaderContext);
|
26
|
+
if (!context) {
|
27
|
+
throw new Error('Page header context was not provided or hook was used outside of the Page header component.');
|
28
|
+
}
|
29
|
+
return context;
|
30
|
+
}
|
31
|
+
|
32
|
+
exports.PageHeaderContext = PageHeaderContext;
|
33
|
+
exports.usePageHeader = usePageHeader;
|
@@ -1,8 +1,8 @@
|
|
1
1
|
/**
|
2
|
-
* Copyright IBM Corp. 2025
|
2
|
+
* Copyright IBM Corp. 2025, 2025
|
3
3
|
*
|
4
4
|
* This source code is licensed under the Apache-2.0 license found in the
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
6
6
|
*/
|
7
|
-
export { PageHeader, PageHeaderBreadcrumbBar, PageHeaderContent, PageHeaderContentPageActions, PageHeaderContentText, PageHeaderTabBar, PageHeaderHeroImage, Root, BreadcrumbBar, Content, ContentPageActions, ContentText, TabBar, HeroImage, } from './PageHeader';
|
8
|
-
export type { PageHeaderProps, PageHeaderBreadcrumbBarProps, PageHeaderContentProps, PageHeaderContentPageActionsProps, PageHeaderContentTextProps, PageHeaderTabBarProps, PageHeaderHeroImageProps, } from './PageHeader';
|
7
|
+
export { PageHeader, PageHeaderBreadcrumbBar, PageHeaderContent, PageHeaderContentPageActions, PageHeaderContentText, PageHeaderTabBar, PageHeaderHeroImage, PageHeaderScrollButton, PageHeaderTitleBreadcrumb, PageHeaderBreadcrumbOverflow, Root, BreadcrumbBar, Content, ContentPageActions, ContentText, TabBar, HeroImage, ScrollButton, TitleBreadcrumb, BreadcrumbOverflow, } from './PageHeader';
|
8
|
+
export type { PageHeaderProps, PageHeaderBreadcrumbBarProps, PageHeaderContentProps, PageHeaderContentPageActionsProps, PageHeaderContentTextProps, PageHeaderTabBarProps, PageHeaderHeroImageProps, PageHeaderScrollButtonProps, } from './PageHeader';
|
@@ -0,0 +1,95 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright IBM Corp. 2025
|
3
|
+
*
|
4
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
6
|
+
*/
|
7
|
+
/**
|
8
|
+
* Calculates the size (width or height) of a given HTML element.
|
9
|
+
*
|
10
|
+
* This function performs an expensive calculation by temporarily changing the
|
11
|
+
* display style of the element if it is not currently visible. It then uses
|
12
|
+
* `getBoundingClientRect` to retrieve the size of the element.
|
13
|
+
*
|
14
|
+
* @param el - The HTML element whose size is to be calculated.
|
15
|
+
* @param dimension - The dimension to measure ('width' or 'height').
|
16
|
+
* @returns The size of the element in pixels. Returns 0 if the element is not provided.
|
17
|
+
*/
|
18
|
+
export declare function getSize(el: HTMLElement, dimension: 'width' | 'height'): number;
|
19
|
+
/**
|
20
|
+
* Options for updating the overflow handler.
|
21
|
+
* Determines which items should be visible and which should be hidden
|
22
|
+
* based on the container size, item sizes, and other constraints.
|
23
|
+
*/
|
24
|
+
export interface UpdateOverflowHandlerOptions {
|
25
|
+
/** The container element that holds the items. */
|
26
|
+
container: HTMLElement;
|
27
|
+
/** An array of item elements to be managed for overflow. */
|
28
|
+
items: HTMLElement[];
|
29
|
+
/** An element that represents the offset, which can be shown or hidden based on overflow. Identified by `data-offset` attribute. */
|
30
|
+
offset: HTMLElement;
|
31
|
+
/** An array of sizes corresponding to each item in the `items` array. */
|
32
|
+
sizes: number[];
|
33
|
+
/** An array of sizes corresponding to each item in the fixed items array. */
|
34
|
+
fixedSizes: number[];
|
35
|
+
/** The size of the offset element. */
|
36
|
+
offsetSize: number;
|
37
|
+
/** The maximum number of items that can be visible at once. If undefined, all items can be visible. */
|
38
|
+
maxVisibleItems?: number;
|
39
|
+
/** The dimension to consider for overflow, either 'width' or 'height'. */
|
40
|
+
dimension: 'width' | 'height';
|
41
|
+
/** A callback function that is called when the visible or hidden items change. */
|
42
|
+
onChange: (visibleItems: HTMLElement[], hiddenItems: HTMLElement[]) => void;
|
43
|
+
/** An array of previously hidden items to compare against the new hidden items. */
|
44
|
+
previousHiddenItems?: HTMLElement[];
|
45
|
+
}
|
46
|
+
/**
|
47
|
+
* Updates the overflow handler by determining which items should be visible and which should be hidden.
|
48
|
+
*
|
49
|
+
* @param options - Configuration options for updating the overflow handler.
|
50
|
+
* @param options.container - Container for overflowing
|
51
|
+
* @param options.items - Child elements within container
|
52
|
+
* @param options.offset - Children with data-offset attribute
|
53
|
+
* @param options.sizes - Sizes of child elements
|
54
|
+
* @param options.fixedSizes - Fixed sizes of child elements with data-fixed attribute
|
55
|
+
* @param options.offsetSize - Total offset size
|
56
|
+
* @param options.maxVisibleItems - Max visible items
|
57
|
+
* @param options.dimension - width | height used to measure overflow
|
58
|
+
* @param options.onChange - onChange callback
|
59
|
+
* @param options.previousHiddenItems - Array of previously hidden items
|
60
|
+
* @returns An array of hidden items after the update.
|
61
|
+
*/
|
62
|
+
export declare function updateOverflowHandler({ container, items, offset, sizes, fixedSizes, offsetSize, maxVisibleItems, dimension, onChange, previousHiddenItems, }: UpdateOverflowHandlerOptions): HTMLElement[];
|
63
|
+
/**
|
64
|
+
* Options for initializing an overflow handler.
|
65
|
+
*/
|
66
|
+
export interface OverflowHandlerOptions {
|
67
|
+
/**
|
68
|
+
* The container element that holds the items. along with offset item
|
69
|
+
*/
|
70
|
+
container: HTMLElement;
|
71
|
+
/**
|
72
|
+
* Maximum number of visible items. If provided, only this number of items will be shown.
|
73
|
+
*/
|
74
|
+
maxVisibleItems?: number;
|
75
|
+
/**
|
76
|
+
* Callback function invoked when the visible and hidden items change.
|
77
|
+
* @param visibleItems - The array of items that are currently visible.
|
78
|
+
* @param hiddenItems - The array of items that are currently hidden.
|
79
|
+
*/
|
80
|
+
onChange: (visibleItems: HTMLElement[], hiddenItems: HTMLElement[]) => void;
|
81
|
+
/**
|
82
|
+
* The dimension to consider for overflow calculations. Defaults to 'width'.
|
83
|
+
*/
|
84
|
+
dimension?: 'width' | 'height';
|
85
|
+
}
|
86
|
+
/**
|
87
|
+
* Represents an instance of an overflow handler.
|
88
|
+
*/
|
89
|
+
export interface OverflowHandler {
|
90
|
+
/**
|
91
|
+
* Disconnects the overflow handler, cleaning up any event listeners or resources.
|
92
|
+
*/
|
93
|
+
disconnect: () => void;
|
94
|
+
}
|
95
|
+
export declare function createOverflowHandler({ container, maxVisibleItems, onChange, dimension, }: OverflowHandlerOptions): OverflowHandler;
|
@@ -0,0 +1,166 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright IBM Corp. 2020, 2025
|
3
|
+
*
|
4
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
6
|
+
*/
|
7
|
+
|
8
|
+
'use strict';
|
9
|
+
|
10
|
+
/**
|
11
|
+
* Calculates the size (width or height) of a given HTML element.
|
12
|
+
*
|
13
|
+
* This function performs an expensive calculation by temporarily changing the
|
14
|
+
* display style of the element if it is not currently visible. It then uses
|
15
|
+
* `getBoundingClientRect` to retrieve the size of the element.
|
16
|
+
*
|
17
|
+
* @param el - The HTML element whose size is to be calculated.
|
18
|
+
* @param dimension - The dimension to measure ('width' or 'height').
|
19
|
+
* @returns The size of the element in pixels. Returns 0 if the element is not provided.
|
20
|
+
*/
|
21
|
+
function getSize(el, dimension) {
|
22
|
+
if (!el) {
|
23
|
+
return 0;
|
24
|
+
}
|
25
|
+
const originalDisplay = el.style.display;
|
26
|
+
if (!el.offsetParent && getComputedStyle(el).display === 'none') {
|
27
|
+
el.style.display = 'inline-block';
|
28
|
+
}
|
29
|
+
let size = el.getBoundingClientRect()[dimension];
|
30
|
+
el.style.display = originalDisplay;
|
31
|
+
const computedStyles = getComputedStyle(el);
|
32
|
+
size = dimension === 'width' ? size + parseInt(computedStyles.paddingLeft) + parseInt(computedStyles.paddingRight) + parseInt(computedStyles.marginLeft) + parseInt(computedStyles.marginRight) : size + parseInt(computedStyles.paddingTop) + parseInt(computedStyles.paddingBottom) + parseInt(computedStyles.marginTop) + parseInt(computedStyles.marginBottom);
|
33
|
+
return size;
|
34
|
+
}
|
35
|
+
|
36
|
+
/**
|
37
|
+
* Options for updating the overflow handler.
|
38
|
+
* Determines which items should be visible and which should be hidden
|
39
|
+
* based on the container size, item sizes, and other constraints.
|
40
|
+
*/
|
41
|
+
|
42
|
+
/**
|
43
|
+
* Updates the overflow handler by determining which items should be visible and which should be hidden.
|
44
|
+
*
|
45
|
+
* @param options - Configuration options for updating the overflow handler.
|
46
|
+
* @param options.container - Container for overflowing
|
47
|
+
* @param options.items - Child elements within container
|
48
|
+
* @param options.offset - Children with data-offset attribute
|
49
|
+
* @param options.sizes - Sizes of child elements
|
50
|
+
* @param options.fixedSizes - Fixed sizes of child elements with data-fixed attribute
|
51
|
+
* @param options.offsetSize - Total offset size
|
52
|
+
* @param options.maxVisibleItems - Max visible items
|
53
|
+
* @param options.dimension - width | height used to measure overflow
|
54
|
+
* @param options.onChange - onChange callback
|
55
|
+
* @param options.previousHiddenItems - Array of previously hidden items
|
56
|
+
* @returns An array of hidden items after the update.
|
57
|
+
*/
|
58
|
+
function updateOverflowHandler(_ref) {
|
59
|
+
let {
|
60
|
+
container,
|
61
|
+
items,
|
62
|
+
offset,
|
63
|
+
sizes,
|
64
|
+
fixedSizes,
|
65
|
+
offsetSize,
|
66
|
+
maxVisibleItems,
|
67
|
+
dimension,
|
68
|
+
onChange,
|
69
|
+
previousHiddenItems = []
|
70
|
+
} = _ref;
|
71
|
+
const containerSize = dimension === 'width' ? container.clientWidth : container.clientHeight;
|
72
|
+
let visibleItems = [];
|
73
|
+
let hiddenItems = [];
|
74
|
+
const totalSize = sizes.reduce((sum, size) => sum + size, 0);
|
75
|
+
const totalFixedSize = fixedSizes.reduce((sum, size) => sum + size, 0);
|
76
|
+
if (totalSize + totalFixedSize <= containerSize) {
|
77
|
+
visibleItems = maxVisibleItems ? items.slice(0, maxVisibleItems) : [...items];
|
78
|
+
hiddenItems = maxVisibleItems ? items.slice(maxVisibleItems) : [];
|
79
|
+
} else {
|
80
|
+
const available = containerSize - offsetSize;
|
81
|
+
let accumulated = 0;
|
82
|
+
for (let i = 0; i < items.length; i++) {
|
83
|
+
const size = sizes[i];
|
84
|
+
if (accumulated + size + totalFixedSize <= available && (!maxVisibleItems || visibleItems.length < maxVisibleItems)) {
|
85
|
+
visibleItems.push(items[i]);
|
86
|
+
accumulated += size;
|
87
|
+
} else {
|
88
|
+
hiddenItems.push(items[i]);
|
89
|
+
}
|
90
|
+
}
|
91
|
+
}
|
92
|
+
if (previousHiddenItems.length === hiddenItems.length && previousHiddenItems.every((item, index) => item === hiddenItems[index])) {
|
93
|
+
return previousHiddenItems;
|
94
|
+
}
|
95
|
+
visibleItems.forEach(item => item.removeAttribute('data-hidden'));
|
96
|
+
hiddenItems.forEach(item => item.setAttribute('data-hidden', ''));
|
97
|
+
if (offset) {
|
98
|
+
offset.toggleAttribute('data-hidden', hiddenItems.length === 0);
|
99
|
+
}
|
100
|
+
onChange(visibleItems, hiddenItems);
|
101
|
+
return hiddenItems;
|
102
|
+
}
|
103
|
+
|
104
|
+
/**
|
105
|
+
* Options for initializing an overflow handler.
|
106
|
+
*/
|
107
|
+
|
108
|
+
/**
|
109
|
+
* Represents an instance of an overflow handler.
|
110
|
+
*/
|
111
|
+
|
112
|
+
function createOverflowHandler(_ref2) {
|
113
|
+
let {
|
114
|
+
container,
|
115
|
+
maxVisibleItems,
|
116
|
+
onChange,
|
117
|
+
dimension = 'width'
|
118
|
+
} = _ref2;
|
119
|
+
// Error handling
|
120
|
+
if (!(container instanceof HTMLElement)) {
|
121
|
+
throw new Error('container must be an HTMLElement');
|
122
|
+
}
|
123
|
+
if (typeof onChange !== 'function') {
|
124
|
+
throw new Error('onChange must be a function');
|
125
|
+
}
|
126
|
+
if (maxVisibleItems !== undefined && (!Number.isInteger(maxVisibleItems) || maxVisibleItems <= 0)) {
|
127
|
+
throw new Error('maxVisibleItems must be a positive integer');
|
128
|
+
}
|
129
|
+
const children = Array.from(container.children);
|
130
|
+
const offset = children.find(item => item.hasAttribute('data-offset'));
|
131
|
+
const fixedItems = children.filter(item => item.hasAttribute('data-fixed'));
|
132
|
+
const items = children.filter(item => item !== offset && !fixedItems.includes(item));
|
133
|
+
const fixedSizes = fixedItems.map(item => getSize(item, dimension));
|
134
|
+
const sizes = items.map(item => getSize(item, dimension));
|
135
|
+
const offsetSize = getSize(offset, dimension);
|
136
|
+
let previousHiddenItems = [];
|
137
|
+
function update() {
|
138
|
+
previousHiddenItems = updateOverflowHandler({
|
139
|
+
container,
|
140
|
+
items,
|
141
|
+
offset,
|
142
|
+
sizes,
|
143
|
+
fixedSizes,
|
144
|
+
offsetSize,
|
145
|
+
maxVisibleItems,
|
146
|
+
dimension,
|
147
|
+
onChange,
|
148
|
+
previousHiddenItems
|
149
|
+
});
|
150
|
+
}
|
151
|
+
const resizeObserver = new ResizeObserver(() => {
|
152
|
+
requestAnimationFrame(update);
|
153
|
+
});
|
154
|
+
resizeObserver.observe(container);
|
155
|
+
requestAnimationFrame(update); // Initial update
|
156
|
+
|
157
|
+
return {
|
158
|
+
disconnect() {
|
159
|
+
resizeObserver.disconnect();
|
160
|
+
}
|
161
|
+
};
|
162
|
+
}
|
163
|
+
|
164
|
+
exports.createOverflowHandler = createOverflowHandler;
|
165
|
+
exports.getSize = getSize;
|
166
|
+
exports.updateOverflowHandler = updateOverflowHandler;
|