@tanstack/react-router 1.89.2 → 1.90.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.d.cts +1 -0
- package/dist/cjs/router.cjs +2 -2
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +2 -2
- package/dist/cjs/useBlocker.cjs +111 -23
- package/dist/cjs/useBlocker.cjs.map +1 -1
- package/dist/cjs/useBlocker.d.cts +58 -13
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/router.d.ts +2 -2
- package/dist/esm/router.js +2 -2
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/useBlocker.d.ts +58 -13
- package/dist/esm/useBlocker.js +111 -23
- package/dist/esm/useBlocker.js.map +1 -1
- package/package.json +2 -2
- package/src/index.tsx +1 -0
- package/src/router.ts +2 -1
- package/src/useBlocker.tsx +245 -41
package/dist/cjs/router.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Store, NoInfer } from '@tanstack/react-store';
|
|
2
2
|
import { DeferredPromiseState } from './defer.cjs';
|
|
3
|
-
import { HistoryState, RouterHistory } from '@tanstack/history';
|
|
3
|
+
import { HistoryLocation, HistoryState, RouterHistory } from '@tanstack/history';
|
|
4
4
|
import { Manifest } from './manifest.cjs';
|
|
5
5
|
import { AnyContext, AnyRoute, AnyRouteWithContext, ErrorRouteComponent, NotFoundRouteComponent, RootRoute, RouteComponent, RouteMask } from './route.cjs';
|
|
6
6
|
import { FullSearchSchema, RouteById, RoutePaths, RoutesById, RoutesByPath } from './routeInfo.cjs';
|
|
@@ -526,7 +526,7 @@ export declare class Router<in out TRouteTree extends AnyRoute, in out TTrailing
|
|
|
526
526
|
buildRouteTree: () => void;
|
|
527
527
|
subscribe: <TType extends keyof RouterEvents>(eventType: TType, fn: ListenerFn<RouterEvents[TType]>) => () => void;
|
|
528
528
|
emit: (routerEvent: RouterEvent) => void;
|
|
529
|
-
parseLocation: (previousLocation?: ParsedLocation<FullSearchSchema<TRouteTree
|
|
529
|
+
parseLocation: (previousLocation?: ParsedLocation<FullSearchSchema<TRouteTree>>, locationToParse?: HistoryLocation) => ParsedLocation<FullSearchSchema<TRouteTree>>;
|
|
530
530
|
resolvePathWithBase: (from: string, path: string) => string;
|
|
531
531
|
get looseRoutesById(): Record<string, AnyRoute>;
|
|
532
532
|
/**
|
package/dist/cjs/useBlocker.cjs
CHANGED
|
@@ -19,47 +19,135 @@ function _interopNamespaceDefault(e) {
|
|
|
19
19
|
return Object.freeze(n);
|
|
20
20
|
}
|
|
21
21
|
const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
|
|
22
|
-
function
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
function _resolveBlockerOpts(opts, condition) {
|
|
23
|
+
if (opts === void 0) {
|
|
24
|
+
return {
|
|
25
|
+
shouldBlockFn: () => true,
|
|
26
|
+
withResolver: false
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
if ("shouldBlockFn" in opts) {
|
|
30
|
+
return opts;
|
|
31
|
+
}
|
|
32
|
+
if (typeof opts === "function") {
|
|
33
|
+
const shouldBlock2 = Boolean(condition ?? true);
|
|
34
|
+
const _customBlockerFn2 = async () => {
|
|
35
|
+
if (shouldBlock2) return await opts();
|
|
36
|
+
return false;
|
|
37
|
+
};
|
|
38
|
+
return {
|
|
39
|
+
shouldBlockFn: _customBlockerFn2,
|
|
40
|
+
enableBeforeUnload: shouldBlock2,
|
|
41
|
+
withResolver: false
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
const shouldBlock = Boolean(opts.condition ?? true);
|
|
45
|
+
const fn = opts.blockerFn;
|
|
46
|
+
const _customBlockerFn = async () => {
|
|
47
|
+
if (shouldBlock && fn !== void 0) {
|
|
48
|
+
return await fn();
|
|
49
|
+
}
|
|
50
|
+
return shouldBlock;
|
|
51
|
+
};
|
|
52
|
+
return {
|
|
53
|
+
shouldBlockFn: _customBlockerFn,
|
|
54
|
+
enableBeforeUnload: shouldBlock,
|
|
55
|
+
withResolver: fn === void 0
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function useBlocker(opts, condition) {
|
|
59
|
+
const {
|
|
60
|
+
shouldBlockFn,
|
|
61
|
+
enableBeforeUnload = true,
|
|
62
|
+
disabled = false,
|
|
63
|
+
withResolver = false
|
|
64
|
+
} = _resolveBlockerOpts(opts, condition);
|
|
65
|
+
const router = useRouter.useRouter();
|
|
66
|
+
const { history } = router;
|
|
28
67
|
const [resolver, setResolver] = React__namespace.useState({
|
|
29
68
|
status: "idle",
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
69
|
+
current: void 0,
|
|
70
|
+
next: void 0,
|
|
71
|
+
action: void 0,
|
|
72
|
+
proceed: void 0,
|
|
73
|
+
reset: void 0
|
|
34
74
|
});
|
|
35
75
|
React__namespace.useEffect(() => {
|
|
36
|
-
const blockerFnComposed = async () => {
|
|
37
|
-
|
|
38
|
-
|
|
76
|
+
const blockerFnComposed = async (blockerFnArgs) => {
|
|
77
|
+
function getLocation(location) {
|
|
78
|
+
const parsedLocation = router.parseLocation(void 0, location);
|
|
79
|
+
const matchedRoutes = router.getMatchedRoutes(parsedLocation);
|
|
80
|
+
if (matchedRoutes.foundRoute === void 0) {
|
|
81
|
+
throw new Error(`No route found for location ${location.href}`);
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
routeId: matchedRoutes.foundRoute.id,
|
|
85
|
+
fullPath: matchedRoutes.foundRoute.fullPath,
|
|
86
|
+
pathname: parsedLocation.pathname,
|
|
87
|
+
params: matchedRoutes.routeParams,
|
|
88
|
+
search: parsedLocation.search
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
const current = getLocation(blockerFnArgs.currentLocation);
|
|
92
|
+
const next = getLocation(blockerFnArgs.nextLocation);
|
|
93
|
+
const shouldBlock = await shouldBlockFn({
|
|
94
|
+
action: blockerFnArgs.action,
|
|
95
|
+
current,
|
|
96
|
+
next
|
|
97
|
+
});
|
|
98
|
+
if (!withResolver) {
|
|
99
|
+
return shouldBlock;
|
|
100
|
+
}
|
|
101
|
+
if (!shouldBlock) {
|
|
102
|
+
return false;
|
|
39
103
|
}
|
|
40
104
|
const promise = new Promise((resolve) => {
|
|
41
105
|
setResolver({
|
|
42
106
|
status: "blocked",
|
|
43
|
-
|
|
44
|
-
|
|
107
|
+
current,
|
|
108
|
+
next,
|
|
109
|
+
action: blockerFnArgs.action,
|
|
110
|
+
proceed: () => resolve(false),
|
|
111
|
+
reset: () => resolve(true)
|
|
45
112
|
});
|
|
46
113
|
});
|
|
47
114
|
const canNavigateAsync = await promise;
|
|
48
115
|
setResolver({
|
|
49
116
|
status: "idle",
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
117
|
+
current: void 0,
|
|
118
|
+
next: void 0,
|
|
119
|
+
action: void 0,
|
|
120
|
+
proceed: void 0,
|
|
121
|
+
reset: void 0
|
|
54
122
|
});
|
|
55
123
|
return canNavigateAsync;
|
|
56
124
|
};
|
|
57
|
-
return
|
|
58
|
-
}, [
|
|
125
|
+
return disabled ? void 0 : history.block({ blockerFn: blockerFnComposed, enableBeforeUnload });
|
|
126
|
+
}, [shouldBlockFn, enableBeforeUnload, disabled, withResolver, history]);
|
|
59
127
|
return resolver;
|
|
60
128
|
}
|
|
61
|
-
|
|
62
|
-
|
|
129
|
+
const _resolvePromptBlockerArgs = (props) => {
|
|
130
|
+
if ("shouldBlockFn" in props) {
|
|
131
|
+
return { ...props };
|
|
132
|
+
}
|
|
133
|
+
const shouldBlock = Boolean(props.condition ?? true);
|
|
134
|
+
const fn = props.blockerFn;
|
|
135
|
+
const _customBlockerFn = async () => {
|
|
136
|
+
if (shouldBlock && fn !== void 0) {
|
|
137
|
+
return await fn();
|
|
138
|
+
}
|
|
139
|
+
return shouldBlock;
|
|
140
|
+
};
|
|
141
|
+
return {
|
|
142
|
+
shouldBlockFn: _customBlockerFn,
|
|
143
|
+
enableBeforeUnload: shouldBlock,
|
|
144
|
+
withResolver: fn === void 0
|
|
145
|
+
};
|
|
146
|
+
};
|
|
147
|
+
function Block(opts) {
|
|
148
|
+
const { children, ...rest } = opts;
|
|
149
|
+
const args = _resolvePromptBlockerArgs(rest);
|
|
150
|
+
const resolver = useBlocker(args);
|
|
63
151
|
return children ? typeof children === "function" ? children(resolver) : children : null;
|
|
64
152
|
}
|
|
65
153
|
exports.Block = Block;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useBlocker.cjs","sources":["../../src/useBlocker.tsx"],"sourcesContent":["import * as React from 'react'\nimport { useRouter } from './useRouter'\nimport type { BlockerFn } from '@tanstack/history'\nimport type { ReactNode } from './route'\n\ntype BlockerResolver = {\n status: 'idle' | 'blocked'\n proceed: () => void\n reset: () => void\n}\n\ntype BlockerOpts = {\n blockerFn?: BlockerFn\n condition?: boolean | any\n}\n\nexport function useBlocker(blockerFnOrOpts?: BlockerOpts): BlockerResolver\n\n/**\n * @deprecated Use the BlockerOpts object syntax instead\n */\nexport function useBlocker(\n blockerFn?: BlockerFn,\n condition?: boolean | any,\n): BlockerResolver\n\nexport function useBlocker(\n blockerFnOrOpts?: BlockerFn | BlockerOpts,\n condition?: boolean | any,\n): BlockerResolver {\n const { blockerFn, blockerCondition } = blockerFnOrOpts\n ? typeof blockerFnOrOpts === 'function'\n ? { blockerFn: blockerFnOrOpts, blockerCondition: condition ?? true }\n : {\n blockerFn: blockerFnOrOpts.blockerFn,\n blockerCondition: blockerFnOrOpts.condition ?? true,\n }\n : { blockerFn: undefined, blockerCondition: condition ?? true }\n const { history } = useRouter()\n\n const [resolver, setResolver] = React.useState<BlockerResolver>({\n status: 'idle',\n proceed: () => {},\n reset: () => {},\n })\n\n React.useEffect(() => {\n const blockerFnComposed = async () => {\n // If a function is provided, it takes precedence over the promise blocker\n if (blockerFn) {\n return await blockerFn()\n }\n\n const promise = new Promise<boolean>((resolve) => {\n setResolver({\n status: 'blocked',\n proceed: () => resolve(true),\n reset: () => resolve(false),\n })\n })\n\n const canNavigateAsync = await promise\n\n setResolver({\n status: 'idle',\n proceed: () => {},\n reset: () => {},\n })\n\n return canNavigateAsync\n }\n\n return !blockerCondition ? undefined : history.block(blockerFnComposed)\n }, [blockerFn, blockerCondition, history])\n\n return resolver\n}\n\nexport function Block({ blockerFn, condition, children }: PromptProps) {\n const resolver = useBlocker({ blockerFn, condition })\n return children\n ? typeof children === 'function'\n ? children(resolver)\n : children\n : null\n}\n\nexport type PromptProps = {\n blockerFn?: BlockerFn\n condition?: boolean | any\n children?: ReactNode | (({ proceed, reset }: BlockerResolver) => ReactNode)\n}\n"],"names":["useRouter","React"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA0BgB,SAAA,WACd,iBACA,WACiB;AACjB,QAAM,EAAE,WAAW,qBAAqB,kBACpC,OAAO,oBAAoB,aACzB,EAAE,WAAW,iBAAiB,kBAAkB,aAAa,SAC7D;AAAA,IACE,WAAW,gBAAgB;AAAA,IAC3B,kBAAkB,gBAAgB,aAAa;AAAA,EAAA,IAEnD,EAAE,WAAW,QAAW,kBAAkB,aAAa,KAAK;AAC1D,QAAA,EAAE,QAAQ,IAAIA,oBAAU;AAE9B,QAAM,CAAC,UAAU,WAAW,IAAIC,iBAAM,SAA0B;AAAA,IAC9D,QAAQ;AAAA,IACR,SAAS,MAAM;AAAA,IAAC;AAAA,IAChB,OAAO,MAAM;AAAA,IAAA;AAAA,EAAC,CACf;AAEDA,mBAAM,UAAU,MAAM;AACpB,UAAM,oBAAoB,YAAY;AAEpC,UAAI,WAAW;AACb,eAAO,MAAM,UAAU;AAAA,MAAA;AAGzB,YAAM,UAAU,IAAI,QAAiB,CAAC,YAAY;AACpC,oBAAA;AAAA,UACV,QAAQ;AAAA,UACR,SAAS,MAAM,QAAQ,IAAI;AAAA,UAC3B,OAAO,MAAM,QAAQ,KAAK;AAAA,QAAA,CAC3B;AAAA,MAAA,CACF;AAED,YAAM,mBAAmB,MAAM;AAEnB,kBAAA;AAAA,QACV,QAAQ;AAAA,QACR,SAAS,MAAM;AAAA,QAAC;AAAA,QAChB,OAAO,MAAM;AAAA,QAAA;AAAA,MAAC,CACf;AAEM,aAAA;AAAA,IACT;AAEA,WAAO,CAAC,mBAAmB,SAAY,QAAQ,MAAM,iBAAiB;AAAA,EACrE,GAAA,CAAC,WAAW,kBAAkB,OAAO,CAAC;AAElC,SAAA;AACT;AAEO,SAAS,MAAM,EAAE,WAAW,WAAW,YAAyB;AACrE,QAAM,WAAW,WAAW,EAAE,WAAW,WAAW;AACpD,SAAO,WACH,OAAO,aAAa,aAClB,SAAS,QAAQ,IACjB,WACF;AACN;;;"}
|
|
1
|
+
{"version":3,"file":"useBlocker.cjs","sources":["../../src/useBlocker.tsx"],"sourcesContent":["import * as React from 'react'\nimport { useRouter } from './useRouter'\nimport type {\n BlockerFnArgs,\n HistoryAction,\n HistoryLocation,\n} from '@tanstack/history'\nimport type { AnyRoute } from './route'\nimport type { ParseRoute } from './routeInfo'\nimport type { AnyRouter, RegisteredRouter } from './router'\n\ninterface ShouldBlockFnLocation<\n out TRouteId,\n out TFullPath,\n out TAllParams,\n out TFullSearchSchema,\n> {\n routeId: TRouteId\n fullPath: TFullPath\n pathname: string\n params: TAllParams\n search: TFullSearchSchema\n}\n\ntype AnyShouldBlockFnLocation = ShouldBlockFnLocation<any, any, any, any>\ntype MakeShouldBlockFnLocationUnion<\n TRouter extends AnyRouter = RegisteredRouter,\n TRoute extends AnyRoute = ParseRoute<TRouter['routeTree']>,\n> = TRoute extends any\n ? ShouldBlockFnLocation<\n TRoute['id'],\n TRoute['fullPath'],\n TRoute['types']['allParams'],\n TRoute['types']['fullSearchSchema']\n >\n : never\n\ntype BlockerResolver<TRouter extends AnyRouter = RegisteredRouter> =\n | {\n status: 'blocked'\n current: MakeShouldBlockFnLocationUnion<TRouter>\n next: MakeShouldBlockFnLocationUnion<TRouter>\n action: HistoryAction\n proceed: () => void\n reset: () => void\n }\n | {\n status: 'idle'\n current: undefined\n next: undefined\n action: undefined\n proceed: undefined\n reset: undefined\n }\n\ntype ShouldBlockFnArgs<TRouter extends AnyRouter = RegisteredRouter> = {\n current: MakeShouldBlockFnLocationUnion<TRouter>\n next: MakeShouldBlockFnLocationUnion<TRouter>\n action: HistoryAction\n}\n\nexport type ShouldBlockFn<TRouter extends AnyRouter = RegisteredRouter> = (\n args: ShouldBlockFnArgs<TRouter>,\n) => boolean | Promise<boolean>\nexport type UseBlockerOpts<\n TRouter extends AnyRouter = RegisteredRouter,\n TWithResolver extends boolean = boolean,\n> = {\n shouldBlockFn: ShouldBlockFn<TRouter>\n enableBeforeUnload?: boolean | (() => boolean)\n disabled?: boolean\n withResolver?: TWithResolver\n}\n\ntype LegacyBlockerFn = () => Promise<any> | any\ntype LegacyBlockerOpts = {\n blockerFn?: LegacyBlockerFn\n condition?: boolean | any\n}\n\nfunction _resolveBlockerOpts(\n opts?: UseBlockerOpts | LegacyBlockerOpts | LegacyBlockerFn,\n condition?: boolean | any,\n): UseBlockerOpts {\n if (opts === undefined) {\n return {\n shouldBlockFn: () => true,\n withResolver: false,\n }\n }\n\n if ('shouldBlockFn' in opts) {\n return opts\n }\n\n if (typeof opts === 'function') {\n const shouldBlock = Boolean(condition ?? true)\n\n const _customBlockerFn = async () => {\n if (shouldBlock) return await opts()\n return false\n }\n\n return {\n shouldBlockFn: _customBlockerFn,\n enableBeforeUnload: shouldBlock,\n withResolver: false,\n }\n }\n\n const shouldBlock = Boolean(opts.condition ?? true)\n const fn = opts.blockerFn\n\n const _customBlockerFn = async () => {\n if (shouldBlock && fn !== undefined) {\n return await fn()\n }\n return shouldBlock\n }\n\n return {\n shouldBlockFn: _customBlockerFn,\n enableBeforeUnload: shouldBlock,\n withResolver: fn === undefined,\n }\n}\n\nexport function useBlocker<\n TRouter extends AnyRouter = RegisteredRouter,\n TWithResolver extends boolean = false,\n>(\n opts: UseBlockerOpts<TRouter, TWithResolver>,\n): TWithResolver extends true ? BlockerResolver<TRouter> : void\n\n/**\n * @deprecated Use the shouldBlockFn property instead\n */\nexport function useBlocker(blockerFnOrOpts?: LegacyBlockerOpts): BlockerResolver\n\n/**\n * @deprecated Use the UseBlockerOpts object syntax instead\n */\nexport function useBlocker(\n blockerFn?: LegacyBlockerFn,\n condition?: boolean | any,\n): BlockerResolver\n\nexport function useBlocker(\n opts?: UseBlockerOpts | LegacyBlockerOpts | LegacyBlockerFn,\n condition?: boolean | any,\n): BlockerResolver | void {\n const {\n shouldBlockFn,\n enableBeforeUnload = true,\n disabled = false,\n withResolver = false,\n } = _resolveBlockerOpts(opts, condition)\n\n const router = useRouter()\n const { history } = router\n\n const [resolver, setResolver] = React.useState<BlockerResolver>({\n status: 'idle',\n current: undefined,\n next: undefined,\n action: undefined,\n proceed: undefined,\n reset: undefined,\n })\n\n React.useEffect(() => {\n const blockerFnComposed = async (blockerFnArgs: BlockerFnArgs) => {\n function getLocation(\n location: HistoryLocation,\n ): AnyShouldBlockFnLocation {\n const parsedLocation = router.parseLocation(undefined, location)\n const matchedRoutes = router.getMatchedRoutes(parsedLocation)\n if (matchedRoutes.foundRoute === undefined) {\n throw new Error(`No route found for location ${location.href}`)\n }\n return {\n routeId: matchedRoutes.foundRoute.id,\n fullPath: matchedRoutes.foundRoute.fullPath,\n pathname: parsedLocation.pathname,\n params: matchedRoutes.routeParams,\n search: parsedLocation.search,\n }\n }\n\n const current = getLocation(blockerFnArgs.currentLocation)\n const next = getLocation(blockerFnArgs.nextLocation)\n\n const shouldBlock = await shouldBlockFn({\n action: blockerFnArgs.action,\n current,\n next,\n })\n if (!withResolver) {\n return shouldBlock\n }\n\n if (!shouldBlock) {\n return false\n }\n\n const promise = new Promise<boolean>((resolve) => {\n setResolver({\n status: 'blocked',\n current,\n next,\n action: blockerFnArgs.action,\n proceed: () => resolve(false),\n reset: () => resolve(true),\n })\n })\n\n const canNavigateAsync = await promise\n setResolver({\n status: 'idle',\n current: undefined,\n next: undefined,\n action: undefined,\n proceed: undefined,\n reset: undefined,\n })\n\n return canNavigateAsync\n }\n\n return disabled\n ? undefined\n : history.block({ blockerFn: blockerFnComposed, enableBeforeUnload })\n }, [shouldBlockFn, enableBeforeUnload, disabled, withResolver, history])\n\n return resolver\n}\n\nconst _resolvePromptBlockerArgs = (\n props: PromptProps | LegacyPromptProps,\n): UseBlockerOpts => {\n if ('shouldBlockFn' in props) {\n return { ...props }\n }\n\n const shouldBlock = Boolean(props.condition ?? true)\n const fn = props.blockerFn\n\n const _customBlockerFn = async () => {\n if (shouldBlock && fn !== undefined) {\n return await fn()\n }\n return shouldBlock\n }\n\n return {\n shouldBlockFn: _customBlockerFn,\n enableBeforeUnload: shouldBlock,\n withResolver: fn === undefined,\n }\n}\n\nexport function Block<\n TRouter extends AnyRouter = RegisteredRouter,\n TWithResolver extends boolean = boolean,\n>(opts: PromptProps<TRouter, TWithResolver>): React.ReactNode\n\n/**\n * @deprecated Use the UseBlockerOpts property instead\n */\nexport function Block(opts: LegacyPromptProps): React.ReactNode\n\nexport function Block(opts: PromptProps | LegacyPromptProps): React.ReactNode {\n const { children, ...rest } = opts\n const args = _resolvePromptBlockerArgs(rest)\n\n const resolver = useBlocker(args)\n return children\n ? typeof children === 'function'\n ? children(resolver as any)\n : children\n : null\n}\n\ntype LegacyPromptProps = {\n blockerFn?: LegacyBlockerFn\n condition?: boolean | any\n children?: React.ReactNode | ((params: BlockerResolver) => React.ReactNode)\n}\n\ntype PromptProps<\n TRouter extends AnyRouter = RegisteredRouter,\n TWithResolver extends boolean = boolean,\n TParams = TWithResolver extends true ? BlockerResolver<TRouter> : void,\n> = UseBlockerOpts<TRouter, TWithResolver> & {\n children?: React.ReactNode | ((params: TParams) => React.ReactNode)\n}\n"],"names":["shouldBlock","_customBlockerFn","useRouter","React"],"mappings":"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"}
|
|
@@ -1,23 +1,68 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { HistoryAction } from '@tanstack/history';
|
|
2
|
+
import { AnyRoute } from './route.cjs';
|
|
3
|
+
import { ParseRoute } from './routeInfo.cjs';
|
|
4
|
+
import { AnyRouter, RegisteredRouter } from './router.cjs';
|
|
5
|
+
import * as React from 'react';
|
|
6
|
+
interface ShouldBlockFnLocation<out TRouteId, out TFullPath, out TAllParams, out TFullSearchSchema> {
|
|
7
|
+
routeId: TRouteId;
|
|
8
|
+
fullPath: TFullPath;
|
|
9
|
+
pathname: string;
|
|
10
|
+
params: TAllParams;
|
|
11
|
+
search: TFullSearchSchema;
|
|
12
|
+
}
|
|
13
|
+
type MakeShouldBlockFnLocationUnion<TRouter extends AnyRouter = RegisteredRouter, TRoute extends AnyRoute = ParseRoute<TRouter['routeTree']>> = TRoute extends any ? ShouldBlockFnLocation<TRoute['id'], TRoute['fullPath'], TRoute['types']['allParams'], TRoute['types']['fullSearchSchema']> : never;
|
|
14
|
+
type BlockerResolver<TRouter extends AnyRouter = RegisteredRouter> = {
|
|
15
|
+
status: 'blocked';
|
|
16
|
+
current: MakeShouldBlockFnLocationUnion<TRouter>;
|
|
17
|
+
next: MakeShouldBlockFnLocationUnion<TRouter>;
|
|
18
|
+
action: HistoryAction;
|
|
5
19
|
proceed: () => void;
|
|
6
20
|
reset: () => void;
|
|
21
|
+
} | {
|
|
22
|
+
status: 'idle';
|
|
23
|
+
current: undefined;
|
|
24
|
+
next: undefined;
|
|
25
|
+
action: undefined;
|
|
26
|
+
proceed: undefined;
|
|
27
|
+
reset: undefined;
|
|
7
28
|
};
|
|
8
|
-
type
|
|
9
|
-
|
|
29
|
+
type ShouldBlockFnArgs<TRouter extends AnyRouter = RegisteredRouter> = {
|
|
30
|
+
current: MakeShouldBlockFnLocationUnion<TRouter>;
|
|
31
|
+
next: MakeShouldBlockFnLocationUnion<TRouter>;
|
|
32
|
+
action: HistoryAction;
|
|
33
|
+
};
|
|
34
|
+
export type ShouldBlockFn<TRouter extends AnyRouter = RegisteredRouter> = (args: ShouldBlockFnArgs<TRouter>) => boolean | Promise<boolean>;
|
|
35
|
+
export type UseBlockerOpts<TRouter extends AnyRouter = RegisteredRouter, TWithResolver extends boolean = boolean> = {
|
|
36
|
+
shouldBlockFn: ShouldBlockFn<TRouter>;
|
|
37
|
+
enableBeforeUnload?: boolean | (() => boolean);
|
|
38
|
+
disabled?: boolean;
|
|
39
|
+
withResolver?: TWithResolver;
|
|
40
|
+
};
|
|
41
|
+
type LegacyBlockerFn = () => Promise<any> | any;
|
|
42
|
+
type LegacyBlockerOpts = {
|
|
43
|
+
blockerFn?: LegacyBlockerFn;
|
|
10
44
|
condition?: boolean | any;
|
|
11
45
|
};
|
|
12
|
-
export declare function useBlocker(
|
|
46
|
+
export declare function useBlocker<TRouter extends AnyRouter = RegisteredRouter, TWithResolver extends boolean = false>(opts: UseBlockerOpts<TRouter, TWithResolver>): TWithResolver extends true ? BlockerResolver<TRouter> : void;
|
|
47
|
+
/**
|
|
48
|
+
* @deprecated Use the shouldBlockFn property instead
|
|
49
|
+
*/
|
|
50
|
+
export declare function useBlocker(blockerFnOrOpts?: LegacyBlockerOpts): BlockerResolver;
|
|
13
51
|
/**
|
|
14
|
-
* @deprecated Use the
|
|
52
|
+
* @deprecated Use the UseBlockerOpts object syntax instead
|
|
15
53
|
*/
|
|
16
|
-
export declare function useBlocker(blockerFn?:
|
|
17
|
-
export declare function Block
|
|
18
|
-
|
|
19
|
-
|
|
54
|
+
export declare function useBlocker(blockerFn?: LegacyBlockerFn, condition?: boolean | any): BlockerResolver;
|
|
55
|
+
export declare function Block<TRouter extends AnyRouter = RegisteredRouter, TWithResolver extends boolean = boolean>(opts: PromptProps<TRouter, TWithResolver>): React.ReactNode;
|
|
56
|
+
/**
|
|
57
|
+
* @deprecated Use the UseBlockerOpts property instead
|
|
58
|
+
*/
|
|
59
|
+
export declare function Block(opts: LegacyPromptProps): React.ReactNode;
|
|
60
|
+
type LegacyPromptProps = {
|
|
61
|
+
blockerFn?: LegacyBlockerFn;
|
|
20
62
|
condition?: boolean | any;
|
|
21
|
-
children?: ReactNode | ((
|
|
63
|
+
children?: React.ReactNode | ((params: BlockerResolver) => React.ReactNode);
|
|
64
|
+
};
|
|
65
|
+
type PromptProps<TRouter extends AnyRouter = RegisteredRouter, TWithResolver extends boolean = boolean, TParams = TWithResolver extends true ? BlockerResolver<TRouter> : void> = UseBlockerOpts<TRouter, TWithResolver> & {
|
|
66
|
+
children?: React.ReactNode | ((params: TParams) => React.ReactNode);
|
|
22
67
|
};
|
|
23
68
|
export {};
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -43,6 +43,7 @@ export { defaultParseSearch, defaultStringifySearch, parseSearchWith, stringifyS
|
|
|
43
43
|
export type { SearchSerializer, SearchParser } from './searchParams.js';
|
|
44
44
|
export { defaultTransformer } from './transformer.js';
|
|
45
45
|
export type { RouterTransformer, TransformerParse, TransformerStringify, DefaultTransformerParse, DefaultTransformerStringify, } from './transformer.js';
|
|
46
|
+
export type { UseBlockerOpts, ShouldBlockFn } from './useBlocker.js';
|
|
46
47
|
export { useBlocker, Block } from './useBlocker.js';
|
|
47
48
|
export { useNavigate, Navigate } from './useNavigate.js';
|
|
48
49
|
export type { UseNavigateResult } from './useNavigate.js';
|
package/dist/esm/router.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Store, NoInfer } from '@tanstack/react-store';
|
|
2
2
|
import { DeferredPromiseState } from './defer.js';
|
|
3
|
-
import { HistoryState, RouterHistory } from '@tanstack/history';
|
|
3
|
+
import { HistoryLocation, HistoryState, RouterHistory } from '@tanstack/history';
|
|
4
4
|
import { Manifest } from './manifest.js';
|
|
5
5
|
import { AnyContext, AnyRoute, AnyRouteWithContext, ErrorRouteComponent, NotFoundRouteComponent, RootRoute, RouteComponent, RouteMask } from './route.js';
|
|
6
6
|
import { FullSearchSchema, RouteById, RoutePaths, RoutesById, RoutesByPath } from './routeInfo.js';
|
|
@@ -526,7 +526,7 @@ export declare class Router<in out TRouteTree extends AnyRoute, in out TTrailing
|
|
|
526
526
|
buildRouteTree: () => void;
|
|
527
527
|
subscribe: <TType extends keyof RouterEvents>(eventType: TType, fn: ListenerFn<RouterEvents[TType]>) => () => void;
|
|
528
528
|
emit: (routerEvent: RouterEvent) => void;
|
|
529
|
-
parseLocation: (previousLocation?: ParsedLocation<FullSearchSchema<TRouteTree
|
|
529
|
+
parseLocation: (previousLocation?: ParsedLocation<FullSearchSchema<TRouteTree>>, locationToParse?: HistoryLocation) => ParsedLocation<FullSearchSchema<TRouteTree>>;
|
|
530
530
|
resolvePathWithBase: (from: string, path: string) => string;
|
|
531
531
|
get looseRoutesById(): Record<string, AnyRoute>;
|
|
532
532
|
/**
|
package/dist/esm/router.js
CHANGED
|
@@ -216,7 +216,7 @@ class Router {
|
|
|
216
216
|
}
|
|
217
217
|
});
|
|
218
218
|
};
|
|
219
|
-
this.parseLocation = (previousLocation) => {
|
|
219
|
+
this.parseLocation = (previousLocation, locationToParse) => {
|
|
220
220
|
const parse = ({
|
|
221
221
|
pathname,
|
|
222
222
|
search,
|
|
@@ -234,7 +234,7 @@ class Router {
|
|
|
234
234
|
state: replaceEqualDeep(previousLocation == null ? void 0 : previousLocation.state, state)
|
|
235
235
|
};
|
|
236
236
|
};
|
|
237
|
-
const location = parse(this.history.location);
|
|
237
|
+
const location = parse(locationToParse ?? this.history.location);
|
|
238
238
|
const { __tempLocation, __tempKey } = location.state;
|
|
239
239
|
if (__tempLocation && (!__tempKey || __tempKey === this.tempLocationKey)) {
|
|
240
240
|
const parsedTempLocation = parse(__tempLocation);
|