@re-flex/transition-group
Version:
Re-flex UI Transtion Controller Package
139 lines (138 loc) • 4.58 kB
JavaScript
import { useCallback, useEffect, useLayoutEffect, useMemo, useState, } from "react";
export var Phase;
(function (Phase) {
Phase[Phase["APPEAR"] = 0] = "APPEAR";
Phase[Phase["APPEARING"] = 1] = "APPEARING";
Phase[Phase["APPEARED"] = 2] = "APPEARED";
Phase[Phase["ENTER"] = 3] = "ENTER";
Phase[Phase["ENTERING"] = 4] = "ENTERING";
Phase[Phase["ENTERED"] = 5] = "ENTERED";
Phase[Phase["EXIT"] = 6] = "EXIT";
Phase[Phase["EXITING"] = 7] = "EXITING";
Phase[Phase["EXITED"] = 8] = "EXITED";
})(Phase || (Phase = {}));
const waitFor = (time) => new Promise((run) => {
let timeout = setTimeout(() => run(timeout), time);
});
const useUseTransition = (props) => {
const { in: inProp = false, appear = false, enter = true, exit = true, duration = 500, onEnter, onEntering, onEntered, onExit, onExiting, onExited, } = props;
let ignoreInPropChange = false;
const [phase, setPhase] = useState(() => {
ignoreInPropChange = true;
return Phase[!inProp ? "EXITED" : appear ? "APPEAR" : "APPEARED"];
});
useLayoutEffect(() => {
if (!!(inProp && enter)) {
setPhase(Phase.ENTER);
}
else if (!!(inProp && !enter)) {
setPhase(Phase.ENTERED);
}
else if (!!(!inProp && exit)) {
setPhase(Phase.EXIT);
}
else if (!!(!inProp && !exit)) {
setPhase(Phase.EXITED);
}
}, [inProp]);
useEffect(() => {
if (phase !== 8)
phaseController();
}, [phase]);
const phaseController = useCallback(async () => {
if (phase === Phase.APPEAR) {
await handleAppear();
}
else if (phase === Phase.APPEARING) {
await waitFor(1);
await handleAppearing();
}
else if (phase === Phase.APPEARED) {
await handleAppeared();
}
else if (phase === Phase.ENTER) {
await handleEnter();
}
else if (phase === Phase.ENTERING) {
await waitFor(1);
await handleEntering();
}
else if (phase === Phase.ENTERED) {
await handleonEntered();
}
else if (phase === Phase.EXIT) {
await handleExit();
}
else if (phase === Phase.EXITING) {
await handleExiting();
}
else if (phase === Phase.EXITED) {
await handleExited();
}
}, [phase]);
const handleAppear = async () => {
if (typeof onEnter === "function")
onEnter();
const timeout = await waitFor(1);
setPhase(Phase.APPEARING);
clearTimeout(timeout);
};
const handleAppearing = async () => {
if (typeof onEntering === "function")
onEntering();
setPhase(Phase.APPEARED);
};
const handleAppeared = () => {
if (typeof onEntered === "function")
onEntered();
};
const handleEnter = async () => {
if (typeof onEnter === "function")
onEnter();
const timeout = await waitFor(1);
setPhase(Phase.ENTERING);
clearTimeout(timeout);
};
const handleEntering = async () => {
if (typeof onEntering === "function")
onEntering();
const timeout = await waitFor(duration - 1);
setPhase(Phase.ENTERED);
clearTimeout(timeout);
};
const handleonEntered = () => {
if (typeof onEntered === "function")
onEntered();
};
const handleExit = async () => {
if (typeof onExit === "function")
onExit();
const timeout = await waitFor(1);
setPhase(Phase.EXITING);
clearTimeout(timeout);
};
const handleExiting = async () => {
if (typeof onExiting === "function")
onExiting();
const timeout = await waitFor(duration - 1);
setPhase(Phase.EXITED);
clearTimeout(timeout);
};
const handleExited = () => {
if (typeof onExited === "function")
onExited();
};
const value = useMemo(() => ({
appear: phase === Phase.APPEAR,
appearActive: phase === Phase.APPEARING,
appearDone: phase === Phase.APPEARED,
enter: phase === Phase.ENTER,
enterActive: phase === Phase.ENTERING,
enterDone: phase === Phase.ENTERED,
exit: phase === Phase.EXIT,
exitActive: phase === Phase.EXITING,
exitDone: phase === Phase.EXITED,
}), [phase]);
return [value, phase];
};
export default useUseTransition;