@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
@@ -14,46 +14,46 @@ import {
14
14
  useHover,
15
15
  useFocus,
16
16
  useDismiss,
17
- useRole,
18
17
  useInteractions,
19
18
  safePolygon,
20
19
  size,
21
20
  autoPlacement,
22
21
  hide,
23
22
  inline,
23
+ useDelayGroupContext,
24
+ useDelayGroup,
24
25
  } from '@floating-ui/react';
25
26
  import {
26
27
  Box,
27
- getDocument,
28
- mergeRefs,
29
- useGlobals,
28
+ Portal,
29
+ cloneElementWithRef,
30
+ useControlledState,
31
+ useId,
30
32
  useMergedRefs,
31
33
  } from '../utils/index.js';
32
- import ReactDOM from 'react-dom';
33
34
  const useTooltip = (options = {}) => {
35
+ const uniqueId = useId();
34
36
  const {
35
- placement,
36
- visible: controlledOpen,
37
- middleware = {
38
- flip: true,
39
- shift: true,
40
- },
37
+ placement = 'top',
38
+ visible,
39
+ onVisibleChange,
40
+ middleware = { flip: true, shift: true },
41
41
  autoUpdateOptions = {},
42
+ reference,
43
+ ariaStrategy = 'description',
44
+ id = uniqueId,
45
+ ...props
42
46
  } = options;
43
- const [uncontrolledOpen, setUncontrolledOpen] = React.useState(false);
44
- const open = controlledOpen ?? uncontrolledOpen;
45
- const data = useFloating({
47
+ const [open, onOpenChange] = useControlledState(
48
+ false,
49
+ visible,
50
+ onVisibleChange,
51
+ );
52
+ const floating = useFloating({
46
53
  placement,
47
54
  open,
48
- onOpenChange: setUncontrolledOpen,
49
- whileElementsMounted: (referenceEl, floatingEl, update) =>
50
- autoUpdate(referenceEl, floatingEl, update, {
51
- animationFrame: autoUpdateOptions.animationFrame,
52
- ancestorScroll: autoUpdateOptions.ancestorScroll,
53
- ancestorResize: autoUpdateOptions.ancestorResize,
54
- elementResize: autoUpdateOptions.elementResize,
55
- layoutShift: autoUpdateOptions.layoutShift,
56
- }),
55
+ onOpenChange,
56
+ whileElementsMounted: (...args) => autoUpdate(...args, autoUpdateOptions),
57
57
  middleware: [
58
58
  middleware.offset !== undefined ? offset(middleware.offset) : offset(4),
59
59
  middleware.flip && flip(),
@@ -63,35 +63,81 @@ const useTooltip = (options = {}) => {
63
63
  middleware.inline && inline(),
64
64
  middleware.hide && hide(),
65
65
  ].filter(Boolean),
66
+ ...(reference && { elements: { reference } }),
66
67
  });
67
- const context = data.context;
68
- const hover = useHover(context, {
69
- enabled: controlledOpen == null,
70
- delay: {
71
- open: 50,
72
- close: 250,
68
+ const ariaProps = React.useMemo(
69
+ () =>
70
+ ariaStrategy === 'description'
71
+ ? { 'aria-describedby': id }
72
+ : ariaStrategy === 'label'
73
+ ? { 'aria-labelledby': id }
74
+ : {},
75
+ [ariaStrategy, id],
76
+ );
77
+ const { delay } = useDelayGroupContext();
78
+ useDelayGroup(floating.context, { id: useId() });
79
+ const interactions = useInteractions([
80
+ useHover(floating.context, {
81
+ delay: delay ?? { open: 50, close: 250 },
82
+ handleClose: safePolygon({ buffer: -Infinity }),
83
+ }),
84
+ useFocus(floating.context),
85
+ useClick(floating.context),
86
+ useDismiss(floating.context),
87
+ ]);
88
+ // Manually add attributes and event handlers to external reference element,
89
+ // because we cannot spread getReferenceProps onto it.
90
+ React.useEffect(() => {
91
+ if (!reference) {
92
+ return;
93
+ }
94
+ /** e.g. onPointerDown --> pointerdown */
95
+ const domEventName = (e) => e.toLowerCase().substring(2);
96
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
97
+ const cleanupValues = {};
98
+ Object.entries({
99
+ ...ariaProps,
100
+ ...interactions.getReferenceProps(),
101
+ }).forEach(([key, value]) => {
102
+ if (typeof value === 'function') {
103
+ reference.addEventListener(domEventName(key), value);
104
+ cleanupValues[key] = value;
105
+ } else if (value) {
106
+ cleanupValues[key] = reference.getAttribute(key);
107
+ reference.setAttribute(key, value);
108
+ }
109
+ });
110
+ return () => {
111
+ Object.entries(cleanupValues).forEach(([key, value]) => {
112
+ if (typeof value === 'function') {
113
+ reference.removeEventListener(domEventName(key), value);
114
+ } else if (value) {
115
+ reference.setAttribute(key, value);
116
+ } else {
117
+ reference.removeAttribute(key);
118
+ }
119
+ });
120
+ };
121
+ }, [ariaProps, reference, interactions]);
122
+ const getReferenceProps = React.useCallback(
123
+ (userProps) => {
124
+ return interactions.getReferenceProps({ ...userProps, ...ariaProps });
73
125
  },
74
- handleClose: safePolygon({ buffer: -Infinity }),
75
- });
76
- const focus = useFocus(context, {
77
- enabled: controlledOpen == null,
78
- });
79
- const click = useClick(context, {
80
- enabled: controlledOpen == null,
81
- });
82
- const dismiss = useDismiss(context, {
83
- enabled: controlledOpen == null,
84
- });
85
- const role = useRole(context, { role: 'tooltip' });
86
- const interactions = useInteractions([click, hover, focus, dismiss, role]);
126
+ [interactions, ariaProps],
127
+ );
128
+ const floatingProps = React.useMemo(
129
+ () =>
130
+ interactions.getFloatingProps({
131
+ hidden: !open,
132
+ 'aria-hidden': 'true',
133
+ ...props,
134
+ id,
135
+ }),
136
+ [interactions, props, id, open],
137
+ );
87
138
  return React.useMemo(
88
- () => ({
89
- open,
90
- setUncontrolledOpen,
91
- ...interactions,
92
- ...data,
93
- }),
94
- [open, interactions, data],
139
+ () => ({ getReferenceProps, floatingProps, ...floating }),
140
+ [getReferenceProps, floatingProps, floating],
95
141
  );
96
142
  };
97
143
  /**
@@ -100,78 +146,35 @@ const useTooltip = (options = {}) => {
100
146
  * @example
101
147
  * <Tooltip content='tooltip text' placement='top'>Hover here</Tooltip>
102
148
  * @example
103
- * const buttonRef = React.useRef();
149
+ * const [trigger, setTrigger] = React.useState(null);
104
150
  * ...
105
- * <Button ref={buttonRef} />
106
- * <Tooltip content='tooltip text' reference={buttonRef} />
151
+ * <Button ref={setTrigger} />
152
+ * <Tooltip content='tooltip text' reference={trigger} />
107
153
  */
108
- export const Tooltip = React.forwardRef((props, forwardRef) => {
109
- const {
110
- content,
111
- children,
112
- portal = true,
113
- placement = 'top',
114
- autoUpdateOptions,
115
- middleware,
116
- style,
117
- className,
118
- visible,
119
- reference,
120
- ...rest
121
- } = props;
122
- const tooltip = useTooltip({
123
- placement,
124
- visible,
125
- autoUpdateOptions,
126
- middleware,
127
- });
128
- const context = useGlobals();
129
- React.useEffect(() => {
130
- if (reference) {
131
- tooltip.refs.setReference(reference.current);
132
- }
133
- }, [reference, tooltip.refs]);
134
- const portalTo =
135
- typeof portal !== 'boolean'
136
- ? portal.to
137
- : portal
138
- ? context?.portalContainer || getDocument()?.body
139
- : null;
140
- const contentBox = React.createElement(
141
- Box,
142
- {
143
- className: cx('iui-tooltip', className),
144
- ref: useMergedRefs(tooltip.refs.setFloating, forwardRef),
145
- style: { ...tooltip.floatingStyles, ...style },
146
- ...tooltip.getFloatingProps(),
147
- ...rest,
148
- },
149
- content,
150
- );
151
- const childrenRef =
152
- React.isValidElement(children) &&
153
- mergeRefs(
154
- tooltip.refs.setReference,
155
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
156
- children.ref,
157
- );
154
+ export const Tooltip = React.forwardRef((props, forwardedRef) => {
155
+ const { content, children, portal = true, className, style, ...rest } = props;
156
+ const tooltip = useTooltip(rest);
158
157
  return React.createElement(
159
158
  React.Fragment,
160
159
  null,
161
- React.isValidElement(children)
162
- ? React.cloneElement(
163
- children,
164
- tooltip.getReferenceProps({
165
- ref: childrenRef,
166
- ...children.props,
167
- }),
168
- )
169
- : null,
170
- tooltip.open
171
- ? portalTo
172
- ? ReactDOM.createPortal(contentBox, portalTo)
173
- : contentBox
174
- : null,
160
+ cloneElementWithRef(children, (children) => ({
161
+ ...tooltip.getReferenceProps(children.props),
162
+ ref: tooltip.refs.setReference,
163
+ })),
164
+ React.createElement(
165
+ Portal,
166
+ { portal: portal },
167
+ React.createElement(
168
+ Box,
169
+ {
170
+ className: cx('iui-tooltip', className),
171
+ ref: useMergedRefs(tooltip.refs.setFloating, forwardedRef),
172
+ style: { ...tooltip.floatingStyles, ...style },
173
+ ...tooltip.floatingProps,
174
+ },
175
+ content,
176
+ ),
177
+ ),
175
178
  );
176
179
  });
177
180
  export default Tooltip;
@@ -13,6 +13,7 @@ import {
13
13
  polymorphic,
14
14
  } from '../utils/index.js';
15
15
  import { List, ListItem } from '../List/index.js';
16
+ import { Label } from '../Label/index.js';
16
17
  // ----------------------------------------------------------------------------
17
18
  // TransferListComponent
18
19
  const TransferListComponent = polymorphic('iui-transfer-list-wrapper');
@@ -143,7 +144,7 @@ const TransferListItem = React.forwardRef((props, ref) => {
143
144
  });
144
145
  TransferListItem.displayName = 'TransferList.Item';
145
146
  const TransferListListboxLabel = React.forwardRef((props, ref) => {
146
- const { children, className, id, ...rest } = props;
147
+ const { children, id, ...rest } = props;
147
148
  const { labelId, setLabelId } = useSafeContext(TransferListContext);
148
149
  React.useEffect(() => {
149
150
  if (id && id !== labelId) {
@@ -151,14 +152,8 @@ const TransferListListboxLabel = React.forwardRef((props, ref) => {
151
152
  }
152
153
  }, [id, labelId, setLabelId]);
153
154
  return React.createElement(
154
- Box,
155
- {
156
- as: 'div',
157
- className: cx('iui-transfer-list-listbox-label', className),
158
- id: labelId,
159
- ref: ref,
160
- ...rest,
161
- },
155
+ Label,
156
+ { as: 'div', id: labelId, ref: ref, ...rest },
162
157
  children,
163
158
  );
164
159
  });
@@ -26,6 +26,8 @@ export { TransferList } from './TransferList/index.js';
26
26
  export { Tabs, Tab } from './Tabs/index.js';
27
27
  export { InformationPanel, InformationPanelWrapper, InformationPanelHeader, InformationPanelBody, InformationPanelContent, } from './InformationPanel/index.js';
28
28
  export { Input } from './Input/index.js';
29
+ export { InputWithDecorations } from './InputWithDecorations/InputWithDecorations.js';
30
+ export { InputGrid } from './InputGrid/InputGrid.js';
29
31
  export { Label } from './Label/index.js';
30
32
  export { LabeledInput } from './LabeledInput/index.js';
31
33
  export { InputGroup } from './InputGroup/index.js';
@@ -63,4 +65,4 @@ export { Anchor, Blockquote, Code, Kbd, KbdKeys, Text, } from './Typography/inde
63
65
  export { Stepper, WorkflowDiagram } from './Stepper/index.js';
64
66
  export type { StepProperties, StepperLocalization } from './Stepper/index.js';
65
67
  export { SearchBox } from './SearchBox/index.js';
66
- export { getUserColor, ColorValue, MiddleTextTruncation, LinkBox, LinkAction, Icon, Flex, VisuallyHidden, Divider, } from './utils/index.js';
68
+ export { getUserColor, ColorValue, MiddleTextTruncation, LinkBox, LinkAction, Icon, Flex, VisuallyHidden, Divider, Popover, } from './utils/index.js';
package/esm/core/index.js CHANGED
@@ -56,6 +56,8 @@ export {
56
56
  InformationPanelContent,
57
57
  } from './InformationPanel/index.js';
58
58
  export { Input } from './Input/index.js';
59
+ export { InputWithDecorations } from './InputWithDecorations/InputWithDecorations.js';
60
+ export { InputGrid } from './InputGrid/InputGrid.js';
59
61
  export { Label } from './Label/index.js';
60
62
  export { LabeledInput } from './LabeledInput/index.js';
61
63
  export { InputGroup } from './InputGroup/index.js';
@@ -126,4 +128,5 @@ export {
126
128
  Flex,
127
129
  VisuallyHidden,
128
130
  Divider,
131
+ Popover,
129
132
  } from './utils/index.js';
@@ -24,6 +24,11 @@ export type IconProps = {
24
24
  * @default 'default'
25
25
  */
26
26
  fill?: 'default' | 'positive' | 'informational' | 'negative' | 'warning' | AnyString;
27
+ /**
28
+ * Option to add padding to the icon.
29
+ * @default false
30
+ */
31
+ padded?: boolean;
27
32
  } & React.ComponentPropsWithoutRef<'span'>;
28
33
  /**
29
34
  * A utility component to provide size and fill to svgs.
@@ -32,12 +32,19 @@ const getSizeValue = (size) => {
32
32
  * </Icon>
33
33
  */
34
34
  export const Icon = React.forwardRef((props, ref) => {
35
- const { size = 'medium', fill = 'default', className, ...rest } = props;
35
+ const {
36
+ size = 'medium',
37
+ fill = 'default',
38
+ className,
39
+ padded = false,
40
+ ...rest
41
+ } = props;
36
42
  return React.createElement(Box, {
37
43
  as: 'span',
38
44
  className: cx('iui-svg-icon', className),
39
45
  'data-iui-icon-size': getSizeValue(size),
40
46
  'data-iui-icon-color': fill,
47
+ 'data-iui-padded': padded ? 'true' : undefined,
41
48
  ref: ref,
42
49
  ...rest,
43
50
  });
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
- export type InputContainerProps<T extends React.ElementType = 'div'> = {
3
- as?: T;
2
+ import type { PolymorphicForwardRefComponent } from '../props.js';
3
+ export type InputContainerProps = {
4
4
  label?: React.ReactNode;
5
5
  disabled?: boolean;
6
6
  required?: boolean;
@@ -8,13 +8,12 @@ export type InputContainerProps<T extends React.ElementType = 'div'> = {
8
8
  message?: React.ReactNode;
9
9
  icon?: JSX.Element;
10
10
  isLabelInline?: boolean;
11
- isIconInline?: boolean;
12
11
  statusMessage?: React.ReactNode;
13
12
  inputId?: string;
14
13
  labelId?: string;
15
- } & React.ComponentPropsWithoutRef<T>;
14
+ };
16
15
  /**
17
16
  * Input container to wrap inputs with label, and add optional message and icon.
18
17
  * @private
19
18
  */
20
- export declare const InputContainer: <T extends React.ElementType<any> = "div">(props: InputContainerProps<T>) => React.JSX.Element;
19
+ export declare const InputContainer: PolymorphicForwardRefComponent<"div", InputContainerProps>;
@@ -5,11 +5,13 @@
5
5
  import * as React from 'react';
6
6
  import cx from 'classnames';
7
7
  import { Box } from './Box.js';
8
+ import { Label } from '../../Label/index.js';
9
+ import { StatusMessage } from '../../StatusMessage/index.js';
8
10
  /**
9
11
  * Input container to wrap inputs with label, and add optional message and icon.
10
12
  * @private
11
13
  */
12
- export const InputContainer = (props) => {
14
+ export const InputContainer = React.forwardRef((props, forwardedRef) => {
13
15
  const {
14
16
  label,
15
17
  disabled,
@@ -18,7 +20,6 @@ export const InputContainer = (props) => {
18
20
  message,
19
21
  icon,
20
22
  isLabelInline,
21
- isIconInline,
22
23
  children,
23
24
  className,
24
25
  style,
@@ -30,29 +31,24 @@ export const InputContainer = (props) => {
30
31
  return React.createElement(
31
32
  Box,
32
33
  {
33
- className: cx(
34
- 'iui-input-container',
35
- {
36
- 'iui-disabled': disabled,
37
- [`iui-${status}`]: !!status,
38
- 'iui-inline-label': isLabelInline,
39
- 'iui-inline-icon': isIconInline,
40
- 'iui-with-message':
41
- (!!message || !!icon || !!statusMessage) && !isLabelInline,
42
- },
43
- className,
44
- ),
34
+ className: cx('iui-input-grid', className),
35
+ 'data-iui-status': status,
36
+ 'data-iui-label-placement': isLabelInline ? 'inline' : undefined,
45
37
  style: style,
38
+ ref: forwardedRef,
46
39
  ...rest,
47
40
  },
48
41
  label &&
49
42
  React.createElement(
50
- Box,
43
+ Label,
44
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
45
+ // @ts-ignore
51
46
  {
47
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
48
+ // @ts-ignore
52
49
  as: inputId && props.as !== 'label' ? 'label' : 'div',
53
- className: cx('iui-label', {
54
- 'iui-required': required,
55
- }),
50
+ required: required,
51
+ disabled: disabled,
56
52
  htmlFor: inputId,
57
53
  id: labelId,
58
54
  },
@@ -61,18 +57,11 @@ export const InputContainer = (props) => {
61
57
  children,
62
58
  statusMessage
63
59
  ? statusMessage
64
- : React.createElement(
65
- React.Fragment,
66
- null,
67
- icon &&
68
- React.createElement(
69
- Box,
70
- { as: 'span', className: 'iui-input-icon', 'aria-hidden': true },
71
- icon,
72
- ),
73
- message &&
74
- !isLabelInline &&
75
- React.createElement(Box, { className: 'iui-message' }, message),
76
- ),
60
+ : message &&
61
+ React.createElement(
62
+ StatusMessage,
63
+ { startIcon: icon, status: status },
64
+ message,
65
+ ),
77
66
  );
78
- };
67
+ });
@@ -2,6 +2,7 @@ import type { PolymorphicForwardRefComponent } from '../props.js';
2
2
  export type InputFlexContainerProps = {
3
3
  isDisabled?: boolean;
4
4
  status?: 'positive' | 'warning' | 'negative';
5
+ size?: 'small' | 'large';
5
6
  };
6
7
  /**
7
8
  * Utility component for input container with display flex abilities.
@@ -10,12 +10,14 @@ import { Box } from './Box.js';
10
10
  * @private
11
11
  */
12
12
  export const InputFlexContainer = React.forwardRef((props, ref) => {
13
- const { isDisabled, status, children, className, style, ...rest } = props;
13
+ const { isDisabled, status, children, className, size, style, ...rest } =
14
+ props;
14
15
  return React.createElement(
15
16
  Box,
16
17
  {
17
18
  className: cx('iui-input-flex-container', className),
18
19
  'data-iui-status': status,
20
+ 'data-iui-size': size,
19
21
  'data-iui-disabled': isDisabled ? 'true' : undefined,
20
22
  ref: ref,
21
23
  style: style,
@@ -1,39 +1,125 @@
1
1
  import * as React from 'react';
2
- import type { TippyProps } from '@tippyjs/react';
3
- import type { Placement, Instance } from 'tippy.js';
4
- export type PopoverInstance = Instance;
5
- export type PopoverProps = {
2
+ import type { Placement } from '@floating-ui/react';
3
+ import type { PolymorphicForwardRefComponent } from '../index.js';
4
+ import type { PortalProps } from './Portal.js';
5
+ type PopoverOptions = {
6
+ /**
7
+ * Placement of the popover content.
8
+ * @default 'bottom-start'
9
+ */
10
+ placement?: Placement;
6
11
  /**
7
12
  * Controlled flag for whether the popover is visible.
8
13
  */
9
14
  visible?: boolean;
10
15
  /**
11
- * Determines the events that cause the popover to show.
12
- * Should not be used when `visible` is set.
13
- * @see [tippy.js trigger prop](https://atomiks.github.io/tippyjs/v6/all-props/#trigger)
16
+ * Callback invoked every time the popover visibility changes as a result
17
+ * of internal logic. Should be used alongside `visible` prop.
14
18
  */
15
- trigger?: string;
19
+ onVisibleChange?: (visible: boolean) => void;
16
20
  /**
17
- * Placement of the popover content.
18
- * @default 'bottom-start'
19
- * @see [tippy.js placement prop](https://atomiks.github.io/tippyjs/v6/all-props/#placement).
21
+ * If true, the popover will close when clicking outside it.
20
22
  */
21
- placement?: Placement;
22
- } & Omit<TippyProps, 'placement' | 'trigger' | 'visible'>;
23
- /**
24
- * Wrapper around [tippy.js](https://atomiks.github.io/tippyjs)
25
- * with pre-configured props and plugins (e.g. lazy mounting, focus, etc).
26
- * @private
27
- */
28
- export declare const Popover: React.ForwardRefExoticComponent<Omit<PopoverProps, "ref"> & React.RefAttributes<unknown>>;
29
- /**
30
- * Plugin to hide Popover when either Esc key is pressed,
31
- * or when the content inside is not tabbable and Tab key is pressed.
32
- */
33
- export declare const hideOnEscOrTab: {
34
- fn(instance: Instance): {
35
- onShow(): void;
36
- onHide(): void;
23
+ closeOnOutsideClick?: boolean;
24
+ /**
25
+ * Whether the popover should match the width of the trigger.
26
+ */
27
+ matchWidth?: boolean;
28
+ };
29
+ type PopoverInternalProps = {
30
+ /**
31
+ * autoUpdate options that recalculates position
32
+ * to ensure the floating element remains anchored
33
+ * to its reference element, such as when scrolling
34
+ * and resizing the screen
35
+ *
36
+ * https://floating-ui.com/docs/autoUpdate#options
37
+ */
38
+ autoUpdateOptions?: {
39
+ ancestorScroll?: boolean;
40
+ ancestorResize?: boolean;
41
+ elementResize?: boolean;
42
+ /**
43
+ * Use this if you want popover to follow moving trigger element
44
+ */
45
+ animationFrame?: boolean;
46
+ layoutShift?: boolean;
47
+ };
48
+ /**
49
+ * Middleware options.
50
+ *
51
+ * @see https://floating-ui.com/docs/offset
52
+ */
53
+ middleware?: {
54
+ offset?: number;
55
+ flip?: boolean;
56
+ shift?: boolean;
57
+ autoPlacement?: boolean;
58
+ hide?: boolean;
59
+ inline?: boolean;
37
60
  };
61
+ /**
62
+ * By default, the popover will only open on click.
63
+ * `hover` and `focus` can be manually specified as triggers.
64
+ */
65
+ trigger?: Partial<Record<'hover' | 'click' | 'focus', boolean>>;
66
+ role?: 'dialog' | 'menu' | 'listbox';
67
+ };
68
+ export declare const usePopover: (options: PopoverOptions & PopoverInternalProps) => {
69
+ placement: Placement;
70
+ strategy: import("@floating-ui/utils").Strategy;
71
+ middlewareData: import("@floating-ui/core").MiddlewareData;
72
+ x: number;
73
+ y: number;
74
+ isPositioned: boolean;
75
+ update: () => void;
76
+ floatingStyles: React.CSSProperties;
77
+ refs: {
78
+ reference: React.MutableRefObject<import("@floating-ui/react-dom").ReferenceType | null>;
79
+ floating: React.MutableRefObject<HTMLElement | null>;
80
+ setReference: (node: import("@floating-ui/react-dom").ReferenceType | null) => void;
81
+ setFloating: (node: HTMLElement | null) => void;
82
+ } & import("@floating-ui/react").ExtendedRefs<import("@floating-ui/react").ReferenceType>;
83
+ elements: {
84
+ reference: import("@floating-ui/react-dom").ReferenceType | null; /**
85
+ * Middleware options.
86
+ *
87
+ * @see https://floating-ui.com/docs/offset
88
+ */
89
+ floating: HTMLElement | null;
90
+ } & import("@floating-ui/react").ExtendedElements<import("@floating-ui/react").ReferenceType>;
91
+ context: {
92
+ x: number;
93
+ y: number;
94
+ placement: Placement;
95
+ strategy: import("@floating-ui/utils").Strategy;
96
+ middlewareData: import("@floating-ui/core").MiddlewareData;
97
+ isPositioned: boolean;
98
+ update: () => void;
99
+ floatingStyles: React.CSSProperties;
100
+ open: boolean;
101
+ onOpenChange: (open: boolean, event?: Event | undefined) => void;
102
+ events: import("@floating-ui/react").FloatingEvents;
103
+ dataRef: React.MutableRefObject<import("@floating-ui/react").ContextData>;
104
+ nodeId: string | undefined;
105
+ floatingId: string;
106
+ refs: import("@floating-ui/react").ExtendedRefs<import("@floating-ui/react").ReferenceType>;
107
+ elements: import("@floating-ui/react").ExtendedElements<import("@floating-ui/react").ReferenceType>;
108
+ };
109
+ getFloatingProps: (userProps?: React.HTMLProps<HTMLElement>) => Record<string, unknown>;
110
+ getReferenceProps: (userProps?: React.HTMLProps<Element> | undefined) => Record<string, unknown>;
111
+ getItemProps: (userProps?: React.HTMLProps<HTMLElement> | undefined) => Record<string, unknown>;
112
+ open: boolean | undefined;
113
+ onOpenChange: React.Dispatch<React.SetStateAction<boolean | undefined>>;
38
114
  };
115
+ type PopoverPublicProps = {
116
+ content?: React.ReactNode;
117
+ children?: React.ReactNode;
118
+ applyBackground?: boolean;
119
+ } & PortalProps & PopoverOptions;
120
+ /**
121
+ * A utility component to help with positioning of floating content.
122
+ * Built on top of [`floating-ui`](https://floating-ui.com/)
123
+ */
124
+ export declare const Popover: PolymorphicForwardRefComponent<"div", PopoverPublicProps>;
39
125
  export default Popover;