@shopify/polaris
Version:
Shopify’s product component library
71 lines (62 loc) • 2.38 kB
JavaScript
import { objectSpread2 as _objectSpread2 } from '../../_virtual/_rollupPluginBabelHelpers.js';
import React$1, { useState, useRef, useCallback, useEffect } from 'react';
import { classNames } from '../../utilities/css.js';
import styles from './Collapsible.scss.js';
function Collapsible({
id,
expandOnPrint,
open,
transition,
children
}) {
const [height, setHeight] = useState(0);
const [isOpen, setIsOpen] = useState(open);
const [animationState, setAnimationState] = useState('idle');
const collapisbleContainer = useRef(null);
const isFullyOpen = animationState === 'idle' && open && isOpen;
const isFullyClosed = animationState === 'idle' && !open && !isOpen;
const content = expandOnPrint || !isFullyClosed ? children : null;
const wrapperClassName = classNames(styles.Collapsible, isFullyClosed && styles.isFullyClosed, expandOnPrint && styles.expandOnPrint);
const collapsibleStyles = _objectSpread2(_objectSpread2({}, transition && {
transitionDuration: `${transition.duration}`,
transitionTimingFunction: `${transition.timingFunction}`
}), {
maxHeight: isFullyOpen ? 'none' : `${height}px`,
overflow: isFullyOpen ? 'visible' : 'hidden'
});
const handleCompleteAnimation = useCallback(() => {
setAnimationState('idle');
setIsOpen(open);
}, [open]);
useEffect(() => {
if (open !== isOpen) {
setAnimationState('measuring');
}
}, [open, isOpen]);
useEffect(() => {
if (!open || !collapisbleContainer.current) return; // If collapsible defaults to open, set an initial height
setHeight(collapisbleContainer.current.scrollHeight); // eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
if (!collapisbleContainer.current) return;
switch (animationState) {
case 'idle':
break;
case 'measuring':
setHeight(collapisbleContainer.current.scrollHeight);
setAnimationState('animating');
break;
case 'animating':
setHeight(open ? collapisbleContainer.current.scrollHeight : 0);
}
}, [animationState, open, isOpen]);
return /*#__PURE__*/React$1.createElement("div", {
id: id,
style: collapsibleStyles,
ref: collapisbleContainer,
className: wrapperClassName,
onTransitionEnd: handleCompleteAnimation,
"aria-expanded": open
}, content);
}
export { Collapsible };