UNPKG

@liveblocks/react-ui

Version:

A set of React pre-built components for the Liveblocks products. Liveblocks is the all-in-one toolkit to build collaborative products like Figma, Notion, and more.

85 lines (81 loc) 2.83 kB
"use client"; import { jsx } from 'react/jsx-runtime'; import { nn } from '@liveblocks/core'; import { useLayoutEffect } from '@liveblocks/react/_private'; import { createContext, useContext, Children, isValidElement, useRef, useState, useCallback } from 'react'; import { flushSync } from 'react-dom'; const PERSIST_NAME = "Persist"; const PersistContext = createContext(null); function usePersist() { const persistContext = useContext(PersistContext); return nn(persistContext, "Persist is missing from the React tree."); } function getChild(children) { const child = Array.isArray(children) ? Children.only(children) : children; return isValidElement(child) ? child : void 0; } function useAnimationPersist(ref) { const [isPresent, unmount] = usePersist(); const previousAnimationName = useRef(null); const unmountAnimationName = useRef(null); useLayoutEffect(() => { const element = ref.current; if (!element) { return; } const handleAnimationEnd = (event) => { if (event.animationName === unmountAnimationName.current) { unmount(); } previousAnimationName.current = event.animationName; }; element.addEventListener("animationcancel", handleAnimationEnd); element.addEventListener("animationend", handleAnimationEnd); return () => { element.removeEventListener("animationcancel", handleAnimationEnd); element.removeEventListener("animationend", handleAnimationEnd); }; }, [ref, unmount]); useLayoutEffect(() => { const element = ref.current; let animationFrameId; if (!element) { return; } if (!isPresent) { animationFrameId = requestAnimationFrame(() => { const styles = getComputedStyle(element); unmountAnimationName.current = styles.animationName; if (styles.animationName === "none" || styles.animationName === previousAnimationName.current || styles.display === "none") { unmount(); } }); } return () => { cancelAnimationFrame(animationFrameId); }; }, [isPresent, ref, unmount]); } function Persist({ children }) { const [isPersisting, setPersisting] = useState(true); const lastPresentChild = useRef(null); const child = getChild(children); const unmount = useCallback(() => { flushSync(() => setPersisting(false)); }, []); useLayoutEffect(() => { if (child) { setPersisting(true); lastPresentChild.current = child; } }, [child]); return /* @__PURE__ */ jsx(PersistContext.Provider, { value: [Boolean(child), unmount], children: child ?? (isPersisting ? lastPresentChild.current : null) }); } if (process.env.NODE_ENV !== "production") { Persist.displayName = PERSIST_NAME; } export { Persist, useAnimationPersist, usePersist }; //# sourceMappingURL=Persist.js.map