UNPKG

@tanstack/react-router

Version:

Modern and scalable routing for React applications

132 lines (131 loc) 3.83 kB
import { useRouter } from "./useRouter.js"; import * as React$1 from "react"; //#region src/useBlocker.tsx function _resolveBlockerOpts(opts, condition) { if (opts === void 0) return { shouldBlockFn: () => true, withResolver: false }; if ("shouldBlockFn" in opts) return opts; if (typeof opts === "function") { const shouldBlock = Boolean(condition ?? true); const _customBlockerFn = async () => { if (shouldBlock) return await opts(); return false; }; return { shouldBlockFn: _customBlockerFn, enableBeforeUnload: shouldBlock, withResolver: false }; } const shouldBlock = Boolean(opts.condition ?? true); const fn = opts.blockerFn; const _customBlockerFn = async () => { if (shouldBlock && fn !== void 0) return await fn(); return shouldBlock; }; return { shouldBlockFn: _customBlockerFn, enableBeforeUnload: shouldBlock, withResolver: fn === void 0 }; } function useBlocker(opts, condition) { const { shouldBlockFn, enableBeforeUnload = true, disabled = false, withResolver = false } = _resolveBlockerOpts(opts, condition); const router = useRouter(); const { history } = router; const [resolver, setResolver] = React$1.useState({ status: "idle", current: void 0, next: void 0, action: void 0, proceed: void 0, reset: void 0 }); React$1.useEffect(() => { const blockerFnComposed = async (blockerFnArgs) => { function getLocation(location) { const parsedLocation = router.parseLocation(location); const matchedRoutes = router.getMatchedRoutes(parsedLocation.pathname); if (matchedRoutes.foundRoute === void 0) return { routeId: "__notFound__", fullPath: parsedLocation.pathname, pathname: parsedLocation.pathname, params: matchedRoutes.routeParams, search: router.options.parseSearch(location.search) }; return { routeId: matchedRoutes.foundRoute.id, fullPath: matchedRoutes.foundRoute.fullPath, pathname: parsedLocation.pathname, params: matchedRoutes.routeParams, search: router.options.parseSearch(location.search) }; } const current = getLocation(blockerFnArgs.currentLocation); const next = getLocation(blockerFnArgs.nextLocation); if (current.routeId === "__notFound__" && next.routeId !== "__notFound__") return false; const shouldBlock = await shouldBlockFn({ action: blockerFnArgs.action, current, next }); if (!withResolver) return shouldBlock; if (!shouldBlock) return false; const canNavigateAsync = await new Promise((resolve) => { setResolver({ status: "blocked", current, next, action: blockerFnArgs.action, proceed: () => resolve(false), reset: () => resolve(true) }); }); setResolver({ status: "idle", current: void 0, next: void 0, action: void 0, proceed: void 0, reset: void 0 }); return canNavigateAsync; }; return disabled ? void 0 : history.block({ blockerFn: blockerFnComposed, enableBeforeUnload }); }, [ shouldBlockFn, enableBeforeUnload, disabled, withResolver, history, router ]); return resolver; } var _resolvePromptBlockerArgs = (props) => { if ("shouldBlockFn" in props) return { ...props }; const shouldBlock = Boolean(props.condition ?? true); const fn = props.blockerFn; const _customBlockerFn = async () => { if (shouldBlock && fn !== void 0) return await fn(); return shouldBlock; }; return { shouldBlockFn: _customBlockerFn, enableBeforeUnload: shouldBlock, withResolver: fn === void 0 }; }; function Block(opts) { const { children, ...rest } = opts; const resolver = useBlocker(_resolvePromptBlockerArgs(rest)); return children ? typeof children === "function" ? children(resolver) : children : null; } //#endregion export { Block, useBlocker }; //# sourceMappingURL=useBlocker.js.map