@mui/material 6.0.0-beta.0 → 6.0.0-beta.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 (207) hide show
  1. package/Autocomplete/Autocomplete.d.ts +6 -7
  2. package/Autocomplete/Autocomplete.js +1 -1
  3. package/Badge/Badge.d.ts +1 -1
  4. package/Badge/Badge.js +2 -2
  5. package/Badge/useBadge.d.ts +13 -0
  6. package/Badge/useBadge.js +41 -0
  7. package/Badge/useBadge.types.d.ts +40 -0
  8. package/Badge/useBadge.types.js +1 -0
  9. package/Breadcrumbs/Breadcrumbs.d.ts +1 -1
  10. package/Breadcrumbs/Breadcrumbs.js +1 -1
  11. package/CHANGELOG.md +48 -0
  12. package/ClickAwayListener/ClickAwayListener.d.ts +47 -0
  13. package/ClickAwayListener/ClickAwayListener.js +178 -0
  14. package/ClickAwayListener/index.d.ts +2 -2
  15. package/ClickAwayListener/index.js +1 -1
  16. package/InputBase/InputBase.js +2 -2
  17. package/ListItem/ListItem.js +1 -1
  18. package/Menu/Menu.js +1 -1
  19. package/Modal/Modal.d.ts +1 -1
  20. package/Modal/Modal.js +1 -1
  21. package/Modal/ModalManager.d.ts +25 -0
  22. package/Modal/ModalManager.js +211 -0
  23. package/Modal/index.d.ts +1 -1
  24. package/Modal/index.js +1 -1
  25. package/Modal/useModal.d.ts +13 -0
  26. package/Modal/useModal.js +195 -0
  27. package/Modal/useModal.types.d.ts +115 -0
  28. package/Modal/useModal.types.js +1 -0
  29. package/NoSsr/NoSsr.d.ts +25 -0
  30. package/NoSsr/NoSsr.js +73 -0
  31. package/NoSsr/NoSsr.types.d.ts +18 -0
  32. package/NoSsr/NoSsr.types.js +1 -0
  33. package/NoSsr/index.d.ts +3 -2
  34. package/NoSsr/index.js +1 -1
  35. package/Popover/Popover.js +1 -1
  36. package/Popper/BasePopper.d.ts +7 -0
  37. package/Popper/BasePopper.js +370 -0
  38. package/Popper/BasePopper.types.d.ts +130 -0
  39. package/Popper/BasePopper.types.js +1 -0
  40. package/Popper/Popper.d.ts +1 -1
  41. package/Popper/Popper.js +1 -1
  42. package/Popper/index.d.ts +2 -1
  43. package/Popper/index.js +2 -1
  44. package/Popper/popperClasses.d.ts +8 -0
  45. package/Popper/popperClasses.js +7 -0
  46. package/Portal/Portal.d.ts +16 -0
  47. package/Portal/Portal.js +92 -0
  48. package/Portal/Portal.types.d.ts +23 -0
  49. package/Portal/Portal.types.js +1 -0
  50. package/Portal/index.d.ts +3 -2
  51. package/Portal/index.js +1 -1
  52. package/Slider/Slider.d.ts +2 -2
  53. package/Slider/Slider.js +3 -2
  54. package/Slider/useSlider.d.ts +14 -0
  55. package/Slider/useSlider.js +647 -0
  56. package/Slider/useSlider.types.d.ts +228 -0
  57. package/Slider/useSlider.types.js +1 -0
  58. package/Snackbar/Snackbar.d.ts +1 -1
  59. package/Snackbar/Snackbar.js +3 -3
  60. package/Snackbar/useSnackbar.d.ts +14 -0
  61. package/Snackbar/useSnackbar.js +133 -0
  62. package/Snackbar/useSnackbar.types.d.ts +60 -0
  63. package/Snackbar/useSnackbar.types.js +1 -0
  64. package/SwipeableDrawer/SwipeableDrawer.js +1 -1
  65. package/TabScrollButton/TabScrollButton.d.ts +1 -1
  66. package/TabScrollButton/TabScrollButton.js +1 -1
  67. package/TablePagination/TablePagination.js +1 -1
  68. package/Tabs/Tabs.d.ts +1 -1
  69. package/Tabs/Tabs.js +1 -1
  70. package/TextareaAutosize/TextareaAutosize.d.ts +14 -0
  71. package/TextareaAutosize/TextareaAutosize.js +222 -0
  72. package/TextareaAutosize/TextareaAutosize.types.d.ts +13 -0
  73. package/TextareaAutosize/TextareaAutosize.types.js +1 -0
  74. package/TextareaAutosize/index.d.ts +3 -2
  75. package/TextareaAutosize/index.js +1 -1
  76. package/Tooltip/Tooltip.js +1 -1
  77. package/Unstable_TrapFocus/FocusTrap.d.ts +10 -0
  78. package/Unstable_TrapFocus/FocusTrap.js +330 -0
  79. package/Unstable_TrapFocus/FocusTrap.types.d.ts +51 -0
  80. package/Unstable_TrapFocus/FocusTrap.types.js +1 -0
  81. package/Unstable_TrapFocus/index.d.ts +2 -2
  82. package/Unstable_TrapFocus/index.js +1 -1
  83. package/index.d.ts +1 -1
  84. package/index.js +2 -2
  85. package/modern/Autocomplete/Autocomplete.js +1 -1
  86. package/modern/Badge/Badge.js +2 -2
  87. package/modern/Badge/useBadge.js +41 -0
  88. package/modern/Badge/useBadge.types.js +1 -0
  89. package/modern/Breadcrumbs/Breadcrumbs.js +1 -1
  90. package/modern/ClickAwayListener/ClickAwayListener.js +178 -0
  91. package/modern/ClickAwayListener/index.js +1 -1
  92. package/modern/InputBase/InputBase.js +2 -2
  93. package/modern/ListItem/ListItem.js +1 -1
  94. package/modern/Menu/Menu.js +1 -1
  95. package/modern/Modal/Modal.js +1 -1
  96. package/modern/Modal/ModalManager.js +211 -0
  97. package/modern/Modal/index.js +1 -1
  98. package/modern/Modal/useModal.js +195 -0
  99. package/modern/Modal/useModal.types.js +1 -0
  100. package/modern/NoSsr/NoSsr.js +73 -0
  101. package/modern/NoSsr/NoSsr.types.js +1 -0
  102. package/modern/NoSsr/index.js +1 -1
  103. package/modern/Popover/Popover.js +1 -1
  104. package/modern/Popper/BasePopper.js +370 -0
  105. package/modern/Popper/BasePopper.types.js +1 -0
  106. package/modern/Popper/Popper.js +1 -1
  107. package/modern/Popper/index.js +2 -1
  108. package/modern/Popper/popperClasses.js +7 -0
  109. package/modern/Portal/Portal.js +92 -0
  110. package/modern/Portal/Portal.types.js +1 -0
  111. package/modern/Portal/index.js +1 -1
  112. package/modern/Slider/Slider.js +3 -2
  113. package/modern/Slider/useSlider.js +647 -0
  114. package/modern/Slider/useSlider.types.js +1 -0
  115. package/modern/Snackbar/Snackbar.js +3 -3
  116. package/modern/Snackbar/useSnackbar.js +133 -0
  117. package/modern/Snackbar/useSnackbar.types.js +1 -0
  118. package/modern/SwipeableDrawer/SwipeableDrawer.js +1 -1
  119. package/modern/TabScrollButton/TabScrollButton.js +1 -1
  120. package/modern/TablePagination/TablePagination.js +1 -1
  121. package/modern/Tabs/Tabs.js +1 -1
  122. package/modern/TextareaAutosize/TextareaAutosize.js +222 -0
  123. package/modern/TextareaAutosize/TextareaAutosize.types.js +1 -0
  124. package/modern/TextareaAutosize/index.js +1 -1
  125. package/modern/Tooltip/Tooltip.js +1 -1
  126. package/modern/Unstable_TrapFocus/FocusTrap.js +330 -0
  127. package/modern/Unstable_TrapFocus/FocusTrap.types.js +1 -0
  128. package/modern/Unstable_TrapFocus/index.js +1 -1
  129. package/modern/index.js +2 -2
  130. package/modern/useAutocomplete/useAutocomplete.js +976 -2
  131. package/modern/utils/PolymorphicComponent.js +1 -0
  132. package/modern/utils/areArraysEqual.js +4 -0
  133. package/modern/utils/index.js +1 -1
  134. package/modern/utils/isHostComponent.js +7 -0
  135. package/modern/utils/omitEventHandlers.js +18 -0
  136. package/modern/utils/shouldSpreadAdditionalProps.js +1 -1
  137. package/modern/utils/useSlot.js +3 -1
  138. package/node/Autocomplete/Autocomplete.js +3 -3
  139. package/node/Badge/Badge.js +5 -5
  140. package/node/Badge/useBadge.js +46 -0
  141. package/node/Badge/useBadge.types.js +5 -0
  142. package/node/Breadcrumbs/Breadcrumbs.js +2 -2
  143. package/node/ClickAwayListener/ClickAwayListener.js +184 -0
  144. package/node/ClickAwayListener/index.js +1 -1
  145. package/node/InputBase/InputBase.js +7 -7
  146. package/node/ListItem/ListItem.js +3 -3
  147. package/node/Menu/Menu.js +3 -3
  148. package/node/Modal/Modal.js +2 -2
  149. package/node/Modal/ModalManager.js +219 -0
  150. package/node/Modal/index.js +2 -2
  151. package/node/Modal/useModal.js +205 -0
  152. package/node/Modal/useModal.types.js +5 -0
  153. package/node/NoSsr/NoSsr.js +81 -0
  154. package/node/NoSsr/NoSsr.types.js +5 -0
  155. package/node/NoSsr/index.js +3 -2
  156. package/node/Popover/Popover.js +2 -2
  157. package/node/Popper/BasePopper.js +379 -0
  158. package/node/Popper/BasePopper.types.js +5 -0
  159. package/node/Popper/Popper.js +2 -2
  160. package/node/Popper/index.js +14 -1
  161. package/node/Popper/popperClasses.js +15 -0
  162. package/node/Portal/Portal.js +100 -0
  163. package/node/Portal/Portal.types.js +5 -0
  164. package/node/Portal/index.js +3 -2
  165. package/node/Slider/Slider.js +14 -13
  166. package/node/Slider/useSlider.js +670 -0
  167. package/node/Slider/useSlider.types.js +5 -0
  168. package/node/Snackbar/Snackbar.js +6 -6
  169. package/node/Snackbar/useSnackbar.js +141 -0
  170. package/node/Snackbar/useSnackbar.types.js +5 -0
  171. package/node/SwipeableDrawer/SwipeableDrawer.js +2 -2
  172. package/node/TabScrollButton/TabScrollButton.js +3 -3
  173. package/node/TablePagination/TablePagination.js +2 -2
  174. package/node/Tabs/Tabs.js +3 -3
  175. package/node/TextareaAutosize/TextareaAutosize.js +230 -0
  176. package/node/TextareaAutosize/TextareaAutosize.types.js +5 -0
  177. package/node/TextareaAutosize/index.js +3 -2
  178. package/node/Tooltip/Tooltip.js +5 -5
  179. package/node/Unstable_TrapFocus/FocusTrap.js +339 -0
  180. package/node/Unstable_TrapFocus/FocusTrap.types.js +5 -0
  181. package/node/Unstable_TrapFocus/index.js +3 -2
  182. package/node/index.js +3 -3
  183. package/node/useAutocomplete/useAutocomplete.js +985 -18
  184. package/node/utils/PolymorphicComponent.js +5 -0
  185. package/node/utils/areArraysEqual.js +10 -0
  186. package/node/utils/index.js +2 -2
  187. package/node/utils/isHostComponent.js +13 -0
  188. package/node/utils/omitEventHandlers.js +24 -0
  189. package/node/utils/shouldSpreadAdditionalProps.js +3 -2
  190. package/node/utils/useSlot.js +6 -4
  191. package/package.json +8 -8
  192. package/styles/overrides.d.ts +1 -1
  193. package/useAutocomplete/useAutocomplete.d.ts +468 -2
  194. package/useAutocomplete/useAutocomplete.js +976 -2
  195. package/utils/PolymorphicComponent.d.ts +17 -0
  196. package/utils/PolymorphicComponent.js +1 -0
  197. package/utils/areArraysEqual.d.ts +3 -0
  198. package/utils/areArraysEqual.js +4 -0
  199. package/utils/index.d.ts +2 -1
  200. package/utils/index.js +1 -1
  201. package/utils/isHostComponent.d.ts +6 -0
  202. package/utils/isHostComponent.js +7 -0
  203. package/utils/omitEventHandlers.d.ts +9 -0
  204. package/utils/omitEventHandlers.js +18 -0
  205. package/utils/shouldSpreadAdditionalProps.js +1 -1
  206. package/utils/types.d.ts +2 -1
  207. package/utils/useSlot.js +3 -1
@@ -0,0 +1,211 @@
1
+ import { unstable_ownerWindow as ownerWindow, unstable_ownerDocument as ownerDocument, unstable_getScrollbarSize as getScrollbarSize } from '@mui/utils';
2
+ // Is a vertical scrollbar displayed?
3
+ function isOverflowing(container) {
4
+ const doc = ownerDocument(container);
5
+ if (doc.body === container) {
6
+ return ownerWindow(container).innerWidth > doc.documentElement.clientWidth;
7
+ }
8
+ return container.scrollHeight > container.clientHeight;
9
+ }
10
+ export function ariaHidden(element, show) {
11
+ if (show) {
12
+ element.setAttribute('aria-hidden', 'true');
13
+ } else {
14
+ element.removeAttribute('aria-hidden');
15
+ }
16
+ }
17
+ function getPaddingRight(element) {
18
+ return parseInt(ownerWindow(element).getComputedStyle(element).paddingRight, 10) || 0;
19
+ }
20
+ function isAriaHiddenForbiddenOnElement(element) {
21
+ // The forbidden HTML tags are the ones from ARIA specification that
22
+ // can be children of body and can't have aria-hidden attribute.
23
+ // cf. https://www.w3.org/TR/html-aria/#docconformance
24
+ const forbiddenTagNames = ['TEMPLATE', 'SCRIPT', 'STYLE', 'LINK', 'MAP', 'META', 'NOSCRIPT', 'PICTURE', 'COL', 'COLGROUP', 'PARAM', 'SLOT', 'SOURCE', 'TRACK'];
25
+ const isForbiddenTagName = forbiddenTagNames.indexOf(element.tagName) !== -1;
26
+ const isInputHidden = element.tagName === 'INPUT' && element.getAttribute('type') === 'hidden';
27
+ return isForbiddenTagName || isInputHidden;
28
+ }
29
+ function ariaHiddenSiblings(container, mountElement, currentElement, elementsToExclude, show) {
30
+ const blacklist = [mountElement, currentElement, ...elementsToExclude];
31
+ [].forEach.call(container.children, element => {
32
+ const isNotExcludedElement = blacklist.indexOf(element) === -1;
33
+ const isNotForbiddenElement = !isAriaHiddenForbiddenOnElement(element);
34
+ if (isNotExcludedElement && isNotForbiddenElement) {
35
+ ariaHidden(element, show);
36
+ }
37
+ });
38
+ }
39
+ function findIndexOf(items, callback) {
40
+ let idx = -1;
41
+ items.some((item, index) => {
42
+ if (callback(item)) {
43
+ idx = index;
44
+ return true;
45
+ }
46
+ return false;
47
+ });
48
+ return idx;
49
+ }
50
+ function handleContainer(containerInfo, props) {
51
+ const restoreStyle = [];
52
+ const container = containerInfo.container;
53
+ if (!props.disableScrollLock) {
54
+ if (isOverflowing(container)) {
55
+ // Compute the size before applying overflow hidden to avoid any scroll jumps.
56
+ const scrollbarSize = getScrollbarSize(ownerDocument(container));
57
+ restoreStyle.push({
58
+ value: container.style.paddingRight,
59
+ property: 'padding-right',
60
+ el: container
61
+ });
62
+ // Use computed style, here to get the real padding to add our scrollbar width.
63
+ container.style.paddingRight = `${getPaddingRight(container) + scrollbarSize}px`;
64
+
65
+ // .mui-fixed is a global helper.
66
+ const fixedElements = ownerDocument(container).querySelectorAll('.mui-fixed');
67
+ [].forEach.call(fixedElements, element => {
68
+ restoreStyle.push({
69
+ value: element.style.paddingRight,
70
+ property: 'padding-right',
71
+ el: element
72
+ });
73
+ element.style.paddingRight = `${getPaddingRight(element) + scrollbarSize}px`;
74
+ });
75
+ }
76
+ let scrollContainer;
77
+ if (container.parentNode instanceof DocumentFragment) {
78
+ scrollContainer = ownerDocument(container).body;
79
+ } else {
80
+ // Support html overflow-y: auto for scroll stability between pages
81
+ // https://css-tricks.com/snippets/css/force-vertical-scrollbar/
82
+ const parent = container.parentElement;
83
+ const containerWindow = ownerWindow(container);
84
+ scrollContainer = parent?.nodeName === 'HTML' && containerWindow.getComputedStyle(parent).overflowY === 'scroll' ? parent : container;
85
+ }
86
+
87
+ // Block the scroll even if no scrollbar is visible to account for mobile keyboard
88
+ // screensize shrink.
89
+ restoreStyle.push({
90
+ value: scrollContainer.style.overflow,
91
+ property: 'overflow',
92
+ el: scrollContainer
93
+ }, {
94
+ value: scrollContainer.style.overflowX,
95
+ property: 'overflow-x',
96
+ el: scrollContainer
97
+ }, {
98
+ value: scrollContainer.style.overflowY,
99
+ property: 'overflow-y',
100
+ el: scrollContainer
101
+ });
102
+ scrollContainer.style.overflow = 'hidden';
103
+ }
104
+ const restore = () => {
105
+ restoreStyle.forEach(({
106
+ value,
107
+ el,
108
+ property
109
+ }) => {
110
+ if (value) {
111
+ el.style.setProperty(property, value);
112
+ } else {
113
+ el.style.removeProperty(property);
114
+ }
115
+ });
116
+ };
117
+ return restore;
118
+ }
119
+ function getHiddenSiblings(container) {
120
+ const hiddenSiblings = [];
121
+ [].forEach.call(container.children, element => {
122
+ if (element.getAttribute('aria-hidden') === 'true') {
123
+ hiddenSiblings.push(element);
124
+ }
125
+ });
126
+ return hiddenSiblings;
127
+ }
128
+ /**
129
+ * @ignore - do not document.
130
+ *
131
+ * Proper state management for containers and the modals in those containers.
132
+ * Simplified, but inspired by react-overlay's ModalManager class.
133
+ * Used by the Modal to ensure proper styling of containers.
134
+ */
135
+ export class ModalManager {
136
+ constructor() {
137
+ this.modals = [];
138
+ this.containers = [];
139
+ }
140
+ add(modal, container) {
141
+ let modalIndex = this.modals.indexOf(modal);
142
+ if (modalIndex !== -1) {
143
+ return modalIndex;
144
+ }
145
+ modalIndex = this.modals.length;
146
+ this.modals.push(modal);
147
+
148
+ // If the modal we are adding is already in the DOM.
149
+ if (modal.modalRef) {
150
+ ariaHidden(modal.modalRef, false);
151
+ }
152
+ const hiddenSiblings = getHiddenSiblings(container);
153
+ ariaHiddenSiblings(container, modal.mount, modal.modalRef, hiddenSiblings, true);
154
+ const containerIndex = findIndexOf(this.containers, item => item.container === container);
155
+ if (containerIndex !== -1) {
156
+ this.containers[containerIndex].modals.push(modal);
157
+ return modalIndex;
158
+ }
159
+ this.containers.push({
160
+ modals: [modal],
161
+ container,
162
+ restore: null,
163
+ hiddenSiblings
164
+ });
165
+ return modalIndex;
166
+ }
167
+ mount(modal, props) {
168
+ const containerIndex = findIndexOf(this.containers, item => item.modals.indexOf(modal) !== -1);
169
+ const containerInfo = this.containers[containerIndex];
170
+ if (!containerInfo.restore) {
171
+ containerInfo.restore = handleContainer(containerInfo, props);
172
+ }
173
+ }
174
+ remove(modal, ariaHiddenState = true) {
175
+ const modalIndex = this.modals.indexOf(modal);
176
+ if (modalIndex === -1) {
177
+ return modalIndex;
178
+ }
179
+ const containerIndex = findIndexOf(this.containers, item => item.modals.indexOf(modal) !== -1);
180
+ const containerInfo = this.containers[containerIndex];
181
+ containerInfo.modals.splice(containerInfo.modals.indexOf(modal), 1);
182
+ this.modals.splice(modalIndex, 1);
183
+
184
+ // If that was the last modal in a container, clean up the container.
185
+ if (containerInfo.modals.length === 0) {
186
+ // The modal might be closed before it had the chance to be mounted in the DOM.
187
+ if (containerInfo.restore) {
188
+ containerInfo.restore();
189
+ }
190
+ if (modal.modalRef) {
191
+ // In case the modal wasn't in the DOM yet.
192
+ ariaHidden(modal.modalRef, ariaHiddenState);
193
+ }
194
+ ariaHiddenSiblings(containerInfo.container, modal.mount, modal.modalRef, containerInfo.hiddenSiblings, false);
195
+ this.containers.splice(containerIndex, 1);
196
+ } else {
197
+ // Otherwise make sure the next top modal is visible to a screen reader.
198
+ const nextTop = containerInfo.modals[containerInfo.modals.length - 1];
199
+ // as soon as a modal is adding its modalRef is undefined. it can't set
200
+ // aria-hidden because the dom element doesn't exist either
201
+ // when modal was unmounted before modalRef gets null
202
+ if (nextTop.modalRef) {
203
+ ariaHidden(nextTop.modalRef, false);
204
+ }
205
+ }
206
+ return modalIndex;
207
+ }
208
+ isTopModal(modal) {
209
+ return this.modals.length > 0 && this.modals[this.modals.length - 1] === modal;
210
+ }
211
+ }
package/Modal/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { ModalManager } from '@mui/base/unstable_useModal'; // exporting ModalManager
1
+ export { ModalManager } from './ModalManager';
2
2
 
3
3
  export { default } from './Modal';
4
4
  export * from './Modal';
package/Modal/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
 
3
- export { ModalManager } from '@mui/base/unstable_useModal';
3
+ export { ModalManager } from './ModalManager';
4
4
  export { default } from './Modal';
5
5
  export { default as modalClasses } from './modalClasses';
6
6
  export * from './modalClasses';
@@ -0,0 +1,13 @@
1
+ import { UseModalParameters, UseModalReturnValue } from './useModal.types';
2
+ /**
3
+ *
4
+ * Demos:
5
+ *
6
+ * - [Modal](https://next.mui.com/base-ui/react-modal/#hook)
7
+ *
8
+ * API:
9
+ *
10
+ * - [useModal API](https://next.mui.com/base-ui/react-modal/hooks-api/#use-modal)
11
+ */
12
+ declare function useModal(parameters: UseModalParameters): UseModalReturnValue;
13
+ export default useModal;
@@ -0,0 +1,195 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import { unstable_ownerDocument as ownerDocument, unstable_useForkRef as useForkRef, unstable_useEventCallback as useEventCallback, unstable_createChainedFunction as createChainedFunction } from '@mui/utils';
5
+ import extractEventHandlers from '@mui/utils/extractEventHandlers';
6
+ import { ModalManager, ariaHidden } from './ModalManager';
7
+ function getContainer(container) {
8
+ return typeof container === 'function' ? container() : container;
9
+ }
10
+ function getHasTransition(children) {
11
+ return children ? children.props.hasOwnProperty('in') : false;
12
+ }
13
+
14
+ // A modal manager used to track and manage the state of open Modals.
15
+ // Modals don't open on the server so this won't conflict with concurrent requests.
16
+ const defaultManager = new ModalManager();
17
+ /**
18
+ *
19
+ * Demos:
20
+ *
21
+ * - [Modal](https://next.mui.com/base-ui/react-modal/#hook)
22
+ *
23
+ * API:
24
+ *
25
+ * - [useModal API](https://next.mui.com/base-ui/react-modal/hooks-api/#use-modal)
26
+ */
27
+ function useModal(parameters) {
28
+ const {
29
+ container,
30
+ disableEscapeKeyDown = false,
31
+ disableScrollLock = false,
32
+ // @ts-ignore internal logic - Base UI supports the manager as a prop too
33
+ manager = defaultManager,
34
+ closeAfterTransition = false,
35
+ onTransitionEnter,
36
+ onTransitionExited,
37
+ children,
38
+ onClose,
39
+ open,
40
+ rootRef
41
+ } = parameters;
42
+
43
+ // @ts-ignore internal logic
44
+ const modal = React.useRef({});
45
+ const mountNodeRef = React.useRef(null);
46
+ const modalRef = React.useRef(null);
47
+ const handleRef = useForkRef(modalRef, rootRef);
48
+ const [exited, setExited] = React.useState(!open);
49
+ const hasTransition = getHasTransition(children);
50
+ let ariaHiddenProp = true;
51
+ if (parameters['aria-hidden'] === 'false' || parameters['aria-hidden'] === false) {
52
+ ariaHiddenProp = false;
53
+ }
54
+ const getDoc = () => ownerDocument(mountNodeRef.current);
55
+ const getModal = () => {
56
+ modal.current.modalRef = modalRef.current;
57
+ modal.current.mount = mountNodeRef.current;
58
+ return modal.current;
59
+ };
60
+ const handleMounted = () => {
61
+ manager.mount(getModal(), {
62
+ disableScrollLock
63
+ });
64
+
65
+ // Fix a bug on Chrome where the scroll isn't initially 0.
66
+ if (modalRef.current) {
67
+ modalRef.current.scrollTop = 0;
68
+ }
69
+ };
70
+ const handleOpen = useEventCallback(() => {
71
+ const resolvedContainer = getContainer(container) || getDoc().body;
72
+ manager.add(getModal(), resolvedContainer);
73
+
74
+ // The element was already mounted.
75
+ if (modalRef.current) {
76
+ handleMounted();
77
+ }
78
+ });
79
+ const isTopModal = React.useCallback(() => manager.isTopModal(getModal()), [manager]);
80
+ const handlePortalRef = useEventCallback(node => {
81
+ mountNodeRef.current = node;
82
+ if (!node) {
83
+ return;
84
+ }
85
+ if (open && isTopModal()) {
86
+ handleMounted();
87
+ } else if (modalRef.current) {
88
+ ariaHidden(modalRef.current, ariaHiddenProp);
89
+ }
90
+ });
91
+ const handleClose = React.useCallback(() => {
92
+ manager.remove(getModal(), ariaHiddenProp);
93
+ }, [ariaHiddenProp, manager]);
94
+ React.useEffect(() => {
95
+ return () => {
96
+ handleClose();
97
+ };
98
+ }, [handleClose]);
99
+ React.useEffect(() => {
100
+ if (open) {
101
+ handleOpen();
102
+ } else if (!hasTransition || !closeAfterTransition) {
103
+ handleClose();
104
+ }
105
+ }, [open, handleClose, hasTransition, closeAfterTransition, handleOpen]);
106
+ const createHandleKeyDown = otherHandlers => event => {
107
+ otherHandlers.onKeyDown?.(event);
108
+
109
+ // The handler doesn't take event.defaultPrevented into account:
110
+ //
111
+ // event.preventDefault() is meant to stop default behaviors like
112
+ // clicking a checkbox to check it, hitting a button to submit a form,
113
+ // and hitting left arrow to move the cursor in a text input etc.
114
+ // Only special HTML elements have these default behaviors.
115
+ if (event.key !== 'Escape' || event.which === 229 ||
116
+ // Wait until IME is settled.
117
+ !isTopModal()) {
118
+ return;
119
+ }
120
+ if (!disableEscapeKeyDown) {
121
+ // Swallow the event, in case someone is listening for the escape key on the body.
122
+ event.stopPropagation();
123
+ if (onClose) {
124
+ onClose(event, 'escapeKeyDown');
125
+ }
126
+ }
127
+ };
128
+ const createHandleBackdropClick = otherHandlers => event => {
129
+ otherHandlers.onClick?.(event);
130
+ if (event.target !== event.currentTarget) {
131
+ return;
132
+ }
133
+ if (onClose) {
134
+ onClose(event, 'backdropClick');
135
+ }
136
+ };
137
+ const getRootProps = (otherHandlers = {}) => {
138
+ const propsEventHandlers = extractEventHandlers(parameters);
139
+
140
+ // The custom event handlers shouldn't be spread on the root element
141
+ delete propsEventHandlers.onTransitionEnter;
142
+ delete propsEventHandlers.onTransitionExited;
143
+ const externalEventHandlers = {
144
+ ...propsEventHandlers,
145
+ ...otherHandlers
146
+ };
147
+ return {
148
+ role: 'presentation',
149
+ ...externalEventHandlers,
150
+ onKeyDown: createHandleKeyDown(externalEventHandlers),
151
+ ref: handleRef
152
+ };
153
+ };
154
+ const getBackdropProps = (otherHandlers = {}) => {
155
+ const externalEventHandlers = otherHandlers;
156
+ return {
157
+ 'aria-hidden': true,
158
+ ...externalEventHandlers,
159
+ onClick: createHandleBackdropClick(externalEventHandlers),
160
+ open
161
+ };
162
+ };
163
+ const getTransitionProps = () => {
164
+ const handleEnter = () => {
165
+ setExited(false);
166
+ if (onTransitionEnter) {
167
+ onTransitionEnter();
168
+ }
169
+ };
170
+ const handleExited = () => {
171
+ setExited(true);
172
+ if (onTransitionExited) {
173
+ onTransitionExited();
174
+ }
175
+ if (closeAfterTransition) {
176
+ handleClose();
177
+ }
178
+ };
179
+ return {
180
+ onEnter: createChainedFunction(handleEnter, children?.props.onEnter),
181
+ onExited: createChainedFunction(handleExited, children?.props.onExited)
182
+ };
183
+ };
184
+ return {
185
+ getRootProps,
186
+ getBackdropProps,
187
+ getTransitionProps,
188
+ rootRef: handleRef,
189
+ portalRef: handlePortalRef,
190
+ isTopModal,
191
+ exited,
192
+ hasTransition
193
+ };
194
+ }
195
+ export default useModal;
@@ -0,0 +1,115 @@
1
+ /// <reference types="react" />
2
+ import { PortalProps } from '../Portal';
3
+ import { EventHandlers } from '../utils/types';
4
+ export interface UseModalRootSlotOwnProps {
5
+ role: React.AriaRole;
6
+ onKeyDown: React.KeyboardEventHandler;
7
+ ref: React.RefCallback<Element> | null;
8
+ }
9
+ export interface UseModalBackdropSlotOwnProps {
10
+ 'aria-hidden': React.AriaAttributes['aria-hidden'];
11
+ onClick: React.MouseEventHandler;
12
+ open?: boolean;
13
+ }
14
+ export type UseModalBackdropSlotProps<TOther = {}> = TOther & UseModalBackdropSlotOwnProps;
15
+ export type UseModalRootSlotProps<TOther = {}> = TOther & UseModalRootSlotOwnProps;
16
+ export type UseModalParameters = {
17
+ 'aria-hidden'?: React.AriaAttributes['aria-hidden'];
18
+ /**
19
+ * A single child content element.
20
+ */
21
+ children: React.ReactElement<any> | undefined | null;
22
+ /**
23
+ * When set to true the Modal waits until a nested Transition is completed before closing.
24
+ * @default false
25
+ */
26
+ closeAfterTransition?: boolean;
27
+ /**
28
+ * An HTML element or function that returns one.
29
+ * The `container` will have the portal children appended to it.
30
+ *
31
+ * You can also provide a callback, which is called in a React layout effect.
32
+ * This lets you set the container from a ref, and also makes server-side rendering possible.
33
+ *
34
+ * By default, it uses the body of the top-level document object,
35
+ * so it's simply `document.body` most of the time.
36
+ */
37
+ container?: PortalProps['container'];
38
+ /**
39
+ * If `true`, hitting escape will not fire the `onClose` callback.
40
+ * @default false
41
+ */
42
+ disableEscapeKeyDown?: boolean;
43
+ /**
44
+ * Disable the scroll lock behavior.
45
+ * @default false
46
+ */
47
+ disableScrollLock?: boolean;
48
+ /**
49
+ * Callback fired when the component requests to be closed.
50
+ * The `reason` parameter can optionally be used to control the response to `onClose`.
51
+ *
52
+ * @param {object} event The event source of the callback.
53
+ * @param {string} reason Can be: `"escapeKeyDown"`, `"backdropClick"`.
54
+ */
55
+ onClose?: {
56
+ bivarianceHack(event: {}, reason: 'backdropClick' | 'escapeKeyDown'): void;
57
+ }['bivarianceHack'];
58
+ onKeyDown?: React.KeyboardEventHandler;
59
+ /**
60
+ * A function called when a transition enters.
61
+ */
62
+ onTransitionEnter?: () => void;
63
+ /**
64
+ * A function called when a transition has exited.
65
+ */
66
+ onTransitionExited?: () => void;
67
+ /**
68
+ * If `true`, the component is shown.
69
+ */
70
+ open: boolean;
71
+ rootRef: React.Ref<Element>;
72
+ };
73
+ export interface UseModalReturnValue {
74
+ /**
75
+ * Resolver for the root slot's props.
76
+ * @param externalProps props for the root slot
77
+ * @returns props that should be spread on the root slot
78
+ */
79
+ getRootProps: <TOther extends EventHandlers = {}>(externalProps?: TOther) => UseModalRootSlotProps<TOther>;
80
+ /**
81
+ * Resolver for the backdrop slot's props.
82
+ * @param externalProps props for the backdrop slot
83
+ * @returns props that should be spread on the backdrop slot
84
+ */
85
+ getBackdropProps: <TOther extends EventHandlers = {}>(externalProps?: TOther) => UseModalBackdropSlotProps<TOther>;
86
+ /**
87
+ * Resolver for the transition related props.
88
+ * @param externalProps props for the transition element
89
+ * @returns props that should be spread on the transition element
90
+ */
91
+ getTransitionProps: <TOther extends EventHandlers = {}>(externalProps?: TOther) => {
92
+ onEnter: () => void;
93
+ onExited: () => void;
94
+ };
95
+ /**
96
+ * A ref to the component's root DOM element.
97
+ */
98
+ rootRef: React.RefCallback<Element> | null;
99
+ /**
100
+ * A ref to the component's portal DOM element.
101
+ */
102
+ portalRef: React.RefCallback<Element> | null;
103
+ /**
104
+ * If `true`, the modal is the top most one.
105
+ */
106
+ isTopModal: () => boolean;
107
+ /**
108
+ * If `true`, the exiting transition finished (to be used for unmounting the component).
109
+ */
110
+ exited: boolean;
111
+ /**
112
+ * If `true`, the component's child is transition component.
113
+ */
114
+ hasTransition: boolean;
115
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,25 @@
1
+ import * as React from 'react';
2
+ import { NoSsrProps } from './NoSsr.types';
3
+ /**
4
+ * NoSsr purposely removes components from the subject of Server Side Rendering (SSR).
5
+ *
6
+ * This component can be useful in a variety of situations:
7
+ *
8
+ * * Escape hatch for broken dependencies not supporting SSR.
9
+ * * Improve the time-to-first paint on the client by only rendering above the fold.
10
+ * * Reduce the rendering time on the server.
11
+ * * Under too heavy server load, you can turn on service degradation.
12
+ *
13
+ * Demos:
14
+ *
15
+ * - [No SSR](https://next.mui.com/material-ui/react-no-ssr/)
16
+ *
17
+ * API:
18
+ *
19
+ * - [NoSsr API](https://next.mui.com/material-ui/api/no-ssr/)
20
+ */
21
+ declare function NoSsr(props: NoSsrProps): React.JSX.Element;
22
+ declare namespace NoSsr {
23
+ var propTypes: any;
24
+ }
25
+ export default NoSsr;
package/NoSsr/NoSsr.js ADDED
@@ -0,0 +1,73 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import PropTypes from 'prop-types';
5
+ import { exactProp, unstable_useEnhancedEffect as useEnhancedEffect } from '@mui/utils';
6
+ import { jsx as _jsx } from "react/jsx-runtime";
7
+ /**
8
+ * NoSsr purposely removes components from the subject of Server Side Rendering (SSR).
9
+ *
10
+ * This component can be useful in a variety of situations:
11
+ *
12
+ * * Escape hatch for broken dependencies not supporting SSR.
13
+ * * Improve the time-to-first paint on the client by only rendering above the fold.
14
+ * * Reduce the rendering time on the server.
15
+ * * Under too heavy server load, you can turn on service degradation.
16
+ *
17
+ * Demos:
18
+ *
19
+ * - [No SSR](https://next.mui.com/material-ui/react-no-ssr/)
20
+ *
21
+ * API:
22
+ *
23
+ * - [NoSsr API](https://next.mui.com/material-ui/api/no-ssr/)
24
+ */
25
+ function NoSsr(props) {
26
+ const {
27
+ children,
28
+ defer = false,
29
+ fallback = null
30
+ } = props;
31
+ const [mountedState, setMountedState] = React.useState(false);
32
+ useEnhancedEffect(() => {
33
+ if (!defer) {
34
+ setMountedState(true);
35
+ }
36
+ }, [defer]);
37
+ React.useEffect(() => {
38
+ if (defer) {
39
+ setMountedState(true);
40
+ }
41
+ }, [defer]);
42
+
43
+ // We need the Fragment here to force react-docgen to recognise NoSsr as a component.
44
+ return /*#__PURE__*/_jsx(React.Fragment, {
45
+ children: mountedState ? children : fallback
46
+ });
47
+ }
48
+ process.env.NODE_ENV !== "production" ? NoSsr.propTypes /* remove-proptypes */ = {
49
+ // ┌────────────────────────────── Warning ──────────────────────────────┐
50
+ // │ These PropTypes are generated from the TypeScript type definitions. │
51
+ // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
52
+ // └─────────────────────────────────────────────────────────────────────┘
53
+ /**
54
+ * You can wrap a node.
55
+ */
56
+ children: PropTypes.node,
57
+ /**
58
+ * If `true`, the component will not only prevent server-side rendering.
59
+ * It will also defer the rendering of the children into a different screen frame.
60
+ * @default false
61
+ */
62
+ defer: PropTypes.bool,
63
+ /**
64
+ * The fallback content to display.
65
+ * @default null
66
+ */
67
+ fallback: PropTypes.node
68
+ } : void 0;
69
+ if (process.env.NODE_ENV !== 'production') {
70
+ // eslint-disable-next-line
71
+ NoSsr['propTypes' + ''] = exactProp(NoSsr.propTypes);
72
+ }
73
+ export default NoSsr;
@@ -0,0 +1,18 @@
1
+ import * as React from 'react';
2
+ export interface NoSsrProps {
3
+ /**
4
+ * You can wrap a node.
5
+ */
6
+ children?: React.ReactNode;
7
+ /**
8
+ * If `true`, the component will not only prevent server-side rendering.
9
+ * It will also defer the rendering of the children into a different screen frame.
10
+ * @default false
11
+ */
12
+ defer?: boolean;
13
+ /**
14
+ * The fallback content to display.
15
+ * @default null
16
+ */
17
+ fallback?: React.ReactNode;
18
+ }
@@ -0,0 +1 @@
1
+ export {};
package/NoSsr/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
- export { NoSsr as default } from '@mui/base/NoSsr';
2
- export * from '@mui/base/NoSsr';
1
+ export { default } from './NoSsr';
2
+ export * from './NoSsr';
3
+ export * from './NoSsr.types';
package/NoSsr/index.js CHANGED
@@ -1 +1 @@
1
- export { NoSsr as default } from '@mui/base/NoSsr';
1
+ export { default } from './NoSsr';