@ringcentral/spring-ui 1.7.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Alert.js +3 -3
- package/Announcement.js +1 -1
- package/Autocomplete.js +216 -243
- package/Avatar.js +27 -13
- package/BottomNavigation.js +0 -3
- package/Checkbox.js +0 -2
- package/DatePicker.js +5 -13
- package/DateUtilsContext.js +0 -1
- package/Dialer.js +2 -50
- package/Dialog.js +18 -6
- package/Dropdown.js +0 -7
- package/FocusTrap.js +0 -32
- package/InlineEditable.js +0 -4
- package/Link.js +1 -1
- package/ListItem.js +1 -1
- package/ListNavigation.js +0 -6
- package/Menu.js +1 -1
- package/MenuDivider.js +2 -2
- package/MenuFooter.js +4 -4
- package/MenuHeader.js +4 -4
- package/MenuItem.js +1 -1
- package/MenuItemText.js +1 -1
- package/Modal.js +1 -1
- package/PageHeader.js +6 -4
- package/Popper.js +0 -1
- package/Rating.js +0 -5
- package/SingleFilter.js +0 -1
- package/Slider.js +1 -4
- package/Snackbar.js +0 -14
- package/SortableListItem.js +0 -1
- package/SplitButton.js +1 -3
- package/StatusIndicator.js +1 -1
- package/StepButton.js +2 -3
- package/StepContent.js +3 -8
- package/SubMenu.js +0 -4
- package/SwipeableDrawer.js +37 -162
- package/Switch.js +1 -4
- package/Tab.js +7 -8
- package/TabContext.js +0 -5
- package/TableBody.js +1 -1
- package/TableCell.js +0 -6
- package/TableRow.js +2 -4
- package/Tabs.js +22 -121
- package/Text.js +2 -4
- package/TimePicker.js +7 -46
- package/VirtualizedList.js +6 -39
- package/VirtualizedMenu.js +1 -1
- package/chunks/Alert.js +8 -7
- package/chunks/BottomNavigationItem.js +0 -1
- package/chunks/Button.js +0 -1
- package/chunks/Chip.js +0 -5
- package/chunks/Drawer.js +1 -30
- package/chunks/ListItem.js +3 -6
- package/chunks/Menu.js +6 -5
- package/chunks/MenuDivider.js +2 -3
- package/chunks/MenuItemText.js +3 -3
- package/chunks/MenuList.js +3 -6
- package/chunks/Modal.js +1 -1
- package/chunks/PickerTextField.js +0 -1
- package/chunks/Popover.js +0 -5
- package/chunks/Select.js +2 -39
- package/chunks/Squircle.js +0 -7
- package/chunks/StatusIndicator.js +1 -0
- package/chunks/StepIcon.js +1 -3
- package/chunks/StepperContext.js +0 -7
- package/chunks/Tooltip.js +0 -36
- package/chunks/VirtualizedMenu.js +45 -99
- package/chunks/getFade.js +4 -0
- package/chunks/useFocusTrapStack.js +0 -8
- package/chunks/useHelperTextId.js +0 -24
- package/chunks/useListNavigation.js +5 -17
- package/chunks/useMenuItemSelect.js +9 -22
- package/chunks/useMotionSafeTransition.js +0 -4
- package/chunks/useNestedParentMenu.js +5 -18
- package/chunks/usePrefersReducedMotion.js +6 -12
- package/chunks/useTooltipForceHide.js +0 -4
- package/chunks/useTrayNavigate.js +0 -1
- package/index.css +434 -135
- package/index.js +1 -1
- package/package.json +4 -4
- package/src/Accordion/Accordion.d.ts +1 -1
- package/src/Accordion/Accordion.type.d.ts +0 -21
- package/src/AccordionHeader/AccordionHeader.d.ts +1 -1
- package/src/AccordionHeader/AccordionHeader.type.d.ts +0 -14
- package/src/Alert/Alert.d.ts +1 -1
- package/src/Alert/Alert.type.d.ts +0 -32
- package/src/Animation/components/ExpandCollapseCaret/ExpandCollapseCaret.d.ts +0 -4
- package/src/Animation/components/ShowHideEye/ShowHideEye.d.ts +0 -4
- package/src/Animation/hooks/useMotionSafeTransition/useMotionSafeTransition.d.ts +0 -4
- package/src/Autocomplete/Autocomplete.d.ts +0 -5
- package/src/Autocomplete/Autocomplete.type.d.ts +0 -84
- package/src/Autocomplete/SuggestionList/SuggestionList.d.ts +5 -89
- package/src/Autocomplete/SuggestionList/SuggestionListItem.d.ts +0 -2
- package/src/Autocomplete/SuggestionList/utils/SuggestionListItem.d.ts +1 -13
- package/src/Autocomplete/SuggestionList/utils/useDynamicHeight.d.ts +0 -6
- package/src/Autocomplete/SuggestionList/utils/useHighlightScroll.d.ts +4 -23
- package/src/Autocomplete/SuggestionList/utils/useSuggestionList.d.ts +3 -41
- package/src/Autocomplete/SuggestionList/utils/useSuggestionListGroup.d.ts +0 -49
- package/src/Autocomplete/useAutocomplete.d.ts +5 -66
- package/src/Autocomplete/useAutocompleteTag.d.ts +3 -36
- package/src/Avatar/Avatar.type.d.ts +0 -58
- package/src/AvatarGroup/AvatarGroup.type.d.ts +0 -3
- package/src/Backdrop/Backdrop.type.d.ts +0 -4
- package/src/Badge/Badge.type.d.ts +0 -33
- package/src/Block/Block.type.d.ts +0 -24
- package/src/BlockHeader/BlockHeader.type.d.ts +0 -5
- package/src/BottomNavigation/BottomNavigation.type.d.ts +0 -34
- package/src/BottomNavigationItem/BottomNavigationItem.type.d.ts +0 -39
- package/src/Button/Button.type.d.ts +0 -30
- package/src/CallButton/CallButton.type.d.ts +0 -4
- package/src/Checkbox/Checkbox.type.d.ts +0 -17
- package/src/Chip/Chip.type.d.ts +0 -41
- package/src/CircularProgressIndicator/CircularProgressIndicator.d.ts +1 -1
- package/src/CircularProgressIndicator/CircularProgressIndicator.type.d.ts +0 -19
- package/src/DatePicker/Calendar.d.ts +1 -20
- package/src/DatePicker/DatePicker.type.d.ts +0 -18
- package/src/DatePicker/DatePickerHeader.d.ts +1 -12
- package/src/DatePicker/Day.d.ts +1 -8
- package/src/DatePicker/Year.d.ts +1 -7
- package/src/DatePicker/Years.d.ts +0 -7
- package/src/Dialer/DialDelete/DialDelete.d.ts +0 -3
- package/src/Dialer/DialPad/DialPad.d.ts +0 -106
- package/src/Dialer/DialPad/utils/types.d.ts +0 -5
- package/src/Dialer/DialPad/utils/useDialKeyboard.d.ts +0 -5
- package/src/Dialer/DialPad/utils/useKeyAudio.d.ts +0 -9
- package/src/Dialer/DialPadButton/DialPadButton.d.ts +0 -14
- package/src/Dialer/DialTextField/DialTextField.d.ts +0 -23
- package/src/Dialer/DialTextField/utils/getDialPadValueOnlyRegex.d.ts +0 -3
- package/src/Dialer/DialTextField/utils/useFixedEndSelection.d.ts +0 -3
- package/src/Dialog/Dialog.classes.d.ts +1 -1
- package/src/Dialog/Dialog.d.ts +1 -1
- package/src/Dialog/Dialog.type.d.ts +3 -11
- package/src/Divider/Divider.type.d.ts +0 -17
- package/src/DragHandle/DragHandle.type.d.ts +0 -4
- package/src/Drawer/Drawer.d.ts +1 -29
- package/src/Drawer/Drawer.type.d.ts +0 -84
- package/src/Dropdown/Dropdown.type.d.ts +0 -64
- package/src/EmptyState/EmptyState.d.ts +1 -1
- package/src/EmptyState/EmptyState.type.d.ts +0 -12
- package/src/FabButton/FabButton.type.d.ts +0 -5
- package/src/FocusTrap/FocusTrap.d.ts +0 -38
- package/src/FocusTrap/useFocusTrapStack.d.ts +0 -9
- package/src/FormField/FormField.type.d.ts +0 -26
- package/src/FormField/useHelperTextId.d.ts +0 -25
- package/src/FormLabel/FormLabel.d.ts +1 -1
- package/src/FormLabel/FormLabel.type.d.ts +0 -14
- package/src/Icon/Icon.d.ts +1 -1
- package/src/Icon/Icon.type.d.ts +0 -15
- package/src/IconButton/IconButton.type.d.ts +0 -30
- package/src/IconButton/IconButtonLabel.d.ts +1 -1
- package/src/IconButton/IconButtonLabel.type.d.ts +0 -3
- package/src/IconButtonGroup/IconButtonGroup.type.d.ts +0 -8
- package/src/InlineEditable/InlineEditable.type.d.ts +0 -75
- package/src/LinearProgressIndicator/LinearProgressIndicator.type.d.ts +0 -31
- package/src/Link/Link.classes.d.ts +1 -1
- package/src/Link/Link.type.d.ts +1 -10
- package/src/ListItem/ListItem.type.d.ts +0 -41
- package/src/ListItemText/ListItemText.d.ts +1 -1
- package/src/ListItemText/ListItemText.type.d.ts +0 -21
- package/src/ListNavigation/useListNavigation.d.ts +0 -16
- package/src/Menu/Menu.d.ts +1 -1
- package/src/Menu/Menu.type.d.ts +0 -10
- package/src/MenuFooter/MenuFooter.type.d.ts +0 -4
- package/src/MenuHeader/MenuHeader.type.d.ts +0 -10
- package/src/MenuItem/MenuItem.d.ts +1 -1
- package/src/MenuItem/MenuItem.type.d.ts +0 -19
- package/src/MenuItem/MenuItemSelectContext.d.ts +0 -3
- package/src/MenuItem/useMenuItemSelect.d.ts +0 -21
- package/src/MenuItemText/MenuItemText.d.ts +1 -1
- package/src/MenuItemText/MenuItemText.type.d.ts +0 -17
- package/src/MenuList/MenuList.type.d.ts +0 -4
- package/src/MenuList/MenuListContext.d.ts +0 -6
- package/src/Modal/InnerModal.d.ts +2 -2
- package/src/Modal/InnerModal.type.d.ts +0 -5
- package/src/Modal/Modal.classes.d.ts +1 -1
- package/src/Modal/Modal.d.ts +3 -3
- package/src/Modal/Modal.type.d.ts +0 -11
- package/src/Modal/ModalContext.d.ts +0 -4
- package/src/NestedMenuContext/NestedMenuContext.d.ts +1 -1
- package/src/Option/Option.d.ts +1 -1
- package/src/Option/Option.type.d.ts +0 -3
- package/src/Overlap/Overlap.type.d.ts +0 -11
- package/src/PageHeader/PageHeader.type.d.ts +0 -4
- package/src/PickerTextField/PickerTextField.type.d.ts +0 -10
- package/src/Popover/Popover.d.ts +1 -1
- package/src/Popover/Popover.type.d.ts +0 -29
- package/src/Popper/Popper.d.ts +1 -1
- package/src/Popper/Popper.type.d.ts +0 -61
- package/src/PopperPaper/PopperPaper.d.ts +1 -1
- package/src/Radio/Radio.type.d.ts +0 -5
- package/src/RadioGroup/RadioGroup.d.ts +1 -1
- package/src/RadioGroup/RadioGroup.type.d.ts +0 -4
- package/src/Rating/Rating.d.ts +1 -1
- package/src/Rating/Rating.type.d.ts +0 -74
- package/src/Rating/RatingItem.d.ts +1 -1
- package/src/Select/Select.type.d.ts +0 -84
- package/src/SingleFilter/FilterButton/FilterButton.d.ts +1 -1
- package/src/SingleFilter/FilterButton/FilterButton.type.d.ts +0 -16
- package/src/SingleFilter/SingleFilter.d.ts +1 -1
- package/src/SingleFilter/SingleFilter.type.d.ts +0 -26
- package/src/Skeleton/Skeleton.type.d.ts +0 -1
- package/src/Skeleton/SkeletonContainer/SkeletonContainer.classes.d.ts +1 -1
- package/src/Slider/Slider.classes.d.ts +1 -5
- package/src/Slider/Slider.d.ts +2 -2
- package/src/Slider/Slider.type.d.ts +0 -104
- package/src/Snackbar/Snackbar.type.d.ts +0 -18
- package/src/SortableListItem/SortableListItemOverlay.d.ts +1 -1
- package/src/SplitButton/SplitButton.d.ts +1 -1
- package/src/SplitButton/SplitButton.type.d.ts +0 -21
- package/src/Squircle/Squircle.type.d.ts +0 -3
- package/src/StatusIndicator/StatusIndicator.classes.d.ts +1 -1
- package/src/StatusIndicator/StatusIndicator.type.d.ts +1 -9
- package/src/Step/Step.type.d.ts +0 -29
- package/src/Step/StepContext.d.ts +0 -7
- package/src/StepButton/StepButton.type.d.ts +0 -15
- package/src/StepContent/StepContent.d.ts +1 -1
- package/src/StepContent/StepContent.type.d.ts +0 -7
- package/src/StepIcon/StepIcon.type.d.ts +0 -26
- package/src/StepLabel/StepLabel.d.ts +1 -1
- package/src/StepLabel/StepLabel.type.d.ts +0 -23
- package/src/Stepper/Stepper.type.d.ts +0 -27
- package/src/SubMenu/PopperMenu.d.ts +1 -1
- package/src/SubMenu/SubMenu.d.ts +1 -1
- package/src/SwipeableDrawer/SwipeableDrawer.d.ts +1 -27
- package/src/SwipeableDrawer/SwipeableDrawer.types.d.ts +0 -67
- package/src/SwipeableDrawer/hooks/useDrawerGestures.d.ts +0 -110
- package/src/SwipeableDrawer/hooks/useElementSizeObserver.d.ts +0 -5
- package/src/SwipeableDrawer/hooks/useSnapPoints.d.ts +0 -60
- package/src/Switch/Switch.type.d.ts +0 -9
- package/src/Tab/Tab.classes.d.ts +3 -2
- package/src/Tab/Tab.d.ts +1 -1
- package/src/Tab/Tab.type.d.ts +0 -29
- package/src/TabContext/TabContext.d.ts +0 -4
- package/src/TabContext/TabContext.type.d.ts +0 -7
- package/src/TabPanel/TabPanel.d.ts +1 -1
- package/src/TabPanel/TabPanel.type.d.ts +0 -10
- package/src/Table/Table.type.d.ts +0 -19
- package/src/TableBody/TableBody.type.d.ts +0 -3
- package/src/TableCell/TableCell.d.ts +0 -4
- package/src/TableCell/TableCell.type.d.ts +0 -35
- package/src/TableContainer/TableContainer.type.d.ts +0 -7
- package/src/TableFooter/TableFooter.type.d.ts +0 -3
- package/src/TableHead/TableHead.type.d.ts +0 -6
- package/src/TablePagination/TablePagination.type.d.ts +0 -47
- package/src/TableRow/TableRow.type.d.ts +0 -17
- package/src/Tabs/TabMoreMenu.d.ts +0 -16
- package/src/Tabs/TabScrollButton.d.ts +1 -11
- package/src/Tabs/Tabs.classes.d.ts +1 -1
- package/src/Tabs/Tabs.d.ts +1 -1
- package/src/Tabs/Tabs.type.d.ts +2 -36
- package/src/Tabs/TabsContext.d.ts +2 -0
- package/src/Tabs/hooks/useTabsScroller.d.ts +0 -30
- package/src/Tag/Tag.d.ts +1 -1
- package/src/Tag/Tag.type.d.ts +0 -12
- package/src/Text/Text.type.d.ts +0 -13
- package/src/TextField/TextField.type.d.ts +0 -64
- package/src/Textarea/Textarea.d.ts +1 -1
- package/src/Textarea/Textarea.type.d.ts +0 -13
- package/src/TimePicker/NumberPicker.d.ts +1 -1
- package/src/TimePicker/NumberPicker.type.d.ts +0 -12
- package/src/TimePicker/SelectionView.d.ts +0 -6
- package/src/TimePicker/TimeButton.d.ts +1 -4
- package/src/TimePicker/TimePicker.type.d.ts +0 -11
- package/src/TimePicker/ToggleText.d.ts +1 -1
- package/src/TimePicker/ToggleText.type.d.ts +0 -3
- package/src/TimePicker/utils/TimeBoundary.d.ts +0 -3
- package/src/TimePicker/utils/TimePickerHelper.d.ts +0 -19
- package/src/TimePicker/utils/getNumberPickerBoundary.d.ts +0 -3
- package/src/Tooltip/TooltipTrigger.a11y.d.ts +0 -9
- package/src/Tooltip/TooltipTrigger.type.d.ts +0 -44
- package/src/Tooltip/TooltipView.type.d.ts +0 -25
- package/src/Tooltip/useTooltipForceHide.d.ts +0 -4
- package/src/Tray/Tray.d.ts +1 -1
- package/src/Tray/Tray.type.d.ts +0 -13
- package/src/Tray/TrayContext.d.ts +0 -4
- package/src/Tray/hooks/useTray.d.ts +0 -16
- package/src/Tray/hooks/useTrayPanel.d.ts +0 -3
- package/src/TrayMenu/TrayMenu.d.ts +1 -1
- package/src/TrayMenu/TrayMenuItem.d.ts +1 -1
- package/src/VirtualizedList/VirtualizedList.type.d.ts +0 -27
- package/src/VirtualizedMenu/VirtualizedMenu.classes.d.ts +1 -1
- package/src/VirtualizedMenu/VirtualizedMenu.type.d.ts +0 -17
package/chunks/Select.js
CHANGED
|
@@ -26,7 +26,6 @@ const useSelect = (props) => {
|
|
|
26
26
|
},
|
|
27
27
|
onKeyDown: (e) => {
|
|
28
28
|
if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
|
|
29
|
-
// prevent scroll
|
|
30
29
|
e.preventDefault();
|
|
31
30
|
handleOpen(true);
|
|
32
31
|
}
|
|
@@ -86,7 +85,6 @@ const Select = forwardRef((inProps, ref) => {
|
|
|
86
85
|
}
|
|
87
86
|
});
|
|
88
87
|
useEffect(() => {
|
|
89
|
-
// close menu when disabled
|
|
90
88
|
if (disabled) {
|
|
91
89
|
handleOpen(false);
|
|
92
90
|
}
|
|
@@ -108,7 +106,6 @@ const Select = forwardRef((inProps, ref) => {
|
|
|
108
106
|
if (getSelectedIndex)
|
|
109
107
|
return getSelectedIndex(value);
|
|
110
108
|
if (Array.isArray(value)) {
|
|
111
|
-
// For multiple selection, focus on the last selected item
|
|
112
109
|
const lastSelectedItem = value.at(-1);
|
|
113
110
|
return lastSelectedItem ? data.indexOf(lastSelectedItem) : -1;
|
|
114
111
|
}
|
|
@@ -117,45 +114,17 @@ const Select = forwardRef((inProps, ref) => {
|
|
|
117
114
|
return true;
|
|
118
115
|
});
|
|
119
116
|
const handleMenuListChange = useEventCallback((newValue) => {
|
|
120
|
-
// for uncontrolled mode
|
|
121
117
|
setValue(newValue);
|
|
122
118
|
if (inputRef.current) {
|
|
123
|
-
/**
|
|
124
|
-
* Programatically trigger the onChange event of the native input element.
|
|
125
|
-
* Doing this means we can avoid cloning another event to mimic the ChangeEvent.
|
|
126
|
-
*/
|
|
127
|
-
/**
|
|
128
|
-
* Set the value property of the input element, avoiding React's overridden setter.
|
|
129
|
-
* This will cause the input element to update its value and fire the onChange event,
|
|
130
|
-
* `handleInputChange` will then call onChange
|
|
131
|
-
*/
|
|
132
119
|
Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value')?.set?.call(inputRef.current, newValue);
|
|
133
120
|
const event = new Event('input', { bubbles: true });
|
|
134
|
-
/**
|
|
135
|
-
* When `selectMode` is `multiple`, the default `event.target.value` type is `string`,
|
|
136
|
-
* but it should actually be `string[]`. Since browsers do not natively support this,
|
|
137
|
-
* we need to override the `value` property to ensure it correctly reflects an array.
|
|
138
|
-
*
|
|
139
|
-
* Why do we need `Object.defineProperty` to override `event.target.value`?
|
|
140
|
-
* - The `target` property of an event object is read-only, so we cannot modify it directly.
|
|
141
|
-
* - `Object.defineProperty` allows us to override `event.target`, but it requires returning
|
|
142
|
-
* an object from the getter.
|
|
143
|
-
* - To dynamically override only the `value` property while preserving all other properties
|
|
144
|
-
* and methods of the input element, we use a `Proxy`.
|
|
145
|
-
*
|
|
146
|
-
* How does this approach help?
|
|
147
|
-
* - Ensures `event.target.value` correctly returns a `string[]` instead of a `string`.
|
|
148
|
-
* - Keeps the event object behaving as expected when accessed by event handlers.
|
|
149
|
-
* - Preserves other native properties (`name`, `id`, `type`, etc.) and methods
|
|
150
|
-
* (`focus()`, `blur()`, etc.), preventing potential "Illegal Invocation" errors.
|
|
151
|
-
*/
|
|
152
121
|
Object.defineProperty(event, 'target', {
|
|
153
122
|
configurable: true,
|
|
154
123
|
get: () => {
|
|
155
124
|
return new Proxy(inputRef.current, {
|
|
156
125
|
get(obj, prop) {
|
|
157
126
|
if (prop === 'value') {
|
|
158
|
-
return newValue;
|
|
127
|
+
return newValue;
|
|
159
128
|
}
|
|
160
129
|
return obj[prop];
|
|
161
130
|
},
|
|
@@ -169,10 +138,6 @@ const Select = forwardRef((inProps, ref) => {
|
|
|
169
138
|
open,
|
|
170
139
|
handleOpen,
|
|
171
140
|
});
|
|
172
|
-
/**
|
|
173
|
-
* The non-virtualized Menu/MenuList components have the necessary contexts
|
|
174
|
-
* baked in. For the virtualized Menu, we need to provide the context values.
|
|
175
|
-
*/
|
|
176
141
|
const { contextValue: virtualizedContextValue } = useMenuItemSelect({
|
|
177
142
|
value,
|
|
178
143
|
onChange: handleMenuListChange,
|
|
@@ -224,9 +189,7 @@ const Select = forwardRef((inProps, ref) => {
|
|
|
224
189
|
prefersReducedMotion: prefersReducedMotion,
|
|
225
190
|
}), children: children }) }) }));
|
|
226
191
|
}
|
|
227
|
-
return (jsxs(Fragment, { children: [jsxs(FormField, { disabled: disabled, required: required, variant: variant, error: error,
|
|
228
|
-
// Make sure the focus style doesn't disappear when the Menu is in its close transition
|
|
229
|
-
focused: open || (!open && !didMenuExit), htmlFor: id, label: label, labelProps: {
|
|
192
|
+
return (jsxs(Fragment, { children: [jsxs(FormField, { disabled: disabled, required: required, variant: variant, error: error, focused: open || (!open && !didMenuExit), htmlFor: id, label: label, labelProps: {
|
|
230
193
|
id: labelId,
|
|
231
194
|
}, ref: ref, contentRef: formFieldContentRef, helperText: helperText, FormHelperTextProps: { id: helperTextId, ...FormHelperTextProps }, className: cls('root', { error }), classes: {
|
|
232
195
|
outlined: cls('outlined'),
|
package/chunks/Squircle.js
CHANGED
|
@@ -7,17 +7,10 @@ const SQUIRCLE_PATH = 'M 0.5 0 C 0.879 0 1 0.121 1 0.5 C 1 0.879 0.879 1 0.5 1 C
|
|
|
7
7
|
const Squircle = forwardRef((inProps, ref) => {
|
|
8
8
|
const props = useThemeProps({ props: inProps, name: 'Squircle' });
|
|
9
9
|
const { component = 'div', focusVisible, active, children: childrenProp, className, classes, interactive = true, fillShape: fillShapeProp = false, ...rest } = props;
|
|
10
|
-
/**
|
|
11
|
-
* If the children passed to this component have a conditionally rendered
|
|
12
|
-
* element, using toArray will ensure that any falsy children are removed.
|
|
13
|
-
* Otherwise fillShape will always be false even if only 1 truthy child
|
|
14
|
-
* is passed to this component.
|
|
15
|
-
*/
|
|
16
10
|
const children = React.Children.toArray(childrenProp);
|
|
17
11
|
const firstChild = children[0];
|
|
18
12
|
const fillShape = fillShapeProp &&
|
|
19
13
|
firstChild &&
|
|
20
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
21
14
|
isValidElement(firstChild);
|
|
22
15
|
const cls = useClasses('squircle', classes, className);
|
|
23
16
|
const clipId = useId('sui-squircle-clip', true);
|
package/chunks/StepIcon.js
CHANGED
|
@@ -5,9 +5,7 @@ import { AlertFilledMd, AlertMd, CheckBoldMd, CheckMd } from '@ringcentral/sprin
|
|
|
5
5
|
import { useThemeProps } from '@ringcentral/spring-theme';
|
|
6
6
|
import { I as Icon } from './Icon.js';
|
|
7
7
|
|
|
8
|
-
const StepIcon = forwardRef(
|
|
9
|
-
// @ts-ignore
|
|
10
|
-
(inProps, ref) => {
|
|
8
|
+
const StepIcon = forwardRef((inProps, ref) => {
|
|
11
9
|
const props = useThemeProps({ props: inProps, name: 'StepIcon' });
|
|
12
10
|
const { classes, className, children, active = false, completed = false, error = false, disabled = false, variant = 'contained', icon, symbol, ...rest } = props;
|
|
13
11
|
const cls = useClasses('step-icon', classes, className);
|
package/chunks/StepperContext.js
CHANGED
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
import { createContext, useContext } from 'react';
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* Provides information about the current step in Stepper.
|
|
5
|
-
*/
|
|
6
3
|
const StepContext = createContext({});
|
|
7
|
-
/**
|
|
8
|
-
* Returns the current StepContext or an empty object if no StepContext
|
|
9
|
-
* has been defined in the component tree.
|
|
10
|
-
*/
|
|
11
4
|
const useStepContext = () => useContext(StepContext);
|
|
12
5
|
|
|
13
6
|
const StepperContext = createContext({});
|
package/chunks/Tooltip.js
CHANGED
|
@@ -10,15 +10,6 @@ import { g as getFade } from './getFade.js';
|
|
|
10
10
|
import { Popper } from '../Popper.js';
|
|
11
11
|
import { P as PopperPaper } from './PopperPaper.js';
|
|
12
12
|
|
|
13
|
-
/**
|
|
14
|
-
* Accessibility naming strategy:
|
|
15
|
-
* - Default (label mode): `title` is treated as an accessible label
|
|
16
|
-
* - string `title` → `aria-label`
|
|
17
|
-
* - React element `title` → `aria-labelledby` while the tooltip is open
|
|
18
|
-
* - Description mode (`describeChild = true`): `title` is treated as an accessible description
|
|
19
|
-
* - when closed → native `title` attribute
|
|
20
|
-
* - when open → `aria-describedby` pointing to the tooltip id
|
|
21
|
-
*/
|
|
22
13
|
const ARIA_DESCRIBEDBY = 'aria-describedby';
|
|
23
14
|
const ARIA_LABEL = 'aria-label';
|
|
24
15
|
const ARIA_LABELLEDBY = 'aria-labelledby';
|
|
@@ -47,49 +38,33 @@ function computeTooltipA11y({ title, describeChild, triggerWhenDisabled, open, t
|
|
|
47
38
|
});
|
|
48
39
|
}
|
|
49
40
|
if (describeChild) {
|
|
50
|
-
// Description mode: tooltip acts as an accessible description
|
|
51
|
-
// When closed: add title attribute (unless user provided their own)
|
|
52
|
-
// When open: swap to aria-describedby
|
|
53
41
|
if (!hasAriaDescribedBy) {
|
|
54
42
|
if (!hasUserTitle) {
|
|
55
|
-
// Only set tooltip title if user hasn't provided one
|
|
56
43
|
nameOrDescProps.title =
|
|
57
44
|
!open && titleIsString ? title : null;
|
|
58
45
|
}
|
|
59
46
|
else if (open) {
|
|
60
|
-
// If user provided a title and tooltip is open, remove native title to prevent duplicate
|
|
61
47
|
nameOrDescProps.title = null;
|
|
62
48
|
}
|
|
63
49
|
nameOrDescProps[ARIA_DESCRIBEDBY] = open ? tooltipId : null;
|
|
64
50
|
}
|
|
65
51
|
}
|
|
66
52
|
else {
|
|
67
|
-
// Label mode (default): tooltip acts as an accessible label
|
|
68
|
-
// Use aria-label for strings, aria-labelledby for React elements
|
|
69
53
|
if (titleIsString && !hasAriaLabel) {
|
|
70
54
|
nameOrDescProps[ARIA_LABEL] = title;
|
|
71
|
-
// For string titles, Tooltip fully owns the label; always remove native title
|
|
72
55
|
nameOrDescProps.title = null;
|
|
73
56
|
}
|
|
74
57
|
else if (!titleIsString && !hasAriaLabelledBy && title) {
|
|
75
|
-
// Only set aria-labelledby if title is truthy (React element exists)
|
|
76
58
|
nameOrDescProps[ARIA_LABELLEDBY] = open ? tooltipId : null;
|
|
77
|
-
// Only remove native title when tooltip is open to prevent duplicate tooltips.
|
|
78
|
-
// When closed, leave existing title as a fallback accessible name.
|
|
79
59
|
if (open) {
|
|
80
60
|
nameOrDescProps.title = null;
|
|
81
61
|
}
|
|
82
62
|
}
|
|
83
63
|
else if (open) {
|
|
84
|
-
// Tooltip is open but we're not providing a label (e.g. child already has aria-label);
|
|
85
|
-
// still remove native title to avoid double tooltips.
|
|
86
64
|
nameOrDescProps.title = null;
|
|
87
65
|
}
|
|
88
66
|
}
|
|
89
67
|
if (triggerWhenDisabled) {
|
|
90
|
-
// When open and child does not already have aria-describedby: use tooltip id,
|
|
91
|
-
// and always remove native title on the disabled control to avoid double tooltips.
|
|
92
|
-
// When closed and title is a string: use native title as a fallback for SR on disabled.
|
|
93
68
|
if (open) {
|
|
94
69
|
if (!hasAriaDescribedBy) {
|
|
95
70
|
disabledOverrides[ARIA_DESCRIBEDBY] = tooltipId;
|
|
@@ -149,15 +124,10 @@ const TooltipTrigger = (props, ref) => {
|
|
|
149
124
|
onOpenStateChange?.(e, false);
|
|
150
125
|
};
|
|
151
126
|
useEventListener(anchorRef, 'mouseenter', (e) => {
|
|
152
|
-
// Ensures touch devices do not trigger the tooltip, mouseleave will never be fired and the tooltip will be stuck open
|
|
153
127
|
if (didInitiateWithTouch.current) {
|
|
154
|
-
// Immediately reset the flag, touchstart will fire again on the next tap and will set the flag back to true
|
|
155
128
|
didInitiateWithTouch.current = false;
|
|
156
129
|
return;
|
|
157
130
|
}
|
|
158
|
-
// Remove the title ahead of time from the trigger.
|
|
159
|
-
// We don't want to wait for the next render commit.
|
|
160
|
-
// We would risk displaying two tooltips at the same time (native + this one).
|
|
161
131
|
if (anchorRef.current) {
|
|
162
132
|
anchorRef.current.removeAttribute('title');
|
|
163
133
|
}
|
|
@@ -174,22 +144,17 @@ const TooltipTrigger = (props, ref) => {
|
|
|
174
144
|
useEventListener(anchorRef, 'focus', (e) => {
|
|
175
145
|
if (disableFocusListener)
|
|
176
146
|
return;
|
|
177
|
-
// handleFocusVisible only support react event type, but it only need target event
|
|
178
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
179
147
|
handleFocusVisible(e);
|
|
180
148
|
if (isFocusVisibleRef.current === true) {
|
|
181
149
|
handleOpen(e);
|
|
182
150
|
}
|
|
183
151
|
});
|
|
184
152
|
useEventListener(anchorRef, 'blur', (e) => {
|
|
185
|
-
// handleBlurVisible only support react event type, but this param is useless
|
|
186
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
187
153
|
handleBlurVisible(e);
|
|
188
154
|
if (isFocusVisibleRef.current === false) {
|
|
189
155
|
handleClose(e);
|
|
190
156
|
}
|
|
191
157
|
});
|
|
192
|
-
// Handle Escape key to close tooltip
|
|
193
158
|
useEventListener(open ? document : null, 'keydown', (e) => {
|
|
194
159
|
if (e.key === 'Escape') {
|
|
195
160
|
handleClose(e);
|
|
@@ -241,7 +206,6 @@ const Tooltip = forwardRef((inProps, ref) => {
|
|
|
241
206
|
const props = useThemeProps({ props: inProps, name: 'Tooltip' });
|
|
242
207
|
const { children, open: openProp, delay, onOpenStateChange, title, disableFocusListener, disableBackdropAnimation, triggerWhenDisabled, triggerWrapperProps, PopperProps, describeChild = false, ...rest } = props;
|
|
243
208
|
const renderTooltip = (open, getAnchorEl, tooltipId) => {
|
|
244
|
-
// hides '', null/undefined, false, NaN)
|
|
245
209
|
const effectiveOpen = open && !(!title && title !== 0);
|
|
246
210
|
const content = effectiveOpen ? (jsx(TooltipView, { disableInteractions: openProp === undefined, ...rest, PopperProps: { ...PopperProps, id: tooltipId }, anchorEl: getAnchorEl, ref: ref, children: title })) : null;
|
|
247
211
|
return disableBackdropAnimation ? (jsx(Fragment, { children: content })) : (jsx(AnimatePresence, { children: content }));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { createContext, useContext, useRef,
|
|
2
|
+
import { createContext, useContext, useRef, useLayoutEffect, forwardRef, useState, useMemo, useEffect } from 'react';
|
|
3
3
|
import { useForkRef, combineProps, useClasses, useEventCallback } from '@ringcentral/spring-base';
|
|
4
4
|
import { useThemeProps } from '@ringcentral/spring-theme';
|
|
5
5
|
import clsx from 'clsx';
|
|
@@ -14,7 +14,11 @@ const VirtualizedMenuList = (props) => {
|
|
|
14
14
|
const actions = useRef(null);
|
|
15
15
|
const handleListActions = useForkRef(actions, actionsProp);
|
|
16
16
|
const listRef = useRef(null);
|
|
17
|
-
|
|
17
|
+
const virtualizedMenuContext = useVirtualizedMenuContext();
|
|
18
|
+
useLayoutEffect(() => {
|
|
19
|
+
if (!virtualizedMenuContext?.open) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
18
22
|
const initialFocus = typeof initialFocusProps === 'function'
|
|
19
23
|
? initialFocusProps()
|
|
20
24
|
: initialFocusProps;
|
|
@@ -24,21 +28,21 @@ const VirtualizedMenuList = (props) => {
|
|
|
24
28
|
else if (typeof initialFocus === 'number') {
|
|
25
29
|
actions.current?.focusByIndex(initialFocus);
|
|
26
30
|
}
|
|
27
|
-
|
|
28
|
-
}, []); // only excute effect when menu list mounted
|
|
31
|
+
}, [virtualizedMenuContext?.open]);
|
|
29
32
|
return (jsx(VirtualizedList, { actions: handleListActions, ...rest, ListProps: combineProps({
|
|
30
33
|
role: 'menu',
|
|
31
34
|
}, rest.ListProps), ref: listRef, totalListHeightChanged: totalListHeightChangedProp, children: children }));
|
|
32
35
|
};
|
|
33
36
|
|
|
37
|
+
const MENU_VERTICAL_PADDING = 8;
|
|
34
38
|
const VirtualizedMenu = forwardRef((inProps, ref) => {
|
|
35
39
|
const props = useThemeProps({ props: inProps, name: 'VirtualizedMenu' });
|
|
36
40
|
const { classes, className, children, open, onClose, data, totalCount, isItemDisabled, VirtualizedListProps, popperActions: popperActionsProp, initialFocus = true, maxHeight, PopperProps, ...rest } = props;
|
|
37
41
|
const popperPaperContentRef = useRef(null);
|
|
38
42
|
const paperContentContainerRef = useRef(null);
|
|
39
|
-
const
|
|
43
|
+
const hasItemsRenderedRef = useRef(false);
|
|
40
44
|
const [waitForHeightCompute, setWaitForHeightCompute] = useState(true);
|
|
41
|
-
const [menuHeight, setMenuHeight] = useState(
|
|
45
|
+
const [menuHeight, setMenuHeight] = useState(MENU_VERTICAL_PADDING * 2);
|
|
42
46
|
const [deferPendingVirtualizedListActions, setDeferPendingVirtualizedListActions,] = useState(true);
|
|
43
47
|
const computedListHeight = useRef(-1);
|
|
44
48
|
const availableHeight = useRef(-1);
|
|
@@ -71,66 +75,25 @@ const VirtualizedMenu = forwardRef((inProps, ref) => {
|
|
|
71
75
|
if (!popperPaperContentRef.current)
|
|
72
76
|
return;
|
|
73
77
|
popperPaperContentRef.current.style.maxHeight = `${availableHeight.current}px`;
|
|
74
|
-
/**
|
|
75
|
-
* Reset the paper content container height to `auto`, otherwise the virtuoso scroller
|
|
76
|
-
* will start misbehaving. We only need to set the height of the container during the
|
|
77
|
-
* initial list height computation to ensure the Popover places it appropriately.
|
|
78
|
-
*/
|
|
79
78
|
if (paperContentContainerRef.current) {
|
|
80
79
|
paperContentContainerRef.current.style.height = `auto`;
|
|
81
80
|
}
|
|
82
81
|
});
|
|
83
82
|
const handleTotalListHeightChanged = useEventCallback((listHeight) => {
|
|
84
|
-
|
|
85
|
-
* As the VirtualizedList has components (Header/Footer used for vertical padding), the
|
|
86
|
-
* first 2 calls to `totalListHeightChanged` after triggering the Menu to open will have
|
|
87
|
-
* only computed the height of those components and not the full list. The next calls
|
|
88
|
-
* will include the actual list height. We ignore this call to prevent the menu from
|
|
89
|
-
* flickering between positions/performing any other unnecessary computations. We also
|
|
90
|
-
* need to know the entire list height to be able to choose the correct placement.
|
|
91
|
-
*
|
|
92
|
-
* If we didn't do this, we'd compute the available height prematurely based on an
|
|
93
|
-
* incorrect initial placement, and the height parameter in further calls to
|
|
94
|
-
* `handleTotalListHeightChanged` would be the adjusted height of the popover for
|
|
95
|
-
* the available space in the viewport and not the actual height of the list. For
|
|
96
|
-
* example, if the user set the `placement` prop to `top` but had a very long list
|
|
97
|
-
* which could not fit above the anchor element, the menu could initially appear
|
|
98
|
-
* above the input despite the fact its best placement is below. The user would
|
|
99
|
-
* then see this placement change when re-opening the menu or scrolling, where the
|
|
100
|
-
* Popover would auto-update the position and then choose the correct placement.
|
|
101
|
-
*/
|
|
102
|
-
if (waitForListHeightComputeCallsCount.current < 2) {
|
|
103
|
-
waitForListHeightComputeCallsCount.current += 1;
|
|
83
|
+
if (!hasItemsRenderedRef.current) {
|
|
104
84
|
return;
|
|
105
85
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
* necessary to ensure the Popover determines the correct amount of space needed for
|
|
110
|
-
* the list. If we set the height directly on the list element it would cause an
|
|
111
|
-
* expensive rerender and if we didn't do either the computed available height
|
|
112
|
-
* for the Popover would not be correct.
|
|
113
|
-
*/
|
|
86
|
+
const adjustedHeight = listHeight + MENU_VERTICAL_PADDING * 2
|
|
87
|
+
;
|
|
88
|
+
computedListHeight.current = adjustedHeight;
|
|
114
89
|
if (paperContentContainerRef.current) {
|
|
115
|
-
paperContentContainerRef.current.style.height = `${
|
|
90
|
+
paperContentContainerRef.current.style.height = `${adjustedHeight}px`;
|
|
116
91
|
}
|
|
117
|
-
// Update the Menu height now we've correctly computed the list height
|
|
118
92
|
updateMenuHeight();
|
|
119
|
-
// Update the Popper position after the list height has been computed
|
|
120
93
|
popperActions.current?.update();
|
|
121
|
-
// No need to wait for the height compute once we have the list height
|
|
122
94
|
if (waitForHeightCompute) {
|
|
123
|
-
/**
|
|
124
|
-
* Perform all pending actions once we know the list height has settled. This is necessary
|
|
125
|
-
* as those pending actions expect the list to have fully rendered before they can be ran.
|
|
126
|
-
*/
|
|
127
95
|
requestAnimationFrame(() => {
|
|
128
96
|
setDeferPendingVirtualizedListActions(false);
|
|
129
|
-
/**
|
|
130
|
-
* Wait for the next repaint to ensure the pending actions have been completed and the height
|
|
131
|
-
* has been computed and painted. If we didn't do this, the menu could flicker if the initial
|
|
132
|
-
* scroll position was set to a value that would cause the list to scroll down.
|
|
133
|
-
*/
|
|
134
97
|
requestAnimationFrame(() => {
|
|
135
98
|
setWaitForHeightCompute(false);
|
|
136
99
|
});
|
|
@@ -138,11 +101,7 @@ const VirtualizedMenu = forwardRef((inProps, ref) => {
|
|
|
138
101
|
}
|
|
139
102
|
});
|
|
140
103
|
const handleAvailableHeightChange = useEventCallback((value) => {
|
|
141
|
-
|
|
142
|
-
* If we haven't yet computed the height of the virtualized list, we need to ignore
|
|
143
|
-
* the available height as the value will be for when the list has not yet fully rendered.
|
|
144
|
-
*/
|
|
145
|
-
if (computedListHeight.current === -1) {
|
|
104
|
+
if (computedListHeight.current === -1 || !hasItemsRenderedRef.current) {
|
|
146
105
|
return;
|
|
147
106
|
}
|
|
148
107
|
availableHeight.current = value;
|
|
@@ -150,34 +109,21 @@ const VirtualizedMenu = forwardRef((inProps, ref) => {
|
|
|
150
109
|
updatePopoverHeight();
|
|
151
110
|
});
|
|
152
111
|
useEffect(() => {
|
|
153
|
-
/**
|
|
154
|
-
* Reset the computed values when the Menu is closed, we'll recompute them when it's reopened
|
|
155
|
-
*/
|
|
156
112
|
if (!open) {
|
|
157
|
-
|
|
158
|
-
computedListHeight.current = -1;
|
|
159
|
-
availableHeight.current = -1;
|
|
113
|
+
hasItemsRenderedRef.current = false;
|
|
160
114
|
}
|
|
161
|
-
/**
|
|
162
|
-
* Hide the menu immediately after being triggered to open to allow time to compute the rendered
|
|
163
|
-
* list height. We need to do this to avoid a potential flicker when the menu first renders, as
|
|
164
|
-
* the virtualized list may not have rendered yet, but its adorning components may have. This may
|
|
165
|
-
* cause the menu to have a different initial placement than it would have after the list has
|
|
166
|
-
* rendered, for example if the user has chosen a preferred `top` placement but the menu cannot
|
|
167
|
-
* actually fit within the space above the anchor element.
|
|
168
|
-
*
|
|
169
|
-
* This is only necessary for the initial render. After the menu has found its correct placement,
|
|
170
|
-
* we can rely on the Popover to auto-update its placement and size as needed in response to list
|
|
171
|
-
* height changes/window resize events.
|
|
172
|
-
*
|
|
173
|
-
* In the `handleTotalListHeightChanged` callback we then reset this flag once we know the total list
|
|
174
|
-
* has actually rendered, so the first place the user sees the menu is in its correct position after
|
|
175
|
-
* all other height computation has been performed.
|
|
176
|
-
*/
|
|
177
115
|
if (open) {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
116
|
+
if (computedListHeight.current !== -1) {
|
|
117
|
+
updateMenuHeight();
|
|
118
|
+
setWaitForHeightCompute(false);
|
|
119
|
+
setDeferPendingVirtualizedListActions(false);
|
|
120
|
+
popperActions.current?.update();
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
setMenuHeight(MENU_VERTICAL_PADDING * 2);
|
|
124
|
+
setWaitForHeightCompute(true);
|
|
125
|
+
setDeferPendingVirtualizedListActions(true);
|
|
126
|
+
}
|
|
181
127
|
if (popperPaperContentRef.current) {
|
|
182
128
|
popperPaperContentRef.current.style.maxHeight = 'none';
|
|
183
129
|
}
|
|
@@ -185,21 +131,24 @@ const VirtualizedMenu = forwardRef((inProps, ref) => {
|
|
|
185
131
|
}, [open]);
|
|
186
132
|
return (jsx(Popover, { bordered: true, PopperProps: { ...PopperProps, padding: popperPadding }, ...rest, open: open, className: clsx(cls('root'), waitForHeightCompute && 'opacity-0'), PopperPaperProps: {
|
|
187
133
|
contentRef: popperPaperContentRef,
|
|
188
|
-
}, onClose: onClose, onAvailableHeightChange: handleAvailableHeightChange, ref: ref,
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
* due to how it uses padding/margin to simulate scrolling. Passing a List
|
|
196
|
-
* wrapper component also doesn't work as the list height computation
|
|
197
|
-
* doesn't account for the padding around the wrapper element.
|
|
198
|
-
*/
|
|
199
|
-
Header: VirtualizedListVerticalPadding,
|
|
200
|
-
Footer: VirtualizedListVerticalPadding,
|
|
201
|
-
},
|
|
134
|
+
}, onClose: onClose, onAvailableHeightChange: handleAvailableHeightChange, ref: ref, motionProps: { variants: undefined }, actions: handlePopperActions, children: jsx("div", { className: cls('paper'), children: jsx("div", { ref: paperContentContainerRef, className: cls('paper-content-container'), children: jsx(VirtualizedMenuContext.Provider, { value: menuContextValue, children: jsx(VirtualizedMenuList, { data: data, totalCount: totalCount, isReady: !deferPendingVirtualizedListActions, isItemDisabled: isItemDisabled, initialFocus: initialFocus, style: { height: menuHeight }, ...combineProps(VirtualizedListProps, {
|
|
135
|
+
ListProps: combineProps(VirtualizedListProps?.ListProps, {
|
|
136
|
+
className: cls('list'),
|
|
137
|
+
style: {
|
|
138
|
+
['--sui-virtualized-menu-vertical-padding']: `${MENU_VERTICAL_PADDING}px`,
|
|
139
|
+
},
|
|
140
|
+
}),
|
|
202
141
|
totalListHeightChanged: handleTotalListHeightChanged,
|
|
142
|
+
itemsRendered: (items) => {
|
|
143
|
+
if (totalCount === 0 ||
|
|
144
|
+
(totalCount === undefined &&
|
|
145
|
+
data !== undefined &&
|
|
146
|
+
data.length === 0) ||
|
|
147
|
+
(items && items.length > 0)) {
|
|
148
|
+
hasItemsRenderedRef.current = true;
|
|
149
|
+
}
|
|
150
|
+
VirtualizedListProps?.itemsRendered?.(items);
|
|
151
|
+
},
|
|
203
152
|
onKeyDown: (e) => {
|
|
204
153
|
if (e.key === 'Tab') {
|
|
205
154
|
e.preventDefault();
|
|
@@ -208,9 +157,6 @@ const VirtualizedMenu = forwardRef((inProps, ref) => {
|
|
|
208
157
|
},
|
|
209
158
|
}), children: children }) }) }) }) }));
|
|
210
159
|
});
|
|
211
|
-
function VirtualizedListVerticalPadding() {
|
|
212
|
-
return jsx("div", { className: "h-2" });
|
|
213
|
-
}
|
|
214
160
|
VirtualizedMenu.displayName = 'SuiVirtualizedMenu';
|
|
215
161
|
|
|
216
162
|
export { VirtualizedMenuContext as V, VirtualizedMenu as a, VirtualizedMenuList as b, useVirtualizedMenuContext as u };
|
package/chunks/getFade.js
CHANGED
|
@@ -16,6 +16,10 @@ const getFade = ({ toggle = true, prefersReducedMotion = false, toggleOnTransiti
|
|
|
16
16
|
transition: prefersReducedMotion
|
|
17
17
|
? motionTransition.instant
|
|
18
18
|
: toggleOffTransition || motionTransition['haste-01-slow'],
|
|
19
|
+
pointerEvents: 'none',
|
|
20
|
+
transitionEnd: {
|
|
21
|
+
pointerEvents: undefined,
|
|
22
|
+
},
|
|
19
23
|
},
|
|
20
24
|
},
|
|
21
25
|
});
|
|
@@ -2,19 +2,12 @@ import { useEffect } from 'react';
|
|
|
2
2
|
import { useWindowContext, useId, useEventCallback } from '@ringcentral/spring-base';
|
|
3
3
|
|
|
4
4
|
const FOCUS_TRAP_STACK = '__SUI_FOCUS_TRAP_STACK__';
|
|
5
|
-
// use global to ensure the work in the same window
|
|
6
5
|
const getFocusTrapStack = (global) => {
|
|
7
|
-
// @ts-ignore
|
|
8
6
|
if (!global[FOCUS_TRAP_STACK]) {
|
|
9
|
-
// @ts-ignore
|
|
10
7
|
global[FOCUS_TRAP_STACK] = [];
|
|
11
8
|
}
|
|
12
|
-
// @ts-ignore
|
|
13
9
|
return global[FOCUS_TRAP_STACK];
|
|
14
10
|
};
|
|
15
|
-
/**
|
|
16
|
-
* Hook to manage focus trap stack for proper layering and focus management
|
|
17
|
-
*/
|
|
18
11
|
const useFocusTrapStack = ({ open, }) => {
|
|
19
12
|
const { globalThis } = useWindowContext();
|
|
20
13
|
const id = useId();
|
|
@@ -30,7 +23,6 @@ const useFocusTrapStack = ({ open, }) => {
|
|
|
30
23
|
stack.splice(index, 1);
|
|
31
24
|
}
|
|
32
25
|
};
|
|
33
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
34
26
|
}, [open]);
|
|
35
27
|
const isEnabled = useEventCallback(() => {
|
|
36
28
|
const stack = getFocusTrapStack(globalThis);
|
|
@@ -12,34 +12,10 @@ const FormField = forwardRef((inProps, ref) => {
|
|
|
12
12
|
});
|
|
13
13
|
FormField.displayName = 'SuiFormField';
|
|
14
14
|
|
|
15
|
-
/**
|
|
16
|
-
* Hook to generate consistent helper text IDs for form field accessibility
|
|
17
|
-
*
|
|
18
|
-
* Follows the pattern: `${id}-helper-text`
|
|
19
|
-
*
|
|
20
|
-
* @param options Configuration options
|
|
21
|
-
* @returns Generated helper text ID or undefined if no helper text
|
|
22
|
-
*
|
|
23
|
-
* @example
|
|
24
|
-
* ```tsx
|
|
25
|
-
* const Select = ({ helperText, FormHelperTextProps, ...props }) => {
|
|
26
|
-
* const id = useId(idProp);
|
|
27
|
-
* const helperTextId = useHelperTextId({ helperText, id, FormHelperTextProps });
|
|
28
|
-
*
|
|
29
|
-
* return (
|
|
30
|
-
* <FormField FormHelperTextProps={{ id: helperTextId, ...FormHelperTextProps }}>
|
|
31
|
-
* <button aria-describedby={helperTextId}>
|
|
32
|
-
* </FormField>
|
|
33
|
-
* );
|
|
34
|
-
* };
|
|
35
|
-
* ```
|
|
36
|
-
*/
|
|
37
15
|
const useHelperTextId = ({ helperText, id, FormHelperTextProps, }) => {
|
|
38
|
-
// Only generate ID if helper text exists
|
|
39
16
|
if (!helperText) {
|
|
40
17
|
return undefined;
|
|
41
18
|
}
|
|
42
|
-
// Use existing ID if provided, otherwise generate standard pattern
|
|
43
19
|
return FormHelperTextProps?.id || `${id}-helper-text`;
|
|
44
20
|
};
|
|
45
21
|
|
|
@@ -14,26 +14,19 @@ const useListNavigation = (props) => {
|
|
|
14
14
|
const skipEnforceFocusRef = useRef(false);
|
|
15
15
|
const focusList = () => {
|
|
16
16
|
skipEnforceFocusRef.current = true;
|
|
17
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
18
17
|
listRef.current.focus();
|
|
19
18
|
};
|
|
20
19
|
const focusTabBoundary = () => {
|
|
21
20
|
skipEnforceFocusRef.current = true;
|
|
22
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
23
21
|
sentinelTabBoundaryRef.current.focus();
|
|
24
22
|
};
|
|
25
23
|
const itemActions = useMemo(() => ({
|
|
26
|
-
// Prevent cache invalidation
|
|
27
|
-
// eslint-disable-next-line sonarjs/no-identical-functions
|
|
28
24
|
onTab: () => {
|
|
29
25
|
skipEnforceFocusRef.current = true;
|
|
30
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
31
26
|
sentinelTabBoundaryRef.current.focus();
|
|
32
27
|
},
|
|
33
|
-
// eslint-disable-next-line sonarjs/no-identical-functions
|
|
34
28
|
onShiftTab: () => {
|
|
35
29
|
skipEnforceFocusRef.current = true;
|
|
36
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
37
30
|
listRef.current.focus();
|
|
38
31
|
},
|
|
39
32
|
updateFocusedItem: (el) => {
|
|
@@ -48,9 +41,7 @@ const useListNavigation = (props) => {
|
|
|
48
41
|
});
|
|
49
42
|
useImperativeHandle(actions, () => ({
|
|
50
43
|
focus: focusFirstItem,
|
|
51
|
-
}),
|
|
52
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
53
|
-
[]);
|
|
44
|
+
}), []);
|
|
54
45
|
const sentinelFocusHandler = (e) => {
|
|
55
46
|
if (e.target === e.currentTarget) {
|
|
56
47
|
const skipEnforceFocus = skipEnforceFocusRef.current;
|
|
@@ -63,9 +54,7 @@ const useListNavigation = (props) => {
|
|
|
63
54
|
};
|
|
64
55
|
const searchAndFocusItemHandler = (searchElementOption) => {
|
|
65
56
|
return searchAndFocusItemHandlerProp(searchElementOption, {
|
|
66
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
67
57
|
sentinelEnd: sentinelArrowNavRef.current,
|
|
68
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
69
58
|
list: listRef.current,
|
|
70
59
|
});
|
|
71
60
|
};
|
|
@@ -96,7 +85,6 @@ const useListNavigation = (props) => {
|
|
|
96
85
|
}
|
|
97
86
|
}
|
|
98
87
|
else {
|
|
99
|
-
// cover case about all item are disabled
|
|
100
88
|
if (e.target === e.currentTarget && key === 'Tab' && !e.shiftKey) {
|
|
101
89
|
focusTabBoundary();
|
|
102
90
|
}
|
|
@@ -125,16 +113,16 @@ const useListNavigation = (props) => {
|
|
|
125
113
|
return (jsxs(ListNavigationContext.Provider, { value: itemActions, children: [items, jsx("div", { "aria-hidden": "true", ref: sentinelArrowNavRef })] }));
|
|
126
114
|
};
|
|
127
115
|
const renderTabBoundary = () => {
|
|
128
|
-
return (jsx("div", {
|
|
129
|
-
// make sentinel end always render in scroller viewport center to
|
|
130
|
-
// prevent scroll when focus to sentinel end
|
|
131
|
-
style: { position: 'fixed', bottom: '50%' }, ref: sentinelTabBoundaryRef, tabIndex: 0, onFocus: sentinelFocusHandler }));
|
|
116
|
+
return (jsx("div", { style: { position: 'fixed', bottom: '50%' }, ref: sentinelTabBoundaryRef, tabIndex: 0, onFocus: sentinelFocusHandler }));
|
|
132
117
|
};
|
|
133
118
|
return { renderItems, renderTabBoundary, getListProps, listRef };
|
|
134
119
|
};
|
|
135
120
|
const isUnfocusable = (el) => el.matches('.sui-disabled, :disabled, hr, [role="separator"], [disabled]');
|
|
136
121
|
const defaultSearchAndFocusItem = (searchElementOption, helperElements) => {
|
|
137
122
|
const { list, sentinelEnd } = helperElements;
|
|
123
|
+
if (list.firstElementChild === sentinelEnd) {
|
|
124
|
+
return { focused: false };
|
|
125
|
+
}
|
|
138
126
|
const getFirstItem = () => {
|
|
139
127
|
const firstItem = list.firstElementChild;
|
|
140
128
|
if (firstItem === sentinelEnd) {
|