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