@tanstack/react-router 1.33.7 → 1.34.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/manifest.d.cts +23 -0
- package/dist/cjs/router.cjs +3 -1
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +3 -0
- package/dist/cjs/useBlocker.cjs +38 -8
- package/dist/cjs/useBlocker.cjs.map +1 -1
- package/dist/cjs/useBlocker.d.cts +18 -4
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/manifest.d.ts +23 -0
- package/dist/esm/router.d.ts +3 -0
- package/dist/esm/router.js +3 -1
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/useBlocker.d.ts +18 -4
- package/dist/esm/useBlocker.js +38 -8
- package/dist/esm/useBlocker.js.map +1 -1
- package/package.json +1 -1
- package/src/index.tsx +1 -0
- package/src/manifest.ts +31 -0
- package/src/router.ts +6 -0
- package/src/useBlocker.tsx +79 -11
package/dist/cjs/router.d.cts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Store, NoInfer } from '@tanstack/react-store';
|
|
2
|
+
import { Manifest } from './manifest.cjs';
|
|
2
3
|
import { HistoryState, RouterHistory } from '@tanstack/history';
|
|
3
4
|
import { AnyContext, AnyRoute, AnySearchSchema, ErrorRouteComponent, NotFoundRouteComponent, RouteMask, RouteComponent } from './route.cjs';
|
|
4
5
|
import { FullSearchSchema, RouteById, RoutePaths, RoutesById, RoutesByPath } from './routeInfo.cjs';
|
|
@@ -297,6 +298,7 @@ export interface DehydratedRouterState {
|
|
|
297
298
|
export type DehydratedRouteMatch = Pick<MakeRouteMatch, 'id' | 'status' | 'updatedAt' | 'loaderData'>;
|
|
298
299
|
export interface DehydratedRouter {
|
|
299
300
|
state: DehydratedRouterState;
|
|
301
|
+
manifest?: Manifest;
|
|
300
302
|
}
|
|
301
303
|
export type RouterConstructorOptions<TRouteTree extends AnyRoute, TTrailingSlashOption extends TrailingSlashOption, TDehydrated extends Record<string, any>, TSerializedError extends Record<string, any>> = Omit<RouterOptions<TRouteTree, TTrailingSlashOption, TDehydrated, TSerializedError>, 'context'> & RouterContextOptions<TRouteTree>;
|
|
302
304
|
export declare const componentTypes: readonly ["component", "errorComponent", "pendingComponent", "notFoundComponent"];
|
|
@@ -335,6 +337,7 @@ export declare class Router<in out TRouteTree extends AnyRoute, in out TTrailing
|
|
|
335
337
|
injectedHtml: Array<InjectedHtmlEntry>;
|
|
336
338
|
dehydratedData?: TDehydrated;
|
|
337
339
|
viewTransitionPromise?: ControlledPromise<true>;
|
|
340
|
+
manifest?: Manifest;
|
|
338
341
|
__store: Store<RouterState<TRouteTree>>;
|
|
339
342
|
options: PickAsRequired<Omit<RouterOptions<TRouteTree, TTrailingSlashOption, TDehydrated, TSerializedError>, 'transformer'> & {
|
|
340
343
|
transformer: RouterTransformer;
|
package/dist/cjs/useBlocker.cjs
CHANGED
|
@@ -19,17 +19,47 @@ function _interopNamespaceDefault(e) {
|
|
|
19
19
|
return Object.freeze(n);
|
|
20
20
|
}
|
|
21
21
|
const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
|
|
22
|
-
function useBlocker(
|
|
22
|
+
function useBlocker(blockerFnOrOpts, condition) {
|
|
23
|
+
const { blockerFn, blockerCondition } = blockerFnOrOpts ? typeof blockerFnOrOpts === "function" ? { blockerFn: blockerFnOrOpts, blockerCondition: condition ?? true } : {
|
|
24
|
+
blockerFn: blockerFnOrOpts.blockerFn,
|
|
25
|
+
blockerCondition: blockerFnOrOpts.condition ?? true
|
|
26
|
+
} : { blockerFn: void 0, blockerCondition: condition ?? true };
|
|
23
27
|
const { history } = useRouter.useRouter();
|
|
24
|
-
React__namespace.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
const [resolver, setResolver] = React__namespace.useState({
|
|
29
|
+
status: "idle",
|
|
30
|
+
proceed: () => {
|
|
31
|
+
},
|
|
32
|
+
reset: () => {
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
const createPromise = () => new Promise((resolve) => {
|
|
36
|
+
setResolver({
|
|
37
|
+
status: "idle",
|
|
38
|
+
proceed: () => resolve(true),
|
|
39
|
+
reset: () => resolve(false)
|
|
40
|
+
});
|
|
28
41
|
});
|
|
42
|
+
const [promise, setPromise] = React__namespace.useState(createPromise);
|
|
43
|
+
React__namespace.useEffect(() => {
|
|
44
|
+
const blockerFnComposed = async () => {
|
|
45
|
+
if (blockerFn) {
|
|
46
|
+
return await blockerFn();
|
|
47
|
+
}
|
|
48
|
+
setResolver((prev) => ({
|
|
49
|
+
...prev,
|
|
50
|
+
status: "blocked"
|
|
51
|
+
}));
|
|
52
|
+
const canNavigateAsync = await promise;
|
|
53
|
+
setPromise(createPromise);
|
|
54
|
+
return canNavigateAsync;
|
|
55
|
+
};
|
|
56
|
+
return !blockerCondition ? void 0 : history.block(blockerFnComposed);
|
|
57
|
+
}, [blockerFn, blockerCondition, history, promise]);
|
|
58
|
+
return resolver;
|
|
29
59
|
}
|
|
30
|
-
function Block({
|
|
31
|
-
useBlocker(
|
|
32
|
-
return children
|
|
60
|
+
function Block({ blockerFn, condition, children }) {
|
|
61
|
+
const resolver = useBlocker({ blockerFn, condition });
|
|
62
|
+
return children ? typeof children === "function" ? children(resolver) : children : null;
|
|
33
63
|
}
|
|
34
64
|
exports.Block = Block;
|
|
35
65
|
exports.useBlocker = useBlocker;
|
|
@@ -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\nexport function useBlocker(\n blockerFn
|
|
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 const createPromise = () =>\n new Promise<boolean>((resolve) => {\n setResolver({\n status: 'idle',\n proceed: () => resolve(true),\n reset: () => resolve(false),\n })\n })\n\n const [promise, setPromise] = React.useState(createPromise)\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 setResolver((prev) => ({\n ...prev,\n status: 'blocked',\n }))\n const canNavigateAsync = await promise\n\n setPromise(createPromise)\n\n return canNavigateAsync\n }\n\n return !blockerCondition ? undefined : history.block(blockerFnComposed)\n }, [blockerFn, blockerCondition, history, promise])\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;AACrD,QAAA,EAAE,YAAYA,UAAAA;AAEpB,QAAM,CAAC,UAAU,WAAW,IAAIC,iBAAM,SAA0B;AAAA,IAC9D,QAAQ;AAAA,IACR,SAAS,MAAM;AAAA,IAAC;AAAA,IAChB,OAAO,MAAM;AAAA,IAAC;AAAA,EAAA,CACf;AAED,QAAM,gBAAgB,MACpB,IAAI,QAAiB,CAAC,YAAY;AACpB,gBAAA;AAAA,MACV,QAAQ;AAAA,MACR,SAAS,MAAM,QAAQ,IAAI;AAAA,MAC3B,OAAO,MAAM,QAAQ,KAAK;AAAA,IAAA,CAC3B;AAAA,EAAA,CACF;AAEH,QAAM,CAAC,SAAS,UAAU,IAAIA,iBAAM,SAAS,aAAa;AAE1DA,mBAAM,UAAU,MAAM;AACpB,UAAM,oBAAoB,YAAY;AAEpC,UAAI,WAAW;AACb,eAAO,MAAM,UAAU;AAAA,MACzB;AAEA,kBAAY,CAAC,UAAU;AAAA,QACrB,GAAG;AAAA,QACH,QAAQ;AAAA,MACR,EAAA;AACF,YAAM,mBAAmB,MAAM;AAE/B,iBAAW,aAAa;AAEjB,aAAA;AAAA,IAAA;AAGT,WAAO,CAAC,mBAAmB,SAAY,QAAQ,MAAM,iBAAiB;AAAA,KACrE,CAAC,WAAW,kBAAkB,SAAS,OAAO,CAAC;AAE3C,SAAA;AACT;AAEO,SAAS,MAAM,EAAE,WAAW,WAAW,YAAyB;AACrE,QAAM,WAAW,WAAW,EAAE,WAAW,UAAW,CAAA;AACpD,SAAO,WACH,OAAO,aAAa,aAClB,SAAS,QAAQ,IACjB,WACF;AACN;;;"}
|
|
@@ -1,10 +1,24 @@
|
|
|
1
1
|
import { BlockerFn } from '@tanstack/history';
|
|
2
2
|
import { ReactNode } from './route.cjs';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
type BlockerResolver = {
|
|
5
|
+
status: 'idle' | 'blocked';
|
|
6
|
+
proceed: () => void;
|
|
7
|
+
reset: () => void;
|
|
8
|
+
};
|
|
9
|
+
type BlockerOpts = {
|
|
10
|
+
blockerFn?: BlockerFn;
|
|
11
|
+
condition?: boolean | any;
|
|
12
|
+
};
|
|
13
|
+
export declare function useBlocker(blockerFnOrOpts?: BlockerOpts): BlockerResolver;
|
|
14
|
+
/**
|
|
15
|
+
* @deprecated Use the BlockerOpts object syntax instead
|
|
16
|
+
*/
|
|
17
|
+
export declare function useBlocker(blockerFn?: BlockerFn, condition?: boolean | any): BlockerResolver;
|
|
18
|
+
export declare function Block({ blockerFn, condition, children }: PromptProps): any;
|
|
6
19
|
export type PromptProps = {
|
|
7
|
-
|
|
20
|
+
blockerFn?: BlockerFn;
|
|
8
21
|
condition?: boolean | any;
|
|
9
|
-
children?: ReactNode;
|
|
22
|
+
children?: ReactNode | (({ proceed, reset }: BlockerResolver) => ReactNode);
|
|
10
23
|
};
|
|
24
|
+
export {};
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -36,3 +36,4 @@ export { escapeJSON, // SSR
|
|
|
36
36
|
useLayoutEffect, // SSR
|
|
37
37
|
pick, functionalUpdate, replaceEqualDeep, isPlainObject, isPlainArray, deepEqual, useStableCallback, shallow, } from './utils';
|
|
38
38
|
export { notFound, isNotFound, CatchNotFound, DefaultGlobalNotFound, type NotFoundError, } from './not-found.js';
|
|
39
|
+
export { type Manifest, type RouterManagedTag } from './manifest.js';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export type Manifest = {
|
|
2
|
+
routes: Record<string, {
|
|
3
|
+
preloads?: Array<string>;
|
|
4
|
+
assets?: Array<RouterManagedTag>;
|
|
5
|
+
}>;
|
|
6
|
+
};
|
|
7
|
+
export type RouterManagedTag = {
|
|
8
|
+
tag: 'title';
|
|
9
|
+
attrs?: Record<string, any>;
|
|
10
|
+
children: string;
|
|
11
|
+
} | {
|
|
12
|
+
tag: 'meta' | 'link';
|
|
13
|
+
attrs?: Record<string, any>;
|
|
14
|
+
children?: never;
|
|
15
|
+
} | {
|
|
16
|
+
tag: 'script';
|
|
17
|
+
attrs?: Record<string, any>;
|
|
18
|
+
children?: string;
|
|
19
|
+
} | {
|
|
20
|
+
tag: 'style';
|
|
21
|
+
attrs?: Record<string, any>;
|
|
22
|
+
children?: string;
|
|
23
|
+
};
|
package/dist/esm/router.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Store, NoInfer } from '@tanstack/react-store';
|
|
2
|
+
import { Manifest } from './manifest.js';
|
|
2
3
|
import { HistoryState, RouterHistory } from '@tanstack/history';
|
|
3
4
|
import { AnyContext, AnyRoute, AnySearchSchema, ErrorRouteComponent, NotFoundRouteComponent, RouteMask, RouteComponent } from './route.js';
|
|
4
5
|
import { FullSearchSchema, RouteById, RoutePaths, RoutesById, RoutesByPath } from './routeInfo.js';
|
|
@@ -297,6 +298,7 @@ export interface DehydratedRouterState {
|
|
|
297
298
|
export type DehydratedRouteMatch = Pick<MakeRouteMatch, 'id' | 'status' | 'updatedAt' | 'loaderData'>;
|
|
298
299
|
export interface DehydratedRouter {
|
|
299
300
|
state: DehydratedRouterState;
|
|
301
|
+
manifest?: Manifest;
|
|
300
302
|
}
|
|
301
303
|
export type RouterConstructorOptions<TRouteTree extends AnyRoute, TTrailingSlashOption extends TrailingSlashOption, TDehydrated extends Record<string, any>, TSerializedError extends Record<string, any>> = Omit<RouterOptions<TRouteTree, TTrailingSlashOption, TDehydrated, TSerializedError>, 'context'> & RouterContextOptions<TRouteTree>;
|
|
302
304
|
export declare const componentTypes: readonly ["component", "errorComponent", "pendingComponent", "notFoundComponent"];
|
|
@@ -335,6 +337,7 @@ export declare class Router<in out TRouteTree extends AnyRoute, in out TTrailing
|
|
|
335
337
|
injectedHtml: Array<InjectedHtmlEntry>;
|
|
336
338
|
dehydratedData?: TDehydrated;
|
|
337
339
|
viewTransitionPromise?: ControlledPromise<true>;
|
|
340
|
+
manifest?: Manifest;
|
|
338
341
|
__store: Store<RouterState<TRouteTree>>;
|
|
339
342
|
options: PickAsRequired<Omit<RouterOptions<TRouteTree, TTrailingSlashOption, TDehydrated, TSerializedError>, 'transformer'> & {
|
|
340
343
|
transformer: RouterTransformer;
|
package/dist/esm/router.js
CHANGED
|
@@ -1205,7 +1205,8 @@ class Router {
|
|
|
1205
1205
|
__isServerError: true
|
|
1206
1206
|
} : void 0
|
|
1207
1207
|
}))
|
|
1208
|
-
}
|
|
1208
|
+
},
|
|
1209
|
+
manifest: this.manifest
|
|
1209
1210
|
};
|
|
1210
1211
|
};
|
|
1211
1212
|
this.hydrate = async (__do_not_use_server_ctx) => {
|
|
@@ -1256,6 +1257,7 @@ class Router {
|
|
|
1256
1257
|
matches
|
|
1257
1258
|
};
|
|
1258
1259
|
});
|
|
1260
|
+
this.manifest = ctx.router.manifest;
|
|
1259
1261
|
};
|
|
1260
1262
|
this.handleNotFound = (matches, err) => {
|
|
1261
1263
|
const matchesByRouteId = Object.fromEntries(
|