@carbon/ibm-products 2.83.0 → 2.84.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 +4 -0
- package/css/carbon.css.map +1 -1
- package/css/index-full-carbon.css +99 -33
- 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 +95 -33
- 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 +95 -33
- 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 +95 -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/AddSelect/AddSelectBody.js +1 -1
- package/es/components/Coachmark/next/Coachmark/CoachmarkBeacon/CoachmarkBeacon.js +6 -6
- package/es/components/Datagrid/Datagrid/addons/CustomizeColumns/CustomizeColumnsTearsheet.js +1 -1
- package/es/components/PageHeader/PageHeader.js +4 -12
- package/es/components/PageHeader/next/PageHeader.js +29 -12
- package/es/components/PageHeader/next/context.d.ts +3 -0
- package/es/components/PageHeader/next/utils.js +8 -0
- package/es/components/SidePanel/SidePanel.js +11 -3
- package/es/components/Tearsheet/TearsheetPresence.d.ts +37 -0
- package/es/components/Tearsheet/TearsheetPresence.js +56 -0
- package/es/components/Tearsheet/TearsheetShell.js +76 -17
- package/es/components/Tearsheet/index.d.ts +2 -0
- package/es/components/Tearsheet/usePresence.d.ts +17 -0
- package/es/components/Tearsheet/usePresence.js +69 -0
- package/es/components/Tearsheet/usePresenceContext.d.ts +25 -0
- package/es/components/Tearsheet/usePresenceContext.js +50 -0
- package/es/global/js/hooks/useMergedRefs.d.ts +1 -0
- package/es/global/js/hooks/useMergedRefs.js +32 -0
- package/es/global/js/hooks/useOverflowString.js +1 -16
- package/es/index.js +1 -0
- package/lib/components/AddSelect/AddSelectBody.js +1 -1
- package/lib/components/Coachmark/next/Coachmark/CoachmarkBeacon/CoachmarkBeacon.js +6 -6
- package/lib/components/Datagrid/Datagrid/addons/CustomizeColumns/CustomizeColumnsTearsheet.js +1 -1
- package/lib/components/PageHeader/PageHeader.js +3 -11
- package/lib/components/PageHeader/next/PageHeader.js +29 -12
- package/lib/components/PageHeader/next/context.d.ts +3 -0
- package/lib/components/PageHeader/next/utils.js +8 -0
- package/lib/components/SidePanel/SidePanel.js +10 -2
- package/lib/components/Tearsheet/TearsheetPresence.d.ts +37 -0
- package/lib/components/Tearsheet/TearsheetPresence.js +61 -0
- package/lib/components/Tearsheet/TearsheetShell.js +74 -15
- package/lib/components/Tearsheet/index.d.ts +2 -0
- package/lib/components/Tearsheet/usePresence.d.ts +17 -0
- package/lib/components/Tearsheet/usePresence.js +71 -0
- package/lib/components/Tearsheet/usePresenceContext.d.ts +25 -0
- package/lib/components/Tearsheet/usePresenceContext.js +52 -0
- package/lib/global/js/hooks/useMergedRefs.d.ts +1 -0
- package/lib/global/js/hooks/useMergedRefs.js +34 -0
- package/lib/global/js/hooks/useOverflowString.js +0 -16
- package/lib/index.js +3 -0
- package/package.json +22 -21
- package/scss/components/APIKeyModal/_api-key-modal.scss +6 -4
- package/scss/components/AboutModal/_about-modal.scss +5 -5
- package/scss/components/ActionBar/_action-bar.scss +2 -0
- package/scss/components/ActionSet/_action-set.scss +12 -11
- package/scss/components/AddSelect/_add-select.scss +28 -29
- package/scss/components/BreadcrumbWithOverflow/_breadcrumb-with-overflow.scss +10 -8
- package/scss/components/ButtonMenu/_button-menu.scss +11 -9
- package/scss/components/Card/_card.scss +12 -10
- package/scss/components/Checklist/_checklist.scss +8 -6
- package/scss/components/Coachmark/_coachmark-overlay.scss +11 -9
- package/scss/components/Coachmark/_coachmark.scss +1 -1
- package/scss/components/CoachmarkStack/_coachmark-stack.scss +6 -4
- package/scss/components/ComboButton/_combo-button.scss +11 -9
- package/scss/components/CreateFullPage/_create-full-page.scss +9 -9
- package/scss/components/CreateModal/_create-modal.scss +9 -7
- package/scss/components/CreateSidePanel/_create-side-panel.scss +6 -4
- package/scss/components/CreateTearsheet/_create-tearsheet.scss +9 -9
- package/scss/components/CreateTearsheetNarrow/_create-tearsheet-narrow.scss +5 -3
- package/scss/components/Datagrid/_datagrid.scss +9 -7
- package/scss/components/Datagrid/styles/_datagrid.scss +86 -86
- package/scss/components/Datagrid/styles/_useExpandedRow.scss +11 -9
- package/scss/components/Datagrid/styles/_useInlineEdit.scss +48 -46
- package/scss/components/Datagrid/styles/_useNestedRows.scss +16 -16
- package/scss/components/Datagrid/styles/_useNestedTable.scss +5 -3
- package/scss/components/Datagrid/styles/_useSelectAllToggle.scss +4 -2
- package/scss/components/Datagrid/styles/_useSortableColumns.scss +21 -19
- package/scss/components/Datagrid/styles/addons/_CustomizeColumnsTearsheet.scss +5 -4
- package/scss/components/Datagrid/styles/addons/_FilterFlyout.scss +5 -5
- package/scss/components/Datagrid/styles/addons/_FilterPanel.scss +11 -8
- package/scss/components/Datagrid/styles/addons/_RowSizeDropdown.scss +18 -16
- package/scss/components/Datagrid/styles/addons/_animations.scss +4 -4
- package/scss/components/DescriptionList/_description-list.scss +6 -4
- package/scss/components/EditInPlace/_edit-in-place.scss +5 -9
- package/scss/components/EditSidePanel/_edit-side-panel.scss +6 -4
- package/scss/components/EditTearsheet/_edit-tearsheet.scss +8 -9
- package/scss/components/ExportModal/_export-modal.scss +7 -5
- package/scss/components/FilterPanel/_filter-panel-accordion-item.scss +6 -5
- package/scss/components/FilterPanel/_filter-panel-checkbox-with-overflow.scss +6 -5
- package/scss/components/FilterPanel/_filter-panel-checkbox.scss +6 -5
- package/scss/components/FilterPanel/_filter-panel.scss +6 -5
- package/scss/components/FilterSummary/_filter-summary.scss +5 -9
- package/scss/components/Guidebanner/_guidebanner.scss +5 -3
- package/scss/components/ImportModal/_import-modal.scss +16 -16
- package/scss/components/InterstitialScreen/_interstitial-screen.scss +6 -4
- package/scss/components/NotificationsPanel/_notifications-panel.scss +13 -8
- package/scss/components/OptionsTile/_options-tile.scss +8 -6
- package/scss/components/PageHeader/_page-header.scss +25 -21
- package/scss/components/RemoveModal/_remove-modal.scss +5 -4
- package/scss/components/Saving/_saving.scss +5 -3
- package/scss/components/SearchBar/_search-bar.scss +5 -4
- package/scss/components/SidePanel/_animations.scss +4 -4
- package/scss/components/SidePanel/_side-panel.scss +31 -12
- package/scss/components/SimpleHeader/_simple-header.scss +5 -4
- package/scss/components/StatusIcon/_status-icon.scss +5 -3
- package/scss/components/StatusIndicator/_status-indicator.scss +3 -2
- package/scss/components/StringFormatter/_string-formatter.scss +5 -4
- package/scss/components/TagOverflow/_tag-overflow.scss +7 -6
- package/scss/components/TagSet/_tag-set.scss +20 -18
- package/scss/components/Tearsheet/_tearsheet.scss +121 -30
- package/scss/components/Toolbar/_toolbar.scss +4 -2
- package/scss/components/TruncatedList/_truncated-list.scss +4 -3
- package/scss/components/TruncatedText/_truncated-text.scss +2 -2
- package/scss/components/UserAvatar/_user-avatar.scss +5 -4
- package/scss/components/UserProfileImage/_user-profile-image.scss +11 -7
- package/scss/components/WebTerminal/_web-terminal.scss +4 -2
- package/telemetry.yml +3 -0
|
@@ -21,6 +21,9 @@ var ActionSet = require('../ActionSet/ActionSet.js');
|
|
|
21
21
|
var Wrap = require('../../global/js/utils/Wrap.js');
|
|
22
22
|
var usePortalTarget = require('../../global/js/hooks/usePortalTarget.js');
|
|
23
23
|
var useFocus = require('../../global/js/hooks/useFocus.js');
|
|
24
|
+
var useMergedRefs = require('../../global/js/hooks/useMergedRefs.js');
|
|
25
|
+
var useId = require('../../global/js/utils/useId.js');
|
|
26
|
+
var TearsheetPresence = require('./TearsheetPresence.js');
|
|
24
27
|
var usePreviousValue = require('../../global/js/hooks/usePreviousValue.js');
|
|
25
28
|
var useIsomorphicEffect = require('../../global/js/hooks/useIsomorphicEffect.js');
|
|
26
29
|
|
|
@@ -74,6 +77,35 @@ const SectionLevel3 = _ref => {
|
|
|
74
77
|
* See the canvas tab for the component API details.
|
|
75
78
|
* */
|
|
76
79
|
const TearsheetShell = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
80
|
+
let {
|
|
81
|
+
open,
|
|
82
|
+
...props
|
|
83
|
+
} = _ref2;
|
|
84
|
+
const id = useId.useId();
|
|
85
|
+
const enablePresence = react.useFeatureFlag('enable-presence');
|
|
86
|
+
const hasPresenceContext = Boolean(React.useContext(TearsheetPresence.TearsheetPresenceContext));
|
|
87
|
+
const hasPresenceOptIn = enablePresence || hasPresenceContext;
|
|
88
|
+
const exclusivePresenceContext = TearsheetPresence.useExclusiveTearsheetPresenceContext(id);
|
|
89
|
+
|
|
90
|
+
// if opt in and not exclusive to a presence context, wrap with presence
|
|
91
|
+
if (hasPresenceOptIn && !exclusivePresenceContext) {
|
|
92
|
+
return /*#__PURE__*/React.createElement(TearsheetPresence.TearsheetPresence, {
|
|
93
|
+
open: open ?? false,
|
|
94
|
+
_presenceId: id
|
|
95
|
+
// do not auto enable styles for opt-in by feature flag
|
|
96
|
+
,
|
|
97
|
+
_autoEnablePresence: hasPresenceContext
|
|
98
|
+
}, /*#__PURE__*/React.createElement(TearsheetShellDialog, _rollupPluginBabelHelpers.extends({
|
|
99
|
+
open: true,
|
|
100
|
+
ref: ref
|
|
101
|
+
}, props)));
|
|
102
|
+
}
|
|
103
|
+
return /*#__PURE__*/React.createElement(TearsheetShellDialog, _rollupPluginBabelHelpers.extends({
|
|
104
|
+
ref: ref,
|
|
105
|
+
open: open
|
|
106
|
+
}, props));
|
|
107
|
+
});
|
|
108
|
+
const TearsheetShellDialog = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
77
109
|
let {
|
|
78
110
|
// The component props, in alphabetical order (for consistency).
|
|
79
111
|
actions,
|
|
@@ -93,7 +125,7 @@ const TearsheetShell = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
93
125
|
label,
|
|
94
126
|
navigation,
|
|
95
127
|
onClose,
|
|
96
|
-
open,
|
|
128
|
+
open: externalOpen,
|
|
97
129
|
portalTarget: portalTargetIn,
|
|
98
130
|
selectorPrimaryFocus,
|
|
99
131
|
selectorsFloatingMenus = [],
|
|
@@ -104,7 +136,7 @@ const TearsheetShell = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
104
136
|
launcherButtonRef,
|
|
105
137
|
// Collect any other property values passed in.
|
|
106
138
|
...rest
|
|
107
|
-
} =
|
|
139
|
+
} = _ref3;
|
|
108
140
|
const carbonPrefix = react.usePrefix();
|
|
109
141
|
const bcModalHeader = `${carbonPrefix}--modal-header`;
|
|
110
142
|
const renderPortalUse = usePortalTarget.usePortalTarget(portalTargetIn);
|
|
@@ -115,13 +147,19 @@ const TearsheetShell = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
115
147
|
const {
|
|
116
148
|
width
|
|
117
149
|
} = useResizeObserver.useResizeObserver(resizer);
|
|
118
|
-
const prevOpen = usePreviousValue.usePreviousValue(open);
|
|
119
150
|
const {
|
|
120
151
|
keyDownListener,
|
|
121
152
|
claimFocus
|
|
122
153
|
} = useFocus.useFocus(modalRef, selectorPrimaryFocus);
|
|
123
154
|
modalRef.current;
|
|
124
155
|
const wide = size === 'wide';
|
|
156
|
+
const presenceContext = React.useContext(TearsheetPresence.TearsheetPresenceContext);
|
|
157
|
+
const mergedRefs = useMergedRefs.useMergedRefs([modalRef, presenceContext?.presenceRef]);
|
|
158
|
+
const enablePresence = react.useFeatureFlag('enable-presence') || presenceContext?.autoEnablePresence;
|
|
159
|
+
|
|
160
|
+
// always mark as open when mounted with presence
|
|
161
|
+
const open = externalOpen || enablePresence;
|
|
162
|
+
const prevOpen = usePreviousValue.usePreviousValue(open);
|
|
125
163
|
|
|
126
164
|
// Keep track of the stack depth and our position in it (1-based, 0=closed)
|
|
127
165
|
const [depth, setDepth] = React.useState(0);
|
|
@@ -148,13 +186,28 @@ const TearsheetShell = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
148
186
|
claimFocus();
|
|
149
187
|
}
|
|
150
188
|
}, [open, currentStep, effectiveHasCloseIcon, claimFocus]);
|
|
189
|
+
|
|
190
|
+
// Focus launcher button on open change for non presence tearsheet
|
|
151
191
|
React.useEffect(() => {
|
|
152
|
-
if (prevOpen && !open && launcherButtonRef?.current) {
|
|
192
|
+
if (!enablePresence && prevOpen && !open && launcherButtonRef?.current) {
|
|
153
193
|
setTimeout(() => {
|
|
154
194
|
launcherButtonRef?.current?.focus();
|
|
155
195
|
}, 10);
|
|
156
196
|
}
|
|
157
|
-
}, [open, prevOpen, launcherButtonRef]);
|
|
197
|
+
}, [enablePresence, open, prevOpen, launcherButtonRef]);
|
|
198
|
+
|
|
199
|
+
// Focus launcher button on unmount for presence tearsheet
|
|
200
|
+
React.useEffect(() => {
|
|
201
|
+
const launcherButton = launcherButtonRef?.current;
|
|
202
|
+
if (!enablePresence || !launcherButton) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
return () => {
|
|
206
|
+
setTimeout(() => {
|
|
207
|
+
launcherButton.focus();
|
|
208
|
+
}, 10);
|
|
209
|
+
};
|
|
210
|
+
}, [enablePresence, launcherButtonRef]);
|
|
158
211
|
React.useEffect(() => {
|
|
159
212
|
requestAnimationFrame(() => {
|
|
160
213
|
if (open && depth === position && !modalRef?.current?.contains(document.activeElement)) {
|
|
@@ -169,6 +222,8 @@ const TearsheetShell = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
169
222
|
}
|
|
170
223
|
}, [claimFocus, hasError, modalRef]);
|
|
171
224
|
React.useEffect(() => {
|
|
225
|
+
// Other tearsheets should already be notified if this tearsheet is exiting
|
|
226
|
+
const isPresent = open && !presenceContext?.isExiting;
|
|
172
227
|
const notify = () => stack.all.forEach(handler => {
|
|
173
228
|
handler(Math.min(stack.open.length, maxDepth), stack.open.indexOf(handler) + 1);
|
|
174
229
|
});
|
|
@@ -181,7 +236,7 @@ const TearsheetShell = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
181
236
|
// false to true to open it then append its notification callback to
|
|
182
237
|
// the end of the stack array (as its ID), and call all the callbacks
|
|
183
238
|
// to notify all open tearsheets that the stacking has changed.
|
|
184
|
-
if (
|
|
239
|
+
if (isPresent) {
|
|
185
240
|
stack.open.push(handleStackChange);
|
|
186
241
|
notify();
|
|
187
242
|
}
|
|
@@ -203,7 +258,7 @@ const TearsheetShell = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
203
258
|
notify();
|
|
204
259
|
}
|
|
205
260
|
};
|
|
206
|
-
}, [open, size]);
|
|
261
|
+
}, [open, presenceContext?.isExiting, size]);
|
|
207
262
|
const areAllSameSizeVariant = () => new Set(stack.sizes).size === 1;
|
|
208
263
|
useIsomorphicEffect.useIsomorphicEffect(() => {
|
|
209
264
|
const setScaleValues = () => {
|
|
@@ -219,8 +274,8 @@ const TearsheetShell = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
219
274
|
};
|
|
220
275
|
};
|
|
221
276
|
if (modalRef.current) {
|
|
222
|
-
Object.entries(setScaleValues()).map(
|
|
223
|
-
let [key, value] =
|
|
277
|
+
Object.entries(setScaleValues()).map(_ref4 => {
|
|
278
|
+
let [key, value] = _ref4;
|
|
224
279
|
modalRef.current.style.setProperty(key, String(value));
|
|
225
280
|
});
|
|
226
281
|
}
|
|
@@ -247,7 +302,9 @@ const TearsheetShell = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
247
302
|
[`${bc}--has-slug`]: deprecated_slug,
|
|
248
303
|
[`${bc}--has-ai-label`]: !!decorator && decorator['type']?.displayName === 'AILabel',
|
|
249
304
|
[`${bc}--has-decorator`]: !!decorator && decorator['type']?.displayName !== 'AILabel',
|
|
250
|
-
[`${bc}--has-close`]: effectiveHasCloseIcon
|
|
305
|
+
[`${bc}--has-close`]: effectiveHasCloseIcon,
|
|
306
|
+
['is-visible']: enablePresence,
|
|
307
|
+
[`${bc}--tearsheet-enable-presence`]: presenceContext?.autoEnablePresence
|
|
251
308
|
}),
|
|
252
309
|
decorator: decorator || deprecated_slug,
|
|
253
310
|
containerClassName: cx(`${bc}__container`, {
|
|
@@ -259,9 +316,10 @@ const TearsheetShell = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
259
316
|
selectorPrimaryFocus,
|
|
260
317
|
onKeyDown: keyDownListener,
|
|
261
318
|
preventCloseOnClickOutside: !isPassive,
|
|
262
|
-
ref:
|
|
319
|
+
ref: mergedRefs,
|
|
263
320
|
selectorsFloatingMenus: [`.${carbonPrefix}--overflow-menu-options`, `.${carbonPrefix}--tooltip`, '.flatpickr-calendar', `.${bc}__container`, `.${carbonPrefix}--menu`, ...selectorsFloatingMenus],
|
|
264
|
-
size: "sm"
|
|
321
|
+
size: "sm",
|
|
322
|
+
"data-tearsheet-exiting": presenceContext?.isExiting || undefined
|
|
265
323
|
}), includeHeader && /*#__PURE__*/React.createElement(react.ModalHeader, {
|
|
266
324
|
className: cx(`${bc}__header`, {
|
|
267
325
|
[`${bc}__header--with-close-icon`]: effectiveHasCloseIcon,
|
|
@@ -272,16 +330,17 @@ const TearsheetShell = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
272
330
|
}),
|
|
273
331
|
closeModal: onClose,
|
|
274
332
|
iconDescription: effectiveHasCloseIcon ? closeIconDescription : undefined
|
|
275
|
-
}, /*#__PURE__*/React.createElement(
|
|
333
|
+
}, /*#__PURE__*/React.createElement(Wrap.Wrap, {
|
|
276
334
|
className: `${bc}__header-content`,
|
|
277
335
|
element: wide ? react.Layer : undefined
|
|
278
336
|
}, /*#__PURE__*/React.createElement(Wrap.Wrap, {
|
|
279
337
|
className: `${bc}__header-fields`
|
|
280
338
|
}, /*#__PURE__*/React.createElement(Wrap.Wrap, {
|
|
281
339
|
className: `${bcModalHeader}__label`
|
|
282
|
-
}, label), /*#__PURE__*/React.createElement(
|
|
340
|
+
}, label), /*#__PURE__*/React.createElement(Wrap.Wrap, {
|
|
341
|
+
element: "h3",
|
|
283
342
|
className: cx(`${bcModalHeader}__heading`, `${bc}__heading`)
|
|
284
|
-
},
|
|
343
|
+
}, title), /*#__PURE__*/React.createElement(Wrap.Wrap, {
|
|
285
344
|
className: `${bc}__header-description`
|
|
286
345
|
}, description)), /*#__PURE__*/React.createElement(Wrap.Wrap, {
|
|
287
346
|
className: `${bc}__header-actions`
|
|
@@ -6,5 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export { Tearsheet } from './Tearsheet';
|
|
8
8
|
export { TearsheetNarrow } from './TearsheetNarrow';
|
|
9
|
+
export { TearsheetPresence, withTearsheetPresence } from './TearsheetPresence';
|
|
9
10
|
export type { TearsheetProps } from './Tearsheet';
|
|
10
11
|
export type { TearsheetNarrowProps } from './TearsheetNarrow';
|
|
12
|
+
export type { TearsheetPresenceProps } from './TearsheetPresence';
|
|
@@ -0,0 +1,17 @@
|
|
|
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
|
+
import { type RefObject } from 'react';
|
|
8
|
+
export declare const usePresence: (ref: RefObject<HTMLElement | null>, isOpen: boolean) => {
|
|
9
|
+
/**
|
|
10
|
+
* Indicates whether the ref object is supposed to be mounted
|
|
11
|
+
*/
|
|
12
|
+
isPresent: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Indicates whether the ref object is currently exiting
|
|
15
|
+
*/
|
|
16
|
+
isExiting: boolean;
|
|
17
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2020, 2026
|
|
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
|
+
var settings = require('../../settings.js');
|
|
12
|
+
|
|
13
|
+
const usePresence = (ref, isOpen) => {
|
|
14
|
+
const [exitState, setExitState] = React.useState(isOpen ? 'idle' : 'finished');
|
|
15
|
+
const isExiting = exitState === 'active';
|
|
16
|
+
|
|
17
|
+
// element is exiting
|
|
18
|
+
if (!isOpen && exitState === 'idle') {
|
|
19
|
+
setExitState('active');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// element exit was interrupted
|
|
23
|
+
if (isOpen && exitState !== 'idle') {
|
|
24
|
+
setExitState('idle');
|
|
25
|
+
}
|
|
26
|
+
const handleAnimationEnd = React.useCallback(() => {
|
|
27
|
+
setExitState('finished');
|
|
28
|
+
}, []);
|
|
29
|
+
React.useLayoutEffect(() => {
|
|
30
|
+
if (!ref.current || !isExiting) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// resolve for JSDOM
|
|
35
|
+
if (!('getAnimations' in ref.current)) {
|
|
36
|
+
handleAnimationEnd();
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// cover all animations that start with the presence prefix
|
|
41
|
+
const animations = ref.current.getAnimations({
|
|
42
|
+
subtree: true
|
|
43
|
+
}).filter(animation => animation instanceof CSSAnimation && animation.animationName.startsWith(`${settings.pkg.prefix}`));
|
|
44
|
+
if (!animations.length) {
|
|
45
|
+
handleAnimationEnd();
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
let cancelled = false;
|
|
49
|
+
Promise.all(animations.map(animation => animation.finished)).finally(() => {
|
|
50
|
+
if (cancelled) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
handleAnimationEnd();
|
|
54
|
+
});
|
|
55
|
+
return () => {
|
|
56
|
+
cancelled = true;
|
|
57
|
+
};
|
|
58
|
+
}, [ref, isExiting, handleAnimationEnd]);
|
|
59
|
+
return {
|
|
60
|
+
/**
|
|
61
|
+
* Indicates whether the ref object is supposed to be mounted
|
|
62
|
+
*/
|
|
63
|
+
isPresent: isOpen || exitState !== 'finished',
|
|
64
|
+
/**
|
|
65
|
+
* Indicates whether the ref object is currently exiting
|
|
66
|
+
*/
|
|
67
|
+
isExiting
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
exports.usePresence = usePresence;
|
|
@@ -0,0 +1,25 @@
|
|
|
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
|
+
import { type RefObject } from 'react';
|
|
8
|
+
export interface PresenceContext {
|
|
9
|
+
/**
|
|
10
|
+
* The ref object the presence mode is mounted with
|
|
11
|
+
*/
|
|
12
|
+
presenceRef: RefObject<HTMLDivElement | null>;
|
|
13
|
+
/**
|
|
14
|
+
* Indicates whether the ref object is currently exiting
|
|
15
|
+
*/
|
|
16
|
+
isExiting: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Returns if the caller is exclusive to this presence context
|
|
19
|
+
*/
|
|
20
|
+
isPresenceExclusive: (id: string) => boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Returns if the presence node is present and the context value to be used by a presence context, e.g. ModalPresence.
|
|
24
|
+
*/
|
|
25
|
+
export declare const usePresenceContext: (open: boolean, initialPresenceId?: string) => readonly [boolean, PresenceContext];
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2020, 2026
|
|
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
|
+
var usePresence = require('./usePresence.js');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Returns if the presence node is present and the context value to be used by a presence context, e.g. ModalPresence.
|
|
15
|
+
*/
|
|
16
|
+
const usePresenceContext = (open, initialPresenceId) => {
|
|
17
|
+
const presenceIdRef = React.useRef(initialPresenceId);
|
|
18
|
+
const presenceRef = React.useRef(null);
|
|
19
|
+
const prevPresenceRef = React.useRef(null);
|
|
20
|
+
|
|
21
|
+
// clean up the presence id, if not predefined and if the presence node was unmounted
|
|
22
|
+
if (!initialPresenceId && prevPresenceRef.current && !presenceRef.current) {
|
|
23
|
+
presenceIdRef.current = null;
|
|
24
|
+
}
|
|
25
|
+
prevPresenceRef.current = presenceRef.current;
|
|
26
|
+
const {
|
|
27
|
+
isPresent,
|
|
28
|
+
isExiting
|
|
29
|
+
} = usePresence.usePresence(presenceRef, open);
|
|
30
|
+
const isPresenceExclusive = React.useCallback(id => {
|
|
31
|
+
if (!id) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// return false if the presence context is occupied
|
|
36
|
+
if (presenceIdRef.current && presenceIdRef.current !== id) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// otherwise occupy presence context and return true
|
|
41
|
+
presenceIdRef.current = id;
|
|
42
|
+
return true;
|
|
43
|
+
}, []);
|
|
44
|
+
const contextValue = React.useMemo(() => ({
|
|
45
|
+
presenceRef,
|
|
46
|
+
isPresenceExclusive,
|
|
47
|
+
isExiting
|
|
48
|
+
}), [presenceRef, isPresenceExclusive, isExiting]);
|
|
49
|
+
return [isPresent, contextValue];
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
exports.usePresenceContext = usePresenceContext;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function useMergedRefs(refs: any): (node: any) => void;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2020, 2026
|
|
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
|
+
* Merges multiple refs into a single callback ref.
|
|
14
|
+
*
|
|
15
|
+
* This hook is useful when you need to attach multiple refs (for example, a ref
|
|
16
|
+
* passed from `forwardRef` and a local ref from `useRef`) to the same node. It
|
|
17
|
+
* accepts an array of refs and returns a callback ref that, when attached to a
|
|
18
|
+
* node, assigns that node to every ref in the array.
|
|
19
|
+
*/
|
|
20
|
+
const useMergedRefs = refs => {
|
|
21
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
22
|
+
const memoizedRefs = React.useMemo(() => refs, refs);
|
|
23
|
+
return React.useCallback(node => {
|
|
24
|
+
memoizedRefs.forEach(ref => {
|
|
25
|
+
if (typeof ref === 'function') {
|
|
26
|
+
ref(node);
|
|
27
|
+
} else if (ref) {
|
|
28
|
+
ref.current = node;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}, [memoizedRefs]);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
exports.useMergedRefs = useMergedRefs;
|
|
@@ -24,21 +24,5 @@ function useOverflowStringWidth(elementRef) {
|
|
|
24
24
|
}, [checkWidthOverflow, elementRef, innerText]);
|
|
25
25
|
return isOverflowing;
|
|
26
26
|
}
|
|
27
|
-
const useOverflowStringHeight = elementRef => {
|
|
28
|
-
const innerText = elementRef?.current?.innerText;
|
|
29
|
-
const [isOverflowing, setIsOverflowing] = React.useState();
|
|
30
|
-
const checkHeightOverflow = React.useCallback(() => {
|
|
31
|
-
const offsetHeight = elementRef?.current?.offsetHeight;
|
|
32
|
-
const scrollHeight = elementRef?.current?.scrollHeight;
|
|
33
|
-
if (offsetHeight && scrollHeight) {
|
|
34
|
-
setIsOverflowing(offsetHeight < scrollHeight);
|
|
35
|
-
}
|
|
36
|
-
}, [elementRef]);
|
|
37
|
-
React.useEffect(() => {
|
|
38
|
-
checkHeightOverflow();
|
|
39
|
-
}, [checkHeightOverflow, elementRef, innerText]);
|
|
40
|
-
return isOverflowing;
|
|
41
|
-
};
|
|
42
27
|
|
|
43
|
-
exports.useOverflowStringHeight = useOverflowStringHeight;
|
|
44
28
|
exports.useOverflowStringWidth = useOverflowStringWidth;
|
package/lib/index.js
CHANGED
|
@@ -51,6 +51,7 @@ var TagOverflow = require('./components/TagOverflow/TagOverflow.js');
|
|
|
51
51
|
var TagSet = require('./components/TagSet/TagSet.js');
|
|
52
52
|
var Tearsheet$1 = require('./components/Tearsheet/Tearsheet.js');
|
|
53
53
|
var TearsheetNarrow = require('./components/Tearsheet/TearsheetNarrow.js');
|
|
54
|
+
var TearsheetPresence = require('./components/Tearsheet/TearsheetPresence.js');
|
|
54
55
|
var WebTerminal = require('./components/WebTerminal/WebTerminal.js');
|
|
55
56
|
var WebTerminalContentWrapper = require('./components/WebTerminal/WebTerminalContentWrapper.js');
|
|
56
57
|
var index$2 = require('./components/WebTerminal/hooks/index.js');
|
|
@@ -195,6 +196,8 @@ exports.TagOverflow = TagOverflow.TagOverflow;
|
|
|
195
196
|
exports.TagSet = TagSet.TagSet;
|
|
196
197
|
exports.Tearsheet = Tearsheet$1.Tearsheet;
|
|
197
198
|
exports.TearsheetNarrow = TearsheetNarrow.TearsheetNarrow;
|
|
199
|
+
exports.TearsheetPresence = TearsheetPresence.TearsheetPresence;
|
|
200
|
+
exports.withTearsheetPresence = TearsheetPresence.withTearsheetPresence;
|
|
198
201
|
exports.WebTerminal = WebTerminal.WebTerminal;
|
|
199
202
|
exports.WebTerminalContentWrapper = WebTerminalContentWrapper.WebTerminalContentWrapper;
|
|
200
203
|
exports.WebTerminalProvider = index$2.WebTerminalProvider;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@carbon/ibm-products",
|
|
3
3
|
"description": "Carbon for IBM Products",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.84.0",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"module": "es/index.js",
|
|
@@ -67,23 +67,24 @@
|
|
|
67
67
|
"@babel/preset-env": "^7.26.9",
|
|
68
68
|
"@babel/preset-react": "^7.26.3",
|
|
69
69
|
"@babel/preset-typescript": "^7.26.0",
|
|
70
|
-
"@carbon/styles": "^1.
|
|
70
|
+
"@carbon/styles": "^1.100.0",
|
|
71
71
|
"@figma/code-connect": "^1.3.5",
|
|
72
72
|
"@ibm/telemetry-js-config-generator": "^2.0.1",
|
|
73
73
|
"@percy/cli": "^1.31.0",
|
|
74
|
-
"@percy/storybook": "^
|
|
74
|
+
"@percy/storybook": "^10.0.0",
|
|
75
75
|
"@rollup/plugin-babel": "^6.0.4",
|
|
76
76
|
"@rollup/plugin-commonjs": "^29.0.0",
|
|
77
77
|
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
78
78
|
"@rollup/plugin-typescript": "^12.1.2",
|
|
79
|
-
"@storybook/addon-a11y": "^9.1.
|
|
80
|
-
"@storybook/addon-docs": "^9.1.
|
|
81
|
-
"@storybook/addon-links": "^9.1.
|
|
79
|
+
"@storybook/addon-a11y": "^9.1.15",
|
|
80
|
+
"@storybook/addon-docs": "^9.1.15",
|
|
81
|
+
"@storybook/addon-links": "^9.1.15",
|
|
82
82
|
"@storybook/csf": "^0.1.13",
|
|
83
|
-
"@storybook/react-vite": "^9.1.
|
|
83
|
+
"@storybook/react-vite": "^9.1.15",
|
|
84
84
|
"@types/react-table": "^7.7.20",
|
|
85
|
+
"@vitejs/plugin-react": "^5.0.0",
|
|
85
86
|
"babel-plugin-dev-expression": "^0.2.3",
|
|
86
|
-
"babel-preset-ibm-cloud-cognitive": "^0.
|
|
87
|
+
"babel-preset-ibm-cloud-cognitive": "^0.42.0",
|
|
87
88
|
"change-case": "5.4.4",
|
|
88
89
|
"classnames": "^2.5.1",
|
|
89
90
|
"copyfiles": "^2.4.1",
|
|
@@ -91,7 +92,7 @@
|
|
|
91
92
|
"fs-extra": "^11.3.0",
|
|
92
93
|
"glob": "^11.0.1",
|
|
93
94
|
"jest": "^29.7.0",
|
|
94
|
-
"jest-config-ibm-cloud-cognitive": "^1.
|
|
95
|
+
"jest-config-ibm-cloud-cognitive": "^1.43.0",
|
|
95
96
|
"jest-environment-jsdom": "^29.7.0",
|
|
96
97
|
"namor": "^1.1.2",
|
|
97
98
|
"npm-run-all2": "^8.0.0",
|
|
@@ -102,7 +103,7 @@
|
|
|
102
103
|
"rollup-plugin-preserve-directives": "^0.4.0",
|
|
103
104
|
"rollup-plugin-strip-banner": "^3.1.0",
|
|
104
105
|
"sass": "^1.93.2",
|
|
105
|
-
"storybook": "^9.1.
|
|
106
|
+
"storybook": "^9.1.15",
|
|
106
107
|
"storybook-addon-accessibility-checker": ">=9.2.0-rc.0",
|
|
107
108
|
"typescript-config-carbon": "^0.9.0",
|
|
108
109
|
"vite": "^7.0.0",
|
|
@@ -111,11 +112,11 @@
|
|
|
111
112
|
"dependencies": {
|
|
112
113
|
"@babel/runtime": "^7.26.10",
|
|
113
114
|
"@carbon-labs/react-resizer": "^0.10.0",
|
|
114
|
-
"@carbon/feature-flags": "^0.
|
|
115
|
-
"@carbon/ibm-products-styles": "^2.
|
|
115
|
+
"@carbon/feature-flags": "^1.0.0",
|
|
116
|
+
"@carbon/ibm-products-styles": "^2.80.0",
|
|
116
117
|
"@carbon/telemetry": "^0.1.0",
|
|
117
|
-
"@carbon/utilities": "^0.
|
|
118
|
-
"@carbon/utilities-react": "0.
|
|
118
|
+
"@carbon/utilities": "^0.16.0",
|
|
119
|
+
"@carbon/utilities-react": "0.19.0",
|
|
119
120
|
"@dnd-kit/core": "^6.3.1",
|
|
120
121
|
"@dnd-kit/modifiers": "^9.0.0",
|
|
121
122
|
"@dnd-kit/sortable": "^10.0.0",
|
|
@@ -125,14 +126,14 @@
|
|
|
125
126
|
"react-window": "^1.8.11"
|
|
126
127
|
},
|
|
127
128
|
"peerDependencies": {
|
|
128
|
-
"@carbon/grid": "^11.
|
|
129
|
-
"@carbon/layout": "^11.
|
|
130
|
-
"@carbon/motion": "^11.
|
|
131
|
-
"@carbon/react": "^1.
|
|
132
|
-
"@carbon/themes": "^11.
|
|
133
|
-
"@carbon/type": "^11.
|
|
129
|
+
"@carbon/grid": "^11.50.0",
|
|
130
|
+
"@carbon/layout": "^11.48.0",
|
|
131
|
+
"@carbon/motion": "^11.41.0",
|
|
132
|
+
"@carbon/react": "^1.101.0",
|
|
133
|
+
"@carbon/themes": "^11.68.0",
|
|
134
|
+
"@carbon/type": "^11.54.0",
|
|
134
135
|
"react": "^16.8.6 || ^17.0.1 || ^18.2.0 || ^19.0.0",
|
|
135
136
|
"react-dom": "^16.8.6 || ^17.0.1 || ^18.2.0 || ^19.0.0"
|
|
136
137
|
},
|
|
137
|
-
"gitHead": "
|
|
138
|
+
"gitHead": "7b0c5737d123755ee2ed937568fcd568e9c76b3f"
|
|
138
139
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//
|
|
2
|
-
// Copyright IBM Corp. 2021,
|
|
2
|
+
// Copyright IBM Corp. 2021, 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.
|
|
@@ -10,19 +10,21 @@
|
|
|
10
10
|
@use '@carbon/styles/scss/components/button/tokens' as *;
|
|
11
11
|
@use '@carbon/styles/scss/spacing' as *;
|
|
12
12
|
@use '@carbon/styles/scss/type';
|
|
13
|
+
@use '@carbon/styles/scss/config' as carbon-config;
|
|
14
|
+
|
|
13
15
|
@use '../../global/styles/project-settings' as c4p-settings;
|
|
14
16
|
|
|
15
17
|
$block-class: #{c4p-settings.$pkg-prefix}--apikey-modal;
|
|
16
18
|
|
|
17
|
-
.#{$block-class} .#{
|
|
19
|
+
.#{$block-class} .#{carbon-config.$prefix}--modal-close {
|
|
18
20
|
display: none;
|
|
19
21
|
}
|
|
20
22
|
|
|
21
|
-
.#{$block-class} .#{
|
|
23
|
+
.#{$block-class} .#{carbon-config.$prefix}--inline-loading {
|
|
22
24
|
min-block-size: 3rem; // increasing the height from 2 to 3 resolves an issue where the scroll bar bounces
|
|
23
25
|
}
|
|
24
26
|
|
|
25
|
-
.#{$block-class} .#{
|
|
27
|
+
.#{$block-class} .#{carbon-config.$prefix}--modal-content {
|
|
26
28
|
padding-inline-end: $spacing-05;
|
|
27
29
|
}
|
|
28
30
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//
|
|
2
|
-
// Copyright IBM Corp. 2020,
|
|
2
|
+
// Copyright IBM Corp. 2020, 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.
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
@use '@carbon/styles/scss/spacing' as *;
|
|
10
10
|
@use '@carbon/styles/scss/type';
|
|
11
11
|
@use '@carbon/type/scss/font-family' as *;
|
|
12
|
+
@use '@carbon/styles/scss/config' as carbon-config;
|
|
12
13
|
|
|
13
14
|
// Standard imports.
|
|
14
15
|
@use '../../global/styles/project-settings' as c4p-settings;
|
|
@@ -16,7 +17,7 @@
|
|
|
16
17
|
// The block part of our conventional BEM class names (blockClass__E--M).
|
|
17
18
|
$block-class: #{c4p-settings.$pkg-prefix}--about-modal;
|
|
18
19
|
|
|
19
|
-
.#{$block-class} .#{
|
|
20
|
+
.#{$block-class} .#{carbon-config.$prefix}--modal-container {
|
|
20
21
|
grid-template-rows: auto auto 1fr auto;
|
|
21
22
|
}
|
|
22
23
|
|
|
@@ -47,14 +48,13 @@ $block-class: #{c4p-settings.$pkg-prefix}--about-modal;
|
|
|
47
48
|
padding-block-start: 0;
|
|
48
49
|
padding-inline: $spacing-05 20%;
|
|
49
50
|
|
|
50
|
-
&:not(.#{
|
|
51
|
+
&:not(.#{carbon-config.$prefix}--modal-scroll-content) {
|
|
51
52
|
margin-block-end: $spacing-06;
|
|
52
53
|
padding-block-end: 0;
|
|
53
54
|
}
|
|
54
55
|
}
|
|
55
56
|
|
|
56
|
-
.#{$block-class}
|
|
57
|
-
.#{c4p-settings.$carbon-prefix}--modal-content--overflow-indicator {
|
|
57
|
+
.#{$block-class} .#{carbon-config.$prefix}--modal-content--overflow-indicator {
|
|
58
58
|
background-image: linear-gradient(to bottom, #00000000, $layer-01);
|
|
59
59
|
inset-block-end: #{$spacing-06};
|
|
60
60
|
}
|
|
@@ -41,11 +41,13 @@ $block-class-overflow-items: #{$_block-class}-overflow-items;
|
|
|
41
41
|
|
|
42
42
|
.#{$block-class-overflow-items}__item-content {
|
|
43
43
|
display: flex;
|
|
44
|
+
align-items: center;
|
|
44
45
|
justify-content: space-between;
|
|
45
46
|
inline-size: 100%;
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
.#{$block-class-overflow-items}__item svg {
|
|
50
|
+
flex-shrink: 0;
|
|
49
51
|
margin: 0 $spacing-02;
|
|
50
52
|
}
|
|
51
53
|
}
|