UNPKG

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