UNPKG

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