@carbon/react 1.88.0 → 1.89.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +848 -848
  2. package/es/components/AILabel/index.d.ts +2 -5
  3. package/es/components/AILabel/index.js +2 -42
  4. package/es/components/ContainedList/ContainedList.d.ts +2 -2
  5. package/es/components/Copy/Copy.js +1 -0
  6. package/es/components/Link/Link.js +15 -1
  7. package/es/components/Menu/MenuContext.d.ts +1 -1
  8. package/es/components/Menu/MenuContext.js +11 -4
  9. package/es/components/Menu/MenuItem.js +2 -9
  10. package/es/components/Modal/Modal.js +15 -7
  11. package/es/components/MultiSelect/FilterableMultiSelect.js +1 -5
  12. package/es/components/MultiSelect/MultiSelect.js +3 -7
  13. package/es/components/Popover/index.d.ts +4 -0
  14. package/es/components/Popover/index.js +11 -22
  15. package/es/components/StructuredList/StructuredList.d.ts +16 -0
  16. package/es/components/StructuredList/StructuredList.js +19 -9
  17. package/es/components/TextArea/TextArea.js +21 -4
  18. package/es/components/Toggletip/index.d.ts +13 -36
  19. package/es/components/Toggletip/index.js +11 -51
  20. package/es/components/UIShell/Header.d.ts +3 -3
  21. package/es/components/UIShell/Header.js +7 -4
  22. package/es/internal/Selection.js +1 -1
  23. package/es/internal/useMergedRefs.js +4 -3
  24. package/lib/components/AILabel/index.d.ts +2 -5
  25. package/lib/components/AILabel/index.js +1 -41
  26. package/lib/components/ContainedList/ContainedList.d.ts +2 -2
  27. package/lib/components/Copy/Copy.js +1 -0
  28. package/lib/components/Link/Link.js +15 -1
  29. package/lib/components/Menu/MenuContext.d.ts +1 -1
  30. package/lib/components/Menu/MenuContext.js +11 -4
  31. package/lib/components/Menu/MenuItem.js +2 -9
  32. package/lib/components/Modal/Modal.js +15 -7
  33. package/lib/components/MultiSelect/FilterableMultiSelect.js +1 -5
  34. package/lib/components/MultiSelect/MultiSelect.js +3 -7
  35. package/lib/components/Popover/index.d.ts +4 -0
  36. package/lib/components/Popover/index.js +10 -21
  37. package/lib/components/StructuredList/StructuredList.d.ts +16 -0
  38. package/lib/components/StructuredList/StructuredList.js +19 -9
  39. package/lib/components/TextArea/TextArea.js +21 -4
  40. package/lib/components/Toggletip/index.d.ts +13 -36
  41. package/lib/components/Toggletip/index.js +10 -50
  42. package/lib/components/UIShell/Header.d.ts +3 -3
  43. package/lib/components/UIShell/Header.js +7 -4
  44. package/lib/internal/Selection.js +1 -1
  45. package/lib/internal/useMergedRefs.js +3 -2
  46. package/package.json +12 -13
  47. package/telemetry.yml +3 -2
@@ -5,6 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import React from 'react';
8
+ import { ToggletipBaseProps } from '../Toggletip';
8
9
  import type { DeprecatedPopoverAlignment, NewPopoverAlignment, PopoverAlignment } from '../Popover';
9
10
  export type AILabelContentProps = React.HTMLAttributes<HTMLSpanElement>;
10
11
  export declare const AILabelContent: React.ForwardRefExoticComponent<AILabelContentProps & React.RefAttributes<unknown>>;
@@ -17,15 +18,11 @@ export declare const AILabelActions: React.ForwardRefExoticComponent<AILabelActi
17
18
  export type DeprecatedAlignment = DeprecatedPopoverAlignment;
18
19
  export type NewAlignment = NewPopoverAlignment;
19
20
  export type Alignment = PopoverAlignment;
20
- export interface AILabelProps {
21
+ export interface AILabelProps extends ToggletipBaseProps {
21
22
  AILabelContent?: React.ReactNode;
22
23
  aiText?: string;
23
24
  aiTextLabel?: string;
24
25
  textLabel?: string;
25
- align?: Alignment;
26
- autoAlign?: boolean;
27
- children?: React.ReactNode;
28
- className?: string;
29
26
  kind?: 'default' | 'inline';
30
27
  onRevertClick?: (evt: React.MouseEvent<HTMLButtonElement>) => void;
31
28
  revertActive?: boolean;
@@ -8,12 +8,10 @@
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
9
  import cx from 'classnames';
10
10
  import PropTypes from 'prop-types';
11
- import deprecateValuesWithin from '../../prop-types/deprecateValuesWithin.js';
12
11
  import React from 'react';
13
12
  import { usePrefix } from '../../internal/usePrefix.js';
14
- import { ToggletipContent, ToggletipActions, Toggletip, ToggletipButton } from '../Toggletip/index.js';
13
+ import { Toggletip, ToggletipContent, ToggletipActions, ToggletipButton } from '../Toggletip/index.js';
15
14
  import { IconButton } from '../IconButton/index.js';
16
- import { mapPopoverAlign } from '../../tools/mapPopoverAlign.js';
17
15
  import { Undo } from '@carbon/icons-react';
18
16
  import { useId } from '../../internal/useId.js';
19
17
  import { deprecate } from '../../prop-types/deprecate.js';
@@ -143,6 +141,7 @@ const AILabel = /*#__PURE__*/React.forwardRef(function AILabel({
143
141
  });
144
142
  AILabel.displayName = 'AILabel';
145
143
  AILabel.propTypes = {
144
+ ...Toggletip.propTypes,
146
145
  /**
147
146
  * Specify the content you want rendered inside the `AILabel` ToggleTip
148
147
  */
@@ -156,49 +155,10 @@ AILabel.propTypes = {
156
155
  * Specify additional text to be rendered next to the AI label in the inline variant
157
156
  */
158
157
  aiTextLabel: deprecate(PropTypes.string, '`aiTextLabel` on `AILabel` has been deprecated - Please use the `textLabel` prop instead'),
159
- /**
160
- * Specify how the popover should align with the button
161
- */
162
- align: deprecateValuesWithin(PropTypes.oneOf(['top', 'top-left',
163
- // deprecated use top-start instead
164
- 'top-right',
165
- // deprecated use top-end instead
166
-
167
- 'bottom', 'bottom-left',
168
- // deprecated use bottom-start instead
169
- 'bottom-right',
170
- // deprecated use bottom-end instead
171
-
172
- 'left', 'left-bottom',
173
- // deprecated use left-end instead
174
- 'left-top',
175
- // deprecated use left-start instead
176
-
177
- 'right', 'right-bottom',
178
- // deprecated use right-end instead
179
- 'right-top',
180
- // deprecated use right-start instead
181
-
182
- // new values to match floating-ui
183
- 'top-start', 'top-end', 'bottom-start', 'bottom-end', 'left-end', 'left-start', 'right-end', 'right-start']), ['top', 'top-start', 'top-end', 'bottom', 'bottom-start', 'bottom-end', 'left', 'left-start', 'left-end', 'right', 'right-start', 'right-end'], mapPopoverAlign),
184
158
  /**
185
159
  * Specify the text that will be provided to the aria-label of the `AILabel` button
186
160
  */
187
161
  'aria-label': PropTypes.string,
188
- /**
189
- * Will auto-align the popover. This prop is currently experimental and is
190
- * subject to future changes. Requires React v17+
191
- * @see https://github.com/carbon-design-system/carbon/issues/18714
192
- */
193
- autoAlign: PropTypes.bool,
194
- /**
195
- * Specify the content you want rendered inside the `AILabel` ToggleTip
196
- */
197
- children: PropTypes.node,
198
- /**
199
- * Specify an optional className to be added to the `AILabel`
200
- */
201
- className: PropTypes.string,
202
162
  /**
203
163
  * Specify the type of `AILabel`, from the following list of types:
204
164
  */
@@ -7,9 +7,9 @@
7
7
  import React, { ReactNode } from 'react';
8
8
  import ContainedListItem from './ContainedListItem';
9
9
  declare const variants: readonly ["on-page", "disclosed"];
10
- export interface ContainedListType extends React.FC<ContainedListProps> {
10
+ export type ContainedListType = React.FC<ContainedListProps> & {
11
11
  ContainedListItem: typeof ContainedListItem;
12
- }
12
+ };
13
13
  export type Variants = (typeof variants)[number];
14
14
  export interface ContainedListProps {
15
15
  /**
@@ -57,6 +57,7 @@ function Copy({
57
57
  autoAlign: autoAlign,
58
58
  className: classNames,
59
59
  label: animation ? feedback : initialLabel,
60
+ leaveDelayMs: animation ? feedbackTimeout : undefined,
60
61
  onClick: composeEventHandlers([onClick, handleClick]),
61
62
  onAnimationEnd: composeEventHandlers([onAnimationEnd, handleAnimationEnd])
62
63
  }, other, {
@@ -48,9 +48,23 @@ const LinkBase = /*#__PURE__*/React.forwardRef(({
48
48
  linkProps['aria-disabled'] = true;
49
49
  }
50
50
  const BaseComponentAsAny = BaseComponent ?? 'a';
51
+ const handleOnClick = event => {
52
+ if (disabled) {
53
+ event.preventDefault();
54
+ event.stopPropagation();
55
+ } else {
56
+ // If the link is not disabled, we allow the onClick event to propagate
57
+ // so that any parent handlers can also respond to the click.
58
+ if (rest.onClick) {
59
+ rest.onClick(event);
60
+ }
61
+ }
62
+ };
51
63
  return /*#__PURE__*/React.createElement(BaseComponentAsAny, _extends({
52
64
  ref: ref
53
- }, linkProps, rest), children, !inline && Icon && /*#__PURE__*/React.createElement("div", {
65
+ }, linkProps, rest, {
66
+ onClick: handleOnClick
67
+ }), children, !inline && Icon && /*#__PURE__*/React.createElement("div", {
54
68
  className: `${prefix}--link__icon`
55
69
  }, /*#__PURE__*/React.createElement(Icon, null)));
56
70
  });
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright IBM Corp. 2023
2
+ * Copyright IBM Corp. 2023, 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.
@@ -28,10 +28,17 @@ function menuReducer(state, action) {
28
28
  hasSelectableItems: true
29
29
  };
30
30
  case 'registerItem':
31
- return {
32
- ...state,
33
- items: [...state.items, action.payload].filter(item => item.ref.current !== null)
34
- };
31
+ {
32
+ const newItem = action.payload;
33
+ const items = state.items.filter(item => item.ref.current);
34
+ const next = newItem.ref.current?.nextElementSibling;
35
+ const idx = items.findIndex(item => item.ref.current === next);
36
+ items.splice(idx < 0 ? items.length : idx, 0, newItem);
37
+ return {
38
+ ...state,
39
+ items
40
+ };
41
+ }
35
42
  }
36
43
  }
37
44
  const MenuContext = /*#__PURE__*/createContext({
@@ -128,18 +128,11 @@ const MenuItem = /*#__PURE__*/forwardRef(function MenuItem({
128
128
  [`${prefix}--menu-item--disabled`]: isDisabled,
129
129
  [`${prefix}--menu-item--danger`]: isDanger
130
130
  });
131
- const [isFocusable, setIsFocusable] = useState(false);
131
+
132
132
  // on first render, register this menuitem in the context's state
133
133
  // (used for keyboard navigation)
134
134
  useEffect(() => {
135
135
  registerItem();
136
-
137
- // Detects if this is the first focusable item
138
- const currentItems = context.state.items;
139
- if (!disabled && menuItem.current && currentItems.length === 0) {
140
- setIsFocusable(true);
141
- }
142
-
143
136
  // eslint-disable-next-line react-hooks/exhaustive-deps
144
137
  }, []);
145
138
 
@@ -178,7 +171,7 @@ const MenuItem = /*#__PURE__*/forwardRef(function MenuItem({
178
171
  }, rest, {
179
172
  ref: ref,
180
173
  className: classNames,
181
- tabIndex: isFocusable ? 0 : -1,
174
+ tabIndex: !disabled ? 0 : -1,
182
175
  "aria-disabled": isDisabled ?? undefined,
183
176
  "aria-haspopup": hasChildren ?? undefined,
184
177
  "aria-expanded": hasChildren ? submenuOpen : undefined,
@@ -81,6 +81,7 @@ const Modal = /*#__PURE__*/React.forwardRef(function Modal({
81
81
  const innerModal = useRef(null);
82
82
  const startTrap = useRef(null);
83
83
  const endTrap = useRef(null);
84
+ const wrapFocusTimeout = useRef(null);
84
85
  const [isScrollable, setIsScrollable] = useState(false);
85
86
  const prevOpen = usePreviousValue(open);
86
87
  const modalInstanceId = `modal-${useId()}`;
@@ -142,13 +143,20 @@ const Modal = /*#__PURE__*/React.forwardRef(function Modal({
142
143
  const {
143
144
  current: endTrapNode
144
145
  } = endTrap;
145
- wrapFocus({
146
- bodyNode,
147
- startTrapNode,
148
- endTrapNode,
149
- currentActiveNode,
150
- oldActiveNode,
151
- selectorsFloatingMenus
146
+ // use setTimeout to ensure focus is set after all browser default focus behavior. Fixes issue of
147
+ // focus not wrapping in Firefox
148
+ wrapFocusTimeout.current = setTimeout(() => {
149
+ wrapFocus({
150
+ bodyNode,
151
+ startTrapNode,
152
+ endTrapNode,
153
+ currentActiveNode,
154
+ oldActiveNode,
155
+ selectorsFloatingMenus
156
+ });
157
+ if (wrapFocusTimeout.current) {
158
+ clearTimeout(wrapFocusTimeout.current);
159
+ }
152
160
  });
153
161
  }
154
162
 
@@ -122,11 +122,7 @@ const FilterableMultiSelect = /*#__PURE__*/forwardRef(function FilterableMultiSe
122
122
  inputValue
123
123
  }), [items, inputValue, itemToString, filterItems]);
124
124
  const nonSelectAllItems = useMemo(() => filteredItems.filter(item => !item.isSelectAll), [filteredItems]);
125
- let selectAll = filteredItems.some(item => item.isSelectAll);
126
- if ((selected ?? []).length > 0 && selectAll) {
127
- console.warn('Warning: `selectAll` should not be used when `selectedItems` is provided. Please pass either `selectAll` or `selectedItems`, not both.');
128
- selectAll = false;
129
- }
125
+ const selectAll = filteredItems.some(item => item.isSelectAll);
130
126
  const {
131
127
  selectedItems: controlledSelectedItems,
132
128
  onItemChange,
@@ -111,11 +111,7 @@ const MultiSelect = /*#__PURE__*/React.forwardRef(({
111
111
  return true; // Return true if item is not an object with undefined values
112
112
  });
113
113
  }, [items]);
114
- let selectAll = filteredItems.some(item => item.isSelectAll);
115
- if ((selected ?? []).length > 0 && selectAll) {
116
- console.warn('Warning: `selectAll` should not be used when `selectedItems` is provided. Please pass either `selectAll` or `selectedItems`, not both.');
117
- selectAll = false;
118
- }
114
+ const selectAll = filteredItems.some(item => item.isSelectAll);
119
115
  const prefix = usePrefix();
120
116
  const {
121
117
  isFluid
@@ -489,13 +485,13 @@ const MultiSelect = /*#__PURE__*/React.forwardRef(({
489
485
  })), slug ? normalizedDecorator : decorator ? /*#__PURE__*/React.createElement("div", {
490
486
  className: `${prefix}--list-box__inner-wrapper--decorator`
491
487
  }, normalizedDecorator) : ''), /*#__PURE__*/React.createElement(ListBox.Menu, menuProps, isOpen && sortItems(filteredItems, sortOptions).map((item, index) => {
492
- const isChecked = selectedItems.filter(selected => isEqual(selected, item)).length > 0;
493
488
  const {
494
489
  hasIndividualSelections,
495
490
  nonSelectAllSelectedCount,
496
491
  totalSelectableCount
497
492
  } = getSelectionStats(selectedItems, filteredItems);
498
- const isIndeterminate = item['isSelectAll'] && hasIndividualSelections && nonSelectAllSelectedCount < totalSelectableCount;
493
+ const isChecked = item.isSelectAll ? nonSelectAllSelectedCount === totalSelectableCount && totalSelectableCount > 0 : selectedItems.some(selected => isEqual(selected, item));
494
+ const isIndeterminate = item.isSelectAll && hasIndividualSelections && nonSelectAllSelectedCount < totalSelectableCount;
499
495
  const itemProps = getItemProps({
500
496
  item,
501
497
  // we don't want Downshift to set aria-selected for us
@@ -25,6 +25,10 @@ export interface PopoverBaseProps {
25
25
  * Specify how the popover should align with the trigger element.
26
26
  */
27
27
  align?: PopoverAlignment;
28
+ /**
29
+ * **Experimental:** Provide an offset value for alignment axis. Only takes effect when `autoalign` is enabled.
30
+ */
31
+ alignmentAxisOffset?: number;
28
32
  /**
29
33
  * Will auto-align the popover on first render if it is not visible. This prop
30
34
  * is currently experimental and is subject to future changes. Requires
@@ -9,7 +9,7 @@ import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js
9
9
  import cx from 'classnames';
10
10
  import PropTypes from 'prop-types';
11
11
  import deprecateValuesWithin from '../../prop-types/deprecateValuesWithin.js';
12
- import React, { useRef, useEffect, useMemo } from 'react';
12
+ import React, { useRef, useMemo, useEffect } from 'react';
13
13
  import useIsomorphicEffect from '../../internal/useIsomorphicEffect.js';
14
14
  import { useMergedRefs } from '../../internal/useMergedRefs.js';
15
15
  import { usePrefix } from '../../internal/usePrefix.js';
@@ -17,7 +17,6 @@ import { useEvent, useWindowEvent } from '../../internal/useEvent.js';
17
17
  import { mapPopoverAlign } from '../../tools/mapPopoverAlign.js';
18
18
  import { useFloating, autoUpdate, offset, flip, arrow, hide } from '@floating-ui/react';
19
19
  import { useFeatureFlag } from '../FeatureFlags/index.js';
20
- import { ToggletipButton } from '../Toggletip/index.js';
21
20
 
22
21
  const PopoverContext = /*#__PURE__*/React.createContext({
23
22
  setFloating: {
@@ -62,7 +61,10 @@ forwardRef) {
62
61
  // The `Popover` should close whenever it and its children loses focus
63
62
  useEvent(popover, 'focusout', event => {
64
63
  const relatedTarget = event.relatedTarget;
64
+
65
+ // No relatedTarget, focus moved to nowhere, so close the popover
65
66
  if (!relatedTarget) {
67
+ onRequestClose?.();
66
68
  return;
67
69
  }
68
70
  const isOutsideMainContainer = !popover.current?.contains(relatedTarget);
@@ -235,7 +237,7 @@ forwardRef) {
235
237
  // For a toggletip there is a specific trigger component, ToggletipButton.
236
238
  // In either of these cases we want to set this as the reference node for floating-ui autoAlign
237
239
  // positioning.
238
- if (enableFloatingStyles && item?.type !== PopoverContent || enableFloatingStyles && item?.type === ToggletipButton) {
240
+ if (enableFloatingStyles && item?.type !== PopoverContent || enableFloatingStyles && item?.type['displayName'] === 'ToggletipButton') {
239
241
  // Set the reference element for floating-ui
240
242
  refs.setReference(node);
241
243
  }
@@ -292,6 +294,10 @@ Popover.propTypes = {
292
294
 
293
295
  // new values to match floating-ui
294
296
  'top-start', 'top-end', 'bottom-start', 'bottom-end', 'left-end', 'left-start', 'right-end', 'right-start']), ['top', 'top-start', 'top-end', 'bottom', 'bottom-start', 'bottom-end', 'left', 'left-start', 'left-end', 'right', 'right-start', 'right-end'], mapPopoverAlign),
297
+ /**
298
+ * **Experimental:** Provide an offset value for alignment axis. Only takes effect when `autoalign` is enabled.
299
+ */
300
+ alignmentAxisOffset: PropTypes.number,
295
301
  /**
296
302
  * Provide a custom element or component to render the top-level node for the
297
303
  * component.
@@ -361,29 +367,12 @@ function PopoverContentRenderFunction(
361
367
  caretRef,
362
368
  autoAlign
363
369
  } = React.useContext(PopoverContext);
364
- const textRef = useRef(null);
365
- const [isMultiLine, setIsMultiLine] = React.useState(false);
366
- const ref = useMergedRefs([setFloating, textRef, forwardRef]);
370
+ const ref = useMergedRefs([setFloating, forwardRef]);
367
371
  const enableFloatingStyles = useFeatureFlag('enable-v12-dynamic-floating-styles') || autoAlign;
368
- useEffect(() => {
369
- checkIfMultiLine();
370
- }, [children]);
371
- const checkIfMultiLine = () => {
372
- const el = textRef.current;
373
- if (el) {
374
- const style = getComputedStyle(el);
375
- const lineHeight = parseFloat(style.lineHeight);
376
- const height = el.offsetHeight;
377
- const lines = Math.floor(height / lineHeight);
378
- setIsMultiLine(lines > 1);
379
- }
380
- };
381
372
  return /*#__PURE__*/React.createElement("span", _extends({}, rest, {
382
373
  className: `${prefix}--popover`
383
374
  }), /*#__PURE__*/React.createElement("span", {
384
- className: cx(`${prefix}--popover-content`, className, {
385
- [`${prefix}--tooltip-content--multiline`]: isMultiLine
386
- }),
375
+ className: cx(`${prefix}--popover-content`, className),
387
376
  ref: ref
388
377
  }, children, enableFloatingStyles && /*#__PURE__*/React.createElement("span", {
389
378
  className: cx({
@@ -32,6 +32,10 @@ export interface StructuredListWrapperProps extends DivAttrs {
32
32
  * Specify whether your StructuredListWrapper should have selections
33
33
  */
34
34
  selection?: boolean;
35
+ /**
36
+ * Specify which row will be selected initially
37
+ */
38
+ selectedInitialRow?: string;
35
39
  }
36
40
  export declare function StructuredListWrapper(props: StructuredListWrapperProps): import("react/jsx-runtime").JSX.Element;
37
41
  export declare namespace StructuredListWrapper {
@@ -65,6 +69,10 @@ export declare namespace StructuredListWrapper {
65
69
  * Specify whether your StructuredListWrapper should have selections
66
70
  */
67
71
  selection: PropTypes.Requireable<boolean>;
72
+ /**
73
+ * Specify which row will be selected initially
74
+ */
75
+ selectedInitialRow: PropTypes.Requireable<string>;
68
76
  };
69
77
  }
70
78
  export interface StructuredListHeadProps extends DivAttrs {
@@ -148,6 +156,10 @@ export interface StructuredListRowProps extends DivAttrs {
148
156
  * Mark if this row should be selectable
149
157
  */
150
158
  selection?: boolean;
159
+ /**
160
+ * Specify row id so that it can be used for initial selection
161
+ */
162
+ id?: string;
151
163
  }
152
164
  export declare function StructuredListRow(props: StructuredListRowProps): import("react/jsx-runtime").JSX.Element;
153
165
  export declare namespace StructuredListRow {
@@ -180,6 +192,10 @@ export declare namespace StructuredListRow {
180
192
  * Mark if this row should be selectable
181
193
  */
182
194
  selection: PropTypes.Requireable<boolean>;
195
+ /**
196
+ * Specify row id so that it can be used for initial selection
197
+ */
198
+ id: PropTypes.Requireable<string>;
183
199
  };
184
200
  }
185
201
  export interface StructuredListInputProps extends DivAttrs {
@@ -30,6 +30,7 @@ function StructuredListWrapper(props) {
30
30
  ariaLabel: deprecatedAriaLabel,
31
31
  isCondensed,
32
32
  isFlush,
33
+ selectedInitialRow,
33
34
  ...other
34
35
  } = props;
35
36
  const prefix = usePrefix();
@@ -38,7 +39,7 @@ function StructuredListWrapper(props) {
38
39
  [`${prefix}--structured-list--condensed`]: isCondensed,
39
40
  [`${prefix}--structured-list--flush`]: isFlush && !selection
40
41
  }, className);
41
- const [selectedRow, setSelectedRow] = React.useState(null);
42
+ const [selectedRow, setSelectedRow] = React.useState(selectedInitialRow ?? null);
42
43
  return /*#__PURE__*/React.createElement(GridSelectedRowStateContext.Provider, {
43
44
  value: selectedRow
44
45
  }, /*#__PURE__*/React.createElement(GridSelectedRowDispatchContext.Provider, {
@@ -79,7 +80,11 @@ StructuredListWrapper.propTypes = {
79
80
  /**
80
81
  * Specify whether your StructuredListWrapper should have selections
81
82
  */
82
- selection: PropTypes.bool
83
+ selection: PropTypes.bool,
84
+ /**
85
+ * Specify which row will be selected initially
86
+ */
87
+ selectedInitialRow: PropTypes.string
83
88
  };
84
89
  function StructuredListHead(props) {
85
90
  const {
@@ -141,21 +146,22 @@ function StructuredListRow(props) {
141
146
  head,
142
147
  onClick,
143
148
  selection,
149
+ id,
144
150
  ...other
145
151
  } = props;
146
152
  const [hasFocusWithin, setHasFocusWithin] = useState(false);
147
- const id = useId('grid-input');
153
+ const rowId = id ?? useId('grid-input');
148
154
  const selectedRow = React.useContext(GridSelectedRowStateContext);
149
155
  const setSelectedRow = React.useContext(GridSelectedRowDispatchContext);
150
156
  const prefix = usePrefix();
151
157
  const value = {
152
- id
158
+ id: rowId
153
159
  };
154
160
  const classes = cx(`${prefix}--structured-list-row`, {
155
161
  [`${prefix}--structured-list-row--header-row`]: head,
156
- [`${prefix}--structured-list-row--focused-within`]: hasFocusWithin && !selection || hasFocusWithin && selection && (selectedRow === id || selectedRow === null),
162
+ [`${prefix}--structured-list-row--focused-within`]: hasFocusWithin && !selection || hasFocusWithin && selection && (selectedRow === rowId || selectedRow === null),
157
163
  // Ensure focus on the first item when navigating through Tab keys and no row is selected (selectedRow === null)
158
- [`${prefix}--structured-list-row--selected`]: selectedRow === id
164
+ [`${prefix}--structured-list-row--selected`]: selectedRow === rowId
159
165
  }, className);
160
166
  const itemRef = useRef(null);
161
167
  const handleClick = () => {
@@ -176,7 +182,7 @@ function StructuredListRow(props) {
176
182
  className: classes,
177
183
  ref: itemRef,
178
184
  onClick: event => {
179
- setSelectedRow?.(id);
185
+ setSelectedRow?.(rowId);
180
186
  onClick && onClick(event);
181
187
  if (selection) {
182
188
  // focus items only when selection is enabled
@@ -192,7 +198,7 @@ function StructuredListRow(props) {
192
198
  onKeyDown: onKeyDown
193
199
  }), /*#__PURE__*/React.createElement(GridRowContext.Provider, {
194
200
  value: value
195
- }, selection && /*#__PURE__*/React.createElement(StructuredListCell, null, selectedRow === id ? /*#__PURE__*/React.createElement(RadioButtonChecked, {
201
+ }, selection && /*#__PURE__*/React.createElement(StructuredListCell, null, selectedRow === rowId ? /*#__PURE__*/React.createElement(RadioButtonChecked, {
196
202
  className: `${prefix}--structured-list__icon`
197
203
  }) : /*#__PURE__*/React.createElement(RadioButton, {
198
204
  className: `${prefix}--structured-list__icon`
@@ -226,7 +232,11 @@ StructuredListRow.propTypes = {
226
232
  /**
227
233
  * Mark if this row should be selectable
228
234
  */
229
- selection: PropTypes.bool
235
+ selection: PropTypes.bool,
236
+ /**
237
+ * Specify row id so that it can be used for initial selection
238
+ */
239
+ id: PropTypes.string
230
240
  };
231
241
  function StructuredListInput(props) {
232
242
  const defaultId = useId('structureListInput');
@@ -59,7 +59,11 @@ const TextArea = frFn((props, forwardRef) => {
59
59
  value
60
60
  } = other;
61
61
  const textAreaInstanceId = useId();
62
+ const wrapperRef = useRef(null);
62
63
  const textareaRef = useRef(null);
64
+ const helperTextRef = useRef(null);
65
+ const errorTextRef = useRef(null);
66
+ const warnTextRef = useRef(null);
63
67
  const ref = useMergedRefs([forwardRef, textareaRef]);
64
68
  function getInitialTextCount() {
65
69
  const targetValue = defaultValue || value || textareaRef.current?.value || '';
@@ -76,13 +80,20 @@ const TextArea = frFn((props, forwardRef) => {
76
80
  // eslint-disable-next-line react-hooks/exhaustive-deps
77
81
  }, [value, defaultValue, counterMode]);
78
82
  useIsomorphicEffect(() => {
83
+ const measuredWidth = wrapperRef.current?.scrollWidth;
79
84
  if (other.cols && textareaRef.current) {
80
85
  textareaRef.current.style.width = '';
81
86
  textareaRef.current.style.resize = 'none';
82
87
  } else if (textareaRef.current) {
83
88
  textareaRef.current.style.width = `100%`;
84
89
  }
85
- }, [other.cols]);
90
+ [helperTextRef, errorTextRef, warnTextRef].forEach(r => {
91
+ if (r.current) {
92
+ r.current.style.maxWidth = `${measuredWidth}px`;
93
+ r.current.style.overflowWrap = 'break-word';
94
+ }
95
+ });
96
+ }, [other.cols, invalid, warn]);
86
97
  const textareaProps = {
87
98
  id,
88
99
  onKeyDown: evt => {
@@ -190,21 +201,26 @@ const TextArea = frFn((props, forwardRef) => {
190
201
  const helper = helperText ? /*#__PURE__*/React.createElement(Text, {
191
202
  as: "div",
192
203
  id: helperId,
193
- className: helperTextClasses
204
+ className: helperTextClasses,
205
+ ref: helperTextRef
194
206
  }, helperText) : null;
195
207
  const errorId = id + '-error-msg';
196
208
  const error = invalid ? /*#__PURE__*/React.createElement(Text, {
197
209
  as: "div",
198
210
  role: "alert",
199
211
  className: `${prefix}--form-requirement`,
200
- id: errorId
212
+ id: errorId,
213
+ ref: errorTextRef
201
214
  }, invalidText, isFluid && /*#__PURE__*/React.createElement(WarningFilled, {
202
215
  className: `${prefix}--text-area__invalid-icon`
203
216
  })) : null;
217
+ const warnId = id + '-warn-msg';
204
218
  const warning = warn ? /*#__PURE__*/React.createElement(Text, {
205
219
  as: "div",
206
220
  role: "alert",
207
- className: `${prefix}--form-requirement`
221
+ className: `${prefix}--form-requirement`,
222
+ id: warnId,
223
+ ref: warnTextRef
208
224
  }, warnText, isFluid && /*#__PURE__*/React.createElement(WarningAltFilled, {
209
225
  className: `${prefix}--text-area__invalid-icon ${prefix}--text-area__invalid-icon--warning`
210
226
  })) : null;
@@ -270,6 +286,7 @@ const TextArea = frFn((props, forwardRef) => {
270
286
  }, /*#__PURE__*/React.createElement("div", {
271
287
  className: `${prefix}--text-area__label-wrapper`
272
288
  }, label, counter), /*#__PURE__*/React.createElement("div", {
289
+ ref: wrapperRef,
273
290
  className: textAreaWrapperClasses,
274
291
  "data-invalid": invalid || null
275
292
  }, invalid && !isFluid && /*#__PURE__*/React.createElement(WarningFilled, {
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import PropTypes from 'prop-types';
8
8
  import React, { type ElementType, type ReactNode } from 'react';
9
- import { type PopoverAlignment } from '../Popover';
9
+ import { type PopoverAlignment, PopoverBaseProps } from '../Popover';
10
10
  import { PolymorphicProps } from '../../types/common';
11
11
  import { PolymorphicComponentPropWithRef } from '../../internal/PolymorphicProps';
12
12
  type ToggletipLabelProps<E extends ElementType> = {
@@ -36,12 +36,7 @@ export declare namespace ToggletipLabel {
36
36
  className: PropTypes.Requireable<string>;
37
37
  };
38
38
  }
39
- export interface ToggletipBaseProps {
40
- align?: PopoverAlignment;
41
- alignmentAxisOffset?: number;
42
- autoAlign?: boolean;
43
- className?: string;
44
- children?: ReactNode;
39
+ export interface ToggletipBaseProps extends Omit<PopoverBaseProps, 'open'> {
45
40
  defaultOpen?: boolean;
46
41
  }
47
42
  export type ToggletipProps<T extends ElementType> = PolymorphicComponentPropWithRef<T, ToggletipBaseProps>;
@@ -53,39 +48,21 @@ export type ToggletipProps<T extends ElementType> = PolymorphicComponentPropWith
53
48
  export declare function Toggletip<E extends ElementType = 'span'>({ align, as, autoAlign, className: customClassName, children, defaultOpen, ...rest }: ToggletipProps<E>): import("react/jsx-runtime").JSX.Element;
54
49
  export declare namespace Toggletip {
55
50
  var propTypes: {
56
- /**
57
- * Specify how the toggletip should align with the button
58
- */
59
- align: PropTypes.Requireable<string>;
60
- /**
61
- * **Experimental:** Provide an offset value for alignment axis. Only takes effect when `autoalign` is enabled.
62
- */
63
- alignmentAxisOffset: PropTypes.Requireable<number>;
64
- /**
65
- * Provide a custom element or component to render the top-level node for the
66
- * component.
67
- */
68
- as: PropTypes.Requireable<PropTypes.ReactComponentLike>;
69
- /**
70
- * Will auto-align the popover on first render if it is not visible. This prop
71
- * is currently experimental and is subject to future changes. Requires
72
- * React v17+
73
- * @see https://github.com/carbon-design-system/carbon/issues/18714
74
- */
75
- autoAlign: PropTypes.Requireable<boolean>;
76
- /**
77
- * Custom children to be rendered as the content of the label
78
- */
79
- children: PropTypes.Requireable<PropTypes.ReactNodeLike>;
80
- /**
81
- * Provide a custom class name to be added to the outermost node in the
82
- * component
83
- */
84
- className: PropTypes.Requireable<string>;
85
51
  /**
86
52
  * Specify if the toggletip should be open by default
87
53
  */
88
54
  defaultOpen: PropTypes.Requireable<boolean>;
55
+ align?: PopoverAlignment;
56
+ alignmentAxisOffset?: number;
57
+ autoAlign?: boolean;
58
+ autoAlignBoundary?: import("@floating-ui/dom").Boundary;
59
+ caret?: boolean;
60
+ children?: React.ReactNode;
61
+ className?: string;
62
+ dropShadow?: boolean;
63
+ highContrast?: boolean;
64
+ isTabTip?: boolean;
65
+ onRequestClose?: () => void;
89
66
  };
90
67
  }
91
68
  export interface ToggletipButtonBaseProps {