@ringcentral/spring-ui 1.11.1 → 1.11.2

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 (121) hide show
  1. package/Autocomplete.js +2 -0
  2. package/Dropdown.js +1 -0
  3. package/ListItem.js +1 -0
  4. package/ListItemText.js +8 -3
  5. package/MenuHeader.js +4 -1
  6. package/MenuItem.js +1 -0
  7. package/MenuItemText.js +1 -0
  8. package/MenuList.js +1 -0
  9. package/Option.js +1 -0
  10. package/Select.js +1 -0
  11. package/SingleFilter.js +2 -0
  12. package/SortableListItem.js +1 -0
  13. package/SortableVirtualizedList.js +1 -0
  14. package/SplitButton.js +1 -0
  15. package/SubMenu.js +2 -0
  16. package/SwipeableDrawer.js +16 -18
  17. package/TablePagination.js +2 -0
  18. package/Tabs.js +2 -0
  19. package/TrayMenu.js +1 -0
  20. package/VirtualizedList.js +4 -3
  21. package/VirtualizedMenu.js +1 -0
  22. package/chunks/MenuItemText.js +2 -1
  23. package/chunks/Modal.js +132 -8
  24. package/chunks/VirtualizedMenu.js +2 -0
  25. package/chunks/hasContent.js +3 -0
  26. package/chunks/useAnimationFrame.js +15 -0
  27. package/chunks/useMenuItemSelect.js +3 -1
  28. package/index.js +2 -0
  29. package/internal/hooks/index.d.ts +1 -0
  30. package/internal/hooks/useAnimationFrame.d.ts +4 -0
  31. package/internal/utils/hasContent.d.ts +2 -0
  32. package/{src/internal → internal}/utils/index.d.ts +1 -0
  33. package/package.json +4 -4
  34. package/src/Accordion/Accordion.d.ts +1 -1
  35. package/src/AccordionHeader/AccordionHeader.d.ts +1 -1
  36. package/src/Announcement/Announcement.d.ts +1 -1
  37. package/src/Autocomplete/SuggestionList/SuggestionListItem.d.ts +1 -1
  38. package/src/Autocomplete/SuggestionList/utils/useSuggestionList.d.ts +1 -1
  39. package/src/Autocomplete/useAutocomplete.d.ts +63 -39
  40. package/src/Autocomplete/useAutocompleteTag.d.ts +57 -33
  41. package/src/Backdrop/Backdrop.d.ts +1 -1
  42. package/src/Badge/Badge.d.ts +1 -2
  43. package/src/BottomNavigation/BottomNavigationGroup/BottomNavigationGroup.d.ts +1 -1
  44. package/src/CircularProgressIndicator/CircularProgressIndicator.d.ts +1 -1
  45. package/src/DatePicker/DatePicker.d.ts +1 -1
  46. package/src/DatePicker/Day.d.ts +1 -1
  47. package/src/DatePicker/Year.d.ts +1 -1
  48. package/src/Dialer/DialTextField/DialTextField.d.ts +1 -1
  49. package/src/Dialog/Dialog.d.ts +4 -4
  50. package/src/Drawer/Drawer.d.ts +1 -1
  51. package/src/EmptyState/EmptyState.d.ts +1 -1
  52. package/src/FormField/FormField.d.ts +1 -1
  53. package/src/FormLabel/FormLabel.d.ts +1 -1
  54. package/src/Icon/Icon.d.ts +1 -1
  55. package/src/IconButton/IconButtonLabel.d.ts +1 -1
  56. package/src/LinearProgressIndicator/LinearProgressIndicator.d.ts +1 -1
  57. package/src/List/List.d.ts +1 -1
  58. package/src/ListItem/ListItem.d.ts +1 -1
  59. package/src/ListItemText/ListItemText.d.ts +1 -1
  60. package/src/ListNavigation/useListNavigation.d.ts +2 -2
  61. package/src/Menu/Menu.d.ts +1 -1
  62. package/src/MenuActions/MenuActions.d.ts +2 -2
  63. package/src/MenuDivider/MenuDivider.d.ts +1 -1
  64. package/src/MenuFooter/MenuFooter.d.ts +1 -1
  65. package/src/MenuHeader/MenuHeader.d.ts +1 -1
  66. package/src/MenuItem/MenuItem.d.ts +1 -1
  67. package/src/MenuItemText/MenuItemText.d.ts +1 -1
  68. package/src/Modal/InnerModal.d.ts +2 -16
  69. package/src/Modal/InnerModal.type.d.ts +1 -0
  70. package/src/Modal/Modal.d.ts +2 -21
  71. package/src/Modal/ModalContext.d.ts +3 -0
  72. package/src/Modal/OverlayBranchRegistry.d.ts +8 -0
  73. package/src/Modal/useOverlayBranch.d.ts +8 -0
  74. package/src/NestedMenuContext/MenuOverlayGroupContext.d.ts +1 -1
  75. package/src/Option/Option.d.ts +1 -1
  76. package/src/PageHeader/PageHeader.d.ts +5 -5
  77. package/src/PickerTextField/PickerTextField.d.ts +1 -1
  78. package/src/Popover/Popover.d.ts +1 -1
  79. package/src/Popper/Popper.d.ts +1 -1
  80. package/src/PopperPaper/PopperPaper.d.ts +1 -1
  81. package/src/RadioGroup/RadioGroup.d.ts +1 -1
  82. package/src/Rating/Rating.d.ts +1 -1
  83. package/src/Rating/RatingItem.d.ts +1 -1
  84. package/src/Rating/utils.d.ts +2 -3
  85. package/src/SingleFilter/FilterButton/FilterButton.d.ts +1 -1
  86. package/src/SingleFilter/SingleFilter.d.ts +1 -1
  87. package/src/Skeleton/Skeleton.d.ts +1 -1
  88. package/src/Slider/Slider.d.ts +1 -1
  89. package/src/Slider/SliderThumb.d.ts +1 -2
  90. package/src/Snackbar/Snackbar.d.ts +1 -1
  91. package/src/Snackbar/SnackbarContent/SnackbarContent.d.ts +1 -1
  92. package/src/SortableListItem/SortableListItem.d.ts +1 -1
  93. package/src/SortableListItem/SortableListItemOverlay.d.ts +1 -1
  94. package/src/SplitButton/SplitButton.d.ts +1 -1
  95. package/src/StatusIndicator/StatusIndicator.d.ts +1 -2
  96. package/src/StepConnector/StepConnector.d.ts +1 -1
  97. package/src/StepContent/StepContent.d.ts +1 -1
  98. package/src/StepIcon/StepIcon.d.ts +1 -1
  99. package/src/StepLabel/StepLabel.d.ts +1 -1
  100. package/src/SubMenu/PopperMenu.d.ts +1 -1
  101. package/src/SubMenu/SubMenu.d.ts +1 -1
  102. package/src/SwipeableDrawer/SwipeableDrawer.d.ts +1 -1
  103. package/src/Tab/Tab.d.ts +1 -1
  104. package/src/TabPanel/TabPanel.d.ts +1 -1
  105. package/src/TableFooter/TableFooter.d.ts +1 -1
  106. package/src/Tabs/TabMoreMenu.d.ts +1 -1
  107. package/src/Tabs/TabScrollButton.d.ts +1 -1
  108. package/src/Tabs/Tabs.d.ts +1 -1
  109. package/src/Tag/Tag.d.ts +1 -1
  110. package/src/TextField/TextField.d.ts +1 -1
  111. package/src/Textarea/Textarea.d.ts +1 -1
  112. package/src/TimePicker/NumberPicker.d.ts +1 -1
  113. package/src/TimePicker/TimeButton.d.ts +1 -1
  114. package/src/TimePicker/ToggleText.d.ts +1 -1
  115. package/src/Tray/Tray.d.ts +1 -1
  116. package/src/Tray/TrayPanel.d.ts +1 -1
  117. package/src/TrayMenu/TrayMenu.d.ts +1 -1
  118. package/src/TrayMenu/TrayMenuItem.d.ts +1 -1
  119. package/src/VirtualizedList/VirtuosoComponents.d.ts +4 -4
  120. package/src/VisuallyHidden/VisuallyHidden.d.ts +1 -1
  121. /package/{src/internal → internal}/utils/composeEventHandlers.d.ts +0 -0
package/Autocomplete.js CHANGED
@@ -14,6 +14,7 @@ import { g as getFade } from './chunks/getFade.js';
14
14
  import { C as Chip } from './chunks/Chip.js';
15
15
  import { Popper } from './Popper.js';
16
16
  import { T as TextField } from './chunks/TextField.js';
17
+ import { u as useAnimationFrame } from './chunks/useAnimationFrame.js';
17
18
  import uniqueId from 'lodash/uniqueId';
18
19
  import './chunks/useMotionSafeTransition.js';
19
20
  import '@mui/base';
@@ -1090,6 +1091,7 @@ const useAutocomplete = ({ multiple: multipleProp, variant, inputValue: inputVal
1090
1091
  const keepHighlightedIndexRef = useRef(false);
1091
1092
  const popperElementRef = useRef(null);
1092
1093
  const { sleep, getSleeping } = useSleep();
1094
+ const { requestAnimationFrame } = useAnimationFrame();
1093
1095
  const multiple = isAutocomplete ? false : multipleProp;
1094
1096
  const inputContainerScrollToBottom = () => {
1095
1097
  requestAnimationFrame(() => {
package/Dropdown.js CHANGED
@@ -27,6 +27,7 @@ import './chunks/Backdrop.js';
27
27
  import './Popper.js';
28
28
  import './chunks/PopperPaper.js';
29
29
  import '@ringcentral/spring-icon';
30
+ import './chunks/useAnimationFrame.js';
30
31
  import './chunks/useNestedMenuItem.js';
31
32
  import './ListNavigation.js';
32
33
  import 'react-virtuoso';
package/ListItem.js CHANGED
@@ -9,6 +9,7 @@ import './chunks/useListNavigation.js';
9
9
  import 'tabbable';
10
10
  import './VirtualizedList.js';
11
11
  import 'react-virtuoso';
12
+ import './chunks/useAnimationFrame.js';
12
13
  import './chunks/List.js';
13
14
  import 'framer-motion';
14
15
  import './chunks/Icon.js';
package/ListItemText.js CHANGED
@@ -2,6 +2,7 @@ import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import { forwardRef } from 'react';
3
3
  import { useClasses } from '@ringcentral/spring-base';
4
4
  import { useThemeProps } from '@ringcentral/spring-theme';
5
+ import { h as hasContent } from './chunks/hasContent.js';
5
6
 
6
7
  var ListItemText$1 = {"sui-list-item-text-root":"sui-list-item-text-root","sui-list-item-text-primary-text":"sui-list-item-text-primary-text","sui-list-item-text-secondary-text":"sui-list-item-text-secondary-text","sui-list-item-text-primary":"sui-list-item-text-primary","sui-list-item-text-primary-primary-text":"sui-list-item-text-primary-primary-text","sui-list-item-text-secondary":"sui-list-item-text-secondary","sui-list-item-text-secondary-primary-text":"sui-list-item-text-secondary-primary-text"};
7
8
 
@@ -9,9 +10,13 @@ const ListItemText = forwardRef((inProps, ref) => {
9
10
  const props = useThemeProps({ props: inProps, name: 'ListItemText' });
10
11
  const { classes, className, primary, secondary, primaryText, secondaryText, variant = 'primary', children, ...rest } = props;
11
12
  const cls = useClasses('list-item-text', classes, className);
12
- const primaryContent = primary || primaryText || children;
13
- const secondaryContent = secondary || secondaryText;
14
- return (jsxs("div", { className: cls('root', variant), ...rest, ref: ref, children: [jsx("span", { className: cls('primary-text', `${variant}-primary-text`), children: primaryContent }), secondaryContent && (jsx("span", { className: cls('secondary-text', `${variant}-secondary-text`), children: secondaryContent }))] }));
13
+ const primaryContent = hasContent(primary)
14
+ ? primary
15
+ : hasContent(primaryText)
16
+ ? primaryText
17
+ : children;
18
+ const secondaryContent = hasContent(secondary) ? secondary : secondaryText;
19
+ return (jsxs("div", { className: cls('root', variant), ...rest, ref: ref, children: [jsx("span", { className: cls('primary-text', `${variant}-primary-text`), children: primaryContent }), hasContent(secondaryContent) && (jsx("span", { className: cls('secondary-text', `${variant}-secondary-text`), children: secondaryContent }))] }));
15
20
  });
16
21
  ListItemText.displayName = 'SuiListItemText';
17
22
 
package/MenuHeader.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
2
  import { forwardRef } from 'react';
3
3
  import { useThemeProps, useClassesWithMode } from '@ringcentral/spring-theme';
4
+ import { h as hasContent } from './chunks/hasContent.js';
4
5
  import { M as MenuDivider } from './chunks/MenuDivider.js';
5
6
  import './chunks/Divider.js';
6
7
  import '@ringcentral/spring-base';
@@ -11,7 +12,9 @@ const MenuHeader = forwardRef((inProps, ref) => {
11
12
  const props = useThemeProps({ props: inProps, name: 'MenuHeader' });
12
13
  const { classes, className, children, start, end, divider = true, ...rest } = props;
13
14
  const cls = useClassesWithMode('menu-header', classes, className);
14
- return (jsxs(Fragment, { children: [jsxs("div", { className: cls('root'), ...rest, ref: ref, children: [start && jsx("div", { className: cls('start'), children: start }), end && jsx("div", { className: cls('end'), children: end }), typeof children === 'string' ? (jsx("span", { className: cls('title'), title: children, children: children })) : (children)] }), divider && jsx(MenuDivider, {})] }));
15
+ const hasStart = hasContent(start);
16
+ const hasEnd = hasContent(end);
17
+ return (jsxs(Fragment, { children: [jsxs("div", { className: cls('root'), ...rest, ref: ref, children: [hasStart && jsx("div", { className: cls('start'), children: start }), hasEnd && jsx("div", { className: cls('end'), children: end }), typeof children === 'string' ? (jsx("span", { className: cls('title'), title: children, children: children })) : (children)] }), divider && jsx(MenuDivider, {})] }));
15
18
  });
16
19
  MenuHeader.displayName = 'SuiMenuHeader';
17
20
 
package/MenuItem.js CHANGED
@@ -5,6 +5,7 @@ import '@ringcentral/spring-base';
5
5
  import '@ringcentral/spring-icon';
6
6
  import '@ringcentral/spring-theme';
7
7
  import './chunks/Icon.js';
8
+ import './chunks/useAnimationFrame.js';
8
9
  import './chunks/useNestedParentMenu.js';
9
10
  import './chunks/useNestedMenuItem.js';
10
11
  import './VirtualizedList.js';
package/MenuItemText.js CHANGED
@@ -3,6 +3,7 @@ import 'react/jsx-runtime';
3
3
  import 'react';
4
4
  import '@ringcentral/spring-base';
5
5
  import '@ringcentral/spring-theme';
6
+ import './chunks/hasContent.js';
6
7
 
7
8
  var MenuItemText = {"sui-menu-item-text-root":"sui-menu-item-text-root","sui-menu-item-text-primary-text":"sui-menu-item-text-primary-text","sui-menu-item-text-info-text":"sui-menu-item-text-info-text","sui-compact":"sui-compact"};
8
9
 
package/MenuList.js CHANGED
@@ -24,6 +24,7 @@ import './Popper.js';
24
24
  import './chunks/PopperPaper.js';
25
25
  import './VirtualizedList.js';
26
26
  import 'react-virtuoso';
27
+ import './chunks/useAnimationFrame.js';
27
28
  import '@ringcentral/spring-icon';
28
29
  import './chunks/useNestedMenuItem.js';
29
30
  import './ListNavigation.js';
package/Option.js CHANGED
@@ -9,6 +9,7 @@ import './chunks/Menu.js';
9
9
  import './VirtualizedList.js';
10
10
  import '@ringcentral/spring-icon';
11
11
  import './chunks/Icon.js';
12
+ import './chunks/useAnimationFrame.js';
12
13
  import './chunks/useNestedParentMenu.js';
13
14
  import './chunks/useNestedMenuItem.js';
14
15
  import './ListNavigation.js';
package/Select.js CHANGED
@@ -24,6 +24,7 @@ import './Popper.js';
24
24
  import './chunks/PopperPaper.js';
25
25
  import './chunks/useMenuItemSelect.js';
26
26
  import '@ringcentral/spring-icon';
27
+ import './chunks/useAnimationFrame.js';
27
28
  import './chunks/useNestedMenuItem.js';
28
29
  import './VirtualizedList.js';
29
30
  import 'react-virtuoso';
package/SingleFilter.js CHANGED
@@ -31,10 +31,12 @@ import './chunks/useNestedParentMenu.js';
31
31
  import './chunks/Popover.js';
32
32
  import './chunks/getGrow.js';
33
33
  import '@ringcentral/spring-icon';
34
+ import './chunks/useAnimationFrame.js';
34
35
  import './chunks/useNestedMenuItem.js';
35
36
  import './ListNavigation.js';
36
37
  import 'react-virtuoso';
37
38
  import './chunks/List.js';
39
+ import './chunks/hasContent.js';
38
40
 
39
41
  var FilterButton$1 = {"sui-filter-button-root":"sui-filter-button-root","sui-focus-visible":"sui-focus-visible","sui-selected":"sui-selected","sui-disabled":"sui-disabled"};
40
42
 
@@ -15,6 +15,7 @@ import './chunks/useListNavigation.js';
15
15
  import 'tabbable';
16
16
  import './VirtualizedList.js';
17
17
  import 'react-virtuoso';
18
+ import './chunks/useAnimationFrame.js';
18
19
  import './chunks/List.js';
19
20
  import './chunks/useMotionSafeTransition.js';
20
21
  import './chunks/usePrefersReducedMotion.js';
@@ -6,6 +6,7 @@ import { forwardRef, useMemo } from 'react';
6
6
  import { VirtualizedList } from './VirtualizedList.js';
7
7
  import '@ringcentral/spring-base';
8
8
  import 'react-virtuoso';
9
+ import './chunks/useAnimationFrame.js';
9
10
  import './chunks/List.js';
10
11
  import './chunks/useListNavigation.js';
11
12
  import 'tabbable';
package/SplitButton.js CHANGED
@@ -35,6 +35,7 @@ import './chunks/useListNavigation.js';
35
35
  import 'tabbable';
36
36
  import './VirtualizedList.js';
37
37
  import 'react-virtuoso';
38
+ import './chunks/useAnimationFrame.js';
38
39
  import '@ringcentral/spring-icon';
39
40
  import './chunks/useNestedMenuItem.js';
40
41
  import './ListNavigation.js';
package/SubMenu.js CHANGED
@@ -22,12 +22,14 @@ import './chunks/usePrefersReducedMotion.js';
22
22
  import './chunks/getFade.js';
23
23
  import './chunks/useFocusTrapStack.js';
24
24
  import './chunks/Backdrop.js';
25
+ import './chunks/useAnimationFrame.js';
25
26
  import './ListNavigation.js';
26
27
  import './chunks/Popover.js';
27
28
  import './chunks/getGrow.js';
28
29
  import './chunks/PopperPaper.js';
29
30
  import 'react-virtuoso';
30
31
  import './chunks/List.js';
32
+ import './chunks/hasContent.js';
31
33
 
32
34
  var PopperMenu$1 = {"sui-popper-menu-root":"sui-popper-menu-root","sui-popper-menu-paper":"sui-popper-menu-paper"};
33
35
 
@@ -7,6 +7,7 @@ import { D as Drawer } from './chunks/Drawer.js';
7
7
  import { D as DragHandle } from './chunks/DragHandle.js';
8
8
  import { useMotionValue, animate, useTransform } from 'framer-motion';
9
9
  import { rubberbandIfOutOfBounds, useDrag } from '@use-gesture/react';
10
+ import { u as useAnimationFrame } from './chunks/useAnimationFrame.js';
10
11
  import { ResizeObserver } from '@juggle/resize-observer';
11
12
  import './chunks/Icon.js';
12
13
  import './chunks/usePrefersReducedMotion.js';
@@ -48,8 +49,7 @@ const observerOptions = {
48
49
  box: 'border-box',
49
50
  };
50
51
  function useElementSizeObserver(ref, { enabled, resizeSourceRef, }) {
51
- const { externalWindow, globalThis } = useWindowContext();
52
- const win = externalWindow ?? globalThis;
52
+ const { requestAnimationFrame, cancelAnimationFrame } = useAnimationFrame();
53
53
  const [size, setSize] = useState(0);
54
54
  const handleResize = useCallback((entries) => {
55
55
  const entry = entries?.[0];
@@ -74,8 +74,6 @@ function useElementSizeObserver(ref, { enabled, resizeSourceRef, }) {
74
74
  if (!enabled) {
75
75
  return;
76
76
  }
77
- const rAF = win.requestAnimationFrame.bind(win);
78
- const cAF = win.cancelAnimationFrame.bind(win);
79
77
  let resizeObserver = null;
80
78
  let rafId = 0;
81
79
  let initialMeasurementRafId = 0;
@@ -85,7 +83,7 @@ function useElementSizeObserver(ref, { enabled, resizeSourceRef, }) {
85
83
  return;
86
84
  resizeObserver = new ResizeObserver(handleResize);
87
85
  resizeObserver.observe(el, observerOptions);
88
- initialMeasurementRafId = rAF(() => {
86
+ initialMeasurementRafId = requestAnimationFrame(() => {
89
87
  const initial = Math.max(el.scrollHeight, el.offsetHeight, el.getBoundingClientRect().height);
90
88
  if (initial > 0) {
91
89
  setSize(initial);
@@ -97,31 +95,33 @@ function useElementSizeObserver(ref, { enabled, resizeSourceRef, }) {
97
95
  startObserving();
98
96
  }
99
97
  else {
100
- rafId = rAF(waitForElement);
98
+ rafId = requestAnimationFrame(waitForElement);
101
99
  }
102
100
  };
103
101
  if (ref.current) {
104
102
  startObserving();
105
103
  }
106
104
  else {
107
- rafId = rAF(waitForElement);
105
+ rafId = requestAnimationFrame(waitForElement);
108
106
  }
109
107
  return () => {
110
108
  if (rafId)
111
- cAF(rafId);
112
- if (initialMeasurementRafId)
113
- cAF(initialMeasurementRafId);
109
+ cancelAnimationFrame(rafId);
110
+ if (initialMeasurementRafId) {
111
+ cancelAnimationFrame(initialMeasurementRafId);
112
+ }
114
113
  if (resizeObserver) {
115
114
  resizeObserver.disconnect();
116
115
  }
117
116
  };
118
- }, [ref, handleResize, enabled, win]);
117
+ }, [ref, handleResize, enabled, requestAnimationFrame, cancelAnimationFrame]);
119
118
  return enabled ? size : 0;
120
119
  }
121
120
 
122
121
  function useMaxHeight(registerReady) {
123
- const { externalWindow, globalThis } = useWindowContext();
124
- const win = externalWindow ?? globalThis;
122
+ const { externalWindow, globalThis: contextGlobal } = useWindowContext();
123
+ const win = externalWindow ?? contextGlobal;
124
+ const { requestAnimationFrame, cancelAnimationFrame } = useAnimationFrame();
125
125
  const setReady = useMemo(() => {
126
126
  return registerReady ? registerReady('maxHeight') : undefined;
127
127
  }, [registerReady]);
@@ -132,13 +132,11 @@ function useMaxHeight(registerReady) {
132
132
  maxReadyCalledRef.current = false;
133
133
  }, [setReady]);
134
134
  useLayoutEffect(() => {
135
- const rAF = win.requestAnimationFrame.bind(win);
136
- const cAF = win.cancelAnimationFrame.bind(win);
137
135
  const handleResize = () => {
138
136
  if (raf.current) {
139
137
  return;
140
138
  }
141
- raf.current = rAF(() => {
139
+ raf.current = requestAnimationFrame(() => {
142
140
  if (raf.current !== 0) {
143
141
  setMaxHeight(win.innerHeight);
144
142
  raf.current = 0;
@@ -153,9 +151,9 @@ function useMaxHeight(registerReady) {
153
151
  }
154
152
  return () => {
155
153
  win.removeEventListener('resize', handleResize);
156
- cAF(raf.current);
154
+ cancelAnimationFrame(raf.current);
157
155
  };
158
- }, [setReady, win]);
156
+ }, [setReady, win, requestAnimationFrame, cancelAnimationFrame]);
159
157
  return maxHeight;
160
158
  }
161
159
  function usePreservedHeight(currentHeight) {
@@ -22,7 +22,9 @@ import './chunks/Modal.js';
22
22
  import './chunks/useFocusTrapStack.js';
23
23
  import './chunks/Backdrop.js';
24
24
  import './chunks/PopperPaper.js';
25
+ import './chunks/hasContent.js';
25
26
  import './chunks/useMenuItemSelect.js';
27
+ import './chunks/useAnimationFrame.js';
26
28
  import './chunks/useNestedParentMenu.js';
27
29
  import './chunks/useNestedMenuItem.js';
28
30
  import './VirtualizedList.js';
package/Tabs.js CHANGED
@@ -36,10 +36,12 @@ import './chunks/useFocusTrapStack.js';
36
36
  import './chunks/Backdrop.js';
37
37
  import './Popper.js';
38
38
  import './chunks/PopperPaper.js';
39
+ import './chunks/useAnimationFrame.js';
39
40
  import './chunks/useNestedMenuItem.js';
40
41
  import './ListNavigation.js';
41
42
  import 'react-virtuoso';
42
43
  import './chunks/List.js';
44
+ import './chunks/hasContent.js';
43
45
  import 'clsx';
44
46
 
45
47
  const TabMenuItem = forwardRef((props, ref) => {
package/TrayMenu.js CHANGED
@@ -24,6 +24,7 @@ import './Popper.js';
24
24
  import './chunks/PopperPaper.js';
25
25
  import './chunks/useMotionSafeTransition.js';
26
26
  import '@ringcentral/spring-icon';
27
+ import './chunks/useAnimationFrame.js';
27
28
  import './chunks/useNestedMenuItem.js';
28
29
  import './ListNavigation.js';
29
30
  import 'react-virtuoso';
@@ -1,8 +1,9 @@
1
1
  import { createContext, useContext, forwardRef, isValidElement, useRef, useState, useImperativeHandle, useEffect } from 'react';
2
2
  import { jsx } from 'react/jsx-runtime';
3
- import { useForkRef, useWindowContext, useVirtuosoExternalWindow, useEventCallback, logInDev } from '@ringcentral/spring-base';
3
+ import { useForkRef, useVirtuosoExternalWindow, useEventCallback, logInDev } from '@ringcentral/spring-base';
4
4
  import { useThemeProps } from '@ringcentral/spring-theme';
5
5
  import { Virtuoso } from 'react-virtuoso';
6
+ import { u as useAnimationFrame } from './chunks/useAnimationFrame.js';
6
7
  import { L as List } from './chunks/List.js';
7
8
  import './chunks/useListNavigation.js';
8
9
  import 'tabbable';
@@ -85,7 +86,7 @@ const VirtualizedList = forwardRef((inProps, ref) => {
85
86
  const handleVirtuosoRef = useForkRef(virtuosoRef, virtuosoActions);
86
87
  const initialFocusItemByIndexPromiseRef = useRef(null);
87
88
  const itemRenderedPromiseRef = useRef(null);
88
- const { globalThis: contextWindow } = useWindowContext();
89
+ const { requestAnimationFrame } = useAnimationFrame();
89
90
  const externalWindowProps = useVirtuosoExternalWindow();
90
91
  const isItemRendered = (index) => {
91
92
  const { startIndex, endIndex } = listRangeRef.current;
@@ -96,7 +97,7 @@ const VirtualizedList = forwardRef((inProps, ref) => {
96
97
  new Promise((resolve) => {
97
98
  initialFocusItemByIndexPromiseRef.current = resolve;
98
99
  }).then(() => {
99
- contextWindow.requestAnimationFrame(() => focusByIndexAction(index));
100
+ requestAnimationFrame(() => focusByIndexAction(index));
100
101
  });
101
102
  }
102
103
  else {
@@ -4,6 +4,7 @@ import 'react';
4
4
  import '@ringcentral/spring-base';
5
5
  import '@ringcentral/spring-theme';
6
6
  import 'clsx';
7
+ import './chunks/useAnimationFrame.js';
7
8
  import './chunks/Popover.js';
8
9
  import '@floating-ui/react-dom';
9
10
  import 'framer-motion';
@@ -2,6 +2,7 @@ import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import { forwardRef } from 'react';
3
3
  import { getTitle } from '@ringcentral/spring-base';
4
4
  import { useThemeProps, useClassesWithMode } from '@ringcentral/spring-theme';
5
+ import { h as hasContent } from './hasContent.js';
5
6
 
6
7
  const MenuItemText = forwardRef((inProps, ref) => {
7
8
  const props = useThemeProps({ props: inProps, name: 'MenuItemText' });
@@ -9,7 +10,7 @@ const MenuItemText = forwardRef((inProps, ref) => {
9
10
  const cls = useClassesWithMode('menu-item-text', classes, className);
10
11
  const primaryContent = primary ?? primaryText ?? children;
11
12
  const secondaryContent = info ?? infoText;
12
- return (jsxs("div", { className: cls('root'), ...rest, ref: ref, children: [jsx("span", { className: cls('primary-text'), title: getTitle(primaryContent), children: primaryContent }), secondaryContent && (jsx("span", { className: cls('info-text'), title: getTitle(secondaryContent), children: secondaryContent }))] }));
13
+ return (jsxs("div", { className: cls('root'), ...rest, ref: ref, children: [jsx("span", { className: cls('primary-text'), title: getTitle(primaryContent), children: primaryContent }), hasContent(secondaryContent) && (jsx("span", { className: cls('info-text'), title: getTitle(secondaryContent), children: secondaryContent }))] }));
13
14
  });
14
15
  MenuItemText.displayName = 'SuiMenuItemText';
15
16
 
package/chunks/Modal.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
- import { createContext, useContext, forwardRef, useState, useEffect } from 'react';
2
+ import { createContext, useContext, useRef, useCallback, useLayoutEffect, forwardRef, useState, useEffect } from 'react';
3
3
  import { useAriaHideOutside, useForkRef, useClasses, useEventCallback, useBodyScrollLock, useWindowContext } from '@ringcentral/spring-base';
4
4
  import { useThemeProps, useTheme } from '@ringcentral/spring-theme';
5
5
  import { FocusTrap, Portal } from '@mui/base';
@@ -13,15 +13,130 @@ import { B as Backdrop } from './Backdrop.js';
13
13
  const ModalContext = createContext(null);
14
14
  const useModalContext = () => useContext(ModalContext);
15
15
 
16
+ const createOverlayBranchRegistry = () => {
17
+ const branchRefCounts = new Map();
18
+ const listeners = new Set();
19
+ const notify = (node, isRegistered) => {
20
+ for (const listener of [...listeners]) {
21
+ listener(node, isRegistered);
22
+ }
23
+ };
24
+ return {
25
+ getBranches: () => new Set(branchRefCounts.keys()),
26
+ register: (node) => {
27
+ const currentCount = branchRefCounts.get(node) ?? 0;
28
+ branchRefCounts.set(node, currentCount + 1);
29
+ if (currentCount === 0) {
30
+ notify(node, true);
31
+ }
32
+ let isCleanedUp = false;
33
+ return () => {
34
+ if (isCleanedUp) {
35
+ return;
36
+ }
37
+ isCleanedUp = true;
38
+ const currentCount = branchRefCounts.get(node);
39
+ if (!currentCount) {
40
+ return;
41
+ }
42
+ if (currentCount > 1) {
43
+ branchRefCounts.set(node, currentCount - 1);
44
+ return;
45
+ }
46
+ branchRefCounts.delete(node);
47
+ notify(node, false);
48
+ };
49
+ },
50
+ subscribe: (listener) => {
51
+ listeners.add(listener);
52
+ return () => {
53
+ listeners.delete(listener);
54
+ };
55
+ },
56
+ };
57
+ };
58
+ const useOverlayBranchRegistry = () => {
59
+ const registryRef = useRef();
60
+ if (!registryRef.current) {
61
+ registryRef.current = createOverlayBranchRegistry();
62
+ }
63
+ return registryRef.current;
64
+ };
65
+
66
+ const useOverlayBranch = ({ active, registry, }) => {
67
+ const nodeRef = useRef(null);
68
+ const registrationRef = useRef(null);
69
+ const syncRegistration = useCallback((node) => {
70
+ const registration = registrationRef.current;
71
+ const shouldKeepRegistration = registration &&
72
+ active &&
73
+ registration.node === node &&
74
+ registration.registry === registry;
75
+ if (shouldKeepRegistration) {
76
+ return;
77
+ }
78
+ registration?.unregister();
79
+ registrationRef.current = null;
80
+ if (active && node && registry) {
81
+ registrationRef.current = {
82
+ node,
83
+ registry,
84
+ unregister: registry.register(node),
85
+ };
86
+ }
87
+ }, [active, registry]);
88
+ const setBranchRef = useCallback((node) => {
89
+ nodeRef.current = node;
90
+ syncRegistration(node);
91
+ }, [syncRegistration]);
92
+ useLayoutEffect(() => {
93
+ syncRegistration(nodeRef.current);
94
+ }, [syncRegistration]);
95
+ useLayoutEffect(() => () => {
96
+ registrationRef.current?.unregister();
97
+ registrationRef.current = null;
98
+ }, []);
99
+ return setBranchRef;
100
+ };
101
+ const useOverlayBranchConsumer = (registry, listener) => {
102
+ useLayoutEffect(() => {
103
+ const unsubscribe = registry.subscribe(listener);
104
+ for (const node of registry.getBranches()) {
105
+ listener(node, true);
106
+ }
107
+ return () => {
108
+ unsubscribe();
109
+ for (const node of registry.getBranches()) {
110
+ listener(node, false);
111
+ }
112
+ };
113
+ }, [listener, registry]);
114
+ };
115
+
16
116
  const InnerModal = forwardRef((props, ref) => {
17
- const { hideBackdrop: hideBackdropProp, children, motionProps, disableBackdropClick: disableBackdropClickProp, onBackdropClick, disableEscapeKeyDown: disableEscapeKeyDownProp, onEscapeKeyDown, onClose, onKeyDown, disableAutoFocus, disableEnforceFocus, disableRestoreFocus, classes, className, backdropProps, open, isEnabled, blocking = true, ...rest } = props;
117
+ const { hideBackdrop: hideBackdropProp, children, motionProps, disableBackdropClick: disableBackdropClickProp, onBackdropClick, disableEscapeKeyDown: disableEscapeKeyDownProp, onEscapeKeyDown, onClose, onKeyDown, disableAutoFocus, disableEnforceFocus, disableRestoreFocus, classes, className, backdropProps, open, isEnabled, blocking = true, shouldUseInert: shouldUseInertProp, ...rest } = props;
118
+ const parentModalContext = useModalContext();
119
+ const ownOverlayBranchRegistry = useOverlayBranchRegistry();
120
+ const shouldUseInert = shouldUseInertProp ?? parentModalContext?.shouldUseInert ?? false;
18
121
  const hideBackdrop = hideBackdropProp ?? !blocking;
19
122
  const disableBackdropClick = disableBackdropClickProp ?? !blocking;
20
123
  const disableEscapeKeyDown = disableEscapeKeyDownProp ?? !blocking;
21
- const { ariaHideOutsideRef, ariaHideEnabled } = useAriaHideOutside({
22
- enable: blocking,
124
+ const { ariaHideOutsideRef, ariaHideEnabled, setAriaHideOutsideTarget } = useAriaHideOutside({
125
+ enable: blocking && open,
126
+ shouldUseInert,
127
+ });
128
+ useOverlayBranchConsumer(ownOverlayBranchRegistry, setAriaHideOutsideTarget);
129
+ const parentOverlayBranchRegistry = parentModalContext?.overlayBranchRegistry;
130
+ const overlayBranchRegistry = ariaHideEnabled
131
+ ? ownOverlayBranchRegistry
132
+ : parentOverlayBranchRegistry;
133
+ const isOverlayBranch = !blocking && open && parentOverlayBranchRegistry != null;
134
+ const ariaHideEnabledForChildren = ariaHideEnabled || parentModalContext?.ariaHideEnabled === true;
135
+ const overlayBranchRef = useOverlayBranch({
136
+ active: isOverlayBranch,
137
+ registry: parentOverlayBranchRegistry,
23
138
  });
24
- const handleRef = useForkRef(ref, ariaHideOutsideRef);
139
+ const handleRef = useForkRef(ref, ariaHideOutsideRef, overlayBranchRef);
25
140
  const cls = useClasses('modal', classes, className);
26
141
  const { onClick: externalOnClick, ...restBackdropProps } = backdropProps || {};
27
142
  const handleBackdropClick = useEventCallback((event) => {
@@ -34,7 +149,11 @@ const InnerModal = forwardRef((props, ref) => {
34
149
  onBackdropClick?.(event);
35
150
  onClose?.(event, 'backdropClick');
36
151
  });
37
- return (jsx(ModalContext.Provider, { value: { ariaHideEnabled }, children: jsxs(motion.div, { ...rest, ...motionProps, role: "presentation", className: cls('root', { 'non-blocking': !blocking }), onKeyDown: (e) => {
152
+ return (jsx(ModalContext.Provider, { value: {
153
+ ariaHideEnabled: ariaHideEnabledForChildren,
154
+ overlayBranchRegistry,
155
+ shouldUseInert,
156
+ }, children: jsxs(motion.div, { ...rest, ...motionProps, role: "presentation", className: cls('root', { 'non-blocking': !blocking }), onKeyDown: (e) => {
38
157
  onKeyDown?.(e);
39
158
  if (!disableEscapeKeyDown &&
40
159
  e.key === 'Escape' &&
@@ -48,7 +167,12 @@ InnerModal.displayName = 'SuiInnerModal';
48
167
 
49
168
  const Modal = forwardRef((inProps, ref) => {
50
169
  const props = useThemeProps({ props: inProps, name: 'Modal' });
51
- const { children, open, container: containerProp, disablePortal, onExitComplete, disableBackdropAnimation, motionProps, disableScrollLock: disableScrollLockProp, blocking = true, ...rest } = props;
170
+ const { children, open, container: containerProp, disablePortal, onExitComplete, disableBackdropAnimation, motionProps, disableScrollLock: disableScrollLockProp, blocking = true, shouldUseInert: themeFallbackShouldUseInert, ...rest } = props;
171
+ const parentModalContext = useModalContext();
172
+ const shouldUseInert = inProps.shouldUseInert ??
173
+ parentModalContext?.shouldUseInert ??
174
+ themeFallbackShouldUseInert ??
175
+ false;
52
176
  const disableScrollLock = disableScrollLockProp ?? !blocking;
53
177
  const [shouldRender, setShouldRender] = useState(open);
54
178
  const [modalElement, setModalElement] = useState(null);
@@ -78,7 +202,7 @@ const Modal = forwardRef((inProps, ref) => {
78
202
  setShouldRender(false);
79
203
  }
80
204
  };
81
- return shouldRender ? (jsx(Portal, { disablePortal: disablePortal, container: container, children: jsx("div", { ...scopeProps, children: jsx(InnerModal, { ...rest, ref: handleRef, open: open, blocking: blocking, isEnabled: isEnabled, motionProps: {
205
+ return shouldRender ? (jsx(Portal, { disablePortal: disablePortal, container: container, children: jsx("div", { ...scopeProps, children: jsx(InnerModal, { ...rest, ref: handleRef, open: open, blocking: blocking, shouldUseInert: shouldUseInert, isEnabled: isEnabled, motionProps: {
82
206
  ...(motionProps ?? getFade({ prefersReducedMotion, toggle: open })),
83
207
  onAnimationComplete,
84
208
  }, children: children }) }) })) : null;
@@ -3,6 +3,7 @@ import { createContext, useContext, useRef, useLayoutEffect, forwardRef, useStat
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';
6
+ import { u as useAnimationFrame } from './useAnimationFrame.js';
6
7
  import { P as Popover } from './Popover.js';
7
8
  import { VirtualizedList } from '../VirtualizedList.js';
8
9
 
@@ -58,6 +59,7 @@ const VirtualizedMenu = forwardRef((inProps, ref) => {
58
59
  : (padding ?? 16);
59
60
  const popperActions = useRef(null);
60
61
  const handlePopperActions = useForkRef(popperActions, popperActionsProp);
62
+ const { requestAnimationFrame } = useAnimationFrame();
61
63
  const menuContextValue = useMemo(() => {
62
64
  return { open };
63
65
  }, [open]);
@@ -0,0 +1,3 @@
1
+ const hasContent = (content) => Boolean(content) || content === 0;
2
+
3
+ export { hasContent as h };
@@ -0,0 +1,15 @@
1
+ import { useMemo } from 'react';
2
+ import { useWindowContext } from '@ringcentral/spring-base';
3
+
4
+ function useAnimationFrame() {
5
+ const { externalWindow, globalThis: contextGlobal } = useWindowContext();
6
+ return useMemo(() => {
7
+ const contextWindow = externalWindow ?? contextGlobal;
8
+ return {
9
+ requestAnimationFrame: (callback) => contextWindow.requestAnimationFrame(callback),
10
+ cancelAnimationFrame: (handle) => contextWindow.cancelAnimationFrame(handle),
11
+ };
12
+ }, [externalWindow, contextGlobal]);
13
+ }
14
+
15
+ export { useAnimationFrame as u };
@@ -4,6 +4,7 @@ import { useFocusVisible, useActive, useForkRef, useId, useHover, useEventCallba
4
4
  import { CheckBoldMd } from '@ringcentral/spring-icon';
5
5
  import { useThemeProps, useClassesWithMode } from '@ringcentral/spring-theme';
6
6
  import { I as Icon } from './Icon.js';
7
+ import { u as useAnimationFrame } from './useAnimationFrame.js';
7
8
  import './useNestedParentMenu.js';
8
9
  import { u as useNestedMenuItem } from './useNestedMenuItem.js';
9
10
  import { useVirtualizedItemPropsContext } from '../VirtualizedList.js';
@@ -124,6 +125,7 @@ const MenuItem = forwardRef((inProps, ref) => {
124
125
  const cls = useClassesWithMode('menu-item', classes, className);
125
126
  const vlItemProps = useVirtualizedItemPropsContext();
126
127
  const isInVlRef = useRef(Boolean(vlItemProps));
128
+ const { requestAnimationFrame } = useAnimationFrame();
127
129
  const useMenuItemHook = (() => {
128
130
  if (isInVlRef.current) {
129
131
  return useVirtualizedMenuItem;
@@ -177,7 +179,7 @@ const MenuItem = forwardRef((inProps, ref) => {
177
179
  });
178
180
  });
179
181
  }
180
- }, [autoFocus]);
182
+ }, [autoFocus, requestAnimationFrame]);
181
183
  return (jsx("div", { className: cls('root', {
182
184
  selectable,
183
185
  selected,
package/index.js CHANGED
@@ -179,6 +179,8 @@ import 'lodash/isString';
179
179
  import '@floating-ui/react-dom';
180
180
  import 'tabbable';
181
181
  import 'lodash/clamp';
182
+ import './chunks/hasContent.js';
183
+ import './chunks/useAnimationFrame.js';
182
184
  import 'dayjs';
183
185
  import '@date-io/dayjs';
184
186
  import '@dnd-kit/utilities';
@@ -0,0 +1 @@
1
+ export * from './useAnimationFrame';
@@ -0,0 +1,4 @@
1
+ export declare function useAnimationFrame(): {
2
+ requestAnimationFrame: (callback: FrameRequestCallback) => number;
3
+ cancelAnimationFrame: (handle: number) => void;
4
+ };
@@ -0,0 +1,2 @@
1
+ import type { ReactNode } from 'react';
2
+ export declare const hasContent: (content: ReactNode) => boolean;