@carbon/react 1.100.0 → 1.101.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/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +966 -966
- package/es/components/AILabel/index.d.ts +1 -1
- package/es/components/AILabel/index.js +1 -12
- package/es/components/Checkbox/Checkbox.js +5 -3
- package/es/components/CheckboxGroup/CheckboxGroup.js +4 -3
- package/es/components/CodeSnippet/CodeSnippet.d.ts +1 -1
- package/es/components/ComboBox/ComboBox.js +18 -10
- package/es/components/ComboButton/index.d.ts +1 -1
- package/es/components/ComboButton/index.js +3 -2
- package/es/components/ComposedModal/ComposedModal.js +17 -22
- package/es/components/ComposedModal/ModalHeader.d.ts +2 -2
- package/es/components/ComposedModal/ModalHeader.js +1 -1
- package/es/components/Copy/Copy.d.ts +1 -1
- package/es/components/CopyButton/CopyButton.d.ts +1 -1
- package/es/components/DataTable/DataTable.d.ts +2 -0
- package/es/components/DataTable/DataTable.js +6 -5
- package/es/components/DataTable/Table.d.ts +1 -1
- package/es/components/DataTable/Table.js +10 -4
- package/es/components/DataTable/state/sorting.d.ts +4 -2
- package/es/components/FileUploader/FileUploaderItem.d.ts +1 -1
- package/es/components/FileUploader/FileUploaderItem.js +3 -2
- package/es/components/Menu/Menu.js +8 -4
- package/es/components/Menu/MenuItem.d.ts +5 -1
- package/es/components/Menu/MenuItem.js +11 -1
- package/es/components/MenuButton/index.d.ts +1 -1
- package/es/components/MenuButton/index.js +3 -2
- package/es/components/MultiSelect/FilterableMultiSelect.d.ts +1 -1
- package/es/components/MultiSelect/FilterableMultiSelect.js +7 -5
- package/es/components/MultiSelect/MultiSelect.js +8 -4
- package/es/components/Notification/Notification.js +2 -1
- package/es/components/NumberInput/NumberInput.d.ts +1 -1
- package/es/components/NumberInput/NumberInput.js +5 -4
- package/es/components/OverflowMenu/OverflowMenu.d.ts +1 -0
- package/es/components/OverflowMenu/OverflowMenu.js +8 -4
- package/es/components/PageHeader/PageHeader.d.ts +1 -1
- package/es/components/PageHeader/PageHeader.js +5 -5
- package/es/components/RadioButtonGroup/RadioButtonGroup.js +4 -3
- package/es/components/Select/Select.js +2 -1
- package/es/components/StructuredList/StructuredList.d.ts +1 -1
- package/es/components/StructuredList/StructuredList.js +2 -4
- package/es/components/Tabs/Tabs.d.ts +2 -2
- package/es/components/Tabs/Tabs.js +20 -26
- package/es/components/Tag/DismissibleTag.js +3 -2
- package/es/components/Tag/OperationalTag.js +3 -2
- package/es/components/Tag/SelectableTag.js +3 -2
- package/es/components/Tag/Tag.js +3 -2
- package/es/components/TextArea/TextArea.d.ts +1 -1
- package/es/components/TextArea/TextArea.js +6 -5
- package/es/components/TextInput/ControlledPasswordInput.js +7 -6
- package/es/components/TextInput/PasswordInput.js +5 -6
- package/es/components/TextInput/TextInput.js +4 -4
- package/es/components/TimePicker/TimePicker.js +2 -2
- package/es/components/Tooltip/DefinitionTooltip.d.ts +1 -1
- package/es/components/Tooltip/DefinitionTooltip.js +3 -2
- package/es/internal/useId.js +3 -4
- package/es/internal/usePresence.js +3 -2
- package/es/internal/useResizeObserver.d.ts +1 -1
- package/es/internal/useResizeObserver.js +5 -7
- package/es/tools/events.d.ts +1 -1
- package/lib/components/AILabel/index.d.ts +1 -1
- package/lib/components/AILabel/index.js +1 -12
- package/lib/components/Checkbox/Checkbox.js +5 -3
- package/lib/components/CheckboxGroup/CheckboxGroup.js +4 -3
- package/lib/components/CodeSnippet/CodeSnippet.d.ts +1 -1
- package/lib/components/ComboBox/ComboBox.js +18 -10
- package/lib/components/ComboButton/index.d.ts +1 -1
- package/lib/components/ComboButton/index.js +2 -1
- package/lib/components/ComposedModal/ComposedModal.js +16 -21
- package/lib/components/ComposedModal/ModalHeader.d.ts +2 -2
- package/lib/components/ComposedModal/ModalHeader.js +1 -1
- package/lib/components/Copy/Copy.d.ts +1 -1
- package/lib/components/CopyButton/CopyButton.d.ts +1 -1
- package/lib/components/DataTable/DataTable.d.ts +2 -0
- package/lib/components/DataTable/DataTable.js +6 -5
- package/lib/components/DataTable/Table.d.ts +1 -1
- package/lib/components/DataTable/Table.js +10 -4
- package/lib/components/DataTable/state/sorting.d.ts +4 -2
- package/lib/components/FileUploader/FileUploaderItem.d.ts +1 -1
- package/lib/components/FileUploader/FileUploaderItem.js +2 -1
- package/lib/components/Menu/Menu.js +7 -3
- package/lib/components/Menu/MenuItem.d.ts +5 -1
- package/lib/components/Menu/MenuItem.js +11 -1
- package/lib/components/MenuButton/index.d.ts +1 -1
- package/lib/components/MenuButton/index.js +2 -1
- package/lib/components/MultiSelect/FilterableMultiSelect.d.ts +1 -1
- package/lib/components/MultiSelect/FilterableMultiSelect.js +6 -4
- package/lib/components/MultiSelect/MultiSelect.js +7 -3
- package/lib/components/Notification/Notification.js +2 -1
- package/lib/components/NumberInput/NumberInput.d.ts +1 -1
- package/lib/components/NumberInput/NumberInput.js +5 -4
- package/lib/components/OverflowMenu/OverflowMenu.d.ts +1 -0
- package/lib/components/OverflowMenu/OverflowMenu.js +7 -3
- package/lib/components/PageHeader/PageHeader.d.ts +1 -1
- package/lib/components/PageHeader/PageHeader.js +4 -4
- package/lib/components/RadioButtonGroup/RadioButtonGroup.js +4 -3
- package/lib/components/Select/Select.js +2 -1
- package/lib/components/StructuredList/StructuredList.d.ts +1 -1
- package/lib/components/StructuredList/StructuredList.js +2 -4
- package/lib/components/Tabs/Tabs.d.ts +2 -2
- package/lib/components/Tabs/Tabs.js +15 -21
- package/lib/components/Tag/DismissibleTag.js +2 -1
- package/lib/components/Tag/OperationalTag.js +2 -1
- package/lib/components/Tag/SelectableTag.js +2 -1
- package/lib/components/Tag/Tag.js +2 -1
- package/lib/components/TextArea/TextArea.d.ts +1 -1
- package/lib/components/TextArea/TextArea.js +6 -5
- package/lib/components/TextInput/ControlledPasswordInput.js +7 -6
- package/lib/components/TextInput/PasswordInput.js +5 -6
- package/lib/components/TextInput/TextInput.js +4 -4
- package/lib/components/TimePicker/TimePicker.js +2 -2
- package/lib/components/Tooltip/DefinitionTooltip.d.ts +1 -1
- package/lib/components/Tooltip/DefinitionTooltip.js +3 -2
- package/lib/internal/useId.js +2 -3
- package/lib/internal/usePresence.js +2 -1
- package/lib/internal/useResizeObserver.d.ts +1 -1
- package/lib/internal/useResizeObserver.js +4 -6
- package/lib/tools/events.d.ts +1 -1
- package/package.json +8 -8
|
@@ -11,7 +11,7 @@ import cx from 'classnames';
|
|
|
11
11
|
import Downshift, { useCombobox, useMultipleSelection } from 'downshift';
|
|
12
12
|
import isEqual from 'react-fast-compare';
|
|
13
13
|
import PropTypes from 'prop-types';
|
|
14
|
-
import React, { forwardRef, useContext, useRef, useState, useMemo, useCallback,
|
|
14
|
+
import React, { forwardRef, useContext, useRef, useState, useMemo, useCallback, useEffect, cloneElement } from 'react';
|
|
15
15
|
import { defaultFilterItems } from './filter.js';
|
|
16
16
|
import { sortingPropTypes } from './MultiSelectPropTypes.js';
|
|
17
17
|
import ListBox from '../ListBox/index.js';
|
|
@@ -34,6 +34,7 @@ import { AILabel } from '../AILabel/index.js';
|
|
|
34
34
|
import { defaultItemToString } from '../../internal/defaultItemToString.js';
|
|
35
35
|
import { isComponentElement } from '../../internal/utils.js';
|
|
36
36
|
import { useNormalizedInputProps } from '../../internal/useNormalizedInputProps.js';
|
|
37
|
+
import useIsomorphicEffect from '../../internal/useIsomorphicEffect.js';
|
|
37
38
|
import { ListBoxTypePropType, ListBoxSizePropType } from '../ListBox/ListBoxPropTypes.js';
|
|
38
39
|
|
|
39
40
|
const {
|
|
@@ -189,7 +190,7 @@ const FilterableMultiSelect = /*#__PURE__*/forwardRef(function FilterableMultiSe
|
|
|
189
190
|
}), hide()],
|
|
190
191
|
whileElementsMounted: autoUpdate
|
|
191
192
|
} : {});
|
|
192
|
-
|
|
193
|
+
useIsomorphicEffect(() => {
|
|
193
194
|
if (autoAlign) {
|
|
194
195
|
const updatedFloatingStyles = {
|
|
195
196
|
...floatingStyles,
|
|
@@ -259,7 +260,8 @@ const FilterableMultiSelect = /*#__PURE__*/forwardRef(function FilterableMultiSe
|
|
|
259
260
|
[`${prefix}--list-box__wrapper--decorator`]: decorator,
|
|
260
261
|
[`${prefix}--autoalign`]: autoAlign
|
|
261
262
|
});
|
|
262
|
-
const
|
|
263
|
+
const hasHelper = typeof helperText !== 'undefined' && helperText !== null;
|
|
264
|
+
const helperId = !hasHelper ? undefined : `filterablemultiselect-helper-text-${filterableMultiSelectInstanceId}`;
|
|
263
265
|
const labelId = `${id}-label`;
|
|
264
266
|
const titleClasses = cx({
|
|
265
267
|
[`${prefix}--label`]: true,
|
|
@@ -275,10 +277,10 @@ const FilterableMultiSelect = /*#__PURE__*/forwardRef(function FilterableMultiSe
|
|
|
275
277
|
[`${prefix}--text-input--empty`]: !inputValue,
|
|
276
278
|
[`${prefix}--text-input--light`]: light
|
|
277
279
|
});
|
|
278
|
-
const helper =
|
|
280
|
+
const helper = hasHelper && /*#__PURE__*/React.createElement("div", {
|
|
279
281
|
id: helperId,
|
|
280
282
|
className: helperClasses
|
|
281
|
-
}, helperText)
|
|
283
|
+
}, helperText);
|
|
282
284
|
const menuId = `${id}__menu`;
|
|
283
285
|
const inputId = `${id}-input`;
|
|
284
286
|
useEffect(() => {
|
|
@@ -11,7 +11,7 @@ import cx from 'classnames';
|
|
|
11
11
|
import { useSelect } from 'downshift';
|
|
12
12
|
import isEqual from 'react-fast-compare';
|
|
13
13
|
import PropTypes from 'prop-types';
|
|
14
|
-
import React, { useMemo, useContext, useState,
|
|
14
|
+
import React, { useMemo, useContext, useState, useRef, isValidElement, useCallback, cloneElement } from 'react';
|
|
15
15
|
import ListBox from '../ListBox/index.js';
|
|
16
16
|
import { sortingPropTypes } from './MultiSelectPropTypes.js';
|
|
17
17
|
import { defaultSortItems, defaultCompareItems } from './tools/sorting.js';
|
|
@@ -33,6 +33,7 @@ import { AILabel } from '../AILabel/index.js';
|
|
|
33
33
|
import { defaultItemToString } from '../../internal/defaultItemToString.js';
|
|
34
34
|
import { isComponentElement } from '../../internal/utils.js';
|
|
35
35
|
import { useNormalizedInputProps } from '../../internal/useNormalizedInputProps.js';
|
|
36
|
+
import useIsomorphicEffect from '../../internal/useIsomorphicEffect.js';
|
|
36
37
|
import { ListBoxTypePropType, ListBoxSizePropType } from '../ListBox/ListBoxPropTypes.js';
|
|
37
38
|
|
|
38
39
|
const {
|
|
@@ -143,7 +144,7 @@ const MultiSelect = /*#__PURE__*/React.forwardRef(({
|
|
|
143
144
|
}), autoAlign && hide()],
|
|
144
145
|
whileElementsMounted: autoUpdate
|
|
145
146
|
} : {});
|
|
146
|
-
|
|
147
|
+
useIsomorphicEffect(() => {
|
|
147
148
|
if (enableFloatingStyles) {
|
|
148
149
|
const updatedFloatingStyles = {
|
|
149
150
|
...floatingStyles,
|
|
@@ -386,8 +387,11 @@ const MultiSelect = /*#__PURE__*/React.forwardRef(({
|
|
|
386
387
|
[`${prefix}--list-box__field--wrapper--input-focused`]: inputFocused
|
|
387
388
|
});
|
|
388
389
|
const handleFocus = evt => {
|
|
389
|
-
|
|
390
|
-
|
|
390
|
+
if (evt.target.classList.contains(`${prefix}--tag__close-icon`)) {
|
|
391
|
+
setIsFocused(false);
|
|
392
|
+
} else {
|
|
393
|
+
setIsFocused(evt.type === 'focus' ? true : false);
|
|
394
|
+
}
|
|
391
395
|
};
|
|
392
396
|
const readOnlyEventHandlers = readOnly ? {
|
|
393
397
|
onClick: evt => {
|
|
@@ -572,7 +572,8 @@ function ActionableNotification({
|
|
|
572
572
|
role: "link",
|
|
573
573
|
className: `${prefix}--visually-hidden`
|
|
574
574
|
}, "Focus sentinel"), /*#__PURE__*/React.createElement("div", {
|
|
575
|
-
ref: innerModal
|
|
575
|
+
ref: innerModal,
|
|
576
|
+
className: `${prefix}--actionable-notification__focus-wrapper`
|
|
576
577
|
}, /*#__PURE__*/React.createElement("div", {
|
|
577
578
|
className: `${prefix}--actionable-notification__details`
|
|
578
579
|
}, /*#__PURE__*/React.createElement(NotificationIcon, {
|
|
@@ -564,10 +564,11 @@ const NumberInput = /*#__PURE__*/React.forwardRef((props, forwardRef) => {
|
|
|
564
564
|
onKeyUp: onKeyUp,
|
|
565
565
|
onKeyDown: e => {
|
|
566
566
|
if (type === 'text') {
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
567
|
+
if (match(e, ArrowUp)) {
|
|
568
|
+
handleStep(e, 'up');
|
|
569
|
+
} else if (match(e, ArrowDown)) {
|
|
570
|
+
handleStep(e, 'down');
|
|
571
|
+
}
|
|
571
572
|
}
|
|
572
573
|
if (rest?.onKeyDown) {
|
|
573
574
|
rest?.onKeyDown(e);
|
|
@@ -44,6 +44,7 @@ export interface OverflowMenuProps extends Omit<IconButtonProps, 'type' | 'aria-
|
|
|
44
44
|
*/
|
|
45
45
|
flipped?: boolean;
|
|
46
46
|
/**
|
|
47
|
+
* @deprecated Tab key is handled with event handler so no need for focus trap.
|
|
47
48
|
* Enable or disable focus trap behavior
|
|
48
49
|
*/
|
|
49
50
|
focusTrap?: boolean;
|
|
@@ -12,7 +12,7 @@ import cx from 'classnames';
|
|
|
12
12
|
import invariant from 'invariant';
|
|
13
13
|
import PropTypes from 'prop-types';
|
|
14
14
|
import { DIRECTION_TOP, DIRECTION_BOTTOM, FloatingMenu } from '../../internal/FloatingMenu.js';
|
|
15
|
-
import { ArrowUp, ArrowRight, ArrowDown, ArrowLeft, Escape } from '../../internal/keyboard/keys.js';
|
|
15
|
+
import { ArrowUp, ArrowRight, ArrowDown, ArrowLeft, Escape, Tab } from '../../internal/keyboard/keys.js';
|
|
16
16
|
import { matches } from '../../internal/keyboard/match.js';
|
|
17
17
|
import { noopFn } from '../../internal/noopFn.js';
|
|
18
18
|
import { PrefixContext } from '../../internal/usePrefix.js';
|
|
@@ -97,7 +97,7 @@ const OverflowMenu = /*#__PURE__*/forwardRef(({
|
|
|
97
97
|
className,
|
|
98
98
|
direction = DIRECTION_BOTTOM,
|
|
99
99
|
flipped = false,
|
|
100
|
-
focusTrap =
|
|
100
|
+
focusTrap = false,
|
|
101
101
|
iconClass,
|
|
102
102
|
iconDescription = 'Options',
|
|
103
103
|
id,
|
|
@@ -200,12 +200,15 @@ const OverflowMenu = /*#__PURE__*/forwardRef(({
|
|
|
200
200
|
evt.preventDefault();
|
|
201
201
|
}
|
|
202
202
|
|
|
203
|
-
// Close the overflow menu on escape
|
|
204
|
-
if (matches(evt, [Escape])) {
|
|
203
|
+
// Close the overflow menu on escape or tab.
|
|
204
|
+
if (matches(evt, [Escape, Tab])) {
|
|
205
205
|
closeMenuOnEscape();
|
|
206
206
|
|
|
207
207
|
// Stop the esc keypress from bubbling out and closing something it shouldn't
|
|
208
208
|
evt.stopPropagation();
|
|
209
|
+
|
|
210
|
+
// Stop the tab key from making the browser focus somewhere else.
|
|
211
|
+
evt.preventDefault();
|
|
209
212
|
}
|
|
210
213
|
};
|
|
211
214
|
|
|
@@ -390,6 +393,7 @@ OverflowMenu.propTypes = {
|
|
|
390
393
|
*/
|
|
391
394
|
flipped: PropTypes.bool,
|
|
392
395
|
/**
|
|
396
|
+
* @deprecated Tab key is handled with event handler so no need for focus trap.
|
|
393
397
|
* Enable or disable focus trap behavior
|
|
394
398
|
*/
|
|
395
399
|
focusTrap: PropTypes.bool,
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
9
|
-
import React, { useRef, useState,
|
|
9
|
+
import React, { useRef, useState, useMemo, useEffect, useCallback } from 'react';
|
|
10
10
|
import PropTypes from 'prop-types';
|
|
11
11
|
import cx from 'classnames';
|
|
12
12
|
import { usePrefix } from '../../internal/usePrefix.js';
|
|
@@ -35,6 +35,7 @@ import '../Grid/Row.js';
|
|
|
35
35
|
import Column from '../Grid/Column.js';
|
|
36
36
|
import '../Grid/ColumnHang.js';
|
|
37
37
|
import '../Grid/GridContext.js';
|
|
38
|
+
import useIsomorphicEffect from '../../internal/useIsomorphicEffect.js';
|
|
38
39
|
|
|
39
40
|
/**
|
|
40
41
|
* ----------
|
|
@@ -130,9 +131,8 @@ const PageHeaderContent = /*#__PURE__*/React.forwardRef(({
|
|
|
130
131
|
setIsEllipsisApplied(element.offsetHeight < element.scrollHeight);
|
|
131
132
|
return element.offsetHeight < element.scrollHeight;
|
|
132
133
|
};
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
titleRef.current && isEllipsisActive(titleRef.current);
|
|
134
|
+
useIsomorphicEffect(() => {
|
|
135
|
+
if (titleRef.current) isEllipsisActive(titleRef.current);
|
|
136
136
|
}, [title]);
|
|
137
137
|
return /*#__PURE__*/React.createElement("div", _extends({
|
|
138
138
|
className: classNames,
|
|
@@ -220,7 +220,7 @@ const PageHeaderContentPageActions = ({
|
|
|
220
220
|
|
|
221
221
|
// need to set the grid columns width based on the menu button's width
|
|
222
222
|
// to avoid overlapping when resizing
|
|
223
|
-
|
|
223
|
+
useIsomorphicEffect(() => {
|
|
224
224
|
if (menuButtonVisibility && offsetRef.current) {
|
|
225
225
|
const width = offsetRef.current.offsetWidth;
|
|
226
226
|
document.documentElement.style.setProperty('--pageheader-title-grid-width', `${width}px`);
|
|
@@ -97,11 +97,12 @@ const RadioButtonGroup = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
97
97
|
const helperClasses = cx(`${prefix}--form__helper-text`, {
|
|
98
98
|
[`${prefix}--form__helper-text--disabled`]: disabled
|
|
99
99
|
});
|
|
100
|
-
const
|
|
101
|
-
const
|
|
100
|
+
const hasHelper = typeof helperText !== 'undefined' && helperText !== null;
|
|
101
|
+
const helperId = !hasHelper ? undefined : `radio-button-group-helper-text-${radioButtonGroupInstanceId}`;
|
|
102
|
+
const helper = hasHelper && /*#__PURE__*/React.createElement("div", {
|
|
102
103
|
id: helperId,
|
|
103
104
|
className: helperClasses
|
|
104
|
-
}, helperText)
|
|
105
|
+
}, helperText);
|
|
105
106
|
const divRef = useRef(null);
|
|
106
107
|
|
|
107
108
|
// AILabel is always size `mini`
|
|
@@ -94,7 +94,8 @@ const Select = /*#__PURE__*/forwardRef(({
|
|
|
94
94
|
const helperTextClasses = cx(`${prefix}--form__helper-text`, {
|
|
95
95
|
[`${prefix}--form__helper-text--disabled`]: normalizedProps.disabled
|
|
96
96
|
});
|
|
97
|
-
const
|
|
97
|
+
const hasHelper = typeof helperText !== 'undefined' && helperText !== null;
|
|
98
|
+
const helper = hasHelper ? /*#__PURE__*/React.createElement(Text, {
|
|
98
99
|
as: "div",
|
|
99
100
|
id: normalizedProps.helperId,
|
|
100
101
|
className: helperTextClasses
|
|
@@ -184,8 +184,7 @@ function StructuredListRow(props) {
|
|
|
184
184
|
ref: itemRef,
|
|
185
185
|
onClick: event => {
|
|
186
186
|
setSelectedRow?.(rowId);
|
|
187
|
-
|
|
188
|
-
onClick && onClick(event);
|
|
187
|
+
onClick?.(event);
|
|
189
188
|
if (selection) {
|
|
190
189
|
// focus items only when selection is enabled
|
|
191
190
|
setHasFocusWithin(true);
|
|
@@ -264,8 +263,7 @@ function StructuredListInput(props) {
|
|
|
264
263
|
value: row?.id ?? '',
|
|
265
264
|
onChange: event => {
|
|
266
265
|
setSelectedRow?.(event.target.value);
|
|
267
|
-
|
|
268
|
-
onChange && onChange(event);
|
|
266
|
+
onChange?.(event);
|
|
269
267
|
},
|
|
270
268
|
id: id ?? defaultId,
|
|
271
269
|
className: classes,
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright IBM Corp. 2016,
|
|
2
|
+
* Copyright IBM Corp. 2016, 2026
|
|
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
7
|
import PropTypes from 'prop-types';
|
|
8
|
-
import React, { type
|
|
8
|
+
import React, { type ComponentType, type HTMLAttributes, type HTMLElementType, type KeyboardEvent, type MouseEvent, type ReactNode } from 'react';
|
|
9
9
|
type DivAttributes = HTMLAttributes<HTMLDivElement>;
|
|
10
10
|
/**
|
|
11
11
|
* Tabs
|
|
@@ -10,14 +10,13 @@ import { Close, ChevronLeft, ChevronRight } from '@carbon/icons-react';
|
|
|
10
10
|
import { breakpoints } from '@carbon/layout';
|
|
11
11
|
import cx from 'classnames';
|
|
12
12
|
import PropTypes from 'prop-types';
|
|
13
|
-
import React, { forwardRef, createContext, useRef, useState, useMemo, isValidElement, useCallback, useEffect } from 'react';
|
|
13
|
+
import React, { forwardRef, createContext, useRef, useState, useMemo, isValidElement, Children, cloneElement, useCallback, useEffect } from 'react';
|
|
14
14
|
import '../Grid/FlexGrid.js';
|
|
15
15
|
import { Grid as GridAsGridComponent } from '../Grid/Grid.js';
|
|
16
16
|
import '../Grid/Row.js';
|
|
17
17
|
import '../Grid/Column.js';
|
|
18
18
|
import '../Grid/ColumnHang.js';
|
|
19
19
|
import '../Grid/GridContext.js';
|
|
20
|
-
import { isElement } from 'react-is';
|
|
21
20
|
import '../Tooltip/DefinitionTooltip.js';
|
|
22
21
|
import { Tooltip } from '../Tooltip/Tooltip.js';
|
|
23
22
|
import { useControllableState } from '../../internal/useControllableState.js';
|
|
@@ -34,6 +33,7 @@ import { useMatchMedia } from '../../internal/useMatchMedia.js';
|
|
|
34
33
|
import { Text } from '../Text/Text.js';
|
|
35
34
|
import '../Text/TextDirection.js';
|
|
36
35
|
import { BadgeIndicator } from '../BadgeIndicator/index.js';
|
|
36
|
+
import { isComponentElement } from '../../internal/utils.js';
|
|
37
37
|
import { debounce } from '../../node_modules/es-toolkit/dist/compat/function/debounce.js';
|
|
38
38
|
|
|
39
39
|
var _ChevronLeft, _ChevronRight, _BadgeIndicator;
|
|
@@ -269,14 +269,7 @@ function TabList({
|
|
|
269
269
|
const nextButton = useRef(null);
|
|
270
270
|
const [isScrollable, setIsScrollable] = useState(false);
|
|
271
271
|
const [scrollLeft, setScrollLeft] = useState(0);
|
|
272
|
-
|
|
273
|
-
if (contained) {
|
|
274
|
-
hasSecondaryLabelTabs = React.Children.toArray(children).some(child => {
|
|
275
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- https://github.com/carbon-design-system/carbon/issues/20452
|
|
276
|
-
const _child = child;
|
|
277
|
-
return /*#__PURE__*/React.isValidElement(child) && !!_child.props.secondaryLabel;
|
|
278
|
-
});
|
|
279
|
-
}
|
|
272
|
+
const hasSecondaryLabelTabs = contained && Children.toArray(children).some(child => isComponentElement(child, Tab) && typeof child.props.secondaryLabel !== 'undefined');
|
|
280
273
|
const isLg = useMatchMedia(lgMediaQuery);
|
|
281
274
|
const distributeWidth = fullWidth && contained && isLg && React.Children.toArray(children).length < 9;
|
|
282
275
|
const className = cx(`${prefix}--tabs`, {
|
|
@@ -487,17 +480,16 @@ function TabList({
|
|
|
487
480
|
onScroll: debouncedOnScroll,
|
|
488
481
|
onKeyDown: onKeyDown,
|
|
489
482
|
onBlur: handleBlur
|
|
490
|
-
}),
|
|
491
|
-
return !
|
|
483
|
+
}), Children.map(children, (child, index) => {
|
|
484
|
+
return ! /*#__PURE__*/isValidElement(child) ? null : /*#__PURE__*/React.createElement(TabContext.Provider, {
|
|
492
485
|
value: {
|
|
493
486
|
index,
|
|
494
487
|
hasSecondaryLabel: hasSecondaryLabelTabs,
|
|
495
488
|
contained
|
|
496
489
|
}
|
|
497
|
-
}, /*#__PURE__*/
|
|
498
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- https://github.com/carbon-design-system/carbon/issues/20452
|
|
499
|
-
child, {
|
|
490
|
+
}, /*#__PURE__*/cloneElement(child, {
|
|
500
491
|
ref: node => {
|
|
492
|
+
if (!node) return;
|
|
501
493
|
tabs.current[index] = node;
|
|
502
494
|
}
|
|
503
495
|
}));
|
|
@@ -641,8 +633,7 @@ function TabListVertical({
|
|
|
641
633
|
if (containerTop && containerHeight) {
|
|
642
634
|
// scrolls so selected tab is in view
|
|
643
635
|
if (selectedPositionTop - halfTabHeight < containerTop || selectedPositionTop - containerTop + verticalTabHeight + halfTabHeight > containerHeight) {
|
|
644
|
-
|
|
645
|
-
ref.current && ref.current.scrollTo({
|
|
636
|
+
ref.current?.scrollTo({
|
|
646
637
|
top: (selectedIndex - 1) * verticalTabHeight,
|
|
647
638
|
behavior: 'smooth'
|
|
648
639
|
});
|
|
@@ -690,16 +681,15 @@ function TabListVertical({
|
|
|
690
681
|
className: `${prefix}--tab--list`,
|
|
691
682
|
onKeyDown: onKeyDown,
|
|
692
683
|
onBlur: handleBlur
|
|
693
|
-
}),
|
|
694
|
-
return !
|
|
684
|
+
}), Children.map(children, (child, index) => {
|
|
685
|
+
return ! /*#__PURE__*/isValidElement(child) ? null : /*#__PURE__*/React.createElement(TabContext.Provider, {
|
|
695
686
|
value: {
|
|
696
687
|
index,
|
|
697
688
|
hasSecondaryLabel: false
|
|
698
689
|
}
|
|
699
|
-
}, /*#__PURE__*/
|
|
700
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- https://github.com/carbon-design-system/carbon/issues/20452
|
|
701
|
-
child, {
|
|
690
|
+
}, /*#__PURE__*/cloneElement(child, {
|
|
702
691
|
ref: node => {
|
|
692
|
+
if (!node) return;
|
|
703
693
|
tabs.current[index] = node;
|
|
704
694
|
}
|
|
705
695
|
}));
|
|
@@ -1045,7 +1035,11 @@ const IconTab = /*#__PURE__*/React.forwardRef(({
|
|
|
1045
1035
|
const value = useMemo(() => ({
|
|
1046
1036
|
badgeIndicator
|
|
1047
1037
|
}), [badgeIndicator]);
|
|
1048
|
-
const hasSize20 = /*#__PURE__*/isValidElement(children) &&
|
|
1038
|
+
const hasSize20 = /*#__PURE__*/isValidElement(children) &&
|
|
1039
|
+
// TODO: The interface allows `size` to be a string. Should this case be
|
|
1040
|
+
// handled here, or should the prop type be restricted to `number`
|
|
1041
|
+
// instead?
|
|
1042
|
+
children.props.size === 20;
|
|
1049
1043
|
const classNames = cx(`${prefix}--tabs__nav-item--icon-only`, customClassName, {
|
|
1050
1044
|
[`${prefix}--tabs__nav-item--icon-only__20`]: hasSize20
|
|
1051
1045
|
});
|
|
@@ -1176,10 +1170,10 @@ function TabPanels({
|
|
|
1176
1170
|
});
|
|
1177
1171
|
}
|
|
1178
1172
|
});
|
|
1179
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null,
|
|
1180
|
-
return !
|
|
1173
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, Children.map(children, (child, index) => {
|
|
1174
|
+
return ! /*#__PURE__*/isValidElement(child) ? null : /*#__PURE__*/React.createElement(TabPanelContext.Provider, {
|
|
1181
1175
|
value: index
|
|
1182
|
-
}, /*#__PURE__*/
|
|
1176
|
+
}, /*#__PURE__*/cloneElement(child, {
|
|
1183
1177
|
ref: element => {
|
|
1184
1178
|
refs.current[index] = element;
|
|
1185
1179
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
9
9
|
import PropTypes from 'prop-types';
|
|
10
|
-
import React, { forwardRef, useRef, useState,
|
|
10
|
+
import React, { forwardRef, useRef, useState, cloneElement } from 'react';
|
|
11
11
|
import cx from 'classnames';
|
|
12
12
|
import { useId } from '../../internal/useId.js';
|
|
13
13
|
import { usePrefix } from '../../internal/usePrefix.js';
|
|
@@ -22,6 +22,7 @@ import { isEllipsisActive } from './isEllipsisActive.js';
|
|
|
22
22
|
import { mergeRefs } from '../../tools/mergeRefs.js';
|
|
23
23
|
import { AILabel } from '../AILabel/index.js';
|
|
24
24
|
import { isComponentElement } from '../../internal/utils.js';
|
|
25
|
+
import useIsomorphicEffect from '../../internal/useIsomorphicEffect.js';
|
|
25
26
|
|
|
26
27
|
var _Close;
|
|
27
28
|
// eslint-disable-next-line react/display-name -- https://github.com/carbon-design-system/carbon/issues/20452
|
|
@@ -48,7 +49,7 @@ const DismissibleTag = /*#__PURE__*/forwardRef(({
|
|
|
48
49
|
const tagId = id || `tag-${useId()}`;
|
|
49
50
|
const tagClasses = cx(`${prefix}--tag--filter`, className);
|
|
50
51
|
const [isEllipsisApplied, setIsEllipsisApplied] = useState(false);
|
|
51
|
-
|
|
52
|
+
useIsomorphicEffect(() => {
|
|
52
53
|
const newElement = tagLabelRef.current?.getElementsByClassName(`${prefix}--tag__label`)[0];
|
|
53
54
|
setIsEllipsisApplied(isEllipsisActive(newElement));
|
|
54
55
|
}, [prefix, tagLabelRef]);
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
9
9
|
import PropTypes from 'prop-types';
|
|
10
|
-
import React, { forwardRef, useRef, useState
|
|
10
|
+
import React, { forwardRef, useRef, useState } from 'react';
|
|
11
11
|
import cx from 'classnames';
|
|
12
12
|
import { useId } from '../../internal/useId.js';
|
|
13
13
|
import { usePrefix } from '../../internal/usePrefix.js';
|
|
@@ -18,6 +18,7 @@ import { Text } from '../Text/Text.js';
|
|
|
18
18
|
import '../Text/TextDirection.js';
|
|
19
19
|
import { isEllipsisActive } from './isEllipsisActive.js';
|
|
20
20
|
import { mergeRefs } from '../../tools/mergeRefs.js';
|
|
21
|
+
import useIsomorphicEffect from '../../internal/useIsomorphicEffect.js';
|
|
21
22
|
|
|
22
23
|
const TYPES = {
|
|
23
24
|
red: 'Red',
|
|
@@ -48,7 +49,7 @@ const OperationalTag = /*#__PURE__*/forwardRef(({
|
|
|
48
49
|
const tagId = id || `tag-${useId()}`;
|
|
49
50
|
const tagClasses = cx(`${prefix}--tag--operational`, className);
|
|
50
51
|
const [isEllipsisApplied, setIsEllipsisApplied] = useState(false);
|
|
51
|
-
|
|
52
|
+
useIsomorphicEffect(() => {
|
|
52
53
|
const newElement = tagRef.current?.getElementsByClassName(`${prefix}--tag__label`)[0];
|
|
53
54
|
setIsEllipsisApplied(isEllipsisActive(newElement));
|
|
54
55
|
}, [prefix, tagRef]);
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
9
9
|
import PropTypes from 'prop-types';
|
|
10
|
-
import React, { forwardRef, useRef, useState
|
|
10
|
+
import React, { forwardRef, useRef, useState } from 'react';
|
|
11
11
|
import cx from 'classnames';
|
|
12
12
|
import { useId } from '../../internal/useId.js';
|
|
13
13
|
import { usePrefix } from '../../internal/usePrefix.js';
|
|
@@ -19,6 +19,7 @@ import '../Text/TextDirection.js';
|
|
|
19
19
|
import { isEllipsisActive } from './isEllipsisActive.js';
|
|
20
20
|
import { mergeRefs } from '../../tools/mergeRefs.js';
|
|
21
21
|
import { useControllableState } from '../../internal/useControllableState.js';
|
|
22
|
+
import useIsomorphicEffect from '../../internal/useIsomorphicEffect.js';
|
|
22
23
|
|
|
23
24
|
// eslint-disable-next-line react/display-name -- https://github.com/carbon-design-system/carbon/issues/20452
|
|
24
25
|
const SelectableTag = /*#__PURE__*/forwardRef(({
|
|
@@ -47,7 +48,7 @@ const SelectableTag = /*#__PURE__*/forwardRef(({
|
|
|
47
48
|
[`${prefix}--tag--selectable-selected`]: selectedTag
|
|
48
49
|
});
|
|
49
50
|
const [isEllipsisApplied, setIsEllipsisApplied] = useState(false);
|
|
50
|
-
|
|
51
|
+
useIsomorphicEffect(() => {
|
|
51
52
|
const newElement = tagRef.current?.getElementsByClassName(`${prefix}--tag__label`)[0];
|
|
52
53
|
setIsEllipsisApplied(isEllipsisActive(newElement));
|
|
53
54
|
}, [prefix, tagRef]);
|
package/es/components/Tag/Tag.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
9
9
|
import PropTypes from 'prop-types';
|
|
10
|
-
import React, { useRef, useState,
|
|
10
|
+
import React, { useRef, useState, cloneElement } from 'react';
|
|
11
11
|
import cx from 'classnames';
|
|
12
12
|
import { Close } from '@carbon/icons-react';
|
|
13
13
|
import { useId } from '../../internal/useId.js';
|
|
@@ -21,6 +21,7 @@ import { isEllipsisActive } from './isEllipsisActive.js';
|
|
|
21
21
|
import { useMergedRefs } from '../../internal/useMergedRefs.js';
|
|
22
22
|
import { AILabel } from '../AILabel/index.js';
|
|
23
23
|
import { isComponentElement } from '../../internal/utils.js';
|
|
24
|
+
import useIsomorphicEffect from '../../internal/useIsomorphicEffect.js';
|
|
24
25
|
|
|
25
26
|
var _Close;
|
|
26
27
|
const TYPES = {
|
|
@@ -76,7 +77,7 @@ const TagBase = /*#__PURE__*/React.forwardRef(({
|
|
|
76
77
|
// eslint-disable-next-line react-hooks/rules-of-hooks -- https://github.com/carbon-design-system/carbon/issues/20452
|
|
77
78
|
const tagId = id || `tag-${useId()}`;
|
|
78
79
|
const [isEllipsisApplied, setIsEllipsisApplied] = useState(false);
|
|
79
|
-
|
|
80
|
+
useIsomorphicEffect(() => {
|
|
80
81
|
const newElement = tagRef.current?.getElementsByClassName(`${prefix}--tag__label`)[0];
|
|
81
82
|
setIsEllipsisApplied(isEllipsisActive(newElement));
|
|
82
83
|
}, [prefix, tagRef]);
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
import React, { type ReactNode } from 'react';
|
|
8
|
-
export interface TextAreaProps extends React.
|
|
8
|
+
export interface TextAreaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
9
9
|
/**
|
|
10
10
|
* Provide a custom className that is applied directly to the underlying
|
|
11
11
|
* `<textarea>` node
|
|
@@ -193,24 +193,25 @@ const TextArea = frFn((props, forwardRef) => {
|
|
|
193
193
|
const helperTextClasses = cx(`${prefix}--form__helper-text`, {
|
|
194
194
|
[`${prefix}--form__helper-text--disabled`]: disabled
|
|
195
195
|
});
|
|
196
|
-
const label = labelText
|
|
196
|
+
const label = typeof labelText !== 'undefined' && labelText !== null && /*#__PURE__*/React.createElement(Text, {
|
|
197
197
|
as: "label",
|
|
198
198
|
htmlFor: id,
|
|
199
199
|
className: labelClasses
|
|
200
|
-
}, labelText)
|
|
200
|
+
}, labelText);
|
|
201
201
|
const counter = enableCounter && maxCount && (counterMode === 'character' || counterMode === 'word') ? /*#__PURE__*/React.createElement(Text, {
|
|
202
202
|
as: "div",
|
|
203
203
|
className: counterClasses,
|
|
204
204
|
"aria-hidden": "true"
|
|
205
205
|
}, `${textCount}/${maxCount}`) : null;
|
|
206
206
|
const counterDescriptionId = enableCounter && maxCount ? `${id}-counter-desc` : undefined;
|
|
207
|
-
const
|
|
208
|
-
const
|
|
207
|
+
const hasHelper = typeof helperText !== 'undefined' && helperText !== null;
|
|
208
|
+
const helperId = !hasHelper ? undefined : `text-area-helper-text-${textAreaInstanceId}`;
|
|
209
|
+
const helper = hasHelper && /*#__PURE__*/React.createElement(Text, {
|
|
209
210
|
as: "div",
|
|
210
211
|
id: helperId,
|
|
211
212
|
className: helperTextClasses,
|
|
212
213
|
ref: helperTextRef
|
|
213
|
-
}, helperText)
|
|
214
|
+
}, helperText);
|
|
214
215
|
const errorId = id + '-error-msg';
|
|
215
216
|
const error = invalid ? /*#__PURE__*/React.createElement(Text, {
|
|
216
217
|
as: "div",
|
|
@@ -71,10 +71,10 @@ const ControlledPasswordInput = /*#__PURE__*/forwardRef(({
|
|
|
71
71
|
const helperTextClasses = cx(`${prefix}--form__helper-text`, {
|
|
72
72
|
[`${prefix}--form__helper-text--disabled`]: disabled
|
|
73
73
|
});
|
|
74
|
-
const label = labelText
|
|
74
|
+
const label = typeof labelText !== 'undefined' && labelText !== null && /*#__PURE__*/React.createElement("label", {
|
|
75
75
|
htmlFor: id,
|
|
76
76
|
className: labelClasses
|
|
77
|
-
}, labelText)
|
|
77
|
+
}, labelText);
|
|
78
78
|
const error = invalid ? /*#__PURE__*/React.createElement("div", {
|
|
79
79
|
className: `${prefix}--form-requirement`,
|
|
80
80
|
id: errorId
|
|
@@ -89,12 +89,13 @@ const ControlledPasswordInput = /*#__PURE__*/forwardRef(({
|
|
|
89
89
|
[`${prefix}--tooltip--${tooltipPosition}`]: tooltipPosition,
|
|
90
90
|
[`${prefix}--tooltip--align-${tooltipAlignment}`]: tooltipAlignment
|
|
91
91
|
});
|
|
92
|
-
const
|
|
92
|
+
const hasHelper = typeof helperText !== 'undefined' && helperText !== null;
|
|
93
|
+
const helperId = !hasHelper ? undefined : `controlled-password-helper-text-${controlledPasswordInstanceId}`;
|
|
93
94
|
const input = /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("input", _extends({}, getTextInputProps({
|
|
94
95
|
invalid,
|
|
95
96
|
sharedTextInputProps,
|
|
96
97
|
invalidId: errorId,
|
|
97
|
-
hasHelper: !error &&
|
|
98
|
+
hasHelper: !error && hasHelper,
|
|
98
99
|
helperId
|
|
99
100
|
}), {
|
|
100
101
|
"data-toggle-password-visibility": type === 'password'
|
|
@@ -105,10 +106,10 @@ const ControlledPasswordInput = /*#__PURE__*/forwardRef(({
|
|
|
105
106
|
}, /*#__PURE__*/React.createElement("span", {
|
|
106
107
|
className: `${prefix}--assistive-text`
|
|
107
108
|
}, passwordIsVisible ? hidePasswordLabel : showPasswordLabel), passwordVisibilityIcon));
|
|
108
|
-
const helper =
|
|
109
|
+
const helper = hasHelper && /*#__PURE__*/React.createElement("div", {
|
|
109
110
|
id: helperId,
|
|
110
111
|
className: helperTextClasses
|
|
111
|
-
}, helperText)
|
|
112
|
+
}, helperText);
|
|
112
113
|
return /*#__PURE__*/React.createElement("div", {
|
|
113
114
|
className: `${prefix}--form-item ${prefix}--text-input-wrapper ${prefix}--password-input-wrapper`
|
|
114
115
|
}, label, /*#__PURE__*/React.createElement("div", {
|
|
@@ -61,8 +61,7 @@ const PasswordInput = /*#__PURE__*/forwardRef(({
|
|
|
61
61
|
} = useContext(FormContext);
|
|
62
62
|
const handleTogglePasswordVisibility = event => {
|
|
63
63
|
setInputType(inputType === 'password' ? 'text' : 'password');
|
|
64
|
-
|
|
65
|
-
onTogglePasswordVisibility && onTogglePasswordVisibility(event);
|
|
64
|
+
onTogglePasswordVisibility?.(event);
|
|
66
65
|
};
|
|
67
66
|
const textInputClasses = cx(`${prefix}--text-input`, `${prefix}--password-input`, className, {
|
|
68
67
|
[`${prefix}--text-input--light`]: light,
|
|
@@ -117,14 +116,14 @@ const PasswordInput = /*#__PURE__*/forwardRef(({
|
|
|
117
116
|
[`${prefix}--text-input__invalid-icon`]: normalizedProps.invalid || normalizedProps.warn,
|
|
118
117
|
[`${prefix}--text-input__invalid-icon--warning`]: normalizedProps.warn
|
|
119
118
|
});
|
|
120
|
-
const label = labelText
|
|
119
|
+
const label = typeof labelText !== 'undefined' && labelText !== null && /*#__PURE__*/React.createElement("label", {
|
|
121
120
|
htmlFor: id,
|
|
122
121
|
className: labelClasses
|
|
123
|
-
}, labelText)
|
|
124
|
-
const helper = helperText
|
|
122
|
+
}, labelText);
|
|
123
|
+
const helper = typeof helperText !== 'undefined' && helperText !== null && /*#__PURE__*/React.createElement("div", {
|
|
125
124
|
id: normalizedProps.helperId,
|
|
126
125
|
className: helperTextClasses
|
|
127
|
-
}, helperText)
|
|
126
|
+
}, helperText);
|
|
128
127
|
const passwordIsVisible = inputType === 'text';
|
|
129
128
|
const passwordVisibilityIcon = passwordIsVisible ? /*#__PURE__*/React.createElement(ViewOff, {
|
|
130
129
|
className: `${prefix}--icon-visibility-off`
|