UNPKG

use-start-view-transition

Version:

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

56 lines (55 loc) 2.03 kB
import { useCallback, useEffect, useRef, useState } from "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 = useRef(options); const isTransitionReadyRef = useRef(false); optionsRef.current = options; useEffect(() => { const frameId = window.requestAnimationFrame(() => { isTransitionReadyRef.current = true; }); return () => { window.cancelAnimationFrame(frameId); }; }, []); return [value, 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 = useRef(_value); const [value, setValue] = useStartViewTransitionWrap(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(useState(state), options); }; //#endregion export { startViewTransition, useStartViewTransitionState, useStartViewTransitionValue, useStartViewTransitionWrap };