@carbon/react 1.42.1 → 1.43.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 (59) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +2542 -1275
  2. package/es/components/Breadcrumb/BreadcrumbItem.js +1 -2
  3. package/es/components/ComboBox/ComboBox.d.ts +5 -0
  4. package/es/components/ComboBox/ComboBox.js +16 -2
  5. package/es/components/ComposedModal/ModalFooter.d.ts +18 -0
  6. package/es/components/ComposedModal/ModalFooter.js +48 -16
  7. package/es/components/DatePickerInput/DatePickerInput.d.ts +4 -0
  8. package/es/components/DatePickerInput/DatePickerInput.js +16 -2
  9. package/es/components/Dropdown/Dropdown.d.ts +5 -0
  10. package/es/components/Dropdown/Dropdown.js +16 -2
  11. package/es/components/InlineLoading/index.js +9 -0
  12. package/es/components/Modal/Modal.d.ts +17 -0
  13. package/es/components/Modal/Modal.js +38 -3
  14. package/es/components/MultiSelect/FilterableMultiSelect.js +17 -3
  15. package/es/components/MultiSelect/MultiSelect.d.ts +5 -0
  16. package/es/components/MultiSelect/MultiSelect.js +17 -3
  17. package/es/components/NumberInput/NumberInput.d.ts +5 -0
  18. package/es/components/NumberInput/NumberInput.js +29 -4
  19. package/es/components/Select/Select.d.ts +6 -1
  20. package/es/components/Select/Select.js +16 -2
  21. package/es/components/Slug/index.js +187 -0
  22. package/es/components/TextArea/TextArea.d.ts +4 -0
  23. package/es/components/TextArea/TextArea.js +47 -31
  24. package/es/components/TextInput/TextInput.d.ts +5 -0
  25. package/es/components/TextInput/TextInput.js +16 -2
  26. package/es/components/UIShell/SideNavHeader.d.ts +29 -0
  27. package/es/components/UIShell/SideNavHeader.js +3 -3
  28. package/es/index.d.ts +1 -0
  29. package/es/index.js +1 -0
  30. package/lib/components/Breadcrumb/BreadcrumbItem.js +1 -2
  31. package/lib/components/ComboBox/ComboBox.d.ts +5 -0
  32. package/lib/components/ComboBox/ComboBox.js +16 -2
  33. package/lib/components/ComposedModal/ModalFooter.d.ts +18 -0
  34. package/lib/components/ComposedModal/ModalFooter.js +48 -16
  35. package/lib/components/DatePickerInput/DatePickerInput.d.ts +4 -0
  36. package/lib/components/DatePickerInput/DatePickerInput.js +16 -2
  37. package/lib/components/Dropdown/Dropdown.d.ts +5 -0
  38. package/lib/components/Dropdown/Dropdown.js +16 -2
  39. package/lib/components/InlineLoading/index.js +17 -0
  40. package/lib/components/Modal/Modal.d.ts +17 -0
  41. package/lib/components/Modal/Modal.js +38 -3
  42. package/lib/components/MultiSelect/FilterableMultiSelect.js +17 -3
  43. package/lib/components/MultiSelect/MultiSelect.d.ts +5 -0
  44. package/lib/components/MultiSelect/MultiSelect.js +17 -3
  45. package/lib/components/NumberInput/NumberInput.d.ts +5 -0
  46. package/lib/components/NumberInput/NumberInput.js +28 -3
  47. package/lib/components/Select/Select.d.ts +6 -1
  48. package/lib/components/Select/Select.js +16 -2
  49. package/lib/components/Slug/index.js +199 -0
  50. package/lib/components/TextArea/TextArea.d.ts +4 -0
  51. package/lib/components/TextArea/TextArea.js +47 -31
  52. package/lib/components/TextInput/TextInput.d.ts +5 -0
  53. package/lib/components/TextInput/TextInput.js +16 -2
  54. package/lib/components/UIShell/SideNavHeader.d.ts +29 -0
  55. package/lib/components/UIShell/SideNavHeader.js +3 -3
  56. package/lib/index.d.ts +1 -0
  57. package/lib/index.js +45 -41
  58. package/package.json +6 -6
  59. package/scss/utilities/_ai-gradient.scss +9 -0
@@ -69,8 +69,7 @@ const BreadcrumbItem = /*#__PURE__*/React__default.forwardRef(function Breadcrum
69
69
  });
70
70
  BreadcrumbItem.displayName = 'BreadcrumbItem';
71
71
  BreadcrumbItem.propTypes = {
72
- // @ts-expect-error - v12 TODO: BREAKING: This should match AriaAttributes['aria-current']
73
- 'aria-current': PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
72
+ 'aria-current': PropTypes.oneOfType([PropTypes.bool, PropTypes.oneOf(['false', 'true', 'page', 'step', 'location', 'date', 'time'])]),
74
73
  /**
75
74
  * Pass in content that will be inside of the BreadcrumbItem
76
75
  */
@@ -5,6 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import Downshift from 'downshift';
8
+ import { ReactNodeLike } from 'prop-types';
8
9
  import { type ComponentProps, type ReactNode, type ComponentType, type ReactElement, type RefAttributes, type PropsWithChildren, type PropsWithoutRef, type InputHTMLAttributes, type MouseEvent } from 'react';
9
10
  import { ListBoxSize } from '../ListBox';
10
11
  type ExcludedAttributes = 'id' | 'onChange' | 'onClick' | 'type' | 'size';
@@ -135,6 +136,10 @@ export interface ComboBoxProps<ItemType> extends Omit<InputHTMLAttributes<HTMLIn
135
136
  * Specify the size of the ListBox. Currently supports either `sm`, `md` or `lg` as an option.
136
137
  */
137
138
  size?: ListBoxSize;
139
+ /**
140
+ * Provide a `Slug` component to be rendered inside the `ComboBox` component
141
+ */
142
+ slug?: ReactNodeLike;
138
143
  /**
139
144
  * Provide text to be used in a `<label>` element that is tied to the
140
145
  * combobox via ARIA attributes.
@@ -112,6 +112,7 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
112
112
  warn,
113
113
  warnText,
114
114
  allowCustomValue = false,
115
+ slug,
115
116
  ...rest
116
117
  } = props;
117
118
  const prefix = usePrefix();
@@ -243,7 +244,8 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
243
244
  });
244
245
  const wrapperClasses = cx(`${prefix}--list-box__wrapper`, [containerClassName, {
245
246
  [`${prefix}--list-box__wrapper--fluid--invalid`]: isFluid && invalid,
246
- [`${prefix}--list-box__wrapper--fluid--focus`]: isFluid && isFocused
247
+ [`${prefix}--list-box__wrapper--fluid--focus`]: isFluid && isFocused,
248
+ [`${prefix}--list-box__wrapper--slug`]: slug
247
249
  }]);
248
250
  const inputClasses = cx(`${prefix}--text-input`, {
249
251
  [`${prefix}--text-input--empty`]: !inputValue,
@@ -252,6 +254,14 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
252
254
 
253
255
  // needs to be Capitalized for react to render it correctly
254
256
  const ItemToElement = itemToElement;
257
+
258
+ // Slug is always size `mini`
259
+ let normalizedSlug;
260
+ if (slug) {
261
+ normalizedSlug = /*#__PURE__*/React__default.cloneElement(slug, {
262
+ size: 'mini'
263
+ });
264
+ }
255
265
  return /*#__PURE__*/React__default.createElement(Downshift, _extends({}, downshiftProps, {
256
266
  onChange: handleOnChange,
257
267
  onInputValueChange: handleOnInputValueChange,
@@ -402,7 +412,7 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
402
412
  }), /*#__PURE__*/React__default.createElement(ListBoxTrigger, _extends({}, buttonProps, {
403
413
  isOpen: isOpen,
404
414
  translateWithId: translateWithId
405
- }))), /*#__PURE__*/React__default.createElement(ListBox.Menu, getMenuProps({
415
+ }))), normalizedSlug, /*#__PURE__*/React__default.createElement(ListBox.Menu, getMenuProps({
406
416
  'aria-label': deprecatedAriaLabel || ariaLabel
407
417
  }), isOpen ? filterItems(items, itemToString, inputValue).map((item, index) => {
408
418
  const isObject = item !== null && typeof item === 'object';
@@ -552,6 +562,10 @@ ComboBox.propTypes = {
552
562
  * Specify the size of the ListBox. Currently supports either `sm`, `md` or `lg` as an option.
553
563
  */
554
564
  size: ListBoxSize,
565
+ /**
566
+ * Provide a `Slug` component to be rendered inside the `ComboBox` component
567
+ */
568
+ slug: PropTypes.node,
555
569
  /**
556
570
  * Provide text to be used in a `<label>` element that is tied to the
557
571
  * combobox via ARIA attributes.
@@ -5,6 +5,7 @@ interface SecondaryButtonProps {
5
5
  }
6
6
  export interface SecondaryButtonSetProps {
7
7
  closeModal(evt: MouseEvent): void;
8
+ disabled?: boolean;
8
9
  onRequestClose(evt: MouseEvent): void;
9
10
  secondaryButtonText?: string;
10
11
  secondaryButtons?: [SecondaryButtonProps, SecondaryButtonProps];
@@ -66,6 +67,23 @@ export interface ModalFooterProps {
66
67
  * Specify a custom className to be applied to the secondary button
67
68
  */
68
69
  secondaryClassName?: string;
70
+ /**
71
+ * loading status
72
+ */
73
+ loadingStatus?: string;
74
+ /**
75
+ * Specify the description for the loading text
76
+ */
77
+ loadingDescription?: string;
78
+ /**
79
+ * Specify the description for the loading text
80
+ */
81
+ loadingIconDescription?: string;
82
+ /**
83
+ * Provide an optional handler to be invoked when loading is
84
+ * successful
85
+ */
86
+ onLoadingSuccess?(): void;
69
87
  }
70
88
  export declare const ModalFooter: React.ForwardRefExoticComponent<ModalFooterProps & React.RefAttributes<HTMLElement>>;
71
89
  export {};
@@ -14,6 +14,7 @@ import ButtonSet from '../ButtonSet/ButtonSet.js';
14
14
  import cx from 'classnames';
15
15
  import { usePrefix } from '../../internal/usePrefix.js';
16
16
  import { noopFn } from '../../internal/noopFn.js';
17
+ import InlineLoading from '../InlineLoading/InlineLoading.js';
17
18
 
18
19
  function SecondaryButtonSet(_ref) {
19
20
  let {
@@ -21,7 +22,8 @@ function SecondaryButtonSet(_ref) {
21
22
  secondaryButtonText,
22
23
  secondaryClassName,
23
24
  closeModal,
24
- onRequestClose
25
+ onRequestClose,
26
+ disabled
25
27
  } = _ref;
26
28
  function handleRequestClose(evt) {
27
29
  closeModal(evt);
@@ -43,6 +45,7 @@ function SecondaryButtonSet(_ref) {
43
45
  }
44
46
  if (secondaryButtonText) {
45
47
  return /*#__PURE__*/React__default.createElement(Button, {
48
+ disabled: disabled,
46
49
  className: secondaryClassName,
47
50
  onClick: handleRequestClose,
48
51
  kind: "secondary"
@@ -52,6 +55,7 @@ function SecondaryButtonSet(_ref) {
52
55
  }
53
56
  SecondaryButtonSet.propTypes = {
54
57
  closeModal: PropTypes.func,
58
+ disabled: PropTypes.bool,
55
59
  onRequestClose: PropTypes.func,
56
60
  secondaryButtonText: PropTypes.string,
57
61
  secondaryButtons: (props, propName, componentName) => {
@@ -86,32 +90,43 @@ const ModalFooter = /*#__PURE__*/React__default.forwardRef(function ModalFooter(
86
90
  secondaryButtonText,
87
91
  secondaryButtons,
88
92
  secondaryClassName,
93
+ loadingStatus = 'inactive',
94
+ loadingDescription,
95
+ loadingIconDescription,
96
+ onLoadingSuccess = noopFn,
89
97
  ...rest
90
98
  } = _ref3;
91
99
  const prefix = usePrefix();
92
100
  const footerClass = cx(`${prefix}--modal-footer`, customClassName, Array.isArray(secondaryButtons) && secondaryButtons.length === 2 ? `${prefix}--modal-footer--three-button` : null);
101
+ const primaryButtonClass = cx(primaryClassName, loadingStatus !== 'inactive' ? `${prefix}--btn--loading` : null);
102
+ const loadingActive = loadingStatus !== 'inactive';
93
103
  const secondaryButtonProps = {
94
104
  closeModal,
95
105
  secondaryButtons,
96
106
  secondaryButtonText,
97
107
  secondaryClassName,
98
- onRequestClose
108
+ onRequestClose,
109
+ disabled: loadingActive
99
110
  };
100
- return (
101
- /*#__PURE__*/
111
+ return /*#__PURE__*/React__default.createElement(ButtonSet, _extends({
112
+ className: footerClass
113
+ }, rest, {
102
114
  // @ts-expect-error: Invalid derived types, will be fine once explicit types are added
103
- React__default.createElement(ButtonSet, _extends({
104
- className: footerClass
105
- }, rest, {
106
- ref: ref
107
- }), /*#__PURE__*/React__default.createElement(SecondaryButtonSet, secondaryButtonProps), primaryButtonText && /*#__PURE__*/React__default.createElement(Button, {
108
- onClick: onRequestSubmit,
109
- className: primaryClassName,
110
- disabled: primaryButtonDisabled,
111
- kind: danger ? 'danger' : 'primary',
112
- ref: inputref
113
- }, primaryButtonText), children)
114
- );
115
+ ref: ref,
116
+ "aria-busy": loadingActive
117
+ }), /*#__PURE__*/React__default.createElement(SecondaryButtonSet, secondaryButtonProps), primaryButtonText && /*#__PURE__*/React__default.createElement(Button, {
118
+ onClick: onRequestSubmit,
119
+ className: primaryButtonClass,
120
+ disabled: loadingActive || primaryButtonDisabled,
121
+ kind: danger ? 'danger' : 'primary',
122
+ ref: inputref
123
+ }, loadingStatus === 'inactive' ? primaryButtonText : /*#__PURE__*/React__default.createElement(InlineLoading, {
124
+ status: loadingStatus,
125
+ description: loadingDescription,
126
+ iconDescription: loadingIconDescription,
127
+ className: `${prefix}--inline-loading--btn`,
128
+ onSuccess: onLoadingSuccess
129
+ })), children);
115
130
  });
116
131
  ModalFooter.propTypes = {
117
132
  /**
@@ -138,6 +153,23 @@ ModalFooter.propTypes = {
138
153
  inputref: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({
139
154
  current: PropTypes.any
140
155
  })]),
156
+ /**
157
+ * Specify the description for the loading text
158
+ */
159
+ loadingDescription: PropTypes.string,
160
+ /**
161
+ * Specify the description for the loading text
162
+ */
163
+ loadingIconDescription: PropTypes.string,
164
+ /**
165
+ * loading status
166
+ */
167
+ loadingStatus: PropTypes.oneOf(['inactive', 'active', 'finished', 'error']),
168
+ /**
169
+ * Provide an optional handler to be invoked when loading is
170
+ * successful
171
+ */
172
+ onLoadingSuccess: PropTypes.func,
141
173
  /**
142
174
  * Specify an optional function for when the modal is requesting to be
143
175
  * closed
@@ -76,6 +76,10 @@ interface DatePickerInputProps extends Omit<ReactAttr<HTMLInputElement>, Exclude
76
76
  * Specify the size of the Date Picker Input. Currently supports either `sm`, `md`, or `lg` as an option.
77
77
  */
78
78
  size?: 'sm' | 'md' | 'lg';
79
+ /**
80
+ * Provide a `Slug` component to be rendered inside the `DatePickerInput` component
81
+ */
82
+ slug?: ReactNodeLike;
79
83
  /**
80
84
  * Specify the type of the `<input>`
81
85
  */
@@ -32,6 +32,7 @@ const DatePickerInput = /*#__PURE__*/React__default.forwardRef(function DatePick
32
32
  pattern = '\\d{1,2}\\/\\d{1,2}\\/\\d{4}',
33
33
  placeholder,
34
34
  size = 'md',
35
+ slug,
35
36
  type = 'text',
36
37
  warn,
37
38
  warnText,
@@ -60,7 +61,8 @@ const DatePickerInput = /*#__PURE__*/React__default.forwardRef(function DatePick
60
61
  };
61
62
  const wrapperClasses = cx(`${prefix}--date-picker-input__wrapper`, {
62
63
  [`${prefix}--date-picker-input__wrapper--invalid`]: invalid,
63
- [`${prefix}--date-picker-input__wrapper--warn`]: warn
64
+ [`${prefix}--date-picker-input__wrapper--warn`]: warn,
65
+ [`${prefix}--date-picker-input__wrapper--slug`]: slug
64
66
  });
65
67
  const labelClasses = cx(`${prefix}--label`, {
66
68
  [`${prefix}--visually-hidden`]: hideLabel,
@@ -93,6 +95,14 @@ const DatePickerInput = /*#__PURE__*/React__default.forwardRef(function DatePick
93
95
  inputProps['data-invalid'] = true;
94
96
  }
95
97
  const input = /*#__PURE__*/React__default.createElement("input", inputProps);
98
+
99
+ // Slug is always size `mini`
100
+ let normalizedSlug;
101
+ if (slug) {
102
+ normalizedSlug = /*#__PURE__*/React__default.cloneElement(slug, {
103
+ size: 'mini'
104
+ });
105
+ }
96
106
  return /*#__PURE__*/React__default.createElement("div", {
97
107
  className: containerClasses
98
108
  }, labelText && /*#__PURE__*/React__default.createElement(Text, {
@@ -101,7 +111,7 @@ const DatePickerInput = /*#__PURE__*/React__default.forwardRef(function DatePick
101
111
  className: labelClasses
102
112
  }, labelText), /*#__PURE__*/React__default.createElement("div", {
103
113
  className: wrapperClasses
104
- }, /*#__PURE__*/React__default.createElement("span", null, input, isFluid && /*#__PURE__*/React__default.createElement(DatePickerIcon, {
114
+ }, /*#__PURE__*/React__default.createElement("span", null, input, normalizedSlug, isFluid && /*#__PURE__*/React__default.createElement(DatePickerIcon, {
105
115
  datePickerType: datePickerType
106
116
  }), /*#__PURE__*/React__default.createElement(DatePickerIcon, {
107
117
  datePickerType: datePickerType,
@@ -195,6 +205,10 @@ DatePickerInput.propTypes = {
195
205
  * Specify the size of the Date Picker Input. Currently supports either `sm`, `md`, or `lg` as an option.
196
206
  */
197
207
  size: PropTypes.oneOf(['sm', 'md', 'lg']),
208
+ /**
209
+ * Provide a `Slug` component to be rendered inside the `DatePickerInput` component
210
+ */
211
+ slug: PropTypes.node,
198
212
  /**
199
213
  * Specify the type of the `<input>`
200
214
  */
@@ -6,6 +6,7 @@
6
6
  */
7
7
  import React, { ReactNode } from 'react';
8
8
  import { UseSelectProps } from 'downshift';
9
+ import { ReactNodeLike } from 'prop-types';
9
10
  import { ListBoxSize, ListBoxType } from '../ListBox';
10
11
  import { ReactAttr } from '../../types/common';
11
12
  type ExcludedAttributes = 'id' | 'onChange';
@@ -110,6 +111,10 @@ export interface DropdownProps<ItemType> extends Omit<ReactAttr<HTMLDivElement>,
110
111
  * Specify the size of the ListBox. Currently supports either `sm`, `md` or `lg` as an option.
111
112
  */
112
113
  size?: ListBoxSize;
114
+ /**
115
+ * Provide a `Slug` component to be rendered inside the `Dropdown` component
116
+ */
117
+ slug?: ReactNodeLike;
113
118
  /**
114
119
  * Provide the title text that will be read by a screen reader when
115
120
  * visiting this control
@@ -69,6 +69,7 @@ const Dropdown = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
69
69
  selectedItem: controlledSelectedItem,
70
70
  downshiftProps,
71
71
  readOnly,
72
+ slug,
72
73
  ...other
73
74
  } = _ref;
74
75
  const prefix = usePrefix();
@@ -159,7 +160,8 @@ const Dropdown = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
159
160
  [`${prefix}--dropdown__wrapper--inline--invalid`]: inline && invalid,
160
161
  [`${prefix}--list-box__wrapper--inline--invalid`]: inline && invalid,
161
162
  [`${prefix}--list-box__wrapper--fluid--invalid`]: isFluid && invalid,
162
- [`${prefix}--list-box__wrapper--fluid--focus`]: isFluid && isFocused && !isOpen
163
+ [`${prefix}--list-box__wrapper--fluid--focus`]: isFluid && isFocused && !isOpen,
164
+ [`${prefix}--list-box__wrapper--slug`]: slug
163
165
  });
164
166
  const helperId = !helperText ? undefined : `dropdown-helper-text-${dropdownInstanceId}`;
165
167
 
@@ -223,6 +225,14 @@ const Dropdown = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
223
225
  }
224
226
  };
225
227
  const menuProps = getMenuProps();
228
+
229
+ // Slug is always size `mini`
230
+ let normalizedSlug;
231
+ if (slug) {
232
+ normalizedSlug = /*#__PURE__*/React__default.cloneElement(slug, {
233
+ size: 'mini'
234
+ });
235
+ }
226
236
  return /*#__PURE__*/React__default.createElement("div", _extends({
227
237
  className: wrapperClasses
228
238
  }, other), titleText && /*#__PURE__*/React__default.createElement("label", _extends({
@@ -261,7 +271,7 @@ const Dropdown = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
261
271
  }, selectedItem ? renderSelectedItem ? renderSelectedItem(selectedItem) : itemToString(selectedItem) : label), /*#__PURE__*/React__default.createElement(ListBox.MenuIcon, {
262
272
  isOpen: isOpen,
263
273
  translateWithId: translateWithId
264
- })), /*#__PURE__*/React__default.createElement(ListBox.Menu, menuProps, isOpen && items.map((item, index) => {
274
+ })), normalizedSlug, /*#__PURE__*/React__default.createElement(ListBox.Menu, menuProps, isOpen && items.map((item, index) => {
265
275
  const isObject = item !== null && typeof item === 'object';
266
276
  const itemProps = getItemProps({
267
277
  item,
@@ -382,6 +392,10 @@ Dropdown.propTypes = {
382
392
  * Specify the size of the ListBox. Currently supports either `sm`, `md` or `lg` as an option.
383
393
  */
384
394
  size: ListBoxSize,
395
+ /**
396
+ * Provide a `Slug` component to be rendered inside the `Dropdown` component
397
+ */
398
+ slug: PropTypes.node,
385
399
  /**
386
400
  * Provide the title text that will be read by a screen reader when
387
401
  * visiting this control
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Copyright IBM Corp. 2016, 2023
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ import InlineLoading from './InlineLoading.js';
9
+ export { default as InlineLoading, default } from './InlineLoading.js';
@@ -54,6 +54,18 @@ export interface ModalProps extends ReactAttr<HTMLDivElement> {
54
54
  * Provide a ref to return focus to once the modal is closed.
55
55
  */
56
56
  launcherButtonRef?: any;
57
+ /**
58
+ * Specify the description for the loading text
59
+ */
60
+ loadingDescription?: string;
61
+ /**
62
+ * Specify the description for the loading text
63
+ */
64
+ loadingIconDescription?: string;
65
+ /**
66
+ * Specify loading status
67
+ */
68
+ loadingStatus?: string;
57
69
  /**
58
70
  * Specify a label to be read by screen readers on the modal root node
59
71
  */
@@ -71,6 +83,11 @@ export interface ModalProps extends ReactAttr<HTMLDivElement> {
71
83
  * @deprecated this property is unused
72
84
  */
73
85
  onKeyDown?: React.KeyboardEventHandler<HTMLElement>;
86
+ /**
87
+ * Specify an optional handler to be invoked when loading is
88
+ * successful
89
+ */
90
+ onLoadingSuccess?: React.ReactEventHandler<HTMLElement>;
74
91
  /**
75
92
  * Specify a handler for closing modal.
76
93
  * The handler should care of closing modal, e.g. changing `open` prop.
@@ -14,6 +14,7 @@ import toggleClass from '../../tools/toggleClass.js';
14
14
  import Button from '../Button/Button.js';
15
15
  import '../Button/Button.Skeleton.js';
16
16
  import ButtonSet from '../ButtonSet/ButtonSet.js';
17
+ import InlineLoading from '../InlineLoading/InlineLoading.js';
17
18
  import requiredIfGivenPropIsTruthy from '../../prop-types/requiredIfGivenPropIsTruthy.js';
18
19
  import wrapFocus, { elementOrParentIsFloatingMenu } from '../../internal/wrapFocus.js';
19
20
  import setupGetInstanceId from '../../tools/setupGetInstanceId.js';
@@ -54,6 +55,10 @@ const Modal = /*#__PURE__*/React__default.forwardRef(function Modal(_ref, ref) {
54
55
  preventCloseOnClickOutside = false,
55
56
  isFullWidth,
56
57
  launcherButtonRef,
58
+ loadingStatus = 'inactive',
59
+ loadingDescription,
60
+ loadingIconDescription,
61
+ onLoadingSuccess = noopFn,
57
62
  ...rest
58
63
  } = _ref;
59
64
  const prefix = usePrefix();
@@ -67,6 +72,10 @@ const Modal = /*#__PURE__*/React__default.forwardRef(function Modal(_ref, ref) {
67
72
  const modalHeadingId = `${prefix}--modal-header__heading--${modalInstanceId}`;
68
73
  const modalBodyId = `${prefix}--modal-body--${modalInstanceId}`;
69
74
  const modalCloseButtonClass = `${prefix}--modal-close`;
75
+ const primaryButtonClass = cx({
76
+ [`${prefix}--btn--loading`]: loadingStatus !== 'inactive'
77
+ });
78
+ const loadingActive = loadingStatus !== 'inactive';
70
79
  function isCloseButton(element) {
71
80
  return !onSecondarySubmit && element === secondaryButton.current || element.classList.contains(modalCloseButtonClass);
72
81
  }
@@ -219,7 +228,8 @@ const Modal = /*#__PURE__*/React__default.forwardRef(function Modal(_ref, ref) {
219
228
  }, hasScrollingContentProps), children), hasScrollingContent && /*#__PURE__*/React__default.createElement("div", {
220
229
  className: `${prefix}--modal-content--overflow-indicator`
221
230
  }), !passiveModal && /*#__PURE__*/React__default.createElement(ButtonSet, {
222
- className: footerClasses
231
+ className: footerClasses,
232
+ "aria-busy": loadingActive
223
233
  }, Array.isArray(secondaryButtons) && secondaryButtons.length <= 2 ? secondaryButtons.map((_ref3, i) => {
224
234
  let {
225
235
  buttonText,
@@ -231,15 +241,23 @@ const Modal = /*#__PURE__*/React__default.forwardRef(function Modal(_ref, ref) {
231
241
  onClick: onButtonClick
232
242
  }, buttonText);
233
243
  }) : secondaryButtonText && /*#__PURE__*/React__default.createElement(Button, {
244
+ disabled: loadingActive,
234
245
  kind: "secondary",
235
246
  onClick: onSecondaryButtonClick,
236
247
  ref: secondaryButton
237
248
  }, secondaryButtonText), /*#__PURE__*/React__default.createElement(Button, {
249
+ className: primaryButtonClass,
238
250
  kind: danger ? 'danger' : 'primary',
239
- disabled: primaryButtonDisabled,
251
+ disabled: loadingActive || primaryButtonDisabled,
240
252
  onClick: onRequestSubmit,
241
253
  ref: button
242
- }, primaryButtonText)));
254
+ }, loadingStatus === 'inactive' ? primaryButtonText : /*#__PURE__*/React__default.createElement(InlineLoading, {
255
+ status: loadingStatus,
256
+ description: loadingDescription,
257
+ iconDescription: loadingIconDescription,
258
+ className: `${prefix}--inline-loading--btn`,
259
+ onSuccess: onLoadingSuccess
260
+ }))));
243
261
  return /*#__PURE__*/React__default.createElement("div", _extends({}, rest, {
244
262
  onKeyDown: handleKeyDown,
245
263
  onMouseDown: handleMousedown,
@@ -303,6 +321,18 @@ Modal.propTypes = {
303
321
  launcherButtonRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({
304
322
  current: PropTypes.any
305
323
  })]),
324
+ /**
325
+ * Specify the description for the loading text
326
+ */
327
+ loadingDescription: PropTypes.string,
328
+ /**
329
+ * Specify the description for the loading text
330
+ */
331
+ loadingIconDescription: PropTypes.string,
332
+ /**
333
+ * loading status
334
+ */
335
+ loadingStatus: PropTypes.oneOf(['inactive', 'active', 'finished', 'error']),
306
336
  /**
307
337
  * Specify a label to be read by screen readers on the modal root node
308
338
  */
@@ -319,6 +349,11 @@ Modal.propTypes = {
319
349
  * Specify a handler for keypresses.
320
350
  */
321
351
  onKeyDown: PropTypes.func,
352
+ /**
353
+ * Provide an optional handler to be invoked when loading is
354
+ * successful
355
+ */
356
+ onLoadingSuccess: PropTypes.func,
322
357
  /**
323
358
  * Specify a handler for closing modal.
324
359
  * The handler should care of closing modal, e.g. changing `open` prop.
@@ -65,7 +65,8 @@ const FilterableMultiSelect = /*#__PURE__*/React__default.forwardRef(function Fi
65
65
  translateWithId,
66
66
  useTitleInItem,
67
67
  warn,
68
- warnText
68
+ warnText,
69
+ slug
69
70
  } = _ref;
70
71
  const {
71
72
  isFluid
@@ -94,7 +95,8 @@ const FilterableMultiSelect = /*#__PURE__*/React__default.forwardRef(function Fi
94
95
  [`${prefix}--list-box__wrapper--inline--invalid`]: inline && invalid,
95
96
  [`${prefix}--list-box--up`]: direction === 'top',
96
97
  [`${prefix}--list-box__wrapper--fluid--invalid`]: isFluid && invalid,
97
- [`${prefix}--list-box__wrapper--fluid--focus`]: isFluid && isFocused
98
+ [`${prefix}--list-box__wrapper--fluid--focus`]: isFluid && isFocused,
99
+ [`${prefix}--list-box__wrapper--slug`]: slug
98
100
  });
99
101
  const helperId = !helperText ? undefined : `filterablemultiselect-helper-text-${filterableMultiSelectInstanceId}`;
100
102
  const labelId = `${id}-label`;
@@ -188,6 +190,14 @@ const FilterableMultiSelect = /*#__PURE__*/React__default.forwardRef(function Fi
188
190
  textInput.current.focus();
189
191
  }
190
192
  }
193
+
194
+ // Slug is always size `mini`
195
+ let normalizedSlug;
196
+ if (slug) {
197
+ normalizedSlug = /*#__PURE__*/React__default.cloneElement(slug, {
198
+ size: 'mini'
199
+ });
200
+ }
191
201
  return /*#__PURE__*/React__default.createElement(Selection, {
192
202
  disabled: disabled,
193
203
  onChange: handleOnChange,
@@ -381,7 +391,7 @@ const FilterableMultiSelect = /*#__PURE__*/React__default.forwardRef(function Fi
381
391
  }), /*#__PURE__*/React__default.createElement(ListBoxTrigger, _extends({}, buttonProps, {
382
392
  isOpen: isOpen,
383
393
  translateWithId: translateWithId
384
- }))), isOpen ? /*#__PURE__*/React__default.createElement(ListBox.Menu, menuProps, sortItems(filterItems(items, {
394
+ }))), normalizedSlug, isOpen ? /*#__PURE__*/React__default.createElement(ListBox.Menu, menuProps, sortItems(filterItems(items, {
385
395
  itemToString,
386
396
  inputValue
387
397
  }), {
@@ -534,6 +544,10 @@ FilterableMultiSelect.propTypes = {
534
544
  * Specify the size of the ListBox. Currently supports either `sm`, `md` or `lg` as an option.
535
545
  */
536
546
  size: ListBoxSize,
547
+ /**
548
+ * Provide a `Slug` component to be rendered inside the `FilterableMultiSelect` component
549
+ */
550
+ slug: PropTypes.node,
537
551
  ...sortingPropTypes,
538
552
  /**
539
553
  * Callback function for translating ListBoxMenuIcon SVG title
@@ -5,6 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import { UseSelectProps } from 'downshift';
8
+ import { ReactNodeLike } from 'prop-types';
8
9
  import React from 'react';
9
10
  import { ListBoxSize, ListBoxType } from '../ListBox';
10
11
  import { ListBoxProps } from '../ListBox/ListBox';
@@ -162,6 +163,10 @@ export interface MultiSelectProps<ItemType> extends MultiSelectSortingProps<Item
162
163
  * Specify the size of the ListBox. Currently supports either `sm`, `md` or `lg` as an option.
163
164
  */
164
165
  size?: ListBoxSize;
166
+ /**
167
+ * Provide a `Slug` component to be rendered inside the `MultiSelect` component
168
+ */
169
+ slug?: ReactNodeLike;
165
170
  /**
166
171
  * Provide text to be used in a `<label>` element that is tied to the
167
172
  * multiselect via ARIA attributes.
@@ -87,7 +87,8 @@ const MultiSelect = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
87
87
  direction = 'bottom',
88
88
  selectedItems: selected,
89
89
  readOnly,
90
- locale = 'en'
90
+ locale = 'en',
91
+ slug
91
92
  } = _ref;
92
93
  const prefix = usePrefix();
93
94
  const {
@@ -181,7 +182,8 @@ const MultiSelect = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
181
182
  [`${prefix}--multi-select__wrapper--inline--invalid`]: inline && invalid,
182
183
  [`${prefix}--list-box__wrapper--inline--invalid`]: inline && invalid,
183
184
  [`${prefix}--list-box__wrapper--fluid--invalid`]: isFluid && invalid,
184
- [`${prefix}--list-box__wrapper--fluid--focus`]: !isOpen && isFluid && isFocused
185
+ [`${prefix}--list-box__wrapper--fluid--focus`]: !isOpen && isFluid && isFocused,
186
+ [`${prefix}--list-box__wrapper--slug`]: slug
185
187
  });
186
188
  const titleClasses = cx(`${prefix}--label`, {
187
189
  [`${prefix}--label--disabled`]: disabled,
@@ -293,6 +295,14 @@ const MultiSelect = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
293
295
  }
294
296
  }
295
297
  } : {};
298
+
299
+ // Slug is always size `mini`
300
+ let normalizedSlug;
301
+ if (slug) {
302
+ normalizedSlug = /*#__PURE__*/React__default.cloneElement(slug, {
303
+ size: 'mini'
304
+ });
305
+ }
296
306
  return /*#__PURE__*/React__default.createElement("div", {
297
307
  className: wrapperClasses
298
308
  }, /*#__PURE__*/React__default.createElement("label", _extends({
@@ -341,7 +351,7 @@ const MultiSelect = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
341
351
  }, label), /*#__PURE__*/React__default.createElement(ListBox.MenuIcon, {
342
352
  isOpen: isOpen,
343
353
  translateWithId: translateWithId
344
- }))), /*#__PURE__*/React__default.createElement(ListBox.Menu, getMenuProps(), isOpen &&
354
+ })), normalizedSlug), /*#__PURE__*/React__default.createElement(ListBox.Menu, getMenuProps(), isOpen &&
345
355
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
346
356
  sortItems(items, sortOptions).map((item, index) => {
347
357
  const isChecked = selectedItems.filter(selected => isEqual(selected, item)).length > 0;
@@ -496,6 +506,10 @@ MultiSelect.propTypes = {
496
506
  * Specify the size of the ListBox. Currently supports either `sm`, `md` or `lg` as an option.
497
507
  */
498
508
  size: ListBoxSize,
509
+ /**
510
+ * Provide a `Slug` component to be rendered inside the `MultiSelect` component
511
+ */
512
+ slug: PropTypes.node,
499
513
  /**
500
514
  * Provide a method that sorts all options in the control. Overriding this
501
515
  * prop means that you also have to handle the sort logic for selected versus
@@ -4,6 +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 { ReactNodeLike } from 'prop-types';
7
8
  import React, { ReactNode } from 'react';
8
9
  export declare const translationIds: {
9
10
  'increment.number': string;
@@ -107,6 +108,10 @@ export interface NumberInputProps extends Omit<React.InputHTMLAttributes<HTMLInp
107
108
  * Specify the size of the Number Input.
108
109
  */
109
110
  size?: 'sm' | 'md' | 'lg';
111
+ /**
112
+ * Provide a `Slug` component to be rendered inside the `TextInput` component
113
+ */
114
+ slug?: ReactNodeLike;
110
115
  /**
111
116
  * Specify how much the values should increase/decrease upon clicking on up/down button
112
117
  */