UNPKG

12.4 kBJavaScriptView Raw
1import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
2import _extends from "@babel/runtime/helpers/esm/extends";
3const _excluded = ["addEndListener", "children", "className", "collapsedSize", "component", "easing", "in", "onEnter", "onEntered", "onEntering", "onExit", "onExited", "onExiting", "orientation", "style", "timeout", "TransitionComponent"];
4import * as React from 'react';
5import clsx from 'clsx';
6import PropTypes from 'prop-types';
7import { Transition } from 'react-transition-group';
8import { elementTypeAcceptingRef } from '@mui/utils';
9import { unstable_composeClasses as composeClasses } from '@mui/base';
10import styled from '../styles/styled';
11import useThemeProps from '../styles/useThemeProps';
12import { duration } from '../styles/createTransitions';
13import { getTransitionProps } from '../transitions/utils';
14import useTheme from '../styles/useTheme';
15import { useForkRef } from '../utils';
16import { getCollapseUtilityClass } from './collapseClasses';
17import { jsx as _jsx } from "react/jsx-runtime";
18
19const useUtilityClasses = ownerState => {
20 const {
21 orientation,
22 classes
23 } = ownerState;
24 const slots = {
25 root: ['root', `${orientation}`],
26 entered: ['entered'],
27 hidden: ['hidden'],
28 wrapper: ['wrapper', `${orientation}`],
29 wrapperInner: ['wrapperInner', `${orientation}`]
30 };
31 return composeClasses(slots, getCollapseUtilityClass, classes);
32};
33
34const CollapseRoot = styled('div', {
35 name: 'MuiCollapse',
36 slot: 'Root',
37 overridesResolver: (props, styles) => {
38 const {
39 ownerState
40 } = props;
41 return [styles.root, styles[ownerState.orientation], ownerState.state === 'entered' && styles.entered, ownerState.state === 'exited' && !ownerState.in && ownerState.collapsedSize === '0px' && styles.hidden];
42 }
43})(({
44 theme,
45 ownerState
46}) => _extends({
47 height: 0,
48 overflow: 'hidden',
49 transition: theme.transitions.create('height')
50}, ownerState.orientation === 'horizontal' && {
51 height: 'auto',
52 width: 0,
53 transition: theme.transitions.create('width')
54}, ownerState.state === 'entered' && _extends({
55 height: 'auto',
56 overflow: 'visible'
57}, ownerState.orientation === 'horizontal' && {
58 width: 'auto'
59}), ownerState.state === 'exited' && !ownerState.in && ownerState.collapsedSize === '0px' && {
60 visibility: 'hidden'
61}));
62const CollapseWrapper = styled('div', {
63 name: 'MuiCollapse',
64 slot: 'Wrapper',
65 overridesResolver: (props, styles) => styles.wrapper
66})(({
67 ownerState
68}) => _extends({
69 // Hack to get children with a negative margin to not falsify the height computation.
70 display: 'flex',
71 width: '100%'
72}, ownerState.orientation === 'horizontal' && {
73 width: 'auto',
74 height: '100%'
75}));
76const CollapseWrapperInner = styled('div', {
77 name: 'MuiCollapse',
78 slot: 'WrapperInner',
79 overridesResolver: (props, styles) => styles.wrapperInner
80})(({
81 ownerState
82}) => _extends({
83 width: '100%'
84}, ownerState.orientation === 'horizontal' && {
85 width: 'auto',
86 height: '100%'
87}));
88/**
89 * The Collapse transition is used by the
90 * [Vertical Stepper](/material-ui/react-stepper/#vertical-stepper) StepContent component.
91 * It uses [react-transition-group](https://github.com/reactjs/react-transition-group) internally.
92 */
93
94const Collapse = /*#__PURE__*/React.forwardRef(function Collapse(inProps, ref) {
95 const props = useThemeProps({
96 props: inProps,
97 name: 'MuiCollapse'
98 });
99
100 const {
101 addEndListener,
102 children,
103 className,
104 collapsedSize: collapsedSizeProp = '0px',
105 component,
106 easing,
107 in: inProp,
108 onEnter,
109 onEntered,
110 onEntering,
111 onExit,
112 onExited,
113 onExiting,
114 orientation = 'vertical',
115 style,
116 timeout = duration.standard,
117 // eslint-disable-next-line react/prop-types
118 TransitionComponent = Transition
119 } = props,
120 other = _objectWithoutPropertiesLoose(props, _excluded);
121
122 const ownerState = _extends({}, props, {
123 orientation,
124 collapsedSize: collapsedSizeProp
125 });
126
127 const classes = useUtilityClasses(ownerState);
128 const theme = useTheme();
129 const timer = React.useRef();
130 const wrapperRef = React.useRef(null);
131 const autoTransitionDuration = React.useRef();
132 const collapsedSize = typeof collapsedSizeProp === 'number' ? `${collapsedSizeProp}px` : collapsedSizeProp;
133 const isHorizontal = orientation === 'horizontal';
134 const size = isHorizontal ? 'width' : 'height';
135 React.useEffect(() => {
136 return () => {
137 clearTimeout(timer.current);
138 };
139 }, []);
140 const nodeRef = React.useRef(null);
141 const handleRef = useForkRef(ref, nodeRef);
142
143 const normalizedTransitionCallback = callback => maybeIsAppearing => {
144 if (callback) {
145 const node = nodeRef.current; // onEnterXxx and onExitXxx callbacks have a different arguments.length value.
146
147 if (maybeIsAppearing === undefined) {
148 callback(node);
149 } else {
150 callback(node, maybeIsAppearing);
151 }
152 }
153 };
154
155 const getWrapperSize = () => wrapperRef.current ? wrapperRef.current[isHorizontal ? 'clientWidth' : 'clientHeight'] : 0;
156
157 const handleEnter = normalizedTransitionCallback((node, isAppearing) => {
158 if (wrapperRef.current && isHorizontal) {
159 // Set absolute position to get the size of collapsed content
160 wrapperRef.current.style.position = 'absolute';
161 }
162
163 node.style[size] = collapsedSize;
164
165 if (onEnter) {
166 onEnter(node, isAppearing);
167 }
168 });
169 const handleEntering = normalizedTransitionCallback((node, isAppearing) => {
170 const wrapperSize = getWrapperSize();
171
172 if (wrapperRef.current && isHorizontal) {
173 // After the size is read reset the position back to default
174 wrapperRef.current.style.position = '';
175 }
176
177 const {
178 duration: transitionDuration,
179 easing: transitionTimingFunction
180 } = getTransitionProps({
181 style,
182 timeout,
183 easing
184 }, {
185 mode: 'enter'
186 });
187
188 if (timeout === 'auto') {
189 const duration2 = theme.transitions.getAutoHeightDuration(wrapperSize);
190 node.style.transitionDuration = `${duration2}ms`;
191 autoTransitionDuration.current = duration2;
192 } else {
193 node.style.transitionDuration = typeof transitionDuration === 'string' ? transitionDuration : `${transitionDuration}ms`;
194 }
195
196 node.style[size] = `${wrapperSize}px`;
197 node.style.transitionTimingFunction = transitionTimingFunction;
198
199 if (onEntering) {
200 onEntering(node, isAppearing);
201 }
202 });
203 const handleEntered = normalizedTransitionCallback((node, isAppearing) => {
204 node.style[size] = 'auto';
205
206 if (onEntered) {
207 onEntered(node, isAppearing);
208 }
209 });
210 const handleExit = normalizedTransitionCallback(node => {
211 node.style[size] = `${getWrapperSize()}px`;
212
213 if (onExit) {
214 onExit(node);
215 }
216 });
217 const handleExited = normalizedTransitionCallback(onExited);
218 const handleExiting = normalizedTransitionCallback(node => {
219 const wrapperSize = getWrapperSize();
220 const {
221 duration: transitionDuration,
222 easing: transitionTimingFunction
223 } = getTransitionProps({
224 style,
225 timeout,
226 easing
227 }, {
228 mode: 'exit'
229 });
230
231 if (timeout === 'auto') {
232 // TODO: rename getAutoHeightDuration to something more generic (width support)
233 // Actually it just calculates animation duration based on size
234 const duration2 = theme.transitions.getAutoHeightDuration(wrapperSize);
235 node.style.transitionDuration = `${duration2}ms`;
236 autoTransitionDuration.current = duration2;
237 } else {
238 node.style.transitionDuration = typeof transitionDuration === 'string' ? transitionDuration : `${transitionDuration}ms`;
239 }
240
241 node.style[size] = collapsedSize;
242 node.style.transitionTimingFunction = transitionTimingFunction;
243
244 if (onExiting) {
245 onExiting(node);
246 }
247 });
248
249 const handleAddEndListener = next => {
250 if (timeout === 'auto') {
251 timer.current = setTimeout(next, autoTransitionDuration.current || 0);
252 }
253
254 if (addEndListener) {
255 // Old call signature before `react-transition-group` implemented `nodeRef`
256 addEndListener(nodeRef.current, next);
257 }
258 };
259
260 return /*#__PURE__*/_jsx(TransitionComponent, _extends({
261 in: inProp,
262 onEnter: handleEnter,
263 onEntered: handleEntered,
264 onEntering: handleEntering,
265 onExit: handleExit,
266 onExited: handleExited,
267 onExiting: handleExiting,
268 addEndListener: handleAddEndListener,
269 nodeRef: nodeRef,
270 timeout: timeout === 'auto' ? null : timeout
271 }, other, {
272 children: (state, childProps) => /*#__PURE__*/_jsx(CollapseRoot, _extends({
273 as: component,
274 className: clsx(classes.root, className, {
275 'entered': classes.entered,
276 'exited': !inProp && collapsedSize === '0px' && classes.hidden
277 }[state]),
278 style: _extends({
279 [isHorizontal ? 'minWidth' : 'minHeight']: collapsedSize
280 }, style),
281 ownerState: _extends({}, ownerState, {
282 state
283 }),
284 ref: handleRef
285 }, childProps, {
286 children: /*#__PURE__*/_jsx(CollapseWrapper, {
287 ownerState: _extends({}, ownerState, {
288 state
289 }),
290 className: classes.wrapper,
291 ref: wrapperRef,
292 children: /*#__PURE__*/_jsx(CollapseWrapperInner, {
293 ownerState: _extends({}, ownerState, {
294 state
295 }),
296 className: classes.wrapperInner,
297 children: children
298 })
299 })
300 }))
301 }));
302});
303process.env.NODE_ENV !== "production" ? Collapse.propTypes
304/* remove-proptypes */
305= {
306 // ----------------------------- Warning --------------------------------
307 // | These PropTypes are generated from the TypeScript type definitions |
308 // | To update them edit the d.ts file and run "yarn proptypes" |
309 // ----------------------------------------------------------------------
310
311 /**
312 * Add a custom transition end trigger. Called with the transitioning DOM
313 * node and a done callback. Allows for more fine grained transition end
314 * logic. Note: Timeouts are still used as a fallback if provided.
315 */
316 addEndListener: PropTypes.func,
317
318 /**
319 * The content node to be collapsed.
320 */
321 children: PropTypes.node,
322
323 /**
324 * Override or extend the styles applied to the component.
325 */
326 classes: PropTypes.object,
327
328 /**
329 * @ignore
330 */
331 className: PropTypes.string,
332
333 /**
334 * The width (horizontal) or height (vertical) of the container when collapsed.
335 * @default '0px'
336 */
337 collapsedSize: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
338
339 /**
340 * The component used for the root node.
341 * Either a string to use a HTML element or a component.
342 */
343 component: elementTypeAcceptingRef,
344
345 /**
346 * The transition timing function.
347 * You may specify a single easing or a object containing enter and exit values.
348 */
349 easing: PropTypes.oneOfType([PropTypes.shape({
350 enter: PropTypes.string,
351 exit: PropTypes.string
352 }), PropTypes.string]),
353
354 /**
355 * If `true`, the component will transition in.
356 */
357 in: PropTypes.bool,
358
359 /**
360 * @ignore
361 */
362 onEnter: PropTypes.func,
363
364 /**
365 * @ignore
366 */
367 onEntered: PropTypes.func,
368
369 /**
370 * @ignore
371 */
372 onEntering: PropTypes.func,
373
374 /**
375 * @ignore
376 */
377 onExit: PropTypes.func,
378
379 /**
380 * @ignore
381 */
382 onExited: PropTypes.func,
383
384 /**
385 * @ignore
386 */
387 onExiting: PropTypes.func,
388
389 /**
390 * The transition orientation.
391 * @default 'vertical'
392 */
393 orientation: PropTypes.oneOf(['horizontal', 'vertical']),
394
395 /**
396 * @ignore
397 */
398 style: PropTypes.object,
399
400 /**
401 * The system prop that allows defining system overrides as well as additional CSS styles.
402 */
403 sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
404
405 /**
406 * The duration for the transition, in milliseconds.
407 * You may specify a single timeout for all transitions, or individually with an object.
408 *
409 * Set to 'auto' to automatically calculate transition time based on height.
410 * @default duration.standard
411 */
412 timeout: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.number, PropTypes.shape({
413 appear: PropTypes.number,
414 enter: PropTypes.number,
415 exit: PropTypes.number
416 })])
417} : void 0;
418Collapse.muiSupportAuto = true;
419export default Collapse;
\No newline at end of file