@itwin/itwinui-react 3.0.0-dev.7 → 3.0.0-dev.9

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 (215) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/cjs/core/Alert/Alert.d.ts +20 -9
  3. package/cjs/core/Alert/Alert.js +48 -10
  4. package/cjs/core/ButtonGroup/ButtonGroup.js +41 -36
  5. package/cjs/core/Buttons/DropdownButton/DropdownButton.js +7 -19
  6. package/cjs/core/Buttons/IconButton/IconButton.js +27 -44
  7. package/cjs/core/Buttons/SplitButton/SplitButton.d.ts +4 -4
  8. package/cjs/core/Buttons/SplitButton/SplitButton.js +54 -29
  9. package/cjs/core/ColorPicker/ColorInputPanel.js +172 -231
  10. package/cjs/core/ComboBox/ComboBox.d.ts +2 -2
  11. package/cjs/core/ComboBox/ComboBox.js +33 -25
  12. package/cjs/core/ComboBox/ComboBoxEndIcon.js +3 -22
  13. package/cjs/core/ComboBox/ComboBoxInput.js +29 -21
  14. package/cjs/core/ComboBox/ComboBoxMenu.d.ts +2 -2
  15. package/cjs/core/ComboBox/ComboBoxMenu.js +73 -93
  16. package/cjs/core/ComboBox/ComboBoxMenuItem.d.ts +1 -1
  17. package/cjs/core/ComboBox/ComboBoxMenuItem.js +8 -6
  18. package/cjs/core/ComboBox/helpers.d.ts +5 -3
  19. package/cjs/core/DatePicker/DatePicker.d.ts +30 -8
  20. package/cjs/core/DatePicker/DatePicker.js +40 -5
  21. package/cjs/core/Dialog/Dialog.js +10 -16
  22. package/cjs/core/Dialog/DialogContext.d.ts +3 -4
  23. package/cjs/core/DropdownMenu/DropdownMenu.d.ts +6 -5
  24. package/cjs/core/DropdownMenu/DropdownMenu.js +59 -55
  25. package/cjs/core/ExpandableBlock/ExpandableBlock.d.ts +20 -14
  26. package/cjs/core/ExpandableBlock/ExpandableBlock.js +38 -15
  27. package/cjs/core/Header/HeaderDropdownButton.js +1 -2
  28. package/cjs/core/Header/HeaderSplitButton.js +2 -2
  29. package/cjs/core/Input/Input.d.ts +4 -0
  30. package/cjs/core/Input/Input.js +2 -1
  31. package/cjs/core/InputGrid/InputGrid.d.ts +25 -0
  32. package/cjs/core/InputGrid/InputGrid.js +39 -0
  33. package/cjs/core/InputGrid/index.d.ts +3 -0
  34. package/cjs/core/InputGrid/index.js +15 -0
  35. package/cjs/core/InputGroup/InputGroup.d.ts +13 -0
  36. package/cjs/core/InputGroup/InputGroup.js +35 -9
  37. package/cjs/core/InputWithDecorations/InputWithDecorations.d.ts +39 -0
  38. package/cjs/core/InputWithDecorations/InputWithDecorations.js +81 -0
  39. package/cjs/core/InputWithDecorations/index.d.ts +3 -0
  40. package/cjs/core/InputWithDecorations/index.js +15 -0
  41. package/cjs/core/Label/Label.d.ts +5 -0
  42. package/cjs/core/Label/Label.js +2 -0
  43. package/cjs/core/LabeledInput/LabeledInput.d.ts +22 -16
  44. package/cjs/core/LabeledInput/LabeledInput.js +52 -29
  45. package/cjs/core/LabeledSelect/LabeledSelect.d.ts +17 -7
  46. package/cjs/core/LabeledSelect/LabeledSelect.js +36 -17
  47. package/cjs/core/LabeledTextarea/LabeledTextarea.d.ts +15 -5
  48. package/cjs/core/LabeledTextarea/LabeledTextarea.js +12 -45
  49. package/cjs/core/Menu/Menu.d.ts +1 -1
  50. package/cjs/core/Menu/Menu.js +2 -2
  51. package/cjs/core/Menu/MenuDivider.d.ts +2 -1
  52. package/cjs/core/Menu/MenuDivider.js +1 -1
  53. package/cjs/core/Menu/MenuItem.d.ts +1 -1
  54. package/cjs/core/Menu/MenuItem.js +78 -55
  55. package/cjs/core/Menu/MenuItemSkeleton.d.ts +1 -1
  56. package/cjs/core/Menu/MenuItemSkeleton.js +0 -1
  57. package/cjs/core/SearchBox/SearchBox.js +1 -1
  58. package/cjs/core/Select/Select.d.ts +9 -5
  59. package/cjs/core/Select/Select.js +81 -99
  60. package/cjs/core/SideNavigation/SideNavigation.js +2 -0
  61. package/cjs/core/Slider/Thumb.js +1 -0
  62. package/cjs/core/StatusMessage/StatusMessage.d.ts +12 -2
  63. package/cjs/core/StatusMessage/StatusMessage.js +23 -9
  64. package/cjs/core/Table/SubRowExpander.js +2 -0
  65. package/cjs/core/Table/columns/actionColumn.js +3 -7
  66. package/cjs/core/Table/filters/DateRangeFilter/DatePickerInput.d.ts +6 -1
  67. package/cjs/core/Table/filters/DateRangeFilter/DatePickerInput.js +56 -33
  68. package/cjs/core/Table/filters/DateRangeFilter/DateRangeFilter.d.ts +2 -0
  69. package/cjs/core/Table/filters/DateRangeFilter/DateRangeFilter.js +2 -0
  70. package/cjs/core/Table/filters/FilterToggle.js +3 -2
  71. package/cjs/core/Textarea/Textarea.d.ts +7 -1
  72. package/cjs/core/Textarea/Textarea.js +6 -11
  73. package/cjs/core/ThemeProvider/ThemeProvider.js +1 -1
  74. package/cjs/core/Tile/Tile.d.ts +139 -15
  75. package/cjs/core/Tile/Tile.js +128 -38
  76. package/cjs/core/Toast/Toast.d.ts +12 -4
  77. package/cjs/core/Toast/Toast.js +20 -4
  78. package/cjs/core/Tooltip/Tooltip.d.ts +35 -28
  79. package/cjs/core/Tooltip/Tooltip.js +116 -117
  80. package/cjs/core/TransferList/TransferList.js +4 -12
  81. package/cjs/core/index.d.ts +3 -1
  82. package/cjs/core/index.js +28 -5
  83. package/cjs/core/utils/components/Icon.d.ts +5 -0
  84. package/cjs/core/utils/components/Icon.js +8 -1
  85. package/cjs/core/utils/components/InputContainer.d.ts +4 -5
  86. package/cjs/core/utils/components/InputContainer.js +21 -37
  87. package/cjs/core/utils/components/InputFlexContainer.d.ts +1 -0
  88. package/cjs/core/utils/components/InputFlexContainer.js +3 -1
  89. package/cjs/core/utils/components/Popover.d.ts +113 -27
  90. package/cjs/core/utils/components/Popover.js +156 -118
  91. package/cjs/core/utils/components/Portal.d.ts +27 -0
  92. package/cjs/core/utils/components/Portal.js +43 -0
  93. package/cjs/core/utils/components/index.d.ts +1 -0
  94. package/cjs/core/utils/components/index.js +1 -0
  95. package/cjs/core/utils/functions/index.d.ts +1 -0
  96. package/cjs/core/utils/functions/index.js +1 -0
  97. package/cjs/core/utils/functions/react.d.ts +8 -0
  98. package/cjs/core/utils/functions/react.js +40 -0
  99. package/cjs/core/utils/hooks/index.d.ts +1 -1
  100. package/cjs/core/utils/hooks/index.js +1 -1
  101. package/cjs/core/utils/hooks/useControlledState.d.ts +13 -0
  102. package/cjs/core/utils/hooks/useControlledState.js +39 -0
  103. package/cjs/styles.js +10 -31
  104. package/esm/core/Alert/Alert.d.ts +20 -9
  105. package/esm/core/Alert/Alert.js +49 -10
  106. package/esm/core/ButtonGroup/ButtonGroup.js +41 -36
  107. package/esm/core/Buttons/DropdownButton/DropdownButton.js +8 -24
  108. package/esm/core/Buttons/IconButton/IconButton.js +25 -40
  109. package/esm/core/Buttons/SplitButton/SplitButton.d.ts +4 -4
  110. package/esm/core/Buttons/SplitButton/SplitButton.js +61 -28
  111. package/esm/core/ColorPicker/ColorInputPanel.js +173 -232
  112. package/esm/core/ComboBox/ComboBox.d.ts +2 -2
  113. package/esm/core/ComboBox/ComboBox.js +34 -25
  114. package/esm/core/ComboBox/ComboBoxEndIcon.js +4 -25
  115. package/esm/core/ComboBox/ComboBoxInput.js +22 -21
  116. package/esm/core/ComboBox/ComboBoxMenu.d.ts +2 -2
  117. package/esm/core/ComboBox/ComboBoxMenu.js +67 -87
  118. package/esm/core/ComboBox/ComboBoxMenuItem.d.ts +1 -1
  119. package/esm/core/ComboBox/ComboBoxMenuItem.js +9 -7
  120. package/esm/core/ComboBox/helpers.d.ts +5 -3
  121. package/esm/core/DatePicker/DatePicker.d.ts +30 -8
  122. package/esm/core/DatePicker/DatePicker.js +25 -5
  123. package/esm/core/Dialog/Dialog.js +11 -23
  124. package/esm/core/Dialog/DialogContext.d.ts +3 -4
  125. package/esm/core/DropdownMenu/DropdownMenu.d.ts +6 -5
  126. package/esm/core/DropdownMenu/DropdownMenu.js +64 -56
  127. package/esm/core/ExpandableBlock/ExpandableBlock.d.ts +20 -14
  128. package/esm/core/ExpandableBlock/ExpandableBlock.js +39 -17
  129. package/esm/core/Header/HeaderDropdownButton.js +1 -2
  130. package/esm/core/Header/HeaderSplitButton.js +2 -2
  131. package/esm/core/Input/Input.d.ts +4 -0
  132. package/esm/core/Input/Input.js +2 -1
  133. package/esm/core/InputGrid/InputGrid.d.ts +25 -0
  134. package/esm/core/InputGrid/InputGrid.js +35 -0
  135. package/esm/core/InputGrid/index.d.ts +3 -0
  136. package/esm/core/InputGrid/index.js +6 -0
  137. package/esm/core/InputGroup/InputGroup.d.ts +13 -0
  138. package/esm/core/InputGroup/InputGroup.js +34 -10
  139. package/esm/core/InputWithDecorations/InputWithDecorations.d.ts +39 -0
  140. package/esm/core/InputWithDecorations/InputWithDecorations.js +80 -0
  141. package/esm/core/InputWithDecorations/index.d.ts +3 -0
  142. package/esm/core/InputWithDecorations/index.js +6 -0
  143. package/esm/core/Label/Label.d.ts +5 -0
  144. package/esm/core/Label/Label.js +2 -0
  145. package/esm/core/LabeledInput/LabeledInput.d.ts +22 -16
  146. package/esm/core/LabeledInput/LabeledInput.js +53 -29
  147. package/esm/core/LabeledSelect/LabeledSelect.d.ts +17 -7
  148. package/esm/core/LabeledSelect/LabeledSelect.js +37 -18
  149. package/esm/core/LabeledTextarea/LabeledTextarea.d.ts +15 -5
  150. package/esm/core/LabeledTextarea/LabeledTextarea.js +14 -45
  151. package/esm/core/Menu/Menu.d.ts +1 -1
  152. package/esm/core/Menu/Menu.js +8 -3
  153. package/esm/core/Menu/MenuDivider.d.ts +2 -1
  154. package/esm/core/Menu/MenuDivider.js +1 -1
  155. package/esm/core/Menu/MenuItem.d.ts +1 -1
  156. package/esm/core/Menu/MenuItem.js +85 -52
  157. package/esm/core/Menu/MenuItemSkeleton.d.ts +1 -1
  158. package/esm/core/Menu/MenuItemSkeleton.js +0 -1
  159. package/esm/core/SearchBox/SearchBox.js +1 -1
  160. package/esm/core/Select/Select.d.ts +9 -5
  161. package/esm/core/Select/Select.js +81 -96
  162. package/esm/core/SideNavigation/SideNavigation.js +2 -0
  163. package/esm/core/Slider/Thumb.js +1 -0
  164. package/esm/core/StatusMessage/StatusMessage.d.ts +12 -2
  165. package/esm/core/StatusMessage/StatusMessage.js +23 -16
  166. package/esm/core/Table/SubRowExpander.js +2 -0
  167. package/esm/core/Table/columns/actionColumn.js +3 -7
  168. package/esm/core/Table/filters/DateRangeFilter/DatePickerInput.d.ts +6 -1
  169. package/esm/core/Table/filters/DateRangeFilter/DatePickerInput.js +56 -33
  170. package/esm/core/Table/filters/DateRangeFilter/DateRangeFilter.d.ts +2 -0
  171. package/esm/core/Table/filters/DateRangeFilter/DateRangeFilter.js +2 -0
  172. package/esm/core/Table/filters/FilterToggle.js +3 -2
  173. package/esm/core/Textarea/Textarea.d.ts +7 -1
  174. package/esm/core/Textarea/Textarea.js +6 -11
  175. package/esm/core/ThemeProvider/ThemeProvider.js +4 -3
  176. package/esm/core/Tile/Tile.d.ts +139 -15
  177. package/esm/core/Tile/Tile.js +128 -38
  178. package/esm/core/Toast/Toast.d.ts +12 -4
  179. package/esm/core/Toast/Toast.js +21 -4
  180. package/esm/core/Tooltip/Tooltip.d.ts +35 -28
  181. package/esm/core/Tooltip/Tooltip.js +119 -116
  182. package/esm/core/TransferList/TransferList.js +4 -9
  183. package/esm/core/index.d.ts +3 -1
  184. package/esm/core/index.js +3 -0
  185. package/esm/core/utils/components/Icon.d.ts +5 -0
  186. package/esm/core/utils/components/Icon.js +8 -1
  187. package/esm/core/utils/components/InputContainer.d.ts +4 -5
  188. package/esm/core/utils/components/InputContainer.js +21 -32
  189. package/esm/core/utils/components/InputFlexContainer.d.ts +1 -0
  190. package/esm/core/utils/components/InputFlexContainer.js +3 -1
  191. package/esm/core/utils/components/Popover.d.ts +113 -27
  192. package/esm/core/utils/components/Popover.js +175 -118
  193. package/esm/core/utils/components/Portal.d.ts +27 -0
  194. package/esm/core/utils/components/Portal.js +36 -0
  195. package/esm/core/utils/components/index.d.ts +1 -0
  196. package/esm/core/utils/components/index.js +1 -0
  197. package/esm/core/utils/functions/index.d.ts +1 -0
  198. package/esm/core/utils/functions/index.js +1 -0
  199. package/esm/core/utils/functions/react.d.ts +8 -0
  200. package/esm/core/utils/functions/react.js +35 -0
  201. package/esm/core/utils/hooks/index.d.ts +1 -1
  202. package/esm/core/utils/hooks/index.js +1 -1
  203. package/esm/core/utils/hooks/useControlledState.d.ts +13 -0
  204. package/esm/core/utils/hooks/useControlledState.js +34 -0
  205. package/esm/styles.js +10 -31
  206. package/package.json +3 -5
  207. package/styles.css +23 -20
  208. package/cjs/core/ComboBox/ComboBoxDropdown.d.ts +0 -7
  209. package/cjs/core/ComboBox/ComboBoxDropdown.js +0 -48
  210. package/cjs/core/utils/hooks/useUncontrolledState.d.ts +0 -6
  211. package/cjs/core/utils/hooks/useUncontrolledState.js +0 -18
  212. package/esm/core/ComboBox/ComboBoxDropdown.d.ts +0 -7
  213. package/esm/core/ComboBox/ComboBoxDropdown.js +0 -42
  214. package/esm/core/utils/hooks/useUncontrolledState.d.ts +0 -6
  215. package/esm/core/utils/hooks/useUncontrolledState.js +0 -13
@@ -10,14 +10,18 @@ const React = tslib_1.__importStar(require('react'));
10
10
  const index_js_1 = require('../utils/index.js');
11
11
  const Menu_js_1 = require('./Menu.js');
12
12
  const ListItem_js_1 = require('../List/ListItem.js');
13
+ const react_dom_1 = require('react-dom');
13
14
  /**
14
15
  * Context used to provide menu item ref to sub-menu items.
15
16
  */
16
- const MenuItemContext = React.createContext({ ref: undefined });
17
+ const MenuItemContext = React.createContext({
18
+ ref: undefined,
19
+ setIsNestedSubmenuVisible: () => {},
20
+ });
17
21
  /**
18
22
  * Basic menu item component. Should be used inside `Menu` component for each item.
19
23
  */
20
- exports.MenuItem = React.forwardRef((props, ref) => {
24
+ exports.MenuItem = React.forwardRef((props, forwardedRef) => {
21
25
  const {
22
26
  children,
23
27
  isSelected,
@@ -26,21 +30,33 @@ exports.MenuItem = React.forwardRef((props, ref) => {
26
30
  onClick,
27
31
  sublabel,
28
32
  size = !!sublabel ? 'large' : 'default',
29
- startIcon: startIconProp,
30
33
  icon,
31
- endIcon: endIconProp,
34
+ startIcon = icon,
32
35
  badge,
36
+ endIcon = badge,
33
37
  role = 'menuitem',
34
38
  subMenuItems = [],
35
39
  ...rest
36
40
  } = props;
37
41
  const menuItemRef = React.useRef(null);
38
- const refs = (0, index_js_1.useMergedRefs)(menuItemRef, ref);
39
- const { ref: parentMenuItemRef } = React.useContext(MenuItemContext);
40
- const subMenuRef = React.useRef(null);
42
+ const [focusOnSubmenu, setFocusOnSubmenu] = React.useState(false);
43
+ const submenuId = (0, index_js_1.useId)();
41
44
  const [isSubmenuVisible, setIsSubmenuVisible] = React.useState(false);
42
- const startIcon = startIconProp ?? icon;
43
- const endIcon = endIconProp ?? badge;
45
+ const [isNestedSubmenuVisible, setIsNestedSubmenuVisible] =
46
+ React.useState(false);
47
+ const parent = React.useContext(MenuItemContext);
48
+ const onVisibleChange = (open) => {
49
+ setIsSubmenuVisible(open);
50
+ // we don't want parent to close when mouse goes into a nested submenu,
51
+ // so we need to let the parent know whether the submenu is still open.
52
+ parent.setIsNestedSubmenuVisible(open);
53
+ };
54
+ const popover = (0, index_js_1.usePopover)({
55
+ visible: isSubmenuVisible || isNestedSubmenuVisible,
56
+ onVisibleChange,
57
+ placement: 'right-start',
58
+ trigger: { hover: true, focus: true },
59
+ });
44
60
  const onKeyDown = (event) => {
45
61
  if (event.altKey) {
46
62
  return;
@@ -56,46 +72,59 @@ exports.MenuItem = React.forwardRef((props, ref) => {
56
72
  case 'ArrowRight': {
57
73
  if (subMenuItems.length > 0) {
58
74
  setIsSubmenuVisible(true);
75
+ // flush and reset state so we are ready to focus again next time
76
+ (0, react_dom_1.flushSync)(() => setFocusOnSubmenu(true));
77
+ setFocusOnSubmenu(false);
59
78
  event.preventDefault();
60
79
  event.stopPropagation();
61
80
  }
62
81
  break;
63
82
  }
64
83
  case 'ArrowLeft': {
65
- parentMenuItemRef?.current?.focus();
84
+ if (parent.ref) {
85
+ parent.ref.current?.focus();
86
+ parent.setIsNestedSubmenuVisible(false);
87
+ }
66
88
  event.stopPropagation();
67
89
  event.preventDefault();
68
90
  break;
69
91
  }
92
+ case 'Escape': {
93
+ // focus might get lost if submenu closes so move it back to parent
94
+ parent.ref?.current?.focus();
95
+ break;
96
+ }
70
97
  default:
71
98
  break;
72
99
  }
73
100
  };
74
- const listItem = React.createElement(
101
+ const handlers = {
102
+ onClick: () => !disabled && onClick?.(value),
103
+ onKeyDown,
104
+ };
105
+ return React.createElement(
75
106
  ListItem_js_1.ListItem,
76
107
  {
108
+ as: 'div',
77
109
  actionable: true,
78
110
  size: size,
79
111
  active: isSelected,
80
112
  disabled: disabled,
81
- onClick: () => !disabled && onClick?.(value),
82
- ref: refs,
113
+ ref: (0, index_js_1.useMergedRefs)(
114
+ menuItemRef,
115
+ forwardedRef,
116
+ subMenuItems.length > 0 ? popover.refs.setReference : null,
117
+ ),
83
118
  role: role,
84
119
  tabIndex: disabled || role === 'presentation' ? undefined : -1,
85
120
  'aria-selected': isSelected,
86
- 'aria-haspopup': subMenuItems.length > 0,
121
+ 'aria-haspopup': subMenuItems.length > 0 ? 'true' : undefined,
122
+ 'aria-controls': subMenuItems.length > 0 ? submenuId : undefined,
123
+ 'aria-expanded': subMenuItems.length > 0 ? popover.open : undefined,
87
124
  'aria-disabled': disabled,
88
- onKeyDown: onKeyDown,
89
- onMouseEnter: () => setIsSubmenuVisible(true),
90
- onMouseLeave: (e) => {
91
- if (
92
- !(e.relatedTarget instanceof Node) ||
93
- !subMenuRef.current?.contains(e.relatedTarget)
94
- ) {
95
- setIsSubmenuVisible(false);
96
- }
97
- },
98
- ...rest,
125
+ ...(subMenuItems.length === 0
126
+ ? { ...handlers, ...rest }
127
+ : popover.getReferenceProps({ ...handlers, ...rest })),
99
128
  },
100
129
  startIcon &&
101
130
  React.createElement(
@@ -123,38 +152,32 @@ exports.MenuItem = React.forwardRef((props, ref) => {
123
152
  { as: 'span', 'aria-hidden': true },
124
153
  endIcon,
125
154
  ),
126
- );
127
- return subMenuItems.length === 0
128
- ? listItem
129
- : React.createElement(
130
- MenuItemContext.Provider,
131
- { value: { ref: menuItemRef } },
155
+ subMenuItems.length > 0 &&
156
+ popover.open &&
157
+ React.createElement(
158
+ index_js_1.Portal,
159
+ null,
132
160
  React.createElement(
133
- index_js_1.Popover,
134
- {
135
- placement: 'right-start',
136
- visible: isSubmenuVisible,
137
- appendTo: 'parent',
138
- content: React.createElement(
139
- 'div',
140
- {
141
- onMouseLeave: () => setIsSubmenuVisible(false),
142
- onBlur: (e) => {
143
- !!(e.relatedTarget instanceof Node) &&
144
- !subMenuRef.current?.contains(e.relatedTarget) &&
145
- !subMenuRef.current?.isEqualNode(e.relatedTarget) &&
146
- setIsSubmenuVisible(false);
161
+ MenuItemContext.Provider,
162
+ { value: { ref: menuItemRef, setIsNestedSubmenuVisible } },
163
+ React.createElement(
164
+ Menu_js_1.Menu,
165
+ {
166
+ setFocus: focusOnSubmenu,
167
+ ref: popover.refs.setFloating,
168
+ ...popover.getFloatingProps({
169
+ id: submenuId,
170
+ onPointerMove: () => {
171
+ // pointer might move into a nested submenu and set isSubmenuVisible to false,
172
+ // so we need to flip it back to true when pointer re-enters this submenu.
173
+ setIsSubmenuVisible(true);
147
174
  },
148
- },
149
- React.createElement(
150
- Menu_js_1.Menu,
151
- { ref: subMenuRef },
152
- subMenuItems,
153
- ),
154
- ),
155
- },
156
- listItem,
175
+ }),
176
+ },
177
+ subMenuItems,
178
+ ),
157
179
  ),
158
- );
180
+ ),
181
+ );
159
182
  });
160
183
  exports.default = exports.MenuItem;
@@ -26,5 +26,5 @@ type MenuItemSkeletonProps = {
26
26
  /**
27
27
  * Menu item that uses skeletons to indicate loading state.
28
28
  */
29
- export declare const MenuItemSkeleton: PolymorphicForwardRefComponent<"li", MenuItemSkeletonProps>;
29
+ export declare const MenuItemSkeleton: PolymorphicForwardRefComponent<"div", MenuItemSkeletonProps>;
30
30
  export default MenuItemSkeleton;
@@ -25,7 +25,6 @@ exports.MenuItemSkeleton = React.forwardRef((props, forwardedRef) => {
25
25
  return React.createElement(
26
26
  index_js_1.Box,
27
27
  {
28
- as: 'li',
29
28
  className: (0, classnames_1.default)('iui-menu-item-skeleton', className),
30
29
  'data-iui-size': hasSublabel && 'large',
31
30
  style: {
@@ -65,7 +65,7 @@ const SearchBoxComponent = React.forwardRef((props, ref) => {
65
65
  { 'iui-expandable-searchbox': expandable },
66
66
  className,
67
67
  ),
68
- 'data-iui-size': size,
68
+ size: size,
69
69
  isDisabled: isDisabled,
70
70
  'data-iui-expanded': isExpanded,
71
71
  ...rest,
@@ -1,5 +1,6 @@
1
1
  import * as React from 'react';
2
- import type { PopoverProps, CommonProps } from '../utils/index.js';
2
+ import { usePopover } from '../utils/index.js';
3
+ import type { CommonProps } from '../utils/index.js';
3
4
  export type ItemRendererProps = {
4
5
  /**
5
6
  * Close handler that closes the dropdown.
@@ -93,6 +94,10 @@ export type SelectProps<T> = {
93
94
  * Modify size of select.
94
95
  */
95
96
  size?: 'small' | 'large';
97
+ /**
98
+ * Status of select.
99
+ */
100
+ status?: 'positive' | 'warning' | 'negative';
96
101
  /**
97
102
  * Custom renderer for an item in the dropdown list. `MenuItem` item props are going to be populated if not provided.
98
103
  */
@@ -106,15 +111,14 @@ export type SelectProps<T> = {
106
111
  */
107
112
  menuStyle?: React.CSSProperties;
108
113
  /**
109
- * Props to customize {@link Popover} behavior.
110
- * @see [tippy.js props](https://atomiks.github.io/tippyjs/v6/all-props/)
114
+ * Props to customize Popover behavior.
111
115
  */
112
- popoverProps?: Omit<PopoverProps, 'onShow' | 'onHide' | 'disabled'>;
116
+ popoverProps?: Pick<Parameters<typeof usePopover>[0], 'visible' | 'onVisibleChange' | 'placement' | 'matchWidth' | 'closeOnOutsideClick'>;
113
117
  /**
114
118
  * Props to pass to the select button (trigger) element.
115
119
  */
116
120
  triggerProps?: React.ComponentPropsWithoutRef<'div'>;
117
- } & SelectMultipleTypeProps<T> & Pick<PopoverProps, 'onShow' | 'onHide'> & Omit<React.ComponentPropsWithoutRef<'div'>, 'size' | 'disabled' | 'placeholder' | 'onChange'>;
121
+ } & SelectMultipleTypeProps<T> & Omit<React.ComponentPropsWithoutRef<'div'>, 'size' | 'disabled' | 'placeholder' | 'onChange'>;
118
122
  /**
119
123
  * Select component to select value from options.
120
124
  * Generic type is used for value. It prevents you from mistakenly using other types in `options`, `value` and `onChange`.
@@ -85,55 +85,27 @@ const Select = (props) => {
85
85
  style,
86
86
  menuClassName,
87
87
  menuStyle,
88
- onShow,
89
- onHide,
90
- popoverProps,
91
88
  multiple = false,
92
89
  triggerProps,
90
+ status,
91
+ popoverProps,
93
92
  ...rest
94
93
  } = props;
95
- const [isOpenState, setIsOpen] = React.useState(false);
96
- const isOpen = popoverProps?.visible ?? isOpenState;
97
- const [minWidth, setMinWidth] = React.useState(0);
94
+ const [isOpen, setIsOpen] = React.useState(false);
98
95
  const [liveRegionSelection, setLiveRegionSelection] = React.useState('');
99
96
  const selectRef = React.useRef(null);
100
- const toggleButtonRef = React.useRef(null);
101
- const onShowHandler = React.useCallback(
102
- (instance) => {
103
- setIsOpen(true);
104
- onShow?.(instance);
105
- },
106
- [onShow],
107
- );
108
- const onHideHandler = React.useCallback(
109
- (instance) => {
110
- setIsOpen(false);
111
- selectRef.current?.focus({ preventScroll: true }); // move focus back to select button
112
- onHide?.(instance);
113
- },
114
- [onHide],
115
- );
116
- React.useEffect(() => {
117
- if (selectRef.current) {
118
- setMinWidth(selectRef.current.offsetWidth);
119
- }
120
- }, [isOpen]);
121
- const onKeyDown = (event) => {
122
- if (event.altKey) {
97
+ const show = React.useCallback(() => {
98
+ if (disabled) {
123
99
  return;
124
100
  }
125
- switch (event.key) {
126
- case 'Enter':
127
- case ' ':
128
- case 'Spacebar': {
129
- setIsOpen((o) => !o);
130
- event.preventDefault();
131
- break;
132
- }
133
- default:
134
- break;
135
- }
136
- };
101
+ setIsOpen(true);
102
+ popoverProps?.onVisibleChange?.(true);
103
+ }, [disabled, popoverProps]);
104
+ const hide = React.useCallback(() => {
105
+ setIsOpen(false);
106
+ selectRef.current?.focus({ preventScroll: true }); // move focus back to select button
107
+ popoverProps?.onVisibleChange?.(false);
108
+ }, [popoverProps]);
137
109
  const menuItems = React.useMemo(() => {
138
110
  return options.map((option, index) => {
139
111
  const isSelected = isMultipleEnabled(value, multiple)
@@ -148,13 +120,18 @@ const Select = (props) => {
148
120
  key: `${label}-${index}`,
149
121
  isSelected,
150
122
  startIcon: startIcon,
123
+ endIcon: isSelected
124
+ ? React.createElement(index_js_2.SvgCheckmark, {
125
+ 'aria-hidden': true,
126
+ })
127
+ : null,
151
128
  onClick: () => {
152
129
  if (option.disabled) {
153
130
  return;
154
131
  }
155
132
  if (isSingleOnChange(onChange, multiple)) {
156
133
  onChange?.(option.value);
157
- setIsOpen(false);
134
+ hide();
158
135
  } else {
159
136
  onChange?.(option.value, isSelected ? 'removed' : 'added');
160
137
  }
@@ -183,7 +160,7 @@ const Select = (props) => {
183
160
  ...menuItem.props,
184
161
  });
185
162
  });
186
- }, [itemRenderer, multiple, onChange, options, value]);
163
+ }, [hide, itemRenderer, multiple, onChange, options, value]);
187
164
  const selectedItems = React.useMemo(() => {
188
165
  if (value == null) {
189
166
  return undefined;
@@ -198,58 +175,42 @@ const Select = (props) => {
198
175
  label: item.label,
199
176
  });
200
177
  }, []);
178
+ const popover = (0, index_js_2.usePopover)({
179
+ visible: isOpen,
180
+ matchWidth: true,
181
+ closeOnOutsideClick: true,
182
+ ...popoverProps,
183
+ onVisibleChange: (open) => (open ? show() : hide()),
184
+ });
201
185
  return React.createElement(
202
- index_js_2.Box,
203
- {
204
- className: (0, classnames_1.default)('iui-input-with-icon', className),
205
- style: style,
206
- ...rest,
207
- },
186
+ React.Fragment,
187
+ null,
208
188
  React.createElement(
209
- index_js_2.Popover,
189
+ index_js_2.Box,
210
190
  {
211
- content: React.createElement(
212
- index_js_1.Menu,
213
- {
214
- role: 'listbox',
215
- className: (0, classnames_1.default)('iui-scroll', menuClassName),
216
- style: {
217
- minInlineSize: minWidth,
218
- maxInlineSize: `min(${minWidth * 2}px, 90vw)`,
219
- ...menuStyle,
220
- },
221
- id: `${uid}-menu`,
222
- key: `${uid}-menu`,
223
- },
224
- menuItems,
225
- ),
226
- placement: 'bottom-start',
227
- aria: { content: null },
228
- onShow: onShowHandler,
229
- onHide: onHideHandler,
230
- ...popoverProps,
231
- visible: isOpen,
232
- onClickOutside: (_, { target }) => {
233
- if (!toggleButtonRef.current?.contains(target)) {
234
- setIsOpen(false);
235
- }
236
- },
191
+ className: (0, classnames_1.default)('iui-input-with-icon', className),
192
+ style: style,
193
+ ...rest,
194
+ ref: popover.refs.setPositionReference,
237
195
  },
238
196
  React.createElement(
239
197
  index_js_2.Box,
240
198
  {
199
+ ...popover.getReferenceProps(),
241
200
  tabIndex: 0,
242
201
  role: 'combobox',
243
- ref: selectRef,
244
202
  'data-iui-size': size,
245
- onClick: () => !disabled && setIsOpen((o) => !o),
246
- onKeyDown: (e) => !disabled && onKeyDown(e),
203
+ 'data-iui-status': status,
247
204
  'aria-disabled': disabled,
248
205
  'aria-autocomplete': 'none',
249
206
  'aria-expanded': isOpen,
250
207
  'aria-haspopup': 'listbox',
251
208
  'aria-controls': `${uid}-menu`,
252
209
  ...triggerProps,
210
+ ref: (0, index_js_2.useMergedRefs)(
211
+ selectRef,
212
+ popover.refs.setReference,
213
+ ),
253
214
  className: (0, classnames_1.default)(
254
215
  'iui-select-button',
255
216
  {
@@ -277,27 +238,48 @@ const Select = (props) => {
277
238
  selectedItemRenderer: selectedItemRenderer,
278
239
  }),
279
240
  ),
241
+ React.createElement(
242
+ index_js_2.Icon,
243
+ {
244
+ as: 'span',
245
+ 'aria-hidden': true,
246
+ className: (0, classnames_1.default)('iui-end-icon', {
247
+ 'iui-disabled': disabled,
248
+ 'iui-open': isOpen,
249
+ }),
250
+ },
251
+ React.createElement(index_js_2.SvgCaretDownSmall, null),
252
+ ),
253
+ multiple
254
+ ? React.createElement(index_js_2.AutoclearingHiddenLiveRegion, {
255
+ text: liveRegionSelection,
256
+ })
257
+ : null,
280
258
  ),
281
- React.createElement(
282
- index_js_2.Box,
283
- {
284
- as: 'span',
285
- 'aria-hidden': true,
286
- ref: toggleButtonRef,
287
- className: (0, classnames_1.default)('iui-end-icon', {
288
- 'iui-actionable': !disabled,
289
- 'iui-disabled': disabled,
290
- 'iui-open': isOpen,
291
- }),
292
- onClick: () => !disabled && setIsOpen((o) => !o),
293
- },
294
- React.createElement(index_js_2.SvgCaretDownSmall, null),
295
- ),
296
- multiple
297
- ? React.createElement(index_js_2.AutoclearingHiddenLiveRegion, {
298
- text: liveRegionSelection,
299
- })
300
- : null,
259
+ popover.open &&
260
+ React.createElement(
261
+ index_js_2.Portal,
262
+ null,
263
+ React.createElement(
264
+ index_js_1.Menu,
265
+ {
266
+ role: 'listbox',
267
+ className: (0, classnames_1.default)('iui-scroll', menuClassName),
268
+ id: `${uid}-menu`,
269
+ key: `${uid}-menu`,
270
+ ...popover.getFloatingProps({
271
+ style: menuStyle,
272
+ onKeyDown: ({ key }) => {
273
+ if (key === 'Tab') {
274
+ hide();
275
+ }
276
+ },
277
+ }),
278
+ ref: popover.refs.setFloating,
279
+ },
280
+ menuItems,
281
+ ),
282
+ ),
301
283
  );
302
284
  };
303
285
  exports.Select = Select;
@@ -48,6 +48,8 @@ exports.SideNavigation = React.forwardRef((props, forwardedRef) => {
48
48
  const ExpandButton = React.createElement(
49
49
  index_js_2.IconButton,
50
50
  {
51
+ label: 'Toggle icon labels',
52
+ 'aria-expanded': _isExpanded,
51
53
  className: 'iui-sidenav-button iui-expand',
52
54
  onClick: React.useCallback(() => {
53
55
  _setIsExpanded((expanded) => !expanded);
@@ -92,6 +92,7 @@ const Thumb = (props) => {
92
92
  {
93
93
  placement: 'top',
94
94
  autoUpdateOptions: { animationFrame: true },
95
+ ariaStrategy: 'none',
95
96
  ...tooltipProps,
96
97
  },
97
98
  React.createElement(index_js_2.Box, {
@@ -1,4 +1,6 @@
1
1
  import * as React from 'react';
2
+ import { Icon } from '../utils/index.js';
3
+ import type { PolymorphicForwardRefComponent } from '../utils/index.js';
2
4
  type StatusMessageProps = {
3
5
  /**
4
6
  * Custom icon to be displayed at the beginning.
@@ -13,12 +15,20 @@ type StatusMessageProps = {
13
15
  * Status of the message.
14
16
  */
15
17
  status?: 'positive' | 'warning' | 'negative';
18
+ /**
19
+ * Passes props to icon
20
+ */
21
+ iconProps?: React.ComponentProps<typeof Icon>;
22
+ /**
23
+ * Passes props to content
24
+ */
25
+ contentProps?: React.ComponentPropsWithRef<'div'>;
16
26
  };
17
27
  /**
18
- * Component to display icon and text below the `Combobox` component.
28
+ * Component to display icon and text below the form field.
19
29
  * @example
20
30
  * <StatusMessage>This is the text</StatusMessage>
21
31
  * <StatusMessage startIcon={<SvgStar />}>This is the text</StatusMessage>
22
32
  */
23
- export declare const StatusMessage: ({ startIcon: userStartIcon, children, status, }: StatusMessageProps) => React.JSX.Element;
33
+ export declare const StatusMessage: PolymorphicForwardRefComponent<"div", StatusMessageProps>;
24
34
  export default StatusMessage;
@@ -8,26 +8,40 @@ const tslib_1 = require('tslib');
8
8
  *--------------------------------------------------------------------------------------------*/
9
9
  const React = tslib_1.__importStar(require('react'));
10
10
  const index_js_1 = require('../utils/index.js');
11
+ const classnames_1 = tslib_1.__importDefault(require('classnames'));
11
12
  /**
12
- * Component to display icon and text below the `Combobox` component.
13
+ * Component to display icon and text below the form field.
13
14
  * @example
14
15
  * <StatusMessage>This is the text</StatusMessage>
15
16
  * <StatusMessage startIcon={<SvgStar />}>This is the text</StatusMessage>
16
17
  */
17
- const StatusMessage = ({ startIcon: userStartIcon, children, status }) => {
18
+ exports.StatusMessage = React.forwardRef((props, ref) => {
19
+ const {
20
+ children,
21
+ startIcon: userStartIcon,
22
+ status,
23
+ className,
24
+ iconProps,
25
+ contentProps,
26
+ ...rest
27
+ } = props;
18
28
  const icon = userStartIcon ?? (status && index_js_1.StatusIconMap[status]());
19
29
  return React.createElement(
20
- React.Fragment,
21
- null,
30
+ index_js_1.Box,
31
+ {
32
+ className: (0, classnames_1.default)('iui-status-message', className),
33
+ 'data-iui-status': status,
34
+ ref: ref,
35
+ ...rest,
36
+ },
22
37
  !!icon
23
38
  ? React.createElement(
24
- index_js_1.Box,
25
- { as: 'span', className: 'iui-input-icon', 'aria-hidden': true },
39
+ index_js_1.Icon,
40
+ { 'aria-hidden': true, ...iconProps },
26
41
  icon,
27
42
  )
28
43
  : null,
29
- React.createElement(index_js_1.Box, { className: 'iui-message' }, children),
44
+ React.createElement(index_js_1.Box, { ...contentProps }, children),
30
45
  );
31
- };
32
- exports.StatusMessage = StatusMessage;
46
+ });
33
47
  exports.default = exports.StatusMessage;
@@ -19,6 +19,8 @@ const SubRowExpander = (props) => {
19
19
  : React.createElement(
20
20
  index_js_2.IconButton,
21
21
  {
22
+ 'aria-label': 'Toggle sub row',
23
+ 'aria-expanded': cell.row.isExpanded ? 'true' : 'false',
22
24
  style: {
23
25
  marginInlineEnd:
24
26
  density === 'default' || density === undefined ? 8 : 4,
@@ -109,13 +109,9 @@ const ActionColumn = ({ columnManager = false } = {}) => {
109
109
  {
110
110
  ...dropdownMenuProps,
111
111
  menuItems: headerCheckBoxes,
112
- onHide: (i) => {
113
- setIsOpen(false);
114
- dropdownMenuProps.onHide?.(i);
115
- },
116
- onShow: (i) => {
117
- setIsOpen(true);
118
- dropdownMenuProps.onShow?.(i);
112
+ onVisibleChange: (open) => {
113
+ setIsOpen(open);
114
+ dropdownMenuProps?.onVisibleChange?.(open);
119
115
  },
120
116
  className: (0, classnames_1.default)(
121
117
  'iui-scroll',
@@ -1,6 +1,7 @@
1
1
  import * as React from 'react';
2
+ import type { LabeledInput } from '../../../LabeledInput/index.js';
2
3
  import type { PolymorphicForwardRefComponent } from '../../../utils/index.js';
3
- import { LabeledInput } from '../../../LabeledInput/index.js';
4
+ import type { DatePickerLocalizedNames } from '../../../DatePicker/DatePicker.js';
4
5
  export type DatePickerInputProps = {
5
6
  date?: Date;
6
7
  onChange: (date?: Date) => void;
@@ -14,6 +15,10 @@ export type DatePickerInputProps = {
14
15
  * The 'to' date for the 'from' DatePickerInput or the 'from' date for the 'to' DatePickerInput
15
16
  */
16
17
  selectedDate?: Date;
18
+ /**
19
+ * Months, short days and days localized names for DatePicker
20
+ */
21
+ localizedNames?: DatePickerLocalizedNames;
17
22
  } & Omit<React.ComponentProps<typeof LabeledInput>, 'value' | 'onChange' | 'svgIcon' | 'displayStyle'>;
18
23
  declare const DatePickerInput: PolymorphicForwardRefComponent<"input", DatePickerInputProps>;
19
24
  export default DatePickerInput;