@carbon/react 1.53.1 → 1.54.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 (86) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +1009 -1096
  2. package/es/components/ComboBox/ComboBox.js +13 -4
  3. package/es/components/ComboButton/index.js +1 -1
  4. package/es/components/ComposedModal/ComposedModal.js +19 -10
  5. package/es/components/DataTable/DataTable.js +1 -1
  6. package/es/components/DataTable/TableBatchAction.d.ts +1 -1
  7. package/es/components/DataTable/TableToolbarMenu.d.ts +5 -1
  8. package/es/components/DataTable/TableToolbarMenu.js +7 -0
  9. package/es/components/DatePicker/DatePicker.d.ts +4 -0
  10. package/es/components/DatePicker/DatePicker.js +37 -0
  11. package/es/components/IconButton/index.d.ts +1 -1
  12. package/es/components/IconButton/index.js +1 -1
  13. package/es/components/ListBox/ListBox.d.ts +8 -0
  14. package/es/components/ListBox/ListBox.js +15 -3
  15. package/es/components/Loading/Loading.d.ts +1 -1
  16. package/es/components/Modal/Modal.js +14 -5
  17. package/es/components/Notification/Notification.js +18 -6
  18. package/es/components/Pagination/Pagination.Skeleton.d.ts +25 -0
  19. package/es/components/Pagination/Pagination.d.ts +102 -0
  20. package/es/components/Pagination/Pagination.js +13 -14
  21. package/es/components/Pagination/index.d.ts +10 -0
  22. package/es/components/Popover/index.d.ts +1 -1
  23. package/es/components/Popover/index.js +175 -108
  24. package/es/components/RadioTile/RadioTile.d.ts +55 -0
  25. package/es/components/RadioTile/RadioTile.js +17 -17
  26. package/es/components/RadioTile/index.d.ts +10 -0
  27. package/es/components/Slug/index.js +23 -2
  28. package/es/components/Stack/HStack.d.ts +10 -0
  29. package/es/components/Stack/HStack.js +23 -0
  30. package/es/components/Stack/Stack.d.ts +1 -1
  31. package/es/components/Stack/Stack.js +2 -2
  32. package/es/components/Stack/VStack.d.ts +10 -0
  33. package/es/components/Stack/{index.js → VStack.js} +1 -8
  34. package/es/components/Stack/index.d.ts +3 -6
  35. package/es/components/TileGroup/TileGroup.js +30 -24
  36. package/es/components/Toggletip/index.d.ts +1 -18
  37. package/es/components/Toggletip/index.js +27 -4
  38. package/es/components/Tooltip/Tooltip.js +23 -5
  39. package/es/index.d.ts +1 -0
  40. package/es/index.js +5 -4
  41. package/es/internal/FloatingMenu.js +26 -5
  42. package/es/internal/wrapFocus.js +51 -1
  43. package/es/tools/createPropAdapter.js +40 -0
  44. package/lib/components/ComboBox/ComboBox.js +13 -4
  45. package/lib/components/ComboButton/index.js +1 -1
  46. package/lib/components/ComposedModal/ComposedModal.js +17 -8
  47. package/lib/components/DataTable/DataTable.js +1 -1
  48. package/lib/components/DataTable/TableBatchAction.d.ts +1 -1
  49. package/lib/components/DataTable/TableToolbarMenu.d.ts +5 -1
  50. package/lib/components/DataTable/TableToolbarMenu.js +7 -0
  51. package/lib/components/DatePicker/DatePicker.d.ts +4 -0
  52. package/lib/components/DatePicker/DatePicker.js +37 -0
  53. package/lib/components/IconButton/index.d.ts +1 -1
  54. package/lib/components/IconButton/index.js +1 -1
  55. package/lib/components/ListBox/ListBox.d.ts +8 -0
  56. package/lib/components/ListBox/ListBox.js +15 -3
  57. package/lib/components/Loading/Loading.d.ts +1 -1
  58. package/lib/components/Modal/Modal.js +14 -5
  59. package/lib/components/Notification/Notification.js +15 -3
  60. package/lib/components/Pagination/Pagination.Skeleton.d.ts +25 -0
  61. package/lib/components/Pagination/Pagination.d.ts +102 -0
  62. package/lib/components/Pagination/Pagination.js +13 -14
  63. package/lib/components/Pagination/index.d.ts +10 -0
  64. package/lib/components/Popover/index.d.ts +1 -1
  65. package/lib/components/Popover/index.js +174 -107
  66. package/lib/components/RadioTile/RadioTile.d.ts +55 -0
  67. package/lib/components/RadioTile/RadioTile.js +17 -17
  68. package/lib/components/RadioTile/index.d.ts +10 -0
  69. package/lib/components/Slug/index.js +23 -2
  70. package/lib/components/Stack/HStack.d.ts +10 -0
  71. package/lib/components/Stack/HStack.js +31 -0
  72. package/lib/components/Stack/Stack.d.ts +1 -1
  73. package/lib/components/Stack/Stack.js +3 -3
  74. package/lib/components/Stack/VStack.d.ts +10 -0
  75. package/lib/components/Stack/{index.js → VStack.js} +0 -8
  76. package/lib/components/Stack/index.d.ts +3 -6
  77. package/lib/components/TileGroup/TileGroup.js +30 -24
  78. package/lib/components/Toggletip/index.d.ts +1 -18
  79. package/lib/components/Toggletip/index.js +27 -4
  80. package/lib/components/Tooltip/Tooltip.js +23 -5
  81. package/lib/index.d.ts +1 -0
  82. package/lib/index.js +15 -14
  83. package/lib/internal/FloatingMenu.js +44 -4
  84. package/lib/internal/wrapFocus.js +51 -0
  85. package/lib/tools/createPropAdapter.js +44 -0
  86. package/package.json +9 -7
@@ -0,0 +1,23 @@
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 { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
+ import React__default from 'react';
10
+ import { Stack } from './Stack.js';
11
+
12
+ const HStack = /*#__PURE__*/React__default.forwardRef(function HStack(_ref, ref) {
13
+ let {
14
+ children,
15
+ ...props
16
+ } = _ref;
17
+ return /*#__PURE__*/React__default.createElement(Stack, _extends({}, props, {
18
+ ref: ref,
19
+ orientation: "horizontal"
20
+ }), children);
21
+ });
22
+
23
+ export { HStack };
@@ -10,7 +10,7 @@ import React from 'react';
10
10
  * @type {Array<number>}
11
11
  */
12
12
  declare const SPACING_STEPS: number[];
13
- interface StackProps extends React.HTMLAttributes<HTMLElement> {
13
+ export interface StackProps extends React.HTMLAttributes<HTMLElement> {
14
14
  /**
15
15
  * Provide a custom element type to render as the outermost element in
16
16
  * the Stack component. By default, this component will render a `div`.
@@ -6,10 +6,10 @@
6
6
  */
7
7
 
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
- import { spacing } from '@carbon/layout';
9
+ import React__default from 'react';
10
10
  import cx from 'classnames';
11
11
  import PropTypes from 'prop-types';
12
- import React__default from 'react';
12
+ import { spacing } from '@carbon/layout';
13
13
  import { usePrefix } from '../../internal/usePrefix.js';
14
14
 
15
15
  /**
@@ -0,0 +1,10 @@
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
+ import React from 'react';
8
+ import { StackProps } from './Stack';
9
+ declare const VStack: React.ForwardRefExoticComponent<StackProps & React.RefAttributes<React.ReactNode>>;
10
+ export { VStack };
@@ -8,14 +8,7 @@
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
9
  import React__default from 'react';
10
10
  import { Stack } from './Stack.js';
11
- export { Stack } from './Stack.js';
12
11
 
13
- const HStack = /*#__PURE__*/React__default.forwardRef(function HStack(props, ref) {
14
- return /*#__PURE__*/React__default.createElement(Stack, _extends({}, props, {
15
- ref: ref,
16
- orientation: "horizontal"
17
- }));
18
- });
19
12
  const VStack = /*#__PURE__*/React__default.forwardRef(function VStack(props, ref) {
20
13
  return /*#__PURE__*/React__default.createElement(Stack, _extends({}, props, {
21
14
  ref: ref,
@@ -23,4 +16,4 @@ const VStack = /*#__PURE__*/React__default.forwardRef(function VStack(props, ref
23
16
  }));
24
17
  });
25
18
 
26
- export { HStack, VStack };
19
+ export { VStack };
@@ -4,9 +4,6 @@
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 { ReactNode } from 'react';
8
- import { Stack } from './Stack';
9
- import { ForwardRefReturn } from '../../types/common';
10
- declare const HStack: ForwardRefReturn<ReactNode>;
11
- declare const VStack: ForwardRefReturn<ReactNode>;
12
- export { HStack, Stack, VStack };
7
+ export { HStack } from './HStack';
8
+ export { VStack } from './VStack';
9
+ export { Stack, type StackProps } from './Stack';
@@ -9,7 +9,6 @@ import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js
9
9
  import PropTypes from 'prop-types';
10
10
  import React__default, { useState } from 'react';
11
11
  import RadioTile from '../RadioTile/RadioTile.js';
12
- import { warning } from '../../internal/warning.js';
13
12
  import { usePrefix } from '../../internal/usePrefix.js';
14
13
  import { noopFn } from '../../internal/noopFn.js';
15
14
 
@@ -36,28 +35,35 @@ const TileGroup = props => {
36
35
  setSelected(valueSelected);
37
36
  setPrevValueSelected(valueSelected);
38
37
  }
39
- const getRadioTiles = () => {
40
- const childrenArray = React__default.Children.toArray(children);
41
- const radioTiles = childrenArray.map(tileRadio => {
42
- const tileRadioProps = tileRadio.props ?? undefined;
43
- const {
44
- value,
45
- ...other
46
- } = tileRadioProps;
47
- /* istanbul ignore if */
48
- if (typeof tileRadioProps.checked !== 'undefined') {
49
- process.env.NODE_ENV !== "production" ? warning(false, `Instead of using the checked property on the RadioTile, set
50
- the defaultSelected property or valueSelected property on the TileGroup.`) : void 0;
51
- }
52
- return /*#__PURE__*/React__default.createElement(RadioTile, _extends({}, other, {
53
- name: name,
54
- key: value,
55
- value: value,
56
- onChange: handleChange,
57
- checked: value === selected
58
- }));
59
- });
60
- return radioTiles;
38
+ const getRadioTilesWithWrappers = children => {
39
+ const traverseAndModifyChildren = children => {
40
+ return React__default.Children.map(children, child => {
41
+ // If RadioTile found, return it with necessary props
42
+ if (child.type === RadioTile) {
43
+ const {
44
+ value,
45
+ ...otherProps
46
+ } = child.props;
47
+ return /*#__PURE__*/React__default.createElement(RadioTile, _extends({}, otherProps, {
48
+ name: name,
49
+ key: value,
50
+ value: value,
51
+ onChange: handleChange,
52
+ checked: value === selected
53
+ }));
54
+ } else if (child.props && child.props.children) {
55
+ // If the child is not RadioTile and has children, recheck the children
56
+ return /*#__PURE__*/React__default.cloneElement(child, {
57
+ ...child.props,
58
+ children: traverseAndModifyChildren(child.props.children)
59
+ });
60
+ } else {
61
+ // If the child is neither a RadioTile nor has children, return it as is
62
+ return child;
63
+ }
64
+ });
65
+ };
66
+ return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, traverseAndModifyChildren(children));
61
67
  };
62
68
  const handleChange = (newSelection, value, evt) => {
63
69
  if (newSelection !== selected) {
@@ -75,7 +81,7 @@ const TileGroup = props => {
75
81
  return /*#__PURE__*/React__default.createElement("fieldset", {
76
82
  className: className ?? `${prefix}--tile-group`,
77
83
  disabled: disabled
78
- }, renderLegend(legend), /*#__PURE__*/React__default.createElement("div", null, getRadioTiles()));
84
+ }, renderLegend(legend), /*#__PURE__*/React__default.createElement("div", null, getRadioTilesWithWrappers(children)));
79
85
  };
80
86
  TileGroup.propTypes = {
81
87
  /**
@@ -89,24 +89,7 @@ export type ToggleTipButtonProps<T extends React.ElementType> = PolymorphicProps
89
89
  * `ToggletipButton` controls the visibility of the Toggletip through mouse
90
90
  * clicks and keyboard interactions.
91
91
  */
92
- export declare function ToggletipButton<T extends React.ElementType>({ children, className: customClassName, label, as: BaseComponent, ...rest }: ToggleTipButtonProps<T>): import("react/jsx-runtime").JSX.Element;
93
- export declare namespace ToggletipButton {
94
- var propTypes: {
95
- /**
96
- * Custom children to be rendered as the content of the label
97
- */
98
- children: PropTypes.Requireable<PropTypes.ReactNodeLike>;
99
- /**
100
- * Provide a custom class name to be added to the outermost node in the
101
- * component
102
- */
103
- className: PropTypes.Requireable<string>;
104
- /**
105
- * Provide an accessible label for this button
106
- */
107
- label: PropTypes.Requireable<string>;
108
- };
109
- }
92
+ export declare const ToggletipButton: React.ForwardRefExoticComponent<Omit<ToggleTipButtonProps<React.ElementType<any>>, "ref"> & React.RefAttributes<unknown>>;
110
93
  interface ToggletipContentProps {
111
94
  children?: ReactNode;
112
95
  className?: string | undefined;
@@ -150,7 +150,28 @@ Toggletip.propTypes = {
150
150
  /**
151
151
  * Specify how the toggletip should align with the button
152
152
  */
153
- align: PropTypes.oneOf(['top', 'top-left', 'top-right', 'bottom', 'bottom-left', 'bottom-right', 'left', 'left-bottom', 'left-top', 'right', 'right-bottom', 'right-top']),
153
+ align: PropTypes.oneOf(['top', 'top-left',
154
+ // deprecated use top-start instead
155
+ 'top-right',
156
+ // deprecated use top-end instead
157
+
158
+ 'bottom', 'bottom-left',
159
+ // deprecated use bottom-start instead
160
+ 'bottom-right',
161
+ // deprecated use bottom-end instead
162
+
163
+ 'left', 'left-bottom',
164
+ // deprecated use left-end instead
165
+ 'left-top',
166
+ // deprecated use left-start instead
167
+
168
+ 'right', 'right-bottom',
169
+ // deprecated use right-end instead
170
+ 'right-top',
171
+ // deprecated use right-start instead
172
+
173
+ // new values to match floating-ui
174
+ 'top-start', 'top-end', 'bottom-start', 'bottom-end', 'left-end', 'left-start', 'right-end', 'right-start']),
154
175
  /**
155
176
  * Provide a custom element or component to render the top-level node for the
156
177
  * component.
@@ -178,7 +199,7 @@ Toggletip.propTypes = {
178
199
  * `ToggletipButton` controls the visibility of the Toggletip through mouse
179
200
  * clicks and keyboard interactions.
180
201
  */
181
- function ToggletipButton(_ref3) {
202
+ const ToggletipButton = /*#__PURE__*/React__default.forwardRef(function ToggletipButton(_ref3, ref) {
182
203
  let {
183
204
  children,
184
205
  className: customClassName,
@@ -198,9 +219,10 @@ function ToggletipButton(_ref3) {
198
219
  return /*#__PURE__*/React__default.createElement("button", _extends({}, toggletip?.buttonProps, {
199
220
  "aria-label": label,
200
221
  type: "button",
201
- className: className
222
+ className: className,
223
+ ref: ref
202
224
  }, rest), children);
203
- }
225
+ });
204
226
  ToggletipButton.propTypes = {
205
227
  /**
206
228
  * Custom children to be rendered as the content of the label
@@ -216,6 +238,7 @@ ToggletipButton.propTypes = {
216
238
  */
217
239
  label: PropTypes.string
218
240
  };
241
+ ToggletipButton.displayName = 'ToggletipButton';
219
242
  /**
220
243
  * `ToggletipContent` is a wrapper around `PopoverContent`. It places the
221
244
  * `children` passed in as a prop inside of `PopoverContent` so that they will
@@ -34,7 +34,6 @@ function Tooltip(_ref) {
34
34
  closeOnActivation = false,
35
35
  ...rest
36
36
  } = _ref;
37
- const containerRef = useRef(null);
38
37
  const tooltipRef = useRef(null);
39
38
  const [open, setOpen] = useDelayedState(defaultOpen);
40
39
  const [isDragging, setIsDragging] = useState(false);
@@ -130,8 +129,7 @@ function Tooltip(_ref) {
130
129
  highContrast: true,
131
130
  onKeyDown: onKeyDown,
132
131
  onMouseLeave: onMouseLeave,
133
- open: open,
134
- ref: containerRef
132
+ open: open
135
133
  }), /*#__PURE__*/React__default.createElement("div", {
136
134
  className: `${prefix}--tooltip-trigger__wrapper`
137
135
  }, child !== undefined ? /*#__PURE__*/React__default.cloneElement(child, {
@@ -141,7 +139,6 @@ function Tooltip(_ref) {
141
139
  "aria-hidden": open ? 'false' : 'true',
142
140
  className: `${prefix}--tooltip-content`,
143
141
  id: id,
144
- ref: tooltipRef,
145
142
  role: "tooltip"
146
143
  }, label || description));
147
144
  }
@@ -149,7 +146,28 @@ Tooltip.propTypes = {
149
146
  /**
150
147
  * Specify how the trigger should align with the tooltip
151
148
  */
152
- align: PropTypes.oneOf(['top', 'top-left', 'top-right', 'bottom', 'bottom-left', 'bottom-right', 'left', 'left-bottom', 'left-top', 'right', 'right-bottom', 'right-top']),
149
+ align: PropTypes.oneOf(['top', 'top-left',
150
+ // deprecated use top-start instead
151
+ 'top-right',
152
+ // deprecated use top-end instead
153
+
154
+ 'bottom', 'bottom-left',
155
+ // deprecated use bottom-start instead
156
+ 'bottom-right',
157
+ // deprecated use bottom-end instead
158
+
159
+ 'left', 'left-bottom',
160
+ // deprecated use left-end instead
161
+ 'left-top',
162
+ // deprecated use left-start instead
163
+
164
+ 'right', 'right-bottom',
165
+ // deprecated use right-end instead
166
+ 'right-top',
167
+ // deprecated use right-start instead
168
+
169
+ // new values to match floating-ui
170
+ 'top-start', 'top-end', 'bottom-start', 'bottom-end', 'left-end', 'left-start', 'right-end', 'right-start']),
153
171
  /**
154
172
  * Pass in the child to which the tooltip will be applied
155
173
  */
package/es/index.d.ts CHANGED
@@ -74,6 +74,7 @@ export * from './components/SkeletonIcon';
74
74
  export * from './components/SkeletonPlaceholder';
75
75
  export * from './components/SkeletonText';
76
76
  export * from './components/Slider';
77
+ export * from './components/Stack';
77
78
  export * from './components/StructuredList';
78
79
  export * from './components/Switch';
79
80
  export * from './components/Tab';
package/es/index.js CHANGED
@@ -73,6 +73,7 @@ export { NumberInput } from './components/NumberInput/NumberInput.js';
73
73
  export { default as OrderedList } from './components/OrderedList/OrderedList.js';
74
74
  export { default as OverflowMenu } from './components/OverflowMenu/index.js';
75
75
  export { default as OverflowMenuItem } from './components/OverflowMenuItem/OverflowMenuItem.js';
76
+ export { default as Pagination } from './components/Pagination/Pagination.js';
76
77
  export { default as PaginationSkeleton } from './components/Pagination/Pagination.Skeleton.js';
77
78
  export { default as PaginationNav } from './components/PaginationNav/PaginationNav.js';
78
79
  export { default as PrimaryButton } from './components/PrimaryButton/PrimaryButton.js';
@@ -81,6 +82,7 @@ export { ProgressIndicator, ProgressStep } from './components/ProgressIndicator/
81
82
  export { default as RadioButton } from './components/RadioButton/RadioButton.js';
82
83
  export { default as RadioButtonSkeleton } from './components/RadioButton/RadioButton.Skeleton.js';
83
84
  export { default as RadioButtonGroup } from './components/RadioButtonGroup/RadioButtonGroup.js';
85
+ export { default as RadioTile } from './components/RadioTile/RadioTile.js';
84
86
  export { default as Search } from './components/Search/Search.js';
85
87
  export { default as SearchSkeleton } from './components/Search/Search.Skeleton.js';
86
88
  export { default as SecondaryButton } from './components/SecondaryButton/SecondaryButton.js';
@@ -92,6 +94,9 @@ export { default as SkeletonIcon } from './components/SkeletonIcon/SkeletonIcon.
92
94
  export { default as SkeletonPlaceholder } from './components/SkeletonPlaceholder/SkeletonPlaceholder.js';
93
95
  export { default as SkeletonText } from './components/SkeletonText/SkeletonText.js';
94
96
  export { default as Slider } from './components/Slider/index.js';
97
+ export { HStack } from './components/Stack/HStack.js';
98
+ export { VStack } from './components/Stack/VStack.js';
99
+ export { Stack } from './components/Stack/Stack.js';
95
100
  export { StructuredListBody, StructuredListCell, StructuredListHead, StructuredListInput, StructuredListRow, StructuredListWrapper } from './components/StructuredList/StructuredList.js';
96
101
  export { default as StructuredListSkeleton } from './components/StructuredList/StructuredList.Skeleton.js';
97
102
  export { default as Switch } from './components/Switch/Switch.js';
@@ -154,7 +159,6 @@ export { Slug as unstable__Slug, SlugActions as unstable__SlugActions, SlugConte
154
159
  export { default as unstable__AiSkeletonPlaceholder } from './components/AiSkeleton/AiSkeletonPlaceholder.js';
155
160
  export { default as unstable__AiSkeletonIcon } from './components/AiSkeleton/AiSkeletonIcon.js';
156
161
  export { default as unstable__AiSkeletonText } from './components/AiSkeleton/AiSkeletonText.js';
157
- export { HStack, VStack } from './components/Stack/index.js';
158
162
  export { DefinitionTooltip } from './components/Tooltip/DefinitionTooltip.js';
159
163
  export { Tooltip } from './components/Tooltip/Tooltip.js';
160
164
  import './components/Text/index.js';
@@ -221,9 +225,6 @@ export { default as TableToolbarSearch } from './components/DataTable/TableToolb
221
225
  export { default as TableToolbarMenu } from './components/DataTable/TableToolbarMenu.js';
222
226
  export { default as FilterableMultiSelect } from './components/MultiSelect/FilterableMultiSelect.js';
223
227
  export { default as MultiSelect } from './components/MultiSelect/MultiSelect.js';
224
- export { default as Pagination } from './components/Pagination/Pagination.js';
225
228
  export { default as ControlledPasswordInput } from './components/TextInput/ControlledPasswordInput.js';
226
229
  export { default as PasswordInput } from './components/TextInput/PasswordInput.js';
227
- export { default as RadioTile } from './components/RadioTile/RadioTile.js';
228
230
  export { default as TreeNode } from './components/TreeView/TreeNode.js';
229
- export { Stack } from './components/Stack/Stack.js';
@@ -13,8 +13,11 @@ import window from 'window-or-global';
13
13
  import OptimizedResize from './OptimizedResize.js';
14
14
  import { selectorTabbable, selectorFocusable } from './keyboard/navigation.js';
15
15
  import { warning } from './warning.js';
16
- import wrapFocus from './wrapFocus.js';
16
+ import wrapFocus, { wrapFocusWithoutSentinels } from './wrapFocus.js';
17
17
  import { PrefixContext } from './usePrefix.js';
18
+ import * as FeatureFlags from '@carbon/feature-flags';
19
+ import { match } from './keyboard/match.js';
20
+ import { Tab } from './keyboard/keys.js';
18
21
 
19
22
  /**
20
23
  * The structure for the position of floating menu.
@@ -348,6 +351,19 @@ class FloatingMenu extends React__default.Component {
348
351
  });
349
352
  }
350
353
  });
354
+ /**
355
+ * Keydown handler for when focus wrap behavior is enabled
356
+ * @param {Event} event
357
+ */
358
+ _defineProperty(this, "handleKeyDown", event => {
359
+ if (match(event, Tab) && this._menuBody) {
360
+ wrapFocusWithoutSentinels({
361
+ containerNode: this._menuBody,
362
+ currentActiveNode: event.target,
363
+ event
364
+ });
365
+ }
366
+ });
351
367
  }
352
368
  componentWillUnmount() {
353
369
  this.hResize.release();
@@ -376,19 +392,24 @@ class FloatingMenu extends React__default.Component {
376
392
  const {
377
393
  context: prefix
378
394
  } = this;
395
+ const focusTrapWithoutSentinels = FeatureFlags.enabled('enable-experimental-focus-wrap-without-sentinels');
379
396
  if (typeof document !== 'undefined') {
380
397
  const {
381
398
  focusTrap,
382
399
  target
383
400
  } = this.props;
384
- return /*#__PURE__*/ReactDOM.createPortal( /*#__PURE__*/React__default.createElement("div", {
385
- onBlur: focusTrap ? this.handleBlur : null
386
- }, /*#__PURE__*/React__default.createElement("span", {
401
+ return /*#__PURE__*/ReactDOM.createPortal(
402
+ /*#__PURE__*/
403
+ //eslint-disable-next-line jsx-a11y/no-static-element-interactions
404
+ React__default.createElement("div", {
405
+ onBlur: focusTrap && !focusTrapWithoutSentinels ? this.handleBlur : () => {},
406
+ onKeyDown: focusTrapWithoutSentinels ? this.handleKeyDown : () => {}
407
+ }, !focusTrapWithoutSentinels && /*#__PURE__*/React__default.createElement("span", {
387
408
  ref: this.startSentinel,
388
409
  tabIndex: "0",
389
410
  role: "link",
390
411
  className: `${prefix}--visually-hidden`
391
- }, "Focus sentinel"), this._getChildrenWithProps(), /*#__PURE__*/React__default.createElement("span", {
412
+ }, "Focus sentinel"), this._getChildrenWithProps(), !focusTrapWithoutSentinels && /*#__PURE__*/React__default.createElement("span", {
392
413
  ref: this.endSentinel,
393
414
  tabIndex: "0",
394
415
  role: "link",
@@ -6,7 +6,9 @@
6
6
  */
7
7
 
8
8
  import findLast from 'lodash.findlast';
9
+ import { useEffect } from 'react';
9
10
  import { DOCUMENT_POSITION_BROAD_PRECEDING, selectorTabbable, DOCUMENT_POSITION_BROAD_FOLLOWING } from './keyboard/navigation.js';
11
+ import { tabbable } from 'tabbable';
10
12
 
11
13
  /**
12
14
  * @param {Node} node A DOM node.
@@ -60,4 +62,52 @@ function wrapFocus(_ref) {
60
62
  }
61
63
  }
62
64
 
63
- export { wrapFocus as default, elementOrParentIsFloatingMenu };
65
+ /**
66
+ * Ensures the focus is kept in the given `containerNode`, implementing "focus-wrap" behavior.
67
+ * Note: This must be called *before* focus moves using onKeyDown or similar.
68
+ * @param {object} options The options.
69
+ * @param {Node|null} options.containerNode
70
+ * @param {EventTarget} options.currentActiveNode The DOM node that has focus.
71
+ * @param {KeyboardEvent} options.event The DOM event
72
+ */
73
+ function wrapFocusWithoutSentinels(_ref2) {
74
+ let {
75
+ containerNode,
76
+ currentActiveNode,
77
+ event
78
+ } = _ref2;
79
+ if (['blur', 'focusout', 'focusin', 'focus'].includes(event.type) && process.env.NODE_ENV !== "production") {
80
+ // eslint-disable-next-line react-hooks/rules-of-hooks
81
+ useEffect(() => {
82
+ throw new Error(`Error: wrapFocusWithoutSentinels(...) called in unsupported ${event.type} event.\n\nCall wrapFocusWithoutSentinels(...) from onKeyDown instead.`);
83
+ });
84
+ }
85
+
86
+ // The reason we're using tabbable is because it returns the tabbable
87
+ // items *in tab order*, whereas using our `selectorTabbable` only
88
+ // returns in DOM order
89
+ const tabbables = tabbable(containerNode);
90
+ const firstTabbable = tabbables[0];
91
+ const lastTabbable = tabbables[tabbables.length - 1];
92
+
93
+ // console.log(`---------------------------------`);
94
+ // console.log(containerNode);
95
+ // console.log(tabbables);
96
+ // console.log(firstTabbable);
97
+ // console.log(lastTabbable);
98
+ // console.log(currentActiveNode);
99
+
100
+ // The shift key is used to determine if focus is moving forwards or backwards
101
+ if (currentActiveNode === lastTabbable && !event.shiftKey) {
102
+ // Cancel the current movement of focus because we're going to place it ourselves
103
+ event.preventDefault();
104
+ firstTabbable.focus();
105
+ }
106
+ if (currentActiveNode === firstTabbable && event.shiftKey) {
107
+ // Cancel the current movement of focus because we're going to place it ourselves
108
+ event.preventDefault();
109
+ lastTabbable.focus();
110
+ }
111
+ }
112
+
113
+ export { wrapFocus as default, elementOrParentIsFloatingMenu, wrapFocusWithoutSentinels };
@@ -0,0 +1,40 @@
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
+ /**
9
+ * Create an adapter that converts an object of props with potentially deprecated
10
+ * prop names to the replacement prop names in a newer version. Useful for guarding
11
+ * against breaking changes when a prop has been renamed
12
+ *
13
+ * @param {Array} spec - an array of options which specify a text or regex
14
+ * matcher alongside a replacement if there is a match
15
+ * @returns {Function}
16
+ */
17
+ function mapPopoverAlignProp(align) {
18
+ switch (align) {
19
+ case 'top-left':
20
+ return 'top-start';
21
+ case 'top-right':
22
+ return 'top-end';
23
+ case 'bottom-left':
24
+ return 'bottom-start';
25
+ case 'bottom-right':
26
+ return 'bottom-end';
27
+ case 'left-bottom':
28
+ return 'left-end';
29
+ case 'left-top':
30
+ return 'left-start';
31
+ case 'right-bottom':
32
+ return 'right-end';
33
+ case 'right-top':
34
+ return 'right-start';
35
+ default:
36
+ return align;
37
+ }
38
+ }
39
+
40
+ export { mapPopoverAlignProp };
@@ -249,7 +249,9 @@ const ComboBox = /*#__PURE__*/React.forwardRef((props, ref) => {
249
249
  const titleClasses = cx__default["default"](`${prefix}--label`, {
250
250
  [`${prefix}--label--disabled`]: disabled
251
251
  });
252
- const comboBoxHelperId = !helperText ? undefined : `combobox-helper-text-${comboBoxInstanceId}`;
252
+ const helperTextId = `combobox-helper-text-${comboBoxInstanceId}`;
253
+ const warnTextId = `combobox-warn-text-${comboBoxInstanceId}`;
254
+ const invalidTextId = `combobox-invalid-text-${comboBoxInstanceId}`;
253
255
  const helperClasses = cx__default["default"](`${prefix}--form__helper-text`, {
254
256
  [`${prefix}--form__helper-text--disabled`]: disabled
255
257
  });
@@ -387,6 +389,11 @@ const ComboBox = /*#__PURE__*/React.forwardRef((props, ref) => {
387
389
  }
388
390
  }
389
391
  } : {};
392
+
393
+ // The input should be described by the appropriate message text id
394
+ // when both the message is supplied *and* when the component is in
395
+ // the matching state (invalid, warn, etc).
396
+ const ariaDescribedBy = invalid && invalidText && invalidTextId || warn && warnText && warnTextId || helperText && !isFluid && helperTextId || undefined;
390
397
  return /*#__PURE__*/React__default["default"].createElement("div", {
391
398
  className: wrapperClasses
392
399
  }, titleText && /*#__PURE__*/React__default["default"].createElement(Text.Text, _rollupPluginBabelHelpers["extends"]({
@@ -399,11 +406,13 @@ const ComboBox = /*#__PURE__*/React.forwardRef((props, ref) => {
399
406
  disabled: disabled,
400
407
  invalid: invalid,
401
408
  invalidText: invalidText,
409
+ invalidTextId: invalidTextId,
402
410
  isOpen: isOpen,
403
411
  light: light,
404
412
  size: size,
405
413
  warn: warn,
406
- warnText: warnText
414
+ warnText: warnText,
415
+ warnTextId: warnTextId
407
416
  }, /*#__PURE__*/React__default["default"].createElement("div", {
408
417
  className: `${prefix}--list-box__field`
409
418
  }, /*#__PURE__*/React__default["default"].createElement("input", _rollupPluginBabelHelpers["extends"]({
@@ -421,7 +430,7 @@ const ComboBox = /*#__PURE__*/React.forwardRef((props, ref) => {
421
430
  }, inputProps, rest, readOnlyEventHandlers, {
422
431
  readOnly: readOnly,
423
432
  ref: mergeRefs["default"](textInput, ref),
424
- "aria-describedby": helperText && !invalid && !warn && !isFluid ? comboBoxHelperId : undefined
433
+ "aria-describedby": ariaDescribedBy
425
434
  })), invalid && /*#__PURE__*/React__default["default"].createElement(iconsReact.WarningFilled, {
426
435
  className: `${prefix}--list-box__invalid-icon`
427
436
  }), showWarning && /*#__PURE__*/React__default["default"].createElement(iconsReact.WarningAltFilled, {
@@ -460,7 +469,7 @@ const ComboBox = /*#__PURE__*/React.forwardRef((props, ref) => {
460
469
  }));
461
470
  }) : null)), helperText && !invalid && !warn && !isFluid && (_Text || (_Text = /*#__PURE__*/React__default["default"].createElement(Text.Text, {
462
471
  as: "div",
463
- id: comboBoxHelperId,
472
+ id: helperTextId,
464
473
  className: helperClasses
465
474
  }, helperText))));
466
475
  });
@@ -162,7 +162,7 @@ ComboButton.propTypes = {
162
162
  /**
163
163
  * Specify how the trigger tooltip should be aligned.
164
164
  */
165
- tooltipAlignment: PropTypes__default["default"].oneOf(['top', 'top-left', 'top-right', 'bottom', 'bottom-left', 'bottom-right', 'left', 'right']),
165
+ tooltipAlignment: PropTypes__default["default"].oneOf(['top', 'top-left', 'top-start', 'top-right', 'top-end', 'bottom', 'bottom-left', 'bottom-start', 'bottom-right', 'bottom-end', 'left', 'right']),
166
166
  /**
167
167
  * Optional method that takes in a message id and returns an
168
168
  * internationalized string.