UNPKG

@wix/design-system

Version:

@wix/design-system

185 lines (181 loc) 8.56 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); exports.__esModule = true; exports.default = useCollapse; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties")); var _react = require("react"); var _mergeRefs = require("../../utils/mergeRefs"); var _utils = require("./utils"); var _excluded = ["duration", "easing", "collapseStyles", "expandStyles", "onExpandStart", "onExpandEnd", "onCollapseStart", "onCollapseEnd", "isExpanded", "defaultExpanded", "hasDisabledAnimation"], _excluded2 = ["style", "onTransitionEnd", "refKey"]; function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } var easeInOut = 'cubic-bezier(0.4, 0, 0.2, 1)'; function useCollapse() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, duration = _ref.duration, _ref$easing = _ref.easing, easing = _ref$easing === void 0 ? easeInOut : _ref$easing, _ref$collapseStyles = _ref.collapseStyles, collapseStyles = _ref$collapseStyles === void 0 ? {} : _ref$collapseStyles, _ref$expandStyles = _ref.expandStyles, expandStyles = _ref$expandStyles === void 0 ? {} : _ref$expandStyles, _ref$onExpandStart = _ref.onExpandStart, onExpandStart = _ref$onExpandStart === void 0 ? _utils.noop : _ref$onExpandStart, _ref$onExpandEnd = _ref.onExpandEnd, onExpandEnd = _ref$onExpandEnd === void 0 ? _utils.noop : _ref$onExpandEnd, _ref$onCollapseStart = _ref.onCollapseStart, onCollapseStart = _ref$onCollapseStart === void 0 ? _utils.noop : _ref$onCollapseStart, _ref$onCollapseEnd = _ref.onCollapseEnd, onCollapseEnd = _ref$onCollapseEnd === void 0 ? _utils.noop : _ref$onCollapseEnd, configIsExpanded = _ref.isExpanded, _ref$defaultExpanded = _ref.defaultExpanded, defaultExpanded = _ref$defaultExpanded === void 0 ? false : _ref$defaultExpanded, _ref$hasDisabledAnima = _ref.hasDisabledAnimation, hasDisabledAnimation = _ref$hasDisabledAnima === void 0 ? false : _ref$hasDisabledAnima, initialConfig = (0, _objectWithoutProperties2.default)(_ref, _excluded); var _useControlledState = (0, _utils.useControlledState)(configIsExpanded, defaultExpanded), _useControlledState2 = (0, _slicedToArray2.default)(_useControlledState, 2), isExpanded = _useControlledState2[0], setExpanded = _useControlledState2[1]; var uniqueId = (0, _utils.useUniqueId)(); var el = (0, _react.useRef)(null); var collapsedHeight = "".concat(initialConfig.collapsedHeight || 0, "px"); var collapsedStyles = { display: 'block', height: collapsedHeight, overflow: 'hidden' }; var _useState = (0, _react.useState)(!configIsExpanded), _useState2 = (0, _slicedToArray2.default)(_useState, 2), exitAnimationEnded = _useState2[0], setExitAnimationEnded = _useState2[1]; var _useState3 = (0, _react.useState)(isExpanded ? {} : collapsedStyles), _useState4 = (0, _slicedToArray2.default)(_useState3, 2), styles = _useState4[0], setStylesRaw = _useState4[1]; var setStyles = newStyles => { // We rely on reading information from layout // at arbitrary times, so ensure all style changes // happen before we might attempt to read them. setStylesRaw(newStyles); }; var mergeStyles = newStyles => { setStyles(oldStyles => _objectSpread(_objectSpread({}, oldStyles), newStyles)); }; function getTransitionStyles(height) { if (hasDisabledAnimation) { return {}; } var _duration = duration || (0, _utils.getAutoHeightDuration)(height); return { transition: "height ".concat(_duration, "ms ").concat(easing) }; } (0, _utils.useEffectAfterMount)(() => { var animationFrameTimer; var innerAnimationFrameTimer; if (isExpanded) { setExitAnimationEnded(false); animationFrameTimer = window.requestAnimationFrame(() => { onExpandStart(); mergeStyles(_objectSpread(_objectSpread({}, expandStyles), {}, { willChange: 'height', display: 'block', overflow: 'hidden' })); innerAnimationFrameTimer = window.requestAnimationFrame(() => { var height = (0, _utils.getElementHeight)(el); mergeStyles(_objectSpread(_objectSpread({}, getTransitionStyles(height)), {}, { overflow: 'visible', height })); }); }); } else { animationFrameTimer = window.requestAnimationFrame(() => { onCollapseStart(); var height = (0, _utils.getElementHeight)(el); mergeStyles(_objectSpread(_objectSpread(_objectSpread({}, collapseStyles), getTransitionStyles(height)), {}, { willChange: 'height', height })); innerAnimationFrameTimer = window.requestAnimationFrame(() => { mergeStyles({ height: collapsedHeight, overflow: 'hidden' }); }); }); } return () => { window.cancelAnimationFrame(animationFrameTimer); window.cancelAnimationFrame(innerAnimationFrameTimer); }; }, [isExpanded, collapsedHeight]); var handleTransitionEnd = e => { // Sometimes onTransitionEnd is triggered by another transition, // such as a nested collapse panel transitioning. But we only // want to handle this if this component's element is transitioning if (e.target !== el.current || e.propertyName !== 'height') { return; } // The height comparisons below are a final check before // completing the transition // Sometimes this callback is run even though we've already begun // transitioning the other direction // The conditions give us the opportunity to bail out, // which will prevent the collapsed content from flashing on the screen if (isExpanded) { var height = (0, _utils.getElementHeight)(el); // If the height at the end of the transition // matches the height we're animating to, if (height === styles.height) { setStyles({}); } else { // If the heights don't match, this could be due the height // of the content changing mid-transition mergeStyles({ height }); } onExpandEnd(); // If the height we should be animating to matches the collapsed height, // it's safe to apply the collapsed overrides } else if (styles.height === collapsedHeight) { setStyles(collapsedStyles); setExitAnimationEnded(true); onCollapseEnd(); } }; function getCollapseProps() { var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref2$style = _ref2.style, style = _ref2$style === void 0 ? {} : _ref2$style, _ref2$onTransitionEnd = _ref2.onTransitionEnd, onTransitionEnd = _ref2$onTransitionEnd === void 0 ? _utils.noop : _ref2$onTransitionEnd, _ref2$refKey = _ref2.refKey, refKey = _ref2$refKey === void 0 ? 'ref' : _ref2$refKey, rest = (0, _objectWithoutProperties2.default)(_ref2, _excluded2); var theirRef = rest[refKey]; return _objectSpread(_objectSpread({ id: "react-collapsed-panel-".concat(uniqueId), 'aria-hidden': !isExpanded }, rest), {}, { [refKey]: (0, _mergeRefs.mergeRefs)(el, theirRef), onTransitionEnd: (0, _utils.callAll)(handleTransitionEnd, onTransitionEnd), style: _objectSpread(_objectSpread({ boxSizing: 'border-box' }, style), styles) }); } return { getCollapseProps, isExpanded, setExpanded, exitAnimationEnded: process.env.NODE_ENV === 'test' ? !isExpanded : exitAnimationEnded }; } //# sourceMappingURL=useCollapse.js.map