UNPKG

12.8 kBJavaScriptView Raw
1"use strict";
2'use client';
3
4var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
5var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
6Object.defineProperty(exports, "__esModule", {
7 value: true
8});
9exports.default = void 0;
10exports.setTranslateValue = setTranslateValue;
11var React = _interopRequireWildcard(require("react"));
12var _propTypes = _interopRequireDefault(require("prop-types"));
13var _reactTransitionGroup = require("react-transition-group");
14var _chainPropTypes = _interopRequireDefault(require("@mui/utils/chainPropTypes"));
15var _HTMLElementType = _interopRequireDefault(require("@mui/utils/HTMLElementType"));
16var _elementAcceptingRef = _interopRequireDefault(require("@mui/utils/elementAcceptingRef"));
17var _getReactElementRef = _interopRequireDefault(require("@mui/utils/getReactElementRef"));
18var _debounce = _interopRequireDefault(require("../utils/debounce"));
19var _useForkRef = _interopRequireDefault(require("../utils/useForkRef"));
20var _zeroStyled = require("../zero-styled");
21var _utils = require("../transitions/utils");
22var _utils2 = require("../utils");
23var _jsxRuntime = require("react/jsx-runtime");
24// Translate the node so it can't be seen on the screen.
25// Later, we're going to translate the node back to its original location with `none`.
26function getTranslateValue(direction, node, resolvedContainer) {
27 const rect = node.getBoundingClientRect();
28 const containerRect = resolvedContainer && resolvedContainer.getBoundingClientRect();
29 const containerWindow = (0, _utils2.ownerWindow)(node);
30 let transform;
31 if (node.fakeTransform) {
32 transform = node.fakeTransform;
33 } else {
34 const computedStyle = containerWindow.getComputedStyle(node);
35 transform = computedStyle.getPropertyValue('-webkit-transform') || computedStyle.getPropertyValue('transform');
36 }
37 let offsetX = 0;
38 let offsetY = 0;
39 if (transform && transform !== 'none' && typeof transform === 'string') {
40 const transformValues = transform.split('(')[1].split(')')[0].split(',');
41 offsetX = parseInt(transformValues[4], 10);
42 offsetY = parseInt(transformValues[5], 10);
43 }
44 if (direction === 'left') {
45 if (containerRect) {
46 return `translateX(${containerRect.right + offsetX - rect.left}px)`;
47 }
48 return `translateX(${containerWindow.innerWidth + offsetX - rect.left}px)`;
49 }
50 if (direction === 'right') {
51 if (containerRect) {
52 return `translateX(-${rect.right - containerRect.left - offsetX}px)`;
53 }
54 return `translateX(-${rect.left + rect.width - offsetX}px)`;
55 }
56 if (direction === 'up') {
57 if (containerRect) {
58 return `translateY(${containerRect.bottom + offsetY - rect.top}px)`;
59 }
60 return `translateY(${containerWindow.innerHeight + offsetY - rect.top}px)`;
61 }
62
63 // direction === 'down'
64 if (containerRect) {
65 return `translateY(-${rect.top - containerRect.top + rect.height - offsetY}px)`;
66 }
67 return `translateY(-${rect.top + rect.height - offsetY}px)`;
68}
69function resolveContainer(containerPropProp) {
70 return typeof containerPropProp === 'function' ? containerPropProp() : containerPropProp;
71}
72function setTranslateValue(direction, node, containerProp) {
73 const resolvedContainer = resolveContainer(containerProp);
74 const transform = getTranslateValue(direction, node, resolvedContainer);
75 if (transform) {
76 node.style.webkitTransform = transform;
77 node.style.transform = transform;
78 }
79}
80
81/**
82 * The Slide transition is used by the [Drawer](/material-ui/react-drawer/) component.
83 * It uses [react-transition-group](https://github.com/reactjs/react-transition-group) internally.
84 */
85const Slide = /*#__PURE__*/React.forwardRef(function Slide(props, ref) {
86 const theme = (0, _zeroStyled.useTheme)();
87 const defaultEasing = {
88 enter: theme.transitions.easing.easeOut,
89 exit: theme.transitions.easing.sharp
90 };
91 const defaultTimeout = {
92 enter: theme.transitions.duration.enteringScreen,
93 exit: theme.transitions.duration.leavingScreen
94 };
95 const {
96 addEndListener,
97 appear = true,
98 children,
99 container: containerProp,
100 direction = 'down',
101 easing: easingProp = defaultEasing,
102 in: inProp,
103 onEnter,
104 onEntered,
105 onEntering,
106 onExit,
107 onExited,
108 onExiting,
109 style,
110 timeout = defaultTimeout,
111 // eslint-disable-next-line react/prop-types
112 TransitionComponent = _reactTransitionGroup.Transition,
113 ...other
114 } = props;
115 const childrenRef = React.useRef(null);
116 const handleRef = (0, _useForkRef.default)((0, _getReactElementRef.default)(children), childrenRef, ref);
117 const normalizedTransitionCallback = callback => isAppearing => {
118 if (callback) {
119 // onEnterXxx and onExitXxx callbacks have a different arguments.length value.
120 if (isAppearing === undefined) {
121 callback(childrenRef.current);
122 } else {
123 callback(childrenRef.current, isAppearing);
124 }
125 }
126 };
127 const handleEnter = normalizedTransitionCallback((node, isAppearing) => {
128 setTranslateValue(direction, node, containerProp);
129 (0, _utils.reflow)(node);
130 if (onEnter) {
131 onEnter(node, isAppearing);
132 }
133 });
134 const handleEntering = normalizedTransitionCallback((node, isAppearing) => {
135 const transitionProps = (0, _utils.getTransitionProps)({
136 timeout,
137 style,
138 easing: easingProp
139 }, {
140 mode: 'enter'
141 });
142 node.style.webkitTransition = theme.transitions.create('-webkit-transform', {
143 ...transitionProps
144 });
145 node.style.transition = theme.transitions.create('transform', {
146 ...transitionProps
147 });
148 node.style.webkitTransform = 'none';
149 node.style.transform = 'none';
150 if (onEntering) {
151 onEntering(node, isAppearing);
152 }
153 });
154 const handleEntered = normalizedTransitionCallback(onEntered);
155 const handleExiting = normalizedTransitionCallback(onExiting);
156 const handleExit = normalizedTransitionCallback(node => {
157 const transitionProps = (0, _utils.getTransitionProps)({
158 timeout,
159 style,
160 easing: easingProp
161 }, {
162 mode: 'exit'
163 });
164 node.style.webkitTransition = theme.transitions.create('-webkit-transform', transitionProps);
165 node.style.transition = theme.transitions.create('transform', transitionProps);
166 setTranslateValue(direction, node, containerProp);
167 if (onExit) {
168 onExit(node);
169 }
170 });
171 const handleExited = normalizedTransitionCallback(node => {
172 // No need for transitions when the component is hidden
173 node.style.webkitTransition = '';
174 node.style.transition = '';
175 if (onExited) {
176 onExited(node);
177 }
178 });
179 const handleAddEndListener = next => {
180 if (addEndListener) {
181 // Old call signature before `react-transition-group` implemented `nodeRef`
182 addEndListener(childrenRef.current, next);
183 }
184 };
185 const updatePosition = React.useCallback(() => {
186 if (childrenRef.current) {
187 setTranslateValue(direction, childrenRef.current, containerProp);
188 }
189 }, [direction, containerProp]);
190 React.useEffect(() => {
191 // Skip configuration where the position is screen size invariant.
192 if (inProp || direction === 'down' || direction === 'right') {
193 return undefined;
194 }
195 const handleResize = (0, _debounce.default)(() => {
196 if (childrenRef.current) {
197 setTranslateValue(direction, childrenRef.current, containerProp);
198 }
199 });
200 const containerWindow = (0, _utils2.ownerWindow)(childrenRef.current);
201 containerWindow.addEventListener('resize', handleResize);
202 return () => {
203 handleResize.clear();
204 containerWindow.removeEventListener('resize', handleResize);
205 };
206 }, [direction, inProp, containerProp]);
207 React.useEffect(() => {
208 if (!inProp) {
209 // We need to update the position of the drawer when the direction change and
210 // when it's hidden.
211 updatePosition();
212 }
213 }, [inProp, updatePosition]);
214 return /*#__PURE__*/(0, _jsxRuntime.jsx)(TransitionComponent, {
215 nodeRef: childrenRef,
216 onEnter: handleEnter,
217 onEntered: handleEntered,
218 onEntering: handleEntering,
219 onExit: handleExit,
220 onExited: handleExited,
221 onExiting: handleExiting,
222 addEndListener: handleAddEndListener,
223 appear: appear,
224 in: inProp,
225 timeout: timeout,
226 ...other,
227 children: (state, childProps) => {
228 return /*#__PURE__*/React.cloneElement(children, {
229 ref: handleRef,
230 style: {
231 visibility: state === 'exited' && !inProp ? 'hidden' : undefined,
232 ...style,
233 ...children.props.style
234 },
235 ...childProps
236 });
237 }
238 });
239});
240process.env.NODE_ENV !== "production" ? Slide.propTypes /* remove-proptypes */ = {
241 // ┌────────────────────────────── Warning ──────────────────────────────┐
242 // │ These PropTypes are generated from the TypeScript type definitions. │
243 // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
244 // └─────────────────────────────────────────────────────────────────────┘
245 /**
246 * Add a custom transition end trigger. Called with the transitioning DOM
247 * node and a done callback. Allows for more fine grained transition end
248 * logic. Note: Timeouts are still used as a fallback if provided.
249 */
250 addEndListener: _propTypes.default.func,
251 /**
252 * Perform the enter transition when it first mounts if `in` is also `true`.
253 * Set this to `false` to disable this behavior.
254 * @default true
255 */
256 appear: _propTypes.default.bool,
257 /**
258 * A single child content element.
259 */
260 children: _elementAcceptingRef.default.isRequired,
261 /**
262 * An HTML element, or a function that returns one.
263 * It's used to set the container the Slide is transitioning from.
264 */
265 container: (0, _chainPropTypes.default)(_propTypes.default.oneOfType([_HTMLElementType.default, _propTypes.default.func]), props => {
266 if (props.open) {
267 const resolvedContainer = resolveContainer(props.container);
268 if (resolvedContainer && resolvedContainer.nodeType === 1) {
269 const box = resolvedContainer.getBoundingClientRect();
270 if (process.env.NODE_ENV !== 'test' && box.top === 0 && box.left === 0 && box.right === 0 && box.bottom === 0) {
271 return new Error(['MUI: The `container` prop provided to the component is invalid.', 'The anchor element should be part of the document layout.', "Make sure the element is present in the document or that it's not display none."].join('\n'));
272 }
273 } else if (!resolvedContainer || typeof resolvedContainer.getBoundingClientRect !== 'function' || resolvedContainer.contextElement != null && resolvedContainer.contextElement.nodeType !== 1) {
274 return new Error(['MUI: The `container` prop provided to the component is invalid.', 'It should be an HTML element instance.'].join('\n'));
275 }
276 }
277 return null;
278 }),
279 /**
280 * Direction the child node will enter from.
281 * @default 'down'
282 */
283 direction: _propTypes.default.oneOf(['down', 'left', 'right', 'up']),
284 /**
285 * The transition timing function.
286 * You may specify a single easing or a object containing enter and exit values.
287 * @default {
288 * enter: theme.transitions.easing.easeOut,
289 * exit: theme.transitions.easing.sharp,
290 * }
291 */
292 easing: _propTypes.default.oneOfType([_propTypes.default.shape({
293 enter: _propTypes.default.string,
294 exit: _propTypes.default.string
295 }), _propTypes.default.string]),
296 /**
297 * If `true`, the component will transition in.
298 */
299 in: _propTypes.default.bool,
300 /**
301 * @ignore
302 */
303 onEnter: _propTypes.default.func,
304 /**
305 * @ignore
306 */
307 onEntered: _propTypes.default.func,
308 /**
309 * @ignore
310 */
311 onEntering: _propTypes.default.func,
312 /**
313 * @ignore
314 */
315 onExit: _propTypes.default.func,
316 /**
317 * @ignore
318 */
319 onExited: _propTypes.default.func,
320 /**
321 * @ignore
322 */
323 onExiting: _propTypes.default.func,
324 /**
325 * @ignore
326 */
327 style: _propTypes.default.object,
328 /**
329 * The duration for the transition, in milliseconds.
330 * You may specify a single timeout for all transitions, or individually with an object.
331 * @default {
332 * enter: theme.transitions.duration.enteringScreen,
333 * exit: theme.transitions.duration.leavingScreen,
334 * }
335 */
336 timeout: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.shape({
337 appear: _propTypes.default.number,
338 enter: _propTypes.default.number,
339 exit: _propTypes.default.number
340 })])
341} : void 0;
342var _default = exports.default = Slide;
\No newline at end of file