UNPKG

@re-flex/transition-group

Version:

Re-flex UI Transtion Controller Package

139 lines (138 loc) 4.58 kB
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;