UNPKG

@atlaskit/motion

Version:

A set of utilities to apply motion in your application.

102 lines (98 loc) 4.58 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.useResizingHeight = void 0; var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _react = require("react"); var _curves = require("../utils/curves"); var _durations = require("../utils/durations"); var _isReducedMotion = require("../utils/is-reduced-motion"); var _useElementRef3 = require("../utils/use-element-ref"); var _useLayoutEffect = require("../utils/use-layout-effect"); var _useRequestAnimationFrame = require("../utils/use-request-animation-frame"); var _useSetTimeout = require("../utils/use-set-timeout"); var _useSnapshotBeforeUpdate = require("../utils/use-snapshot-before-update"); /* eslint-disable @repo/internal/deprecations/deprecation-ticket-required */ /** * `useResizingHeight` animates height changes over state changes. If the height hasn't changed nothing will happen. * * __WARNING__: Potentially janky. This hook animates height which is * [notoriously unperformant](https://firefox-source-docs.mozilla.org/performance/bestpractices.html#Get_familiar_with_the_pipeline_that_gets_pixels_to_the_screen). * Test your app over low powered devices, you may want to avoid this if you can see it impacting FPS. * * See [examples](https://atlaskit.atlassian.com/packages/design-system/motion/docs/resizing-motions). * * @deprecated Use `useResizing` from `@atlaskit/motion/resizing` instead. Pass `dimension: 'height'` * to animate height changes. The new hook supports `'width'`, `'height'`, or `'both'`. */ var useResizingHeight = exports.useResizingHeight = function useResizingHeight() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref$duration = _ref.duration, calcDuration = _ref$duration === void 0 ? function () { return _durations.durations.medium; } : _ref$duration, _ref$timingFunction = _ref.timingFunction, calcTimingFunction = _ref$timingFunction === void 0 ? function () { return _curves.easeInOut; } : _ref$timingFunction; var prevDimensions = (0, _react.useRef)(); var _useElementRef = (0, _useElementRef3.useElementRef)(), _useElementRef2 = (0, _slicedToArray2.default)(_useElementRef, 2), element = _useElementRef2[0], setElementRef = _useElementRef2[1]; // We cleanup on the next effect to prevent the previous timeout being called during // the next motion - as now the timeout has essentially been extended! var setTimeout = (0, _useSetTimeout.useSetTimeout)({ cleanup: 'next-effect' }); var requestAnimationFrame = (0, _useRequestAnimationFrame.useRequestAnimationFrame)(); (0, _useSnapshotBeforeUpdate.useSnapshotBeforeUpdate)(function () { if ((0, _isReducedMotion.isReducedMotion)() || !element) { return; } prevDimensions.current = element.getBoundingClientRect(); }); (0, _useLayoutEffect.useLayoutEffect)(function () { if ((0, _isReducedMotion.isReducedMotion)() || !element || !prevDimensions.current) { return; } // We might already be animating. // Because of that we need to expand to the destination height first. element.setAttribute('style', ''); var nextDimensions = element.getBoundingClientRect(); if (nextDimensions.height === prevDimensions.current.height) { return; } var duration = calcDuration(prevDimensions.current.height, nextDimensions.height); var newStyles = { height: "".concat(prevDimensions.current.height, "px"), willChange: 'height', transitionProperty: 'height', transitionDuration: "".concat(duration, "ms"), boxSizing: 'border-box', transitionTimingFunction: calcTimingFunction(prevDimensions.current.height, nextDimensions.height, duration) }; Object.assign(element.style, newStyles); // We split this over two animation frames so the DOM has enough time to flush the changes. // We are deliberately not skipping this frame if another render happens - if we do the motion doesn't finish properly. requestAnimationFrame(function () { requestAnimationFrame(function () { if (!element) { return; } element.style.height = "".concat(nextDimensions.height, "px"); setTimeout(function () { if (!element) { return; } element.setAttribute('style', ''); }, duration); }); }); }); return { ref: setElementRef }; };