@ringcentral/spring-ui 1.11.2 → 1.13.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.
Files changed (241) hide show
  1. package/Accordion.js +90 -34
  2. package/AccordionHeader.js +72 -20
  3. package/Alert.js +120 -28
  4. package/Animation.js +2 -45
  5. package/Announcement.js +46 -35
  6. package/Autocomplete.js +1011 -580
  7. package/Avatar.js +134 -73
  8. package/AvatarGroup.js +50 -7
  9. package/Backdrop.js +45 -7
  10. package/Badge.js +77 -15
  11. package/Block.js +34 -12
  12. package/BlockHeader.js +55 -11
  13. package/BottomNavigation.js +181 -65
  14. package/BottomNavigationItem.js +93 -30
  15. package/Button.js +160 -24
  16. package/CallButton.js +53 -31
  17. package/Checkbox.js +88 -26
  18. package/Chip.js +126 -26
  19. package/CircularProgressIndicator.js +80 -8
  20. package/ClickAwayListener.js +4 -1
  21. package/ComponentsProps.js +1 -0
  22. package/DatePicker.js +611 -190
  23. package/DateUtilsContext.js +43 -25
  24. package/Dialer.js +576 -250
  25. package/Dialog.js +100 -45
  26. package/Divider.js +43 -7
  27. package/DragHandle.js +32 -6
  28. package/Drawer.js +117 -19
  29. package/Dropdown.js +154 -74
  30. package/EmptyState.js +63 -11
  31. package/FabButton.js +51 -17
  32. package/FocusTrap.js +109 -12
  33. package/FormField.js +106 -8
  34. package/FormLabel.js +81 -7
  35. package/Icon.js +1 -8
  36. package/IconButton.js +142 -26
  37. package/IconButtonGroup.js +35 -12
  38. package/InlineEditable.js +98 -44
  39. package/LinearProgressIndicator.js +73 -24
  40. package/Link.js +40 -11
  41. package/List.js +54 -9
  42. package/ListItem.js +152 -23
  43. package/ListItemText.js +44 -16
  44. package/ListNavigation.js +272 -20
  45. package/Menu.js +139 -23
  46. package/MenuActions.js +37 -12
  47. package/MenuDivider.js +34 -8
  48. package/MenuFooter.js +36 -12
  49. package/MenuHeader.js +54 -15
  50. package/MenuItem.js +402 -33
  51. package/MenuItemText.js +51 -8
  52. package/MenuList.js +87 -34
  53. package/Modal.js +345 -16
  54. package/NestedMenuContext.js +183 -11
  55. package/Option.js +32 -34
  56. package/Overlap.js +54 -7
  57. package/PageHeader.js +62 -24
  58. package/PickerTextField.js +156 -33
  59. package/Popover.js +262 -21
  60. package/Popper.js +130 -77
  61. package/PopperPaper.js +54 -8
  62. package/Portal.js +6 -1
  63. package/Radio.js +65 -21
  64. package/RadioGroup.js +56 -17
  65. package/Rating.js +223 -87
  66. package/Select.js +387 -41
  67. package/SingleFilter.js +148 -77
  68. package/Skeleton.js +68 -17
  69. package/Slider.js +168 -69
  70. package/Snackbar.js +122 -59
  71. package/SortableList.js +32 -12
  72. package/SortableListDndContext.js +69 -22
  73. package/SortableListItem.js +92 -47
  74. package/SortableVirtualizedList.js +52 -28
  75. package/SplitButton.js +124 -86
  76. package/Squircle.js +4 -7
  77. package/StatusIndicator.js +51 -9
  78. package/Step.js +63 -38
  79. package/StepButton.js +51 -23
  80. package/StepConnector.js +48 -8
  81. package/StepContent.js +68 -25
  82. package/StepIcon.js +90 -9
  83. package/StepLabel.js +90 -14
  84. package/Stepper.js +65 -23
  85. package/SubMenu.js +203 -99
  86. package/SwipeableDrawer.js +439 -194
  87. package/Switch.js +70 -23
  88. package/Tab.js +120 -57
  89. package/TabContext.js +59 -15
  90. package/TabPanel.js +40 -13
  91. package/Table.js +60 -17
  92. package/TableBody.js +42 -12
  93. package/TableCell.js +84 -50
  94. package/TableContainer.js +32 -10
  95. package/TableFooter.js +38 -10
  96. package/TableHead.js +49 -15
  97. package/TablePagination.js +153 -77
  98. package/TableRow.js +60 -21
  99. package/Tabs.js +593 -268
  100. package/Tag.js +51 -16
  101. package/Text.js +68 -37
  102. package/TextField.js +209 -29
  103. package/Textarea.js +51 -40
  104. package/TimePicker.js +490 -230
  105. package/Tooltip.js +48 -23
  106. package/Tray.js +237 -13
  107. package/TrayMenu.js +62 -41
  108. package/VirtualizedList.js +208 -109
  109. package/VirtualizedMenu.js +359 -29
  110. package/VisuallyHidden.js +29 -6
  111. package/chunks/1250.js +98 -0
  112. package/chunks/1294.js +126 -0
  113. package/chunks/2956.js +18 -0
  114. package/chunks/4476.js +460 -0
  115. package/chunks/4491.js +10 -0
  116. package/chunks/4535.js +364 -0
  117. package/chunks/5047.js +3 -0
  118. package/chunks/6335.js +24 -0
  119. package/chunks/7279.js +10 -0
  120. package/chunks/8011.js +8 -0
  121. package/chunks/8307.js +56 -0
  122. package/chunks/8467.js +8 -0
  123. package/chunks/8809.js +8 -0
  124. package/chunks/{RadioGroup.context.js → 9551.js} +12 -6
  125. package/chunks/987.js +8 -0
  126. package/index.css +2624 -2416
  127. package/index.js +245 -193
  128. package/internal/utils/index.d.ts +1 -0
  129. package/internal/utils/setRef.d.ts +2 -0
  130. package/package.json +8 -8
  131. package/src/Alert/Alert.type.d.ts +2 -1
  132. package/src/Animation/components/Fade/Fade.d.ts +4 -2
  133. package/src/Animation/components/Grow/Grow.d.ts +4 -2
  134. package/src/Animation/components/ShowHideEye/ShowHideEye.d.ts +1 -1
  135. package/src/Animation/components/SlideIn/SlideIn.d.ts +4 -2
  136. package/src/Animation/components/SlideIn/getSlideIn.d.ts +1 -1
  137. package/src/Animation/hooks/useMotionSafeTransition/useMotionSafeTransition.d.ts +2 -0
  138. package/src/Autocomplete/SuggestionList/SuggestionList.d.ts +1 -1
  139. package/src/Autocomplete/useAutocomplete.d.ts +18 -18
  140. package/src/Autocomplete/useAutocompleteTag.d.ts +18 -18
  141. package/src/Badge/Badge.d.ts +2 -1
  142. package/src/Button/Button.classes.d.ts +1 -1
  143. package/src/ComponentsProps.d.ts +111 -110
  144. package/src/DatePicker/DatePickerDataAttributes.d.ts +11 -0
  145. package/src/DatePicker/utils/DatePickerAriaLabelUtils.d.ts +2 -1
  146. package/src/DatePicker/utils/DatePickerUtils.d.ts +1 -1
  147. package/src/Dialer/DialDelete/DialDelete.d.ts +2 -2
  148. package/src/Dialer/DialPad/DialPad.d.ts +2 -2
  149. package/src/Dialer/Dialer.d.ts +4 -2
  150. package/src/Dropdown/Dropdown.type.d.ts +2 -2
  151. package/src/InlineEditable/InlineEditable.type.d.ts +2 -1
  152. package/src/ListNavigation/useListNavigation.d.ts +3 -3
  153. package/src/MenuActions/MenuActions.d.ts +2 -2
  154. package/src/MenuItem/MenuItem.type.d.ts +1 -0
  155. package/src/MenuItem/useMenuItem.d.ts +1 -1
  156. package/src/MenuItem/useVirtualizedMenuItem.d.ts +1 -1
  157. package/src/MenuList/MenuList.type.d.ts +1 -1
  158. package/src/MenuList/MenuListContext.d.ts +2 -3
  159. package/src/Modal/Modal.type.d.ts +1 -0
  160. package/src/NestedMenuContext/MenuOverlayGroupContext.d.ts +2 -2
  161. package/src/Popover/Popover.classes.d.ts +1 -1
  162. package/src/Popover/Popover.internal.d.ts +8 -0
  163. package/src/Popover/Popover.type.d.ts +1 -0
  164. package/src/Popper/Popper.type.d.ts +10 -7
  165. package/src/Rating/utils.d.ts +3 -2
  166. package/src/Select/Select.type.d.ts +7 -5
  167. package/src/Slider/Slider.d.ts +2 -2
  168. package/src/Slider/SliderThumb.d.ts +2 -1
  169. package/src/Squircle/Squircle.d.ts +1 -1
  170. package/src/StatusIndicator/StatusIndicator.d.ts +2 -1
  171. package/src/SubMenu/PopperMenu.type.d.ts +4 -1
  172. package/src/Table/Table.type.d.ts +3 -0
  173. package/src/Table/TableContext.d.ts +3 -0
  174. package/src/Table/TableRowContext.d.ts +7 -0
  175. package/src/Table/index.d.ts +1 -0
  176. package/src/TableCell/TableCell.classes.d.ts +1 -1
  177. package/src/TableFooter/TableFooter.classes.d.ts +1 -1
  178. package/src/TableFooter/TableFooter.type.d.ts +1 -0
  179. package/src/TableHead/TableHead.classes.d.ts +1 -1
  180. package/src/TableHead/TableHead.type.d.ts +1 -0
  181. package/src/TableRow/TableRow.type.d.ts +2 -0
  182. package/chunks/AccordionContext.js +0 -6
  183. package/chunks/Alert.js +0 -48
  184. package/chunks/AvatarGroup.js +0 -22
  185. package/chunks/Backdrop.js +0 -18
  186. package/chunks/Badge.js +0 -32
  187. package/chunks/BottomNavigationItem.js +0 -36
  188. package/chunks/Button.js +0 -88
  189. package/chunks/Chip.js +0 -73
  190. package/chunks/CircularProgressIndicator.js +0 -36
  191. package/chunks/Divider.js +0 -19
  192. package/chunks/DragHandle.js +0 -11
  193. package/chunks/Drawer.js +0 -32
  194. package/chunks/ExpandCollapseCaret.js +0 -24
  195. package/chunks/FormLabel.js +0 -27
  196. package/chunks/Icon.js +0 -25
  197. package/chunks/IconButtonLabel.js +0 -68
  198. package/chunks/List.js +0 -22
  199. package/chunks/ListItem.js +0 -83
  200. package/chunks/Menu.js +0 -61
  201. package/chunks/MenuDivider.js +0 -14
  202. package/chunks/MenuItemText.js +0 -17
  203. package/chunks/MenuList.js +0 -46
  204. package/chunks/Modal.js +0 -212
  205. package/chunks/Overlap.js +0 -25
  206. package/chunks/PickerTextField.js +0 -85
  207. package/chunks/Popover.js +0 -53
  208. package/chunks/PopperPaper.js +0 -15
  209. package/chunks/Select.js +0 -220
  210. package/chunks/ShowHideEye.js +0 -56
  211. package/chunks/SlideIn.js +0 -19
  212. package/chunks/SortableArrow.js +0 -73
  213. package/chunks/Squircle.js +0 -31
  214. package/chunks/StatusIndicator.js +0 -20
  215. package/chunks/StepConnector.js +0 -21
  216. package/chunks/StepIcon.js +0 -43
  217. package/chunks/StepLabel.js +0 -29
  218. package/chunks/StepperContext.js +0 -9
  219. package/chunks/TableContext.js +0 -6
  220. package/chunks/Tablelvl2Context.js +0 -6
  221. package/chunks/TabsContext.js +0 -6
  222. package/chunks/TextField.js +0 -110
  223. package/chunks/Tooltip.js +0 -217
  224. package/chunks/VirtualizedMenu.js +0 -164
  225. package/chunks/VisuallyHidden.js +0 -12
  226. package/chunks/getFade.js +0 -27
  227. package/chunks/getGrow.js +0 -70
  228. package/chunks/getSlideIn.js +0 -30
  229. package/chunks/hasContent.js +0 -3
  230. package/chunks/useAnimationFrame.js +0 -15
  231. package/chunks/useFocusTrapStack.js +0 -36
  232. package/chunks/useHelperTextId.js +0 -22
  233. package/chunks/useListNavigation.js +0 -199
  234. package/chunks/useMenuItemSelect.js +0 -273
  235. package/chunks/useMotionSafeTransition.js +0 -9
  236. package/chunks/useNestedMenuItem.js +0 -27
  237. package/chunks/useNestedParentMenu.js +0 -113
  238. package/chunks/usePrefersReducedMotion.js +0 -36
  239. package/chunks/useTooltipForceHide.js +0 -27
  240. package/chunks/useTrayNavigate.js +0 -150
  241. package/chunks/withTooltip.js +0 -15
package/MenuList.js CHANGED
@@ -1,34 +1,87 @@
1
- export { M as MenuList } from './chunks/MenuList.js';
2
- export { e as MenuListContext, f as useMenuListContext } from './chunks/useMenuItemSelect.js';
3
- import 'react/jsx-runtime';
4
- import 'react';
5
- import '@ringcentral/spring-base';
6
- import '@ringcentral/spring-theme';
7
- import './chunks/List.js';
8
- import './chunks/useListNavigation.js';
9
- import 'tabbable';
10
- import './chunks/Menu.js';
11
- import './chunks/useNestedParentMenu.js';
12
- import './chunks/Popover.js';
13
- import '@floating-ui/react-dom';
14
- import 'framer-motion';
15
- import './chunks/Icon.js';
16
- import './chunks/usePrefersReducedMotion.js';
17
- import './chunks/getGrow.js';
18
- import './chunks/Modal.js';
19
- import '@mui/base';
20
- import './chunks/getFade.js';
21
- import './chunks/useFocusTrapStack.js';
22
- import './chunks/Backdrop.js';
23
- import './Popper.js';
24
- import './chunks/PopperPaper.js';
25
- import './VirtualizedList.js';
26
- import 'react-virtuoso';
27
- import './chunks/useAnimationFrame.js';
28
- import '@ringcentral/spring-icon';
29
- import './chunks/useNestedMenuItem.js';
30
- import './ListNavigation.js';
31
-
32
- var MenuList = {"sui-menu-list-root":"sui-menu-list-root"};
33
-
34
- export { MenuList as menuListStyle };
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { forwardRef, useLayoutEffect, useMemo, useRef } from "react";
3
+ import { useClasses, useForkRef, useWindowContext } from "@ringcentral/spring-base";
4
+ import { useThemeProps } from "@ringcentral/spring-theme";
5
+ import { List as List_List } from "./List.js";
6
+ import { useMenuContext } from "./Menu.js";
7
+ import { MenuItemSelectContext, MenuListContext, useMenuItemSelect } from "./MenuItem.js";
8
+
9
+
10
+
11
+
12
+
13
+ // extracted by css-extract-rspack-plugin
14
+ /* export default */ var MenuList = ({"sui-menu-list-root":"sui-menu-list-root"});
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+ const MenuList_MenuList = /*#__PURE__*/ forwardRef((inProps, ref)=>{
25
+ const props = useThemeProps({
26
+ props: inProps,
27
+ name: 'MenuList'
28
+ });
29
+ const { classes, className, children, widget, selectMode = 'single', nowrap, value: valueProp, onChange, autoFocus: autoFocusProp, ...rest } = props;
30
+ const menuContext = useMenuContext();
31
+ const autoFocus = Boolean(autoFocusProp ?? menuContext?.autoFocus);
32
+ const cls = useClasses('menu-list', classes, className);
33
+ const menuListContextValue = useMemo(()=>({
34
+ nowrap
35
+ }), [
36
+ nowrap
37
+ ]);
38
+ const { contextValue } = useMenuItemSelect({
39
+ widget,
40
+ selectMode,
41
+ value: valueProp,
42
+ onChange,
43
+ autoFocus
44
+ });
45
+ const actions = useRef(null);
46
+ const listRef = useRef(null);
47
+ const handleListRef = useForkRef(listRef, ref);
48
+ const { document } = useWindowContext();
49
+ useLayoutEffect(()=>{
50
+ if (autoFocus && // ensure item can auto focus correctly
51
+ !listRef.current?.contains(document?.activeElement ?? null)) {
52
+ actions.current?.focus();
53
+ }
54
+ }, [
55
+ autoFocus
56
+ ]);
57
+ // Use appropriate role and ARIA attributes based on widget type
58
+ const listRole = widget === 'select' ? 'listbox' : 'menu';
59
+ const listboxProps = widget === 'select' ? {
60
+ 'aria-multiselectable': selectMode === 'multiple'
61
+ } : {};
62
+ return /*#__PURE__*/ jsx(List_List, {
63
+ className: cls('root'),
64
+ role: listRole,
65
+ ...listboxProps,
66
+ ...rest,
67
+ ref: handleListRef,
68
+ actions: actions,
69
+ children: /*#__PURE__*/ jsx(MenuListContext.Provider, {
70
+ value: menuListContextValue,
71
+ children: /*#__PURE__*/ jsx(MenuItemSelectContext.Provider, {
72
+ value: contextValue,
73
+ children: children
74
+ })
75
+ })
76
+ });
77
+ });
78
+ MenuList_MenuList.displayName = 'SuiMenuList';
79
+
80
+
81
+
82
+
83
+
84
+
85
+
86
+ export { MenuList as menuListStyle, MenuList_MenuList as MenuList };
87
+ export { MenuListContext, useMenuListContext } from "./MenuItem.js";
package/Modal.js CHANGED
@@ -1,16 +1,345 @@
1
- export { I as InnerModal, M as Modal, a as ModalContext, u as useModalContext } from './chunks/Modal.js';
2
- import 'react/jsx-runtime';
3
- import 'react';
4
- import '@ringcentral/spring-base';
5
- import '@ringcentral/spring-theme';
6
- import '@mui/base';
7
- import 'framer-motion';
8
- import './chunks/Icon.js';
9
- import './chunks/usePrefersReducedMotion.js';
10
- import './chunks/getFade.js';
11
- import './chunks/useFocusTrapStack.js';
12
- import './chunks/Backdrop.js';
13
-
14
- var Modal = {"sui-modal-root":"sui-modal-root","sui-modal-non-blocking":"sui-modal-non-blocking","sui-backdrop-root":"sui-backdrop-root"};
15
-
16
- export { Modal as modalStyles };
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { createContext, forwardRef, useCallback, useContext, useEffect, useLayoutEffect, useRef, useState } from "react";
3
+ import { motion } from "framer-motion";
4
+ import { useAriaHideOutside, useBodyScrollLock, useClasses, useEventCallback, useForkRef, useWindowContext } from "@ringcentral/spring-base";
5
+ import { FocusTrap } from "@mui/base";
6
+ import { useTheme, useThemeProps } from "@ringcentral/spring-theme";
7
+ import { Backdrop as Backdrop_Backdrop } from "./Backdrop.js";
8
+ import { Portal } from "./Portal.js";
9
+ import { getFade } from "./chunks/4476.js";
10
+ import { useFocusTrapStack } from "./FocusTrap.js";
11
+ import { usePrefersReducedMotion } from "./chunks/1294.js";
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+ const ModalContext = createContext(null);
21
+ const useModalContext = ()=>useContext(ModalContext);
22
+
23
+
24
+
25
+ const createOverlayBranchRegistry = ()=>{
26
+ const branchRefCounts = new Map();
27
+ const listeners = new Set();
28
+ const notify = (node, isRegistered)=>{
29
+ for (const listener of [
30
+ ...listeners
31
+ ]){
32
+ listener(node, isRegistered);
33
+ }
34
+ };
35
+ return {
36
+ getBranches: ()=>new Set(branchRefCounts.keys()),
37
+ register: (node)=>{
38
+ const currentCount = branchRefCounts.get(node) ?? 0;
39
+ branchRefCounts.set(node, currentCount + 1);
40
+ if (currentCount === 0) {
41
+ notify(node, true);
42
+ }
43
+ let isCleanedUp = false;
44
+ return ()=>{
45
+ if (isCleanedUp) {
46
+ return;
47
+ }
48
+ isCleanedUp = true;
49
+ const currentCount = branchRefCounts.get(node);
50
+ if (!currentCount) {
51
+ return;
52
+ }
53
+ if (currentCount > 1) {
54
+ branchRefCounts.set(node, currentCount - 1);
55
+ return;
56
+ }
57
+ branchRefCounts.delete(node);
58
+ notify(node, false);
59
+ };
60
+ },
61
+ subscribe: (listener)=>{
62
+ listeners.add(listener);
63
+ return ()=>{
64
+ listeners.delete(listener);
65
+ };
66
+ }
67
+ };
68
+ };
69
+ const useOverlayBranchRegistry = ()=>{
70
+ const registryRef = useRef();
71
+ if (!registryRef.current) {
72
+ registryRef.current = createOverlayBranchRegistry();
73
+ }
74
+ return registryRef.current;
75
+ };
76
+
77
+
78
+
79
+ /**
80
+ * Registers a logical overlay branch with its owner, including owner changes,
81
+ * portal node replacement, deactivation, and unmount cleanup.
82
+ */ const useOverlayBranch = ({ active, registry })=>{
83
+ const nodeRef = useRef(null);
84
+ const registrationRef = useRef(null);
85
+ const syncRegistration = useCallback((node)=>{
86
+ const registration = registrationRef.current;
87
+ const shouldKeepRegistration = registration && active && registration.node === node && registration.registry === registry;
88
+ if (shouldKeepRegistration) {
89
+ return;
90
+ }
91
+ registration?.unregister();
92
+ registrationRef.current = null;
93
+ if (active && node && registry) {
94
+ registrationRef.current = {
95
+ node,
96
+ registry,
97
+ unregister: registry.register(node)
98
+ };
99
+ }
100
+ }, [
101
+ active,
102
+ registry
103
+ ]);
104
+ const setBranchRef = useCallback((node)=>{
105
+ nodeRef.current = node;
106
+ syncRegistration(node);
107
+ }, [
108
+ syncRegistration
109
+ ]);
110
+ useLayoutEffect(()=>{
111
+ syncRegistration(nodeRef.current);
112
+ }, [
113
+ syncRegistration
114
+ ]);
115
+ useLayoutEffect(()=>()=>{
116
+ registrationRef.current?.unregister();
117
+ registrationRef.current = null;
118
+ }, []);
119
+ return setBranchRef;
120
+ };
121
+ /**
122
+ * Connects one policy consumer to a registry. It subscribes before replaying a
123
+ * snapshot of existing branches so reentrant registrations are not missed.
124
+ * Cleanup removes every currently registered branch from the consumer.
125
+ */ const useOverlayBranchConsumer = (registry, listener)=>{
126
+ useLayoutEffect(()=>{
127
+ const unsubscribe = registry.subscribe(listener);
128
+ for (const node of registry.getBranches()){
129
+ listener(node, true);
130
+ }
131
+ return ()=>{
132
+ unsubscribe();
133
+ for (const node of registry.getBranches()){
134
+ listener(node, false);
135
+ }
136
+ };
137
+ }, [
138
+ listener,
139
+ registry
140
+ ]);
141
+ };
142
+
143
+
144
+
145
+
146
+
147
+
148
+
149
+
150
+
151
+
152
+ const InnerModal = /*#__PURE__*/ forwardRef((props, ref)=>{
153
+ 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;
154
+ const parentModalContext = useModalContext();
155
+ const ownOverlayBranchRegistry = useOverlayBranchRegistry();
156
+ const shouldUseInert = shouldUseInertProp ?? parentModalContext?.shouldUseInert ?? false;
157
+ // Centralized `blocking` defaults: when callers omit these, derive from
158
+ // `blocking`. Explicit values (including `false`) always win.
159
+ const hideBackdrop = hideBackdropProp ?? !blocking;
160
+ const disableBackdropClick = disableBackdropClickProp ?? !blocking;
161
+ const disableEscapeKeyDown = disableEscapeKeyDownProp ?? !blocking;
162
+ const { ariaHideOutsideRef, ariaHideEnabled, setAriaHideOutsideTarget } = useAriaHideOutside({
163
+ enable: blocking && open,
164
+ shouldUseInert
165
+ });
166
+ useOverlayBranchConsumer(ownOverlayBranchRegistry, setAriaHideOutsideTarget);
167
+ // Forward the nearest active blocking owner through non-blocking layers.
168
+ const parentOverlayBranchRegistry = parentModalContext?.overlayBranchRegistry;
169
+ const overlayBranchRegistry = ariaHideEnabled ? ownOverlayBranchRegistry : parentOverlayBranchRegistry;
170
+ // Propagate outside hiding so nested Poppers stay in the available branch.
171
+ const ariaHideEnabledForChildren = ariaHideEnabled || parentModalContext?.ariaHideEnabled === true;
172
+ // Register an open non-blocking overlay with its nearest blocking owner.
173
+ const overlayBranchRef = useOverlayBranch({
174
+ active: !blocking && open,
175
+ registry: parentOverlayBranchRegistry
176
+ });
177
+ const handleRef = useForkRef(ref, ariaHideOutsideRef, overlayBranchRef);
178
+ const cls = useClasses('modal', classes, className);
179
+ const { onClick: externalOnClick, ...restBackdropProps } = backdropProps || {};
180
+ const handleBackdropClick = useEventCallback((event)=>{
181
+ if (disableBackdropClick) return;
182
+ if (event.target !== event.currentTarget) {
183
+ return;
184
+ }
185
+ externalOnClick?.(event);
186
+ onBackdropClick?.(event);
187
+ onClose?.(event, 'backdropClick');
188
+ });
189
+ return /*#__PURE__*/ jsx(ModalContext.Provider, {
190
+ value: {
191
+ ariaHideEnabled: ariaHideEnabledForChildren,
192
+ overlayBranchRegistry,
193
+ shouldUseInert
194
+ },
195
+ children: /*#__PURE__*/ jsxs(motion.div, {
196
+ ...rest,
197
+ ...motionProps,
198
+ role: "presentation",
199
+ className: cls('root', {
200
+ 'non-blocking': !blocking
201
+ }),
202
+ onKeyDown: (e)=>{
203
+ onKeyDown?.(e);
204
+ if (!disableEscapeKeyDown && e.key === 'Escape' && (isEnabled?.() ?? true)) {
205
+ onEscapeKeyDown?.(e);
206
+ onClose?.(e, 'escapeKeyDown');
207
+ }
208
+ },
209
+ ref: handleRef,
210
+ children: [
211
+ /*#__PURE__*/ jsx(Backdrop_Backdrop, {
212
+ ...restBackdropProps,
213
+ isTransparent: hideBackdrop,
214
+ onClick: handleBackdropClick
215
+ }),
216
+ /*#__PURE__*/ jsx(FocusTrap, {
217
+ open: open,
218
+ isEnabled: isEnabled,
219
+ disableAutoFocus: disableAutoFocus || !blocking,
220
+ disableEnforceFocus: disableEnforceFocus || !blocking,
221
+ disableRestoreFocus: disableRestoreFocus || !blocking,
222
+ children: children
223
+ })
224
+ ]
225
+ })
226
+ });
227
+ });
228
+ InnerModal.displayName = 'SuiInnerModal';
229
+
230
+
231
+
232
+
233
+
234
+
235
+ // extracted by css-extract-rspack-plugin
236
+ /* export default */ var Modal = ({"sui-modal-root":"sui-modal-root","sui-modal-non-blocking":"sui-modal-non-blocking","sui-backdrop-root":"sui-backdrop-root"});
237
+
238
+
239
+
240
+
241
+
242
+
243
+
244
+
245
+
246
+
247
+ const Modal_Modal = /*#__PURE__*/ forwardRef((inProps, ref)=>{
248
+ const props = useThemeProps({
249
+ props: inProps,
250
+ name: 'Modal'
251
+ });
252
+ const { children, open, container: containerProp, disablePortal, onExitComplete, onAfterClose, disableBackdropAnimation, motionProps, disableScrollLock: disableScrollLockProp, blocking = true, shouldUseInert: themeFallbackShouldUseInert, ...rest } = props;
253
+ const parentModalContext = useModalContext();
254
+ const shouldUseInert = inProps.shouldUseInert ?? parentModalContext?.shouldUseInert ?? themeFallbackShouldUseInert ?? false;
255
+ // When `disableScrollLock` is not provided, derive it from `blocking`:
256
+ // non-blocking overlays should not contribute to body scroll lock by default.
257
+ // Explicit values always win to preserve back-compat.
258
+ const disableScrollLock = disableScrollLockProp ?? !blocking;
259
+ const [shouldRender, setShouldRender] = useState(open);
260
+ const [modalElement, setModalElement] = useState(null);
261
+ const handleRef = useForkRef(setModalElement, ref);
262
+ const prefersReducedMotion = usePrefersReducedMotion();
263
+ const { isEnabled } = useFocusTrapStack({
264
+ open
265
+ });
266
+ useBodyScrollLock(open, modalElement, {
267
+ disabled: disableScrollLock
268
+ });
269
+ useEffect(()=>{
270
+ if (open) {
271
+ setShouldRender(true);
272
+ } else {
273
+ if (disableBackdropAnimation) {
274
+ setShouldRender(false);
275
+ }
276
+ }
277
+ }, [
278
+ open,
279
+ disableBackdropAnimation
280
+ ]);
281
+ const hasRenderedContentRef = useRef(open);
282
+ const handleAfterClose = useEventCallback(()=>{
283
+ onAfterClose?.();
284
+ });
285
+ useEffect(()=>{
286
+ if (shouldRender) {
287
+ hasRenderedContentRef.current = true;
288
+ return;
289
+ }
290
+ // Runs after the commit that removed the content, so consumers can rely on
291
+ // the modal subtree being gone. Guarded so an initially closed modal and
292
+ // repeated effect runs do not report a close that never happened.
293
+ if (hasRenderedContentRef.current) {
294
+ hasRenderedContentRef.current = false;
295
+ handleAfterClose();
296
+ }
297
+ }, [
298
+ shouldRender,
299
+ handleAfterClose
300
+ ]);
301
+ const { document } = useWindowContext();
302
+ const container = containerProp ?? document?.body;
303
+ const { scopeProps } = useTheme();
304
+ const onAnimationComplete = (e)=>{
305
+ motionProps?.onAnimationComplete?.(e);
306
+ if (!open) {
307
+ onExitComplete?.();
308
+ setShouldRender(false);
309
+ }
310
+ };
311
+ return shouldRender ? /*#__PURE__*/ jsx(Portal, {
312
+ disablePortal: disablePortal,
313
+ container: container,
314
+ children: /*#__PURE__*/ jsx("div", {
315
+ ...scopeProps,
316
+ children: /*#__PURE__*/ jsx(InnerModal, {
317
+ ...rest,
318
+ ref: handleRef,
319
+ open: open,
320
+ blocking: blocking,
321
+ shouldUseInert: shouldUseInert,
322
+ isEnabled: isEnabled,
323
+ motionProps: {
324
+ ...motionProps ?? getFade({
325
+ prefersReducedMotion,
326
+ toggle: open
327
+ }),
328
+ onAnimationComplete
329
+ },
330
+ children: children
331
+ })
332
+ })
333
+ }) : null;
334
+ });
335
+ Modal_Modal.displayName = 'SuiModal';
336
+
337
+
338
+
339
+
340
+
341
+
342
+
343
+
344
+
345
+ export { InnerModal, Modal as modalStyles, ModalContext, Modal_Modal as Modal, useModalContext, useOverlayBranch };
@@ -1,24 +1,196 @@
1
- import { u as useNestedMenuContext } from './chunks/useNestedParentMenu.js';
2
- export { N as NestedMenuContext, a as useNestedParentMenu } from './chunks/useNestedParentMenu.js';
3
- import { useEventCallback } from '@ringcentral/spring-base';
4
- import { useEffect } from 'react';
5
- export { u as useNestedMenuItem } from './chunks/useNestedMenuItem.js';
1
+ import { createContext, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef } from "react";
2
+ import { useEventCallback } from "@ringcentral/spring-base";
6
3
 
7
- const useNestedChildMenu = (props) => {
4
+
5
+
6
+ const NestedMenuContext = /*#__PURE__*/ createContext(null);
7
+ const useNestedMenuContext = ()=>{
8
+ return useContext(NestedMenuContext);
9
+ };
10
+
11
+
12
+
13
+
14
+
15
+
16
+ const useNestedChildMenu = (props)=>{
8
17
  const { open, closeMenu, getAnchorElement, id } = props;
9
18
  const context = useNestedMenuContext();
10
19
  const { registOpenedSubMenu } = context ?? {};
11
- const closeMenuMemo = useEventCallback((options) => closeMenu(options));
12
- useEffect(() => {
20
+ const closeMenuMemo = useEventCallback((options)=>closeMenu(options));
21
+ useEffect(()=>{
13
22
  if (open) {
14
23
  return registOpenedSubMenu?.({
15
24
  anchorId: id,
16
25
  getAnchorElement,
17
- closeSubMenu: closeMenuMemo,
26
+ closeSubMenu: closeMenuMemo
18
27
  });
19
28
  }
20
29
  return undefined;
21
- }, [closeMenuMemo, getAnchorElement, id, open, registOpenedSubMenu]);
30
+ }, [
31
+ closeMenuMemo,
32
+ getAnchorElement,
33
+ id,
34
+ open,
35
+ registOpenedSubMenu
36
+ ]);
37
+ };
38
+
39
+
40
+
41
+
42
+ const useNestedMenuItem = (props)=>{
43
+ const context = useNestedMenuContext();
44
+ const { hovered, id } = props;
45
+ const { isPointerMovingToSubMenu: isPointerMovingToSubMenuContext, onPointerGraceIntentChange, registHoveredItem } = context ?? {};
46
+ const requestItemHover = useCallback((event, options)=>{
47
+ const canApplyHover = registHoveredItem?.(id, event, options);
48
+ return canApplyHover ?? true;
49
+ }, [
50
+ id,
51
+ registHoveredItem
52
+ ]);
53
+ useEffect(()=>{
54
+ if (hovered) {
55
+ requestItemHover();
56
+ }
57
+ }, [
58
+ hovered,
59
+ requestItemHover
60
+ ]);
61
+ const isPointerMovingToSubMenu = useCallback((event, intent)=>{
62
+ return isPointerMovingToSubMenuContext?.(event, intent) ?? false;
63
+ }, [
64
+ isPointerMovingToSubMenuContext
65
+ ]);
66
+ return {
67
+ isPointerMovingToSubMenu,
68
+ onPointerGraceIntentChange,
69
+ requestItemHover
70
+ };
71
+ };
72
+
73
+
74
+ const getPointFromPointerEvent = (event)=>({
75
+ x: event.clientX,
76
+ y: event.clientY
77
+ });
78
+ const isPointInPolygon = (point, polygon)=>{
79
+ let inside = false;
80
+ for(let i = 0, j = polygon.length - 1; i < polygon.length; j = i++){
81
+ const pointI = polygon[i];
82
+ const pointJ = polygon[j];
83
+ const intersects = pointI.y > point.y !== pointJ.y > point.y && point.x < (pointJ.x - pointI.x) * (point.y - pointI.y) / (pointJ.y - pointI.y) + pointI.x;
84
+ if (intersects) {
85
+ inside = !inside;
86
+ }
87
+ }
88
+ return inside;
22
89
  };
90
+ const isPointerInGraceArea = (event, area)=>{
91
+ if (!area) return false;
92
+ return isPointInPolygon(getPointFromPointerEvent(event), area);
93
+ };
94
+
95
+
96
+
97
+ const useNestedParentMenu = (props)=>{
98
+ const openedSubMenuSymbolRef = useRef(null);
99
+ const pointerGraceIntentRef = useRef(null);
100
+ const pointerDirRef = useRef('right');
101
+ const lastPointerXRef = useRef(0);
102
+ const { open } = props;
103
+ const onPointerGraceIntentChange = useCallback((intent)=>{
104
+ pointerGraceIntentRef.current = intent;
105
+ }, []);
106
+ const isPointerMovingToSubMenu = useCallback((event, intentArg)=>{
107
+ const intent = intentArg === undefined ? pointerGraceIntentRef.current : intentArg;
108
+ const isMovingTowards = pointerDirRef.current === intent?.side;
109
+ return isMovingTowards && isPointerInGraceArea(event, intent?.area);
110
+ }, []);
111
+ const onContentPointerMove = useCallback((event)=>{
112
+ const pointerXHasChanged = lastPointerXRef.current !== event.clientX;
113
+ if (pointerXHasChanged) {
114
+ pointerDirRef.current = event.clientX > lastPointerXRef.current ? 'right' : 'left';
115
+ lastPointerXRef.current = event.clientX;
116
+ }
117
+ }, []);
118
+ const onContentClickCapture = useCallback((event)=>{
119
+ const target = event.target;
120
+ const openedSubMenu = openedSubMenuSymbolRef.current;
121
+ if (!target || !event.currentTarget.contains(target)) {
122
+ return;
123
+ }
124
+ if (openedSubMenu?.getAnchorElement?.()?.contains(target)) {
125
+ return;
126
+ }
127
+ openedSubMenu?.closeSubMenu();
128
+ }, []);
129
+ const contextValue = useMemo(()=>{
130
+ return {
131
+ registHoveredItem: (id, event, options)=>{
132
+ // Close opened SubMenu if hovering on a different item
133
+ const symbol = openedSubMenuSymbolRef.current;
134
+ if (!symbol || id === symbol.anchorId) {
135
+ return true;
136
+ }
137
+ if (event && isPointerMovingToSubMenu(event)) {
138
+ return false;
139
+ }
140
+ if (options?.closeOpenedSubMenu ?? true) {
141
+ symbol.closeSubMenu();
142
+ }
143
+ return true;
144
+ },
145
+ registOpenedSubMenu: (menuItemSymbol)=>{
146
+ openedSubMenuSymbolRef.current?.closeSubMenu();
147
+ openedSubMenuSymbolRef.current = menuItemSymbol;
148
+ // This cleanup is returned to useNestedChildMenu's useEffect.
149
+ // It runs when:
150
+ // (a) the effect re-runs (open goes false -> true), or
151
+ // (b) the component unmounts.
152
+ // `menuItemSymbol` here is the value captured by closure at registration time -
153
+ // it never changes. `openedSubMenuSymbolRef.current` is the live ref value at
154
+ // cleanup time, which may have been replaced by a newer symbol.
155
+ return ()=>{
156
+ if (openedSubMenuSymbolRef.current === menuItemSymbol) {
157
+ openedSubMenuSymbolRef.current = null;
158
+ }
159
+ };
160
+ },
161
+ isPointerMovingToSubMenu,
162
+ onPointerGraceIntentChange
163
+ };
164
+ }, [
165
+ isPointerMovingToSubMenu,
166
+ onPointerGraceIntentChange
167
+ ]);
168
+ // Ensure that all menus can be visually closed at the same time
169
+ useLayoutEffect(()=>{
170
+ if (!open) {
171
+ openedSubMenuSymbolRef.current?.closeSubMenu();
172
+ openedSubMenuSymbolRef.current = null;
173
+ onPointerGraceIntentChange(null);
174
+ }
175
+ }, [
176
+ onPointerGraceIntentChange,
177
+ open
178
+ ]);
179
+ return {
180
+ contentClickHandlers: {
181
+ onClickCapture: onContentClickCapture
182
+ },
183
+ contentPointerHandlers: {
184
+ onPointerMove: onContentPointerMove
185
+ },
186
+ contextValue,
187
+ getHaveOpenedSubMenu: ()=>Boolean(openedSubMenuSymbolRef.current)
188
+ };
189
+ };
190
+
191
+
192
+
193
+
194
+
23
195
 
24
- export { useNestedChildMenu, useNestedMenuContext };
196
+ export { NestedMenuContext, useNestedChildMenu, useNestedMenuContext, useNestedMenuItem, useNestedParentMenu };