123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
- import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
- import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
- import { useEvent } from 'rc-util';
- import useState from "rc-util/es/hooks/useState";
- import useSyncState from "rc-util/es/hooks/useSyncState";
- import * as React from 'react';
- import { useEffect, useRef } from 'react';
- import { STATUS_APPEAR, STATUS_ENTER, STATUS_LEAVE, STATUS_NONE, STEP_ACTIVE, STEP_PREPARE, STEP_PREPARED, STEP_START } from "../interface";
- import useDomMotionEvents from "./useDomMotionEvents";
- import useIsomorphicLayoutEffect from "./useIsomorphicLayoutEffect";
- import useStepQueue, { DoStep, isActive, SkipStep } from "./useStepQueue";
- export default function useStatus(supportMotion, visible, getElement, _ref) {
- var _ref$motionEnter = _ref.motionEnter,
- motionEnter = _ref$motionEnter === void 0 ? true : _ref$motionEnter,
- _ref$motionAppear = _ref.motionAppear,
- motionAppear = _ref$motionAppear === void 0 ? true : _ref$motionAppear,
- _ref$motionLeave = _ref.motionLeave,
- motionLeave = _ref$motionLeave === void 0 ? true : _ref$motionLeave,
- motionDeadline = _ref.motionDeadline,
- motionLeaveImmediately = _ref.motionLeaveImmediately,
- onAppearPrepare = _ref.onAppearPrepare,
- onEnterPrepare = _ref.onEnterPrepare,
- onLeavePrepare = _ref.onLeavePrepare,
- onAppearStart = _ref.onAppearStart,
- onEnterStart = _ref.onEnterStart,
- onLeaveStart = _ref.onLeaveStart,
- onAppearActive = _ref.onAppearActive,
- onEnterActive = _ref.onEnterActive,
- onLeaveActive = _ref.onLeaveActive,
- onAppearEnd = _ref.onAppearEnd,
- onEnterEnd = _ref.onEnterEnd,
- onLeaveEnd = _ref.onLeaveEnd,
- onVisibleChanged = _ref.onVisibleChanged;
- // Used for outer render usage to avoid `visible: false & status: none` to render nothing
- var _useState = useState(),
- _useState2 = _slicedToArray(_useState, 2),
- asyncVisible = _useState2[0],
- setAsyncVisible = _useState2[1];
- var _useSyncState = useSyncState(STATUS_NONE),
- _useSyncState2 = _slicedToArray(_useSyncState, 2),
- getStatus = _useSyncState2[0],
- setStatus = _useSyncState2[1];
- var _useState3 = useState(null),
- _useState4 = _slicedToArray(_useState3, 2),
- style = _useState4[0],
- setStyle = _useState4[1];
- var currentStatus = getStatus();
- var mountedRef = useRef(false);
- var deadlineRef = useRef(null);
- // =========================== Dom Node ===========================
- function getDomElement() {
- return getElement();
- }
- // ========================== Motion End ==========================
- var activeRef = useRef(false);
- /**
- * Clean up status & style
- */
- function updateMotionEndStatus() {
- setStatus(STATUS_NONE);
- setStyle(null, true);
- }
- var onInternalMotionEnd = useEvent(function (event) {
- var status = getStatus();
- // Do nothing since not in any transition status.
- // This may happen when `motionDeadline` trigger.
- if (status === STATUS_NONE) {
- return;
- }
- var element = getDomElement();
- if (event && !event.deadline && event.target !== element) {
- // event exists
- // not initiated by deadline
- // transitionEnd not fired by inner elements
- return;
- }
- var currentActive = activeRef.current;
- var canEnd;
- if (status === STATUS_APPEAR && currentActive) {
- canEnd = onAppearEnd === null || onAppearEnd === void 0 ? void 0 : onAppearEnd(element, event);
- } else if (status === STATUS_ENTER && currentActive) {
- canEnd = onEnterEnd === null || onEnterEnd === void 0 ? void 0 : onEnterEnd(element, event);
- } else if (status === STATUS_LEAVE && currentActive) {
- canEnd = onLeaveEnd === null || onLeaveEnd === void 0 ? void 0 : onLeaveEnd(element, event);
- }
- // Only update status when `canEnd` and not destroyed
- if (currentActive && canEnd !== false) {
- updateMotionEndStatus();
- }
- });
- var _useDomMotionEvents = useDomMotionEvents(onInternalMotionEnd),
- _useDomMotionEvents2 = _slicedToArray(_useDomMotionEvents, 1),
- patchMotionEvents = _useDomMotionEvents2[0];
- // ============================= Step =============================
- var getEventHandlers = function getEventHandlers(targetStatus) {
- switch (targetStatus) {
- case STATUS_APPEAR:
- return _defineProperty(_defineProperty(_defineProperty({}, STEP_PREPARE, onAppearPrepare), STEP_START, onAppearStart), STEP_ACTIVE, onAppearActive);
- case STATUS_ENTER:
- return _defineProperty(_defineProperty(_defineProperty({}, STEP_PREPARE, onEnterPrepare), STEP_START, onEnterStart), STEP_ACTIVE, onEnterActive);
- case STATUS_LEAVE:
- return _defineProperty(_defineProperty(_defineProperty({}, STEP_PREPARE, onLeavePrepare), STEP_START, onLeaveStart), STEP_ACTIVE, onLeaveActive);
- default:
- return {};
- }
- };
- var eventHandlers = React.useMemo(function () {
- return getEventHandlers(currentStatus);
- }, [currentStatus]);
- var _useStepQueue = useStepQueue(currentStatus, !supportMotion, function (newStep) {
- // Only prepare step can be skip
- if (newStep === STEP_PREPARE) {
- var onPrepare = eventHandlers[STEP_PREPARE];
- if (!onPrepare) {
- return SkipStep;
- }
- return onPrepare(getDomElement());
- }
- // Rest step is sync update
- if (step in eventHandlers) {
- var _eventHandlers$step;
- setStyle(((_eventHandlers$step = eventHandlers[step]) === null || _eventHandlers$step === void 0 ? void 0 : _eventHandlers$step.call(eventHandlers, getDomElement(), null)) || null);
- }
- if (step === STEP_ACTIVE && currentStatus !== STATUS_NONE) {
- // Patch events when motion needed
- patchMotionEvents(getDomElement());
- if (motionDeadline > 0) {
- clearTimeout(deadlineRef.current);
- deadlineRef.current = setTimeout(function () {
- onInternalMotionEnd({
- deadline: true
- });
- }, motionDeadline);
- }
- }
- if (step === STEP_PREPARED) {
- updateMotionEndStatus();
- }
- return DoStep;
- }),
- _useStepQueue2 = _slicedToArray(_useStepQueue, 2),
- startStep = _useStepQueue2[0],
- step = _useStepQueue2[1];
- var active = isActive(step);
- activeRef.current = active;
- // ============================ Status ============================
- var visibleRef = useRef(null);
- // Update with new status
- useIsomorphicLayoutEffect(function () {
- // When use Suspense, the `visible` will repeat trigger,
- // But not real change of the `visible`, we need to skip it.
- // https://github.com/ant-design/ant-design/issues/44379
- if (mountedRef.current && visibleRef.current === visible) {
- return;
- }
- setAsyncVisible(visible);
- var isMounted = mountedRef.current;
- mountedRef.current = true;
- // if (!supportMotion) {
- // return;
- // }
- var nextStatus;
- // Appear
- if (!isMounted && visible && motionAppear) {
- nextStatus = STATUS_APPEAR;
- }
- // Enter
- if (isMounted && visible && motionEnter) {
- nextStatus = STATUS_ENTER;
- }
- // Leave
- if (isMounted && !visible && motionLeave || !isMounted && motionLeaveImmediately && !visible && motionLeave) {
- nextStatus = STATUS_LEAVE;
- }
- var nextEventHandlers = getEventHandlers(nextStatus);
- // Update to next status
- if (nextStatus && (supportMotion || nextEventHandlers[STEP_PREPARE])) {
- setStatus(nextStatus);
- startStep();
- } else {
- // Set back in case no motion but prev status has prepare step
- setStatus(STATUS_NONE);
- }
- visibleRef.current = visible;
- }, [visible]);
- // ============================ Effect ============================
- // Reset when motion changed
- useEffect(function () {
- if (
- // Cancel appear
- currentStatus === STATUS_APPEAR && !motionAppear ||
- // Cancel enter
- currentStatus === STATUS_ENTER && !motionEnter ||
- // Cancel leave
- currentStatus === STATUS_LEAVE && !motionLeave) {
- setStatus(STATUS_NONE);
- }
- }, [motionAppear, motionEnter, motionLeave]);
- useEffect(function () {
- return function () {
- mountedRef.current = false;
- clearTimeout(deadlineRef.current);
- };
- }, []);
- // Trigger `onVisibleChanged`
- var firstMountChangeRef = React.useRef(false);
- useEffect(function () {
- // [visible & motion not end] => [!visible & motion end] still need trigger onVisibleChanged
- if (asyncVisible) {
- firstMountChangeRef.current = true;
- }
- if (asyncVisible !== undefined && currentStatus === STATUS_NONE) {
- // Skip first render is invisible since it's nothing changed
- if (firstMountChangeRef.current || asyncVisible) {
- onVisibleChanged === null || onVisibleChanged === void 0 || onVisibleChanged(asyncVisible);
- }
- firstMountChangeRef.current = true;
- }
- }, [asyncVisible, currentStatus]);
- // ============================ Styles ============================
- var mergedStyle = style;
- if (eventHandlers[STEP_PREPARE] && step === STEP_START) {
- mergedStyle = _objectSpread({
- transition: 'none'
- }, mergedStyle);
- }
- return [currentStatus, step, mergedStyle, asyncVisible !== null && asyncVisible !== void 0 ? asyncVisible : visible];
- }
|