UNPKG

@shopify/polaris

Version:

Shopify’s product component library

155 lines (132 loc) 4.14 kB
import { objectSpread2 as _objectSpread2 } from '../../_virtual/_rollupPluginBabelHelpers.js'; import React$1, { Component, createRef, createContext } from 'react'; import { classNames } from '../../utilities/css.js'; import styles from './Collapsible.scss.js'; var ParentCollapsibleExpandingContext = /*#__PURE__*/createContext(false); class CollapsibleInner extends Component { constructor(...args) { super(...args); this.context = void 0; this.state = { height: null, animationState: 'idle', // eslint-disable-next-line react/no-unused-state open: this.props.open }; this.node = /*#__PURE__*/createRef(); this.heightNode = /*#__PURE__*/createRef(); this.handleTransitionEnd = event => { var { target } = event; if (target === this.node.current) { this.setState({ animationState: 'idle', height: null }); } }; } static getDerivedStateFromProps({ open: willOpen }, { open, animationState: prevAnimationState }) { var nextAnimationState = prevAnimationState; if (open !== willOpen) { nextAnimationState = 'measuring'; } return { animationState: nextAnimationState, open: willOpen }; } componentDidUpdate({ open: wasOpen }) { var { animationState } = this.state; var parentCollapsibleExpanding = this.context; if (parentCollapsibleExpanding && animationState !== 'idle') { // eslint-disable-next-line react/no-did-update-set-state this.setState({ animationState: 'idle' }); return; } requestAnimationFrame(() => { var heightNode = this.heightNode.current; switch (animationState) { case 'idle': break; case 'measuring': this.setState({ animationState: wasOpen ? 'closingStart' : 'openingStart', height: wasOpen && heightNode ? heightNode.scrollHeight : 0 }); break; case 'closingStart': this.setState({ animationState: 'closing', height: 0 }); break; case 'openingStart': this.setState({ animationState: 'opening', height: heightNode ? heightNode.scrollHeight : 0 }); } }); } render() { var { id, expandOnPrint, open, children, transition } = this.props; var { animationState, height } = this.state; var parentCollapsibleExpanding = this.context; var animating = animationState !== 'idle'; var wrapperClassName = classNames(styles.Collapsible, open && styles.open, animating && styles.animating, !animating && open && styles.fullyOpen, expandOnPrint && styles.expandOnPrint); var displayHeight = collapsibleHeight(open, animationState, height); var content = animating || open || expandOnPrint ? children : null; var transitionProperties = transition ? { transitionDuration: "".concat(transition.duration), transitionTimingFunction: "".concat(transition.timingFunction) } : null; return /*#__PURE__*/React$1.createElement(ParentCollapsibleExpandingContext.Provider, { value: parentCollapsibleExpanding || open && animationState !== 'idle' }, /*#__PURE__*/React$1.createElement("div", { id: id, "aria-hidden": !open, style: _objectSpread2({ maxHeight: "".concat(displayHeight) }, transitionProperties), className: wrapperClassName, ref: this.node, onTransitionEnd: this.handleTransitionEnd }, /*#__PURE__*/React$1.createElement("div", { ref: this.heightNode }, content))); } } CollapsibleInner.contextType = ParentCollapsibleExpandingContext; function collapsibleHeight(open, animationState, height) { if (animationState === 'idle' && open) { return open ? 'none' : undefined; } if (animationState === 'measuring') { return open ? undefined : 'none'; } return "".concat(height || 0, "px"); } var Collapsible = CollapsibleInner; export { Collapsible };