UNPKG

use-start-view-transition

Version:

A set of hooks to use `document.startViewTransition` upon state/value changes

60 lines (59 loc) 2.28 kB
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); let react = require("react"); //#region src/index.ts const startViewTransition = async (fn) => { if (typeof window === "undefined" || !("startViewTransition" in document)) { fn(); return; } try { return document.startViewTransition(fn).ready.catch((error) => { if (error instanceof Error && (error.name === "AbortError" || error.name === "InvalidStateError")) return; throw error; }); } catch (error) { if (error instanceof Error && (error.name === "AbortError" || error.name === "InvalidStateError")) { fn(); return; } throw error; } }; const useStartViewTransitionWrap = ([value, _setState], options = {}) => { const optionsRef = (0, react.useRef)(options); const isTransitionReadyRef = (0, react.useRef)(false); optionsRef.current = options; (0, react.useEffect)(() => { const frameId = window.requestAnimationFrame(() => { isTransitionReadyRef.current = true; }); return () => { window.cancelAnimationFrame(frameId); }; }, []); return [value, (0, react.useCallback)(async (v) => { const { skipTransition } = optionsRef.current; const skipFn = typeof skipTransition === "function" ? skipTransition : (v) => skipTransition; if (isTransitionReadyRef.current && !skipFn(value)) return startViewTransition(() => _setState(v)); _setState(v); }, [_setState, value])]; }; const useStartViewTransitionValue = (_value, options = {}) => { const valueRef = (0, react.useRef)(_value); const [value, setValue] = useStartViewTransitionWrap((0, react.useState)(_value), options); const { skipTransition } = options; const shouldSkip = (typeof skipTransition === "function" ? skipTransition : (v) => skipTransition)(_value); if (_value !== valueRef.current) { valueRef.current = _value; setValue(_value); } return shouldSkip ? _value : value; }; const useStartViewTransitionState = (state, options = {}) => { return useStartViewTransitionWrap((0, react.useState)(state), options); }; //#endregion exports.startViewTransition = startViewTransition; exports.useStartViewTransitionState = useStartViewTransitionState; exports.useStartViewTransitionValue = useStartViewTransitionValue; exports.useStartViewTransitionWrap = useStartViewTransitionWrap;