@carbon/react 1.78.1 → 1.79.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.
Files changed (58) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +844 -844
  2. package/es/components/Button/Button.js +28 -17
  3. package/es/components/Button/ButtonBase.js +2 -0
  4. package/es/components/DataTable/TableContainer.js +3 -2
  5. package/es/components/Grid/Column.d.ts +2 -2
  6. package/es/components/Grid/Column.js +7 -8
  7. package/es/components/IconButton/index.d.ts +2 -2
  8. package/es/components/IconButton/index.js +1 -1
  9. package/es/components/MultiSelect/index.d.ts +1 -1
  10. package/es/components/MultiSelect/index.js +1 -8
  11. package/es/components/OverflowMenu/OverflowMenu.d.ts +21 -196
  12. package/es/components/OverflowMenu/OverflowMenu.js +267 -336
  13. package/es/components/OverflowMenu/index.d.ts +5 -5
  14. package/es/components/OverflowMenu/index.js +2 -2
  15. package/es/components/OverflowMenu/next/index.d.ts +2 -2
  16. package/es/components/Slider/Slider.d.ts +23 -29
  17. package/es/components/Slider/Slider.js +35 -37
  18. package/es/components/Tabs/Tabs.js +8 -9
  19. package/es/components/Tile/Tile.js +8 -4
  20. package/es/index.js +1 -1
  21. package/es/internal/FloatingMenu.d.ts +2 -2
  22. package/es/internal/FloatingMenu.js +4 -1
  23. package/es/internal/createClassWrapper.d.ts +3 -3
  24. package/es/internal/createClassWrapper.js +4 -4
  25. package/es/internal/useMatchMedia.d.ts +8 -0
  26. package/es/internal/useMatchMedia.js +10 -20
  27. package/es/internal/useNormalizedInputProps.d.ts +52 -0
  28. package/es/internal/useNormalizedInputProps.js +9 -36
  29. package/lib/components/Button/Button.js +28 -17
  30. package/lib/components/Button/ButtonBase.js +2 -0
  31. package/lib/components/DataTable/TableContainer.js +3 -2
  32. package/lib/components/Grid/Column.d.ts +2 -2
  33. package/lib/components/Grid/Column.js +7 -8
  34. package/lib/components/IconButton/index.d.ts +2 -2
  35. package/lib/components/IconButton/index.js +1 -1
  36. package/lib/components/MultiSelect/index.d.ts +1 -1
  37. package/lib/components/MultiSelect/index.js +1 -8
  38. package/lib/components/OverflowMenu/OverflowMenu.d.ts +21 -196
  39. package/lib/components/OverflowMenu/OverflowMenu.js +266 -334
  40. package/lib/components/OverflowMenu/index.d.ts +5 -5
  41. package/lib/components/OverflowMenu/index.js +2 -2
  42. package/lib/components/OverflowMenu/next/index.d.ts +2 -2
  43. package/lib/components/Slider/Slider.d.ts +23 -29
  44. package/lib/components/Slider/Slider.js +35 -37
  45. package/lib/components/Tabs/Tabs.js +8 -9
  46. package/lib/components/Tile/Tile.js +8 -4
  47. package/lib/index.js +2 -2
  48. package/lib/internal/FloatingMenu.d.ts +2 -2
  49. package/lib/internal/FloatingMenu.js +4 -1
  50. package/lib/internal/createClassWrapper.d.ts +3 -3
  51. package/lib/internal/createClassWrapper.js +4 -4
  52. package/lib/internal/useMatchMedia.d.ts +8 -0
  53. package/lib/internal/useMatchMedia.js +10 -20
  54. package/lib/internal/useNormalizedInputProps.d.ts +52 -0
  55. package/lib/internal/useNormalizedInputProps.js +9 -36
  56. package/package.json +6 -6
  57. package/es/internal/useEffectOnce.js +0 -30
  58. package/lib/internal/useEffectOnce.js +0 -34
@@ -1,13 +1,13 @@
1
1
  /**
2
- * Copyright IBM Corp. 2016, 2023
2
+ * Copyright IBM Corp. 2016, 2025
3
3
  *
4
4
  * This source code is licensed under the Apache-2.0 license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import { type OverflowMenuProps } from './OverflowMenu';
8
- declare function OverflowMenu(props: any): import("react/jsx-runtime").JSX.Element;
9
- declare namespace OverflowMenu {
10
- var displayName: string;
11
- }
8
+ declare const OverflowMenu: {
9
+ (props: OverflowMenuProps): import("react/jsx-runtime").JSX.Element;
10
+ displayName: string;
11
+ };
12
12
  export default OverflowMenu;
13
13
  export { OverflowMenu, type OverflowMenuProps };
@@ -12,10 +12,10 @@ import { OverflowMenu as OverflowMenu$1 } from './OverflowMenu.js';
12
12
  import { createClassWrapper } from '../../internal/createClassWrapper.js';
13
13
 
14
14
  const OverflowMenuV11 = createClassWrapper(OverflowMenu$1);
15
- function OverflowMenu(props) {
15
+ const OverflowMenu = props => {
16
16
  const enableV12OverflowMenu = useFeatureFlag('enable-v12-overflowmenu');
17
17
  return enableV12OverflowMenu ? /*#__PURE__*/React__default.createElement(OverflowMenu$2, props) : /*#__PURE__*/React__default.createElement(OverflowMenuV11, props);
18
- }
18
+ };
19
19
  OverflowMenu.displayName = 'OverflowMenu';
20
20
 
21
21
  export { OverflowMenu, OverflowMenu as default };
@@ -4,7 +4,7 @@
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
- import React, { type ComponentType, type FunctionComponent } from 'react';
7
+ import React, { type ElementType } from 'react';
8
8
  interface OverflowMenuProps {
9
9
  /**
10
10
  * **Experimental**: Will attempt to automatically align the floating element to avoid collisions with the viewport and being clipped by ancestor elements.
@@ -29,7 +29,7 @@ interface OverflowMenuProps {
29
29
  /**
30
30
  * A component used to render an icon.
31
31
  */
32
- renderIcon?: ComponentType | FunctionComponent;
32
+ renderIcon?: ElementType;
33
33
  /**
34
34
  * Specify the size of the menu, from a list of available sizes.
35
35
  */
@@ -164,11 +164,6 @@ export interface SliderProps extends Omit<React.InputHTMLAttributes<HTMLInputEle
164
164
  */
165
165
  warnText?: React.ReactNode;
166
166
  }
167
- interface CalcValueProps {
168
- clientX?: number;
169
- value?: number;
170
- useRawValue?: boolean;
171
- }
172
167
  interface CalcLeftPercentProps {
173
168
  clientX?: number;
174
169
  value?: number;
@@ -415,30 +410,29 @@ declare class Slider extends PureComponent<SliderProps> {
415
410
  onInputKeyDown: (evt: any) => void;
416
411
  processNewInputValue: (input: HTMLInputElement) => void;
417
412
  calcLeftPercent: ({ clientX, value, range }: CalcLeftPercentProps) => number;
418
- calcSteppedValuePercent: ({ leftPercent, range }: {
419
- leftPercent: any;
420
- range: any;
421
- }) => number[];
422
- /**
423
- * Calculates a new Slider `value` and `left` (thumb offset) given a `clientX`,
424
- * `value`, or neither of those.
425
- * - If `clientX` is specified, it will be used in
426
- * conjunction with the Slider's bounding rectangle to calculate the new
427
- * values.
428
- * - If `clientX` is not specified and `value` is, it will be used to
429
- * calculate new values as though it were the current value of the Slider.
430
- * - If neither `clientX` nor `value` are specified, `this.props.value` will
431
- * be used to calculate the new values as though it were the current value
432
- * of the Slider.
433
- *
434
- * @param {object} params
435
- * @param {number} [params.clientX] Optional clientX value expected to be from
436
- * an event fired by one of the Slider's `DRAG_EVENT_TYPES` events.
437
- * @param {number} [params.value] Optional value use during calculations if
438
- * clientX is not provided.
439
- * @param {boolean} [params.useRawValue=false] `true` to use the given value as-is.
440
- */
441
- calcValue: ({ clientX, value, useRawValue }: CalcValueProps) => {
413
+ /**
414
+ * Calculates the discrete value (snapped to the nearest step) along
415
+ * with the corresponding handle position percentage.
416
+ */
417
+ calcDiscreteValueAndPercent: ({ leftPercent, }: {
418
+ /** The percentage representing the position on the track. */
419
+ leftPercent: number;
420
+ }) => {
421
+ discreteValue: number;
422
+ discretePercent: number;
423
+ };
424
+ /**
425
+ * Calculates the slider's value and handle position based on either a
426
+ * mouse/touch event or an explicit value.
427
+ */
428
+ calcValue: ({ clientX, value, useRawValue, }: {
429
+ /** The x-coordinate from a mouse/touch event. */
430
+ clientX?: number;
431
+ /** Value to base the calculations on (if no `clientX`). */
432
+ value?: number;
433
+ /** Whether to bypass the stepping logic and use the raw value. */
434
+ useRawValue?: boolean;
435
+ }) => {
442
436
  value: number | undefined;
443
437
  left: number;
444
438
  };
@@ -523,67 +523,65 @@ class Slider extends PureComponent {
523
523
  // re-assure Typescript, return 0.
524
524
  return 0;
525
525
  });
526
- _defineProperty(this, "calcSteppedValuePercent", _ref3 => {
526
+ /**
527
+ * Calculates the discrete value (snapped to the nearest step) along
528
+ * with the corresponding handle position percentage.
529
+ */
530
+ _defineProperty(this, "calcDiscreteValueAndPercent", _ref3 => {
527
531
  let {
528
- leftPercent,
529
- range
532
+ leftPercent
530
533
  } = _ref3;
531
534
  const {
532
- step = 1
535
+ step = 1,
536
+ min,
537
+ max
533
538
  } = this.props;
534
- const totalSteps = range / step;
535
- let steppedValue = Math.round(leftPercent * totalSteps) * step;
536
- const steppedPercent = this.clamp(steppedValue / range, 0, 1);
537
- steppedValue = this.clamp(steppedValue + this.props.min, this.props.min, this.props.max);
538
- return [steppedValue, steppedPercent];
539
+ const numSteps = Math.floor((max - min) / step) + ((max - min) % step === 0 ? 1 : 2);
540
+ /** Index of the step that corresponds to `leftPercent`. */
541
+ const stepIndex = Math.round(leftPercent * (numSteps - 1));
542
+ const discreteValue = stepIndex === numSteps - 1 ? max : min + step * stepIndex;
543
+ /** Percentage corresponding to the step index. */
544
+ const discretePercent = stepIndex / (numSteps - 1);
545
+ return {
546
+ discreteValue,
547
+ discretePercent
548
+ };
539
549
  });
540
550
  /**
541
- * Calculates a new Slider `value` and `left` (thumb offset) given a `clientX`,
542
- * `value`, or neither of those.
543
- * - If `clientX` is specified, it will be used in
544
- * conjunction with the Slider's bounding rectangle to calculate the new
545
- * values.
546
- * - If `clientX` is not specified and `value` is, it will be used to
547
- * calculate new values as though it were the current value of the Slider.
548
- * - If neither `clientX` nor `value` are specified, `this.props.value` will
549
- * be used to calculate the new values as though it were the current value
550
- * of the Slider.
551
- *
552
- * @param {object} params
553
- * @param {number} [params.clientX] Optional clientX value expected to be from
554
- * an event fired by one of the Slider's `DRAG_EVENT_TYPES` events.
555
- * @param {number} [params.value] Optional value use during calculations if
556
- * clientX is not provided.
557
- * @param {boolean} [params.useRawValue=false] `true` to use the given value as-is.
551
+ * Calculates the slider's value and handle position based on either a
552
+ * mouse/touch event or an explicit value.
558
553
  */
559
554
  _defineProperty(this, "calcValue", _ref4 => {
560
555
  let {
561
556
  clientX,
562
557
  value,
563
- useRawValue = false
558
+ useRawValue
564
559
  } = _ref4;
565
560
  const range = this.props.max - this.props.min;
566
-
567
- // @todo solve for rtl.
568
- const leftPercent = this.calcLeftPercent({
561
+ const leftPercentRaw = this.calcLeftPercent({
569
562
  clientX,
570
563
  value,
571
564
  range
572
565
  });
566
+ /** `leftPercentRaw` clamped between 0 and 1. */
567
+ const leftPercent = Math.min(1, Math.max(0, leftPercentRaw));
573
568
  if (useRawValue) {
574
- // Adjusts only for min/max of thumb position
575
569
  return {
576
570
  value,
577
- left: Math.min(1, Math.max(0, leftPercent)) * 100
571
+ left: leftPercent * 100
578
572
  };
579
573
  }
580
- const [steppedValue, steppedPercent] = this.calcSteppedValuePercent({
581
- leftPercent,
582
- range
574
+
575
+ // Use the discrete value and percentage for snapping.
576
+ const {
577
+ discreteValue,
578
+ discretePercent
579
+ } = this.calcDiscreteValueAndPercent({
580
+ leftPercent
583
581
  });
584
582
  return {
585
- value: steppedValue,
586
- left: steppedPercent * 100
583
+ value: discreteValue,
584
+ left: discretePercent * 100
587
585
  };
588
586
  });
589
587
  _defineProperty(this, "calcDistanceToHandle", (handle, clientX) => {
@@ -21,7 +21,6 @@ import { isElement } from 'react-is';
21
21
  import '../Tooltip/DefinitionTooltip.js';
22
22
  import { Tooltip } from '../Tooltip/Tooltip.js';
23
23
  import { useControllableState } from '../../internal/useControllableState.js';
24
- import { useEffectOnce } from '../../internal/useEffectOnce.js';
25
24
  import { useId } from '../../internal/useId.js';
26
25
  import useIsomorphicEffect from '../../internal/useIsomorphicEffect.js';
27
26
  import { useMergedRefs } from '../../internal/useMergedRefs.js';
@@ -382,7 +381,7 @@ function TabList(_ref4) {
382
381
  }
383
382
  }
384
383
  }
385
- useEffectOnce(() => {
384
+ useEffect(() => {
386
385
  const tab = tabs.current[selectedIndex];
387
386
  if (scrollIntoView && tab) {
388
387
  tab.scrollIntoView({
@@ -390,7 +389,7 @@ function TabList(_ref4) {
390
389
  inline: 'nearest'
391
390
  });
392
391
  }
393
- });
392
+ }, []);
394
393
  useEffect(() => {
395
394
  //adding 1 in calculation for firefox support
396
395
  setIsNextButtonVisible(ref.current ? scrollLeft + buttonWidth + ref.current.clientWidth + 1 < ref.current.scrollWidth : false);
@@ -400,7 +399,7 @@ function TabList(_ref4) {
400
399
  }
401
400
  }
402
401
  }, [scrollLeft, children, dismissable, isScrollable]);
403
- useEffectOnce(() => {
402
+ useEffect(() => {
404
403
  if (tabs.current[selectedIndex]?.disabled) {
405
404
  const activeTabs = tabs.current.filter(tab => {
406
405
  return !tab.disabled;
@@ -410,7 +409,7 @@ function TabList(_ref4) {
410
409
  setSelectedIndex(tabs.current.indexOf(tab));
411
410
  }
412
411
  }
413
- });
412
+ }, []);
414
413
  useIsomorphicEffect(() => {
415
414
  if (ref.current) {
416
415
  // adding 1 in calculation for firefox support
@@ -624,7 +623,7 @@ function TabListVertical(_ref8) {
624
623
  setActiveIndex(selectedIndex);
625
624
  }
626
625
  }
627
- useEffectOnce(() => {
626
+ useEffect(() => {
628
627
  if (tabs.current[selectedIndex]?.disabled) {
629
628
  const activeTabs = tabs.current.filter(tab => {
630
629
  return !tab.disabled;
@@ -634,7 +633,7 @@ function TabListVertical(_ref8) {
634
633
  setSelectedIndex(tabs.current.indexOf(tab));
635
634
  }
636
635
  }
637
- });
636
+ }, []);
638
637
  useEffect(() => {
639
638
  function handler() {
640
639
  const containerHeight = ref.current?.offsetHeight;
@@ -1123,7 +1122,7 @@ const TabPanel = /*#__PURE__*/React__default.forwardRef(function TabPanel(_ref12
1123
1122
  const className = cx(`${prefix}--tab-content`, customClassName, {
1124
1123
  [`${prefix}--tab-content--interactive`]: interactiveContent
1125
1124
  });
1126
- useEffectOnce(() => {
1125
+ useEffect(() => {
1127
1126
  if (!panel.current) {
1128
1127
  return;
1129
1128
  }
@@ -1132,7 +1131,7 @@ const TabPanel = /*#__PURE__*/React__default.forwardRef(function TabPanel(_ref12
1132
1131
  setInteractiveContent(true);
1133
1132
  setTabIndex(-1);
1134
1133
  }
1135
- });
1134
+ }, []);
1136
1135
 
1137
1136
  // tabindex should only be 0 if no interactive content in children
1138
1137
  useEffect(() => {
@@ -255,14 +255,18 @@ const SelectableTile = /*#__PURE__*/React__default.forwardRef(function Selectabl
255
255
  evt?.persist?.();
256
256
  if (matches(evt, [Enter, Space])) {
257
257
  evt.preventDefault();
258
- setIsSelected(!isSelected);
259
- onChange(evt, isSelected, id);
258
+ setIsSelected(prevSelected => {
259
+ const newSelected = !prevSelected;
260
+ onChange(evt, newSelected, id);
261
+ return newSelected;
262
+ });
260
263
  }
261
264
  keyDownHandler(evt);
262
265
  }
263
266
  function handleChange(event) {
264
- setIsSelected(event.target.checked);
265
- onChange(event, isSelected, id);
267
+ const newSelected = event.target.checked;
268
+ setIsSelected(newSelected);
269
+ onChange(event, newSelected, id);
266
270
  }
267
271
  if (selected !== prevSelected) {
268
272
  setIsSelected(selected);
package/es/index.js CHANGED
@@ -207,6 +207,7 @@ export { default as unstable_PageSelector } from './components/Pagination/experi
207
207
  export { default as unstable_Pagination } from './components/Pagination/experimental/Pagination.js';
208
208
  export { default as ContainedListItem } from './components/ContainedList/ContainedListItem/ContainedListItem.js';
209
209
  export { default as ContainedList } from './components/ContainedList/ContainedList.js';
210
+ export { default as MultiSelect } from './components/MultiSelect/MultiSelect.js';
210
211
  export { default as SliderSkeleton } from './components/Slider/Slider.Skeleton.js';
211
212
  export { default as TextInputSkeleton } from './components/TextInput/TextInput.Skeleton.js';
212
213
  export { default as TextInput } from './components/TextInput/TextInput.js';
@@ -238,4 +239,3 @@ export { default as TableToolbarContent } from './components/DataTable/TableTool
238
239
  export { default as TableToolbarSearch } from './components/DataTable/TableToolbarSearch.js';
239
240
  export { default as TableToolbarMenu } from './components/DataTable/TableToolbarMenu.js';
240
241
  export { default as FilterableMultiSelect } from './components/MultiSelect/FilterableMultiSelect.js';
241
- export { default as MultiSelect } from './components/MultiSelect/MultiSelect.js';
@@ -10,8 +10,8 @@ export declare const DIRECTION_TOP = "top";
10
10
  export declare const DIRECTION_RIGHT = "right";
11
11
  export declare const DIRECTION_BOTTOM = "bottom";
12
12
  export interface Offset {
13
- top?: number;
14
- left?: number;
13
+ top: number;
14
+ left: number;
15
15
  }
16
16
  interface Container {
17
17
  rect: DOMRect;
@@ -83,7 +83,10 @@ const FloatingMenu = _ref2 => {
83
83
  flipped,
84
84
  focusTrap,
85
85
  menuDirection = DIRECTION_BOTTOM,
86
- menuOffset = {},
86
+ menuOffset = {
87
+ top: 0,
88
+ left: 0
89
+ },
87
90
  menuRef: externalMenuRef,
88
91
  onPlace,
89
92
  selectorPrimaryFocus,
@@ -1,12 +1,12 @@
1
1
  /**
2
- * Copyright IBM Corp. 2016, 2023
2
+ * Copyright IBM Corp. 2016, 2025
3
3
  *
4
4
  * This source code is licensed under the Apache-2.0 license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- import { ComponentClass, FunctionComponent } from 'react';
7
+ import { type ComponentClass, type ForwardRefExoticComponent, type FunctionComponent, type PropsWithChildren } from 'react';
8
8
  /**
9
9
  * Wrap a class component with a functional component. This prevents an end-user
10
10
  * from being able to pass `ref` and access the underlying class instance.
11
11
  */
12
- export declare function createClassWrapper<Props>(Component: ComponentClass<Props>): FunctionComponent<Props>;
12
+ export declare const createClassWrapper: <Props extends PropsWithChildren>(Component: ComponentClass<Props> | ForwardRefExoticComponent<Props>) => FunctionComponent<Props>;
@@ -11,13 +11,13 @@ import React__default from 'react';
11
11
  * Wrap a class component with a functional component. This prevents an end-user
12
12
  * from being able to pass `ref` and access the underlying class instance.
13
13
  */
14
- function createClassWrapper(Component) {
15
- function ClassWrapper(props) {
14
+ const createClassWrapper = Component => {
15
+ const ClassWrapper = props => {
16
16
  return /*#__PURE__*/React__default.createElement(Component, props);
17
- }
17
+ };
18
18
  const name = Component.displayName || Component.name;
19
19
  ClassWrapper.displayName = `ClassWrapper(${name})`;
20
20
  return ClassWrapper;
21
- }
21
+ };
22
22
 
23
23
  export { createClassWrapper };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Copyright IBM Corp. 2016, 2025
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ /** Listens to changes in a media query and returns whether it matches. */
8
+ export declare const useMatchMedia: (mediaQuery: string) => boolean;
@@ -8,37 +8,27 @@
8
8
  import { useState, useEffect } from 'react';
9
9
  import { canUseDOM } from './environment.js';
10
10
 
11
- function useMatchMedia(mediaQueryString) {
11
+ /** Listens to changes in a media query and returns whether it matches. */
12
+ const useMatchMedia = mediaQuery => {
12
13
  const [matches, setMatches] = useState(() => {
13
14
  if (canUseDOM) {
14
- const mediaQueryList = window.matchMedia(mediaQueryString);
15
+ const mediaQueryList = window.matchMedia(mediaQuery);
15
16
  return mediaQueryList.matches;
16
17
  }
17
18
  return false;
18
19
  });
19
20
  useEffect(() => {
20
- function listener(event) {
21
+ const listener = event => {
21
22
  setMatches(event.matches);
22
- }
23
- const mediaQueryList = window.matchMedia(mediaQueryString);
24
- // Support fallback to `addListener` for broader browser support
25
- if (mediaQueryList.addEventListener) {
26
- mediaQueryList.addEventListener('change', listener);
27
- } else {
28
- mediaQueryList.addListener(listener);
29
- }
30
-
31
- // Make sure the media query list is in sync with the matches state
23
+ };
24
+ const mediaQueryList = window.matchMedia(mediaQuery);
25
+ mediaQueryList.addEventListener('change', listener);
32
26
  setMatches(mediaQueryList.matches);
33
27
  return () => {
34
- if (mediaQueryList.addEventListener) {
35
- mediaQueryList.removeEventListener('change', listener);
36
- } else {
37
- mediaQueryList.removeListener(listener);
38
- }
28
+ mediaQueryList.removeEventListener('change', listener);
39
29
  };
40
- }, [mediaQueryString]);
30
+ }, [mediaQuery]);
41
31
  return matches;
42
- }
32
+ };
43
33
 
44
34
  export { useMatchMedia };
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Copyright IBM Corp. 2021, 2025
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ import { type ComponentType, type ReactNode } from 'react';
8
+ interface InputProps {
9
+ /** The ID for the input. */
10
+ id: string;
11
+ /** Whether the input is read-only. */
12
+ readOnly?: boolean;
13
+ /** Whether the input is disabled. */
14
+ disabled: boolean;
15
+ /** Whether the input is an invalid state. */
16
+ invalid: boolean;
17
+ /** The message displayed when the input is invalid. */
18
+ invalidText?: ReactNode;
19
+ /** Whether the input is in a warning state. */
20
+ warn: boolean;
21
+ /** The message displayed when the input is in a warning state. */
22
+ warnText?: ReactNode;
23
+ }
24
+ interface NormalizedInputProps {
25
+ /** Disabled state. */
26
+ disabled: boolean;
27
+ /** Invalid state. */
28
+ invalid: boolean;
29
+ /** The generated ID for the error message. */
30
+ invalidId: string;
31
+ /** The generated ID for the helper text. */
32
+ helperId: string;
33
+ /** Warning state. */
34
+ warn: boolean;
35
+ /** The generated ID for the warning message. */
36
+ warnId: string;
37
+ /** A React node containing the validation message. */
38
+ validation: ReactNode | null;
39
+ /** A React component representing the accompanying icon. */
40
+ icon: ComponentType | null;
41
+ }
42
+ /**
43
+ * Returns an object containing normalized properties for an input component.
44
+ *
45
+ * This hook ensures that only one of `invalid` or `warn` is active (with
46
+ * `invalid` taking precedence) and that `readOnly` overrides the `disabled`,
47
+ * `invalid`, and `warn` states. It generates unique IDs for error, warning, and
48
+ * helper messages, and conditionally provides the appropriate validation
49
+ * message and accompanying icon.
50
+ */
51
+ export declare const useNormalizedInputProps: ({ id, readOnly, disabled, invalid, invalidText, warn, warnText, }: InputProps) => NormalizedInputProps;
52
+ export {};
@@ -7,47 +7,20 @@
7
7
 
8
8
  import React__default from 'react';
9
9
  import { WarningFilled, WarningAltFilled } from '@carbon/icons-react';
10
- import { usePrefix } from './usePrefix.js';
11
10
  import '../components/Text/index.js';
11
+ import { usePrefix } from './usePrefix.js';
12
12
  import { Text } from '../components/Text/Text.js';
13
13
 
14
14
  /**
15
- * @typedef {object} InputProps
16
- * @property {string} id - The input's id
17
- * @property {boolean | undefined} readOnly - Whether the input should be readonly
18
- * @property {boolean} disabled - Whether the input should be disabled
19
- * @property {boolean} invalid - Whether the input should be marked as invalid
20
- * @property {React.ReactNode | undefined} invalidText - The validation message displayed in case the input is considered invalid
21
- * @property {boolean} warn - Whether the input should be in warning state
22
- * @property {React.ReactNode | undefined} warnText - The validation message displayed in case the input is in warning state
23
- */
24
-
25
- /**
26
- * @typedef {object} NormalizedInputProps
27
- * @property {boolean} disabled - Whether the input is disabled
28
- * @property {boolean} invalid - Whether the input is invalid (takes precedence over warn)
29
- * @property {string} invalidId - The invalid message's id
30
- * @property {string} helperId - id used for helper text
31
- * @property {boolean} warn - Whether the input is in warning state
32
- * @property {string} warnId - The warning message's id
33
- * @property {React.ReactNode | null} validation – React node rendering the appropriate validation message (if any)
34
- * @property {React.ReactNode | null} icon – React node rendering the appropriate accompanying icon (if any)
35
- */
36
-
37
- /**
38
- * Returns an object containing non-colliding props and additional, generated ones.
39
- * This hook ensures that only either "invalid" or "warn" is true but never both at
40
- * the same time. Regardless whether "invalid" or "warn", the appropriate validation
41
- * message is passed as "validation". If the input should be accompanied by an icon
42
- * (to visually represent a readonly, invalid or warning state), the appropriate icon
43
- * is passed as "icon".
44
- * It also ensure that neither "invalid", nor "warn", nor "disabled" are enabled when
45
- * "readonly" is passed as "readonly" takes precedence over these variants.
15
+ * Returns an object containing normalized properties for an input component.
46
16
  *
47
- * @param {InputProps} props - The props passed to the component
48
- * @returns {NormalizedInputProps}
17
+ * This hook ensures that only one of `invalid` or `warn` is active (with
18
+ * `invalid` taking precedence) and that `readOnly` overrides the `disabled`,
19
+ * `invalid`, and `warn` states. It generates unique IDs for error, warning, and
20
+ * helper messages, and conditionally provides the appropriate validation
21
+ * message and accompanying icon.
49
22
  */
50
- function useNormalizedInputProps(_ref) {
23
+ const useNormalizedInputProps = _ref => {
51
24
  let {
52
25
  id,
53
26
  readOnly,
@@ -84,6 +57,6 @@ function useNormalizedInputProps(_ref) {
84
57
  }, warnText);
85
58
  }
86
59
  return normalizedProps;
87
- }
60
+ };
88
61
 
89
62
  export { useNormalizedInputProps };
@@ -85,23 +85,34 @@ const Button = /*#__PURE__*/React__default["default"].forwardRef((props, ref) =>
85
85
  if (tooltipPosition === 'right' || tooltipPosition === 'left') {
86
86
  align = tooltipPosition;
87
87
  }
88
- return /*#__PURE__*/React__default["default"].createElement(index.IconButton, _rollupPluginBabelHelpers["extends"]({}, rest, {
89
- ref: ref,
90
- as: as,
91
- align: align,
92
- label: iconDescription,
93
- kind: kind,
94
- size: size,
95
- highContrast: tooltipHighContrast,
96
- dropShadow: tooltipDropShadow,
97
- onMouseEnter: onMouseEnter,
98
- onMouseLeave: onMouseLeave,
99
- onFocus: onFocus,
100
- onBlur: onBlur,
101
- autoAlign: autoAlign,
102
- onClick: events.composeEventHandlers([onClick, handleClick]),
103
- renderIcon: iconOnlyImage ? null : ButtonImageElement // avoid doubling the icon.
104
- }), iconOnlyImage ?? children);
88
+ return (
89
+ /*#__PURE__*/
90
+ // @ts-expect-error - `IconButton` does not support all `size`s that
91
+ // `Button` supports.
92
+ //
93
+ // TODO: What should be done here?
94
+ // 1. Should the `IconButton` not be rendered if the `size` is not
95
+ // supported?
96
+ // 2. Should an error be thrown?
97
+ // 3. Something else?
98
+ React__default["default"].createElement(index.IconButton, _rollupPluginBabelHelpers["extends"]({}, rest, {
99
+ ref: ref,
100
+ as: as,
101
+ align: align,
102
+ label: iconDescription,
103
+ kind: kind,
104
+ size: size,
105
+ highContrast: tooltipHighContrast,
106
+ dropShadow: tooltipDropShadow,
107
+ onMouseEnter: onMouseEnter,
108
+ onMouseLeave: onMouseLeave,
109
+ onFocus: onFocus,
110
+ onBlur: onBlur,
111
+ autoAlign: autoAlign,
112
+ onClick: events.composeEventHandlers([onClick, handleClick]),
113
+ renderIcon: iconOnlyImage ? null : ButtonImageElement // avoid doubling the icon.
114
+ }), iconOnlyImage ?? children)
115
+ );
105
116
  }
106
117
  });
107
118
  Button.displayName = 'Button';
@@ -50,6 +50,8 @@ const ButtonBase = /*#__PURE__*/React__default["default"].forwardRef(function Bu
50
50
  // TODO: V12 - Remove this class
51
51
  [`${prefix}--btn--md`]: size === 'md' && !isExpressive,
52
52
  // TODO: V12 - Remove this class
53
+ [`${prefix}--btn--lg`]: size === 'lg' && !isExpressive,
54
+ // TODO: V12 - Remove this class
53
55
  [`${prefix}--btn--xl`]: size === 'xl',
54
56
  // TODO: V12 - Remove this class
55
57
  [`${prefix}--btn--2xl`]: size === '2xl',