@carbon/react 1.104.1 → 1.105.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.
Files changed (85) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +939 -939
  2. package/es/components/AISkeleton/AISkeletonPlaceholder.d.ts +1 -1
  3. package/es/components/Checkbox/Checkbox.js +1 -1
  4. package/es/components/CheckboxGroup/CheckboxGroup.js +1 -1
  5. package/es/components/ComboBox/ComboBox.js +2 -2
  6. package/es/components/ComposedModal/ComposedModal.js +1 -1
  7. package/es/components/DataTable/TableDecoratorRow.js +1 -1
  8. package/es/components/DataTable/TableExpandRow.js +1 -1
  9. package/es/components/DataTable/TableHeader.js +1 -1
  10. package/es/components/DataTable/TableRow.js +1 -1
  11. package/es/components/DataTable/tools/normalize.js +1 -1
  12. package/es/components/DatePicker/DatePicker.d.ts +0 -8
  13. package/es/components/DatePicker/DatePicker.js +5 -28
  14. package/es/components/DatePicker/plugins/fixEventsPlugin.d.ts +18 -2
  15. package/es/components/DatePicker/plugins/fixEventsPlugin.js +13 -16
  16. package/es/components/DatePickerInput/DatePickerInput.js +1 -2
  17. package/es/components/Dropdown/Dropdown.js +2 -2
  18. package/es/components/FluidDatePicker/FluidDatePicker.js +1 -3
  19. package/es/components/FluidMultiSelect/FluidMultiSelect.d.ts +2 -2
  20. package/es/components/Menu/Menu.js +10 -3
  21. package/es/components/Menu/MenuItem.js +1 -1
  22. package/es/components/Modal/Modal.js +1 -1
  23. package/es/components/MultiSelect/FilterableMultiSelect.js +2 -2
  24. package/es/components/MultiSelect/MultiSelect.js +2 -2
  25. package/es/components/NumberInput/NumberInput.js +2 -2
  26. package/es/components/Pagination/Pagination.js +60 -29
  27. package/es/components/Popover/index.js +7 -4
  28. package/es/components/RadioButton/RadioButton.js +1 -1
  29. package/es/components/RadioButtonGroup/RadioButtonGroup.js +1 -1
  30. package/es/components/RadioTile/RadioTile.js +1 -1
  31. package/es/components/Select/Select.js +1 -1
  32. package/es/components/Slider/Slider.js +60 -45
  33. package/es/components/Tabs/Tabs.js +1 -1
  34. package/es/components/Tag/DismissibleTag.js +1 -1
  35. package/es/components/Tag/Tag.js +1 -1
  36. package/es/components/TextArea/TextArea.js +1 -1
  37. package/es/components/TextInput/TextInput.js +1 -1
  38. package/es/components/Tile/Tile.js +1 -1
  39. package/es/components/UIShell/HeaderPanel.js +1 -1
  40. package/es/components/UIShell/Switcher.js +1 -1
  41. package/es/internal/useNoInteractiveChildren.d.ts +2 -10
  42. package/es/internal/useNoInteractiveChildren.js +16 -27
  43. package/lib/components/AISkeleton/AISkeletonPlaceholder.d.ts +1 -1
  44. package/lib/components/AISkeleton/AISkeletonPlaceholder.js +1 -1
  45. package/lib/components/Checkbox/Checkbox.js +1 -1
  46. package/lib/components/CheckboxGroup/CheckboxGroup.js +1 -1
  47. package/lib/components/ComboBox/ComboBox.js +2 -2
  48. package/lib/components/ComposedModal/ComposedModal.js +1 -1
  49. package/lib/components/DataTable/TableDecoratorRow.js +1 -1
  50. package/lib/components/DataTable/TableExpandRow.js +1 -1
  51. package/lib/components/DataTable/TableHeader.js +1 -1
  52. package/lib/components/DataTable/TableRow.js +1 -1
  53. package/lib/components/DataTable/tools/normalize.js +1 -1
  54. package/lib/components/DatePicker/DatePicker.d.ts +0 -8
  55. package/lib/components/DatePicker/DatePicker.js +1 -24
  56. package/lib/components/DatePicker/plugins/fixEventsPlugin.d.ts +18 -2
  57. package/lib/components/DatePicker/plugins/fixEventsPlugin.js +13 -16
  58. package/lib/components/DatePickerInput/DatePickerInput.js +1 -2
  59. package/lib/components/Dropdown/Dropdown.js +2 -2
  60. package/lib/components/FluidDatePicker/FluidDatePicker.js +1 -3
  61. package/lib/components/FluidMultiSelect/FluidMultiSelect.d.ts +2 -2
  62. package/lib/components/Menu/Menu.js +10 -3
  63. package/lib/components/Menu/MenuItem.js +1 -1
  64. package/lib/components/Modal/Modal.js +1 -1
  65. package/lib/components/MultiSelect/FilterableMultiSelect.js +2 -2
  66. package/lib/components/MultiSelect/MultiSelect.js +2 -2
  67. package/lib/components/NumberInput/NumberInput.js +2 -2
  68. package/lib/components/Pagination/Pagination.js +59 -28
  69. package/lib/components/Popover/index.js +7 -4
  70. package/lib/components/RadioButton/RadioButton.js +1 -1
  71. package/lib/components/RadioButtonGroup/RadioButtonGroup.js +1 -1
  72. package/lib/components/RadioTile/RadioTile.js +1 -1
  73. package/lib/components/Select/Select.js +1 -1
  74. package/lib/components/Slider/Slider.js +60 -45
  75. package/lib/components/Tabs/Tabs.js +1 -1
  76. package/lib/components/Tag/DismissibleTag.js +1 -1
  77. package/lib/components/Tag/Tag.js +1 -1
  78. package/lib/components/TextArea/TextArea.js +1 -1
  79. package/lib/components/TextInput/TextInput.js +1 -1
  80. package/lib/components/Tile/Tile.js +1 -1
  81. package/lib/components/UIShell/HeaderPanel.js +1 -1
  82. package/lib/components/UIShell/Switcher.js +1 -1
  83. package/lib/internal/useNoInteractiveChildren.d.ts +2 -10
  84. package/lib/internal/useNoInteractiveChildren.js +16 -27
  85. package/package.json +7 -7
@@ -50,13 +50,18 @@ const translationIds = { "carbon.slider.auto-correct-announcement": "carbon.slid
50
50
  const defaultTranslations = { [translationIds["carbon.slider.auto-correct-announcement"]]: "The inputted value \"{correctedValue}\" was corrected to the nearest allowed digit." };
51
51
  const defaultTranslateWithId = (messageId, args) => {
52
52
  const template = defaultTranslations[messageId];
53
- if (args?.correctedValue) return template.replace("{correctedValue}", args.correctedValue);
54
- return template;
53
+ const correctedValue = args?.correctedValue ?? "";
54
+ return template.replace("{correctedValue}", correctedValue);
55
55
  };
56
56
  const defaultFormatLabel = (value, label) => {
57
57
  return `${value}${label ?? ""}`;
58
58
  };
59
59
  const hasUpperValue = (valueUpper) => typeof valueUpper !== "undefined";
60
+ const calcRawLeftPercent = ({ max, min, value }) => {
61
+ const range = max - min;
62
+ if (range === 0) return 0;
63
+ return require_clamp.clamp((value - min) / range, 0, 1);
64
+ };
60
65
  /**
61
66
  * Minimum time between processed "drag" events in milliseconds.
62
67
  */
@@ -73,6 +78,12 @@ var HandlePosition = /* @__PURE__ */ function(HandlePosition) {
73
78
  return HandlePosition;
74
79
  }(HandlePosition || {});
75
80
  const Slider = (props) => {
81
+ const controlledValue = props.value;
82
+ const controlledValueUpper = props.unstable_valueUpper;
83
+ const controlledMax = props.max;
84
+ const controlledMin = props.min;
85
+ const onChange = props.onChange;
86
+ const onRelease = props.onRelease;
76
87
  const [state, setState] = (0, react.useReducer)((prev, args) => ({
77
88
  ...prev,
78
89
  ...args
@@ -145,18 +156,20 @@ const Slider = (props) => {
145
156
  };
146
157
  }, []);
147
158
  (0, react.useEffect)(() => {
148
- if (twoHandles) {
149
- if (filledTrackRef.current) filledTrackRef.current.style.transform = state.isRtl ? `translate(${100 - state.leftUpper}%, -50%) scaleX(${(state.leftUpper - state.left) / 100})` : `translate(${state.left}%, -50%) scaleX(${(state.leftUpper - state.left) / 100})`;
150
- } else if (filledTrackRef.current) filledTrackRef.current.style.transform = state.isRtl ? `translate(100%, -50%) scaleX(-${state.left / 100})` : `translate(0%, -50%) scaleX(${state.left / 100})`;
159
+ const el = filledTrackRef.current;
160
+ if (!el) return;
161
+ if (twoHandles) el.style.transform = state.isRtl ? `translate(${100 - state.leftUpper}%, -50%) scaleX(${(state.leftUpper - state.left) / 100})` : `translate(${state.left}%, -50%) scaleX(${(state.leftUpper - state.left) / 100})`;
162
+ else el.style.transform = state.isRtl ? `translate(100%, -50%) scaleX(-${state.left / 100})` : `translate(0%, -50%) scaleX(${state.left / 100})`;
151
163
  }, [
164
+ state.isRtl,
152
165
  state.left,
153
166
  state.leftUpper,
154
- state.isRtl
167
+ twoHandles
155
168
  ]);
156
169
  const prevValsRef = (0, react.useRef)(null);
157
170
  (0, react.useEffect)(() => {
158
171
  const prev = prevValsRef.current;
159
- if (prev && (prev.value !== state.value || prev.valueUpper !== state.valueUpper) && typeof props.onChange === "function") props.onChange({
172
+ if (prev && (prev.value !== state.value || prev.valueUpper !== state.valueUpper) && typeof onChange === "function") onChange({
160
173
  value: state.value,
161
174
  valueUpper: state.valueUpper
162
175
  });
@@ -167,56 +180,59 @@ const Slider = (props) => {
167
180
  }, [
168
181
  state.value,
169
182
  state.valueUpper,
170
- props.onChange
183
+ onChange
171
184
  ]);
172
185
  (0, react.useEffect)(() => {
173
- if (state.needsOnRelease && typeof props.onRelease === "function") {
174
- props.onRelease({
186
+ if (state.needsOnRelease && typeof onRelease === "function") {
187
+ onRelease({
175
188
  value: state.value,
176
189
  valueUpper: state.valueUpper
177
190
  });
178
191
  setState({ needsOnRelease: false });
179
192
  }
180
193
  }, [
194
+ onRelease,
181
195
  state.needsOnRelease,
182
196
  state.value,
183
- state.valueUpper,
184
- props.onRelease
197
+ state.valueUpper
185
198
  ]);
186
199
  const prevSyncKeysRef = (0, react.useRef)(null);
187
200
  (0, react.useEffect)(() => {
188
201
  const prev = prevSyncKeysRef.current;
189
202
  const next = [
190
- props.value,
191
- props.unstable_valueUpper,
192
- props.max,
193
- props.min
203
+ controlledValue,
204
+ controlledValueUpper,
205
+ controlledMax,
206
+ controlledMin
194
207
  ];
195
208
  if (!prev || prev[0] !== next[0] || prev[1] !== next[1] || prev[2] !== next[2] || prev[3] !== next[3]) {
196
- setState(calcValue({
197
- value: props.value,
198
- useRawValue: true
199
- }));
200
- if (typeof props.unstable_valueUpper !== "undefined") {
201
- const { value: valueUpper, left: leftUpper } = calcValue({
202
- value: props.unstable_valueUpper,
203
- useRawValue: true
204
- });
205
- setState({
206
- valueUpper,
207
- leftUpper
208
- });
209
- } else setState({
209
+ setState({
210
+ value: controlledValue,
211
+ left: calcRawLeftPercent({
212
+ max: controlledMax,
213
+ min: controlledMin,
214
+ value: controlledValue
215
+ }) * 100
216
+ });
217
+ if (typeof controlledValueUpper !== "undefined") setState({
218
+ valueUpper: controlledValueUpper,
219
+ leftUpper: calcRawLeftPercent({
220
+ max: controlledMax,
221
+ min: controlledMin,
222
+ value: controlledValueUpper
223
+ }) * 100
224
+ });
225
+ else setState({
210
226
  valueUpper: void 0,
211
227
  leftUpper: void 0
212
228
  });
213
229
  prevSyncKeysRef.current = next;
214
230
  }
215
231
  }, [
216
- props.value,
217
- props.unstable_valueUpper,
218
- props.max,
219
- props.min
232
+ controlledMax,
233
+ controlledMin,
234
+ controlledValue,
235
+ controlledValueUpper
220
236
  ]);
221
237
  /**
222
238
  * Rounds a given value to the nearest step defined by the slider's `step`
@@ -291,7 +307,7 @@ const Slider = (props) => {
291
307
  const _onDragRef = (0, react.useRef)(null);
292
308
  _onDragRef.current = (evt, activeHandle) => {
293
309
  activeHandle = activeHandle ?? stateRef.current.activeHandle;
294
- if (propsRef.current.disabled || propsRef.current.readOnly || !evt) return;
310
+ if (propsRef.current.disabled || propsRef.current.readOnly) return;
295
311
  const { value, left } = calcValue({
296
312
  clientX: getClientXFromEvent(evt),
297
313
  value: stateRef.current.value
@@ -358,7 +374,6 @@ const Slider = (props) => {
358
374
  */
359
375
  const onChangeInput = (evt) => {
360
376
  if (props.disabled || props.readOnly) return;
361
- if (!evt || !("target" in evt) || typeof evt.target.value !== "string") return;
362
377
  const activeHandle = evt.target.dataset.handlePosition ?? HandlePosition.LOWER;
363
378
  const targetValue = Number.parseFloat(evt.target.value);
364
379
  if (twoHandles) if (isNaN(targetValue)) setValueForHandle(activeHandle, evt.target.value);
@@ -382,7 +397,6 @@ const Slider = (props) => {
382
397
  * Handles state change to isValid state.
383
398
  */
384
399
  const onBlurInput = (evt) => {
385
- if (!evt || !("target" in evt) || typeof evt.target.value !== "string") return;
386
400
  const { value: targetValue } = evt.target;
387
401
  processNewInputValue(evt.target);
388
402
  props.onBlur?.({
@@ -392,7 +406,6 @@ const Slider = (props) => {
392
406
  };
393
407
  const onInputKeyDown = (evt) => {
394
408
  if (props.disabled || props.readOnly || !(evt.target instanceof HTMLInputElement)) return;
395
- if (!evt || !("target" in evt) || typeof evt.target.value !== "string") return;
396
409
  if (require_match.matches(evt, [require_keys.Enter])) processNewInputValue(evt.target);
397
410
  };
398
411
  const processNewInputValue = (input) => {
@@ -439,13 +452,17 @@ const Slider = (props) => {
439
452
  });
440
453
  }
441
454
  };
442
- const calcLeftPercent = ({ clientX, value, range }) => {
455
+ const calcLeftPercent = ({ clientX, value }) => {
443
456
  const boundingRect = elementRef.current?.getBoundingClientRect?.();
444
457
  let width = boundingRect ? boundingRect.right - boundingRect.left : 0;
458
+ const nextValue = value ?? props.min;
445
459
  if (width <= 0) width = 1;
446
460
  if (clientX) return (state.isRtl ? (boundingRect?.right ?? 0) - clientX : clientX - (boundingRect?.left ?? 0)) / width;
447
- else if (value !== null && typeof value !== "undefined" && range) return range === 0 ? 0 : (value - props.min) / range;
448
- return 0;
461
+ return calcRawLeftPercent({
462
+ max: props.max,
463
+ min: props.min,
464
+ value: nextValue
465
+ });
449
466
  };
450
467
  /**
451
468
  * Calculates the discrete value (snapped to the nearest step) along
@@ -469,8 +486,7 @@ const Slider = (props) => {
469
486
  /** `leftPercentRaw` clamped between 0 and 1. */
470
487
  const leftPercent = require_clamp.clamp(calcLeftPercent({
471
488
  clientX,
472
- value,
473
- range: props.max - props.min
489
+ value
474
490
  }), 0, 1);
475
491
  if (useRawValue) return {
476
492
  value,
@@ -539,8 +555,7 @@ const Slider = (props) => {
539
555
  max
540
556
  })) return false;
541
557
  if (handle === HandlePosition.LOWER) return !valueUpper || newValue <= valueUpper;
542
- else if (handle === HandlePosition.UPPER) return !value || newValue >= value;
543
- return false;
558
+ return !value || newValue >= value;
544
559
  };
545
560
  const isValidValue = ({ value, min, max }) => {
546
561
  return !(value < min || value > max);
@@ -13,11 +13,11 @@ const require_match = require('../../internal/keyboard/match.js');
13
13
  const require_useIsomorphicEffect = require('../../internal/useIsomorphicEffect.js');
14
14
  const require_useId = require('../../internal/useId.js');
15
15
  const require_deprecate = require('../../prop-types/deprecate.js');
16
+ const require_utils = require('../../internal/utils.js');
16
17
  const require_useMergedRefs = require('../../internal/useMergedRefs.js');
17
18
  const require_useEvent = require('../../internal/useEvent.js');
18
19
  const require_Tooltip = require('../Tooltip/Tooltip.js');
19
20
  const require_index = require('../BadgeIndicator/index.js');
20
- const require_utils = require('../../internal/utils.js');
21
21
  const require_useControllableState = require('../../internal/useControllableState.js');
22
22
  const require_Grid = require('../Grid/Grid.js');
23
23
  const require_useMatchMedia = require('../../internal/useMatchMedia.js');
@@ -11,9 +11,9 @@ const require_Text = require('../Text/Text.js');
11
11
  const require_useIsomorphicEffect = require('../../internal/useIsomorphicEffect.js');
12
12
  const require_useId = require('../../internal/useId.js');
13
13
  const require_deprecate = require('../../prop-types/deprecate.js');
14
+ const require_utils = require('../../internal/utils.js');
14
15
  const require_Tooltip = require('../Tooltip/Tooltip.js');
15
16
  const require_index = require('../AILabel/index.js');
16
- const require_utils = require('../../internal/utils.js');
17
17
  const require_mergeRefs = require('../../tools/mergeRefs.js');
18
18
  const require_isEllipsisActive = require('./isEllipsisActive.js');
19
19
  const require_Tag = require('./Tag.js');
@@ -11,10 +11,10 @@ const require_Text = require('../Text/Text.js');
11
11
  const require_useIsomorphicEffect = require('../../internal/useIsomorphicEffect.js');
12
12
  const require_useId = require('../../internal/useId.js');
13
13
  const require_deprecate = require('../../prop-types/deprecate.js');
14
+ const require_utils = require('../../internal/utils.js');
14
15
  const require_useMergedRefs = require('../../internal/useMergedRefs.js');
15
16
  const require_DefinitionTooltip = require('../Tooltip/DefinitionTooltip.js');
16
17
  const require_index = require('../AILabel/index.js');
17
- const require_utils = require('../../internal/utils.js');
18
18
  const require_isEllipsisActive = require('./isEllipsisActive.js');
19
19
  let classnames = require("classnames");
20
20
  classnames = require_runtime.__toESM(classnames);
@@ -12,9 +12,9 @@ const require_useIsomorphicEffect = require('../../internal/useIsomorphicEffect.
12
12
  const require_useId = require('../../internal/useId.js');
13
13
  const require_noopFn = require('../../internal/noopFn.js');
14
14
  const require_deprecate = require('../../prop-types/deprecate.js');
15
+ const require_utils = require('../../internal/utils.js');
15
16
  const require_useMergedRefs = require('../../internal/useMergedRefs.js');
16
17
  const require_index = require('../AILabel/index.js');
17
- const require_utils = require('../../internal/utils.js');
18
18
  const require_FormContext = require('../FluidForm/FormContext.js');
19
19
  const require_getAnnouncement = require('../../internal/getAnnouncement.js');
20
20
  let classnames = require("classnames");
@@ -9,9 +9,9 @@ const require_runtime = require('../../_virtual/_rolldown/runtime.js');
9
9
  const require_usePrefix = require('../../internal/usePrefix.js');
10
10
  const require_Text = require('../Text/Text.js');
11
11
  const require_deprecate = require('../../prop-types/deprecate.js');
12
+ const require_utils = require('../../internal/utils.js');
12
13
  const require_useMergedRefs = require('../../internal/useMergedRefs.js');
13
14
  const require_index = require('../AILabel/index.js');
14
- const require_utils = require('../../internal/utils.js');
15
15
  const require_FormContext = require('../FluidForm/FormContext.js');
16
16
  const require_useNormalizedInputProps = require('../../internal/useNormalizedInputProps.js');
17
17
  const require_util = require('./util.js');
@@ -14,11 +14,11 @@ const require_useIsomorphicEffect = require('../../internal/useIsomorphicEffect.
14
14
  const require_useId = require('../../internal/useId.js');
15
15
  const require_deprecate = require('../../prop-types/deprecate.js');
16
16
  const require_index = require('../Link/index.js');
17
+ const require_utils = require('../../internal/utils.js');
17
18
  const require_useMergedRefs = require('../../internal/useMergedRefs.js');
18
19
  const require_index$1 = require('../FeatureFlags/index.js');
19
20
  const require_useNoInteractiveChildren = require('../../internal/useNoInteractiveChildren.js');
20
21
  const require_index$2 = require('../AILabel/index.js');
21
- const require_utils = require('../../internal/utils.js');
22
22
  const require_events = require('../../tools/events.js');
23
23
  let classnames = require("classnames");
24
24
  classnames = require_runtime.__toESM(classnames);
@@ -10,9 +10,9 @@ const require_usePrefix = require('../../internal/usePrefix.js');
10
10
  const require_keys = require('../../internal/keyboard/keys.js');
11
11
  const require_match = require('../../internal/keyboard/match.js');
12
12
  const require_noopFn = require('../../internal/noopFn.js');
13
+ const require_utils = require('../../internal/utils.js');
13
14
  const require_useMergedRefs = require('../../internal/useMergedRefs.js');
14
15
  const require_useEvent = require('../../internal/useEvent.js');
15
- const require_utils = require('../../internal/utils.js');
16
16
  const require_Switcher = require('./Switcher.js');
17
17
  let classnames = require("classnames");
18
18
  classnames = require_runtime.__toESM(classnames);
@@ -7,8 +7,8 @@
7
7
 
8
8
  const require_runtime = require('../../_virtual/_rolldown/runtime.js');
9
9
  const require_usePrefix = require('../../internal/usePrefix.js');
10
- const require_useMergedRefs = require('../../internal/useMergedRefs.js');
11
10
  const require_utils = require('../../internal/utils.js');
11
+ const require_useMergedRefs = require('../../internal/useMergedRefs.js');
12
12
  const require_AriaPropTypes = require('../../prop-types/AriaPropTypes.js');
13
13
  const require_SwitcherItem = require('./SwitcherItem.js');
14
14
  const require_SwitcherDivider = require('./SwitcherDivider.js');
@@ -8,18 +8,10 @@ import { type RefObject } from 'react';
8
8
  export declare const useNoInteractiveChildren: (ref: RefObject<HTMLElement | null>, message?: string) => void;
9
9
  export declare const useInteractiveChildrenNeedDescription: (ref: RefObject<HTMLElement | null>, message?: string) => void;
10
10
  /**
11
- * Determines if a given DOM node has interactive content, or is itself
12
- * interactive. It returns the interactive node if one is found.
13
- *
14
- * @param node - The node to check.
15
- * @returns The interactive node, or `null` if none is found.
11
+ * Finds an interactive node in a given DOM node, including the node itself.
16
12
  */
17
13
  export declare const getInteractiveContent: (node: HTMLElement) => HTMLElement | null;
18
14
  /**
19
- * Determines if a given DOM node has a `role`, or has itself a `role`.
20
- * It returns the node with a `role` if one is found.
21
- *
22
- * @param node - The node to check.
23
- * @returns The node with a `role`, or `null` if none is found.
15
+ * Finds a node with a `role` in a given DOM node, including the node itself.
24
16
  */
25
17
  export declare const getRoleContent: (node: HTMLElement) => HTMLElement | null;
@@ -35,39 +35,28 @@ const useInteractiveChildrenNeedDescription = (ref, message = `interactive child
35
35
  if (node && !node.hasAttribute("aria-describedby")) throw new Error(`Error: ${message}.\n\nInstead found: ${node.outerHTML}`);
36
36
  }, [message, ref]);
37
37
  };
38
- /**
39
- * Determines if a given DOM node has interactive content, or is itself
40
- * interactive. It returns the interactive node if one is found.
41
- *
42
- * @param node - The node to check.
43
- * @returns The interactive node, or `null` if none is found.
44
- */
45
- const getInteractiveContent = (node) => {
46
- if (!node || !node.childNodes) return null;
47
- if (isFocusable(node)) return node;
48
- for (const childNode of node.childNodes) if (childNode instanceof HTMLElement) {
49
- const interactiveNode = getInteractiveContent(childNode);
50
- if (interactiveNode) return interactiveNode;
38
+ const findMatchingContent = (node, matcher) => {
39
+ if (matcher(node)) return node;
40
+ for (const child of node.children) {
41
+ if (!(child instanceof HTMLElement)) continue;
42
+ const matchingChild = findMatchingContent(child, matcher);
43
+ if (matchingChild) return matchingChild;
51
44
  }
52
45
  return null;
53
46
  };
54
47
  /**
55
- * Determines if a given DOM node has a `role`, or has itself a `role`.
56
- * It returns the node with a `role` if one is found.
57
- *
58
- * @param node - The node to check.
59
- * @returns The node with a `role`, or `null` if none is found.
48
+ * Finds an interactive node in a given DOM node, including the node itself.
60
49
  */
61
- const getRoleContent = (node) => {
62
- if (!node || !node.childNodes) return null;
63
- if (node.getAttribute("role") && node.getAttribute("role") !== "") return node;
64
- for (const childNode of node.childNodes) if (childNode instanceof HTMLElement) {
65
- const roleNode = getRoleContent(childNode);
66
- if (roleNode) return roleNode;
67
- }
68
- return null;
50
+ const getInteractiveContent = (node) => findMatchingContent(node, isFocusable);
51
+ const hasRole = (element) => {
52
+ const role = element.getAttribute("role");
53
+ return role !== null && role !== "";
69
54
  };
70
55
  /**
56
+ * Finds a node with a `role` in a given DOM node, including the node itself.
57
+ */
58
+ const getRoleContent = (node) => findMatchingContent(node, hasRole);
59
+ /**
71
60
  * Determines if the given element is focusable.
72
61
  *
73
62
  * @param element - The element to check.
@@ -75,7 +64,7 @@ const getRoleContent = (node) => {
75
64
  * @see https://github.com/w3c/aria-practices/blob/0553bb51588ffa517506e2a1b2ca1422ed438c5f/examples/js/utils.js#L68
76
65
  */
77
66
  const isFocusable = (element) => {
78
- if (element.tabIndex === void 0 || element.tabIndex < 0) return false;
67
+ if (element.tabIndex < 0) return false;
79
68
  if (element instanceof HTMLButtonElement || element instanceof HTMLInputElement || element instanceof HTMLSelectElement || element instanceof HTMLTextAreaElement) {
80
69
  if (element.disabled) return false;
81
70
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@carbon/react",
3
3
  "description": "React components for the Carbon Design System",
4
- "version": "1.104.1",
4
+ "version": "1.105.0",
5
5
  "license": "Apache-2.0",
6
6
  "main": "lib/index.js",
7
7
  "types": "lib/index.d.ts",
@@ -53,9 +53,9 @@
53
53
  "dependencies": {
54
54
  "@babel/runtime": "^7.27.3",
55
55
  "@carbon/feature-flags": "^1.2.0",
56
- "@carbon/icons-react": "^11.77.1",
57
- "@carbon/layout": "^11.50.0",
58
- "@carbon/styles": "^1.103.0",
56
+ "@carbon/icons-react": "^11.78.0",
57
+ "@carbon/layout": "^11.51.0",
58
+ "@carbon/styles": "^1.104.0",
59
59
  "@carbon/utilities": "^0.18.0",
60
60
  "@floating-ui/react": "^0.27.4",
61
61
  "@ibm/telemetry-js": "^1.5.0",
@@ -78,8 +78,8 @@
78
78
  "@babel/preset-env": "^7.27.2",
79
79
  "@babel/preset-react": "^7.27.1",
80
80
  "@babel/preset-typescript": "^7.27.1",
81
- "@carbon/test-utils": "^10.40.0",
82
- "@carbon/themes": "^11.70.0",
81
+ "@carbon/test-utils": "^10.41.0",
82
+ "@carbon/themes": "^11.71.0",
83
83
  "@figma/code-connect": "^1.4.2",
84
84
  "@stackblitz/sdk": "^1.11.0",
85
85
  "@storybook/addon-a11y": "^9.1.8",
@@ -125,5 +125,5 @@
125
125
  "**/*.scss",
126
126
  "**/*.css"
127
127
  ],
128
- "gitHead": "a4755588e3a7d4e4d9c53abcc65367644dca7e73"
128
+ "gitHead": "937649543e9cc6af9dfb6b53a2adb76760bca986"
129
129
  }