@tanstack/react-router 0.0.1-beta.231 → 0.0.1-beta.233

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.
@@ -24,11 +24,6 @@ export type MatchRouteFn<TRouteTree extends AnyRoute> = <TFrom extends RoutePath
24
24
  export type BuildLocationFn<TRouteTree extends AnyRoute> = (opts: BuildNextOptions) => ParsedLocation;
25
25
  export type InjectedHtmlEntry = string | (() => Promise<string> | string);
26
26
  export declare const routerContext: React.Context<Router<any, Record<string, any>>>;
27
- export declare class SearchParamError extends Error {
28
- }
29
- export declare class PathParamError extends Error {
30
- }
31
- export declare function getInitialRouterState(location: ParsedLocation): RouterState<any>;
32
27
  export declare function RouterProvider<TRouteTree extends AnyRoute = RegisteredRouter['routeTree'], TDehydrated extends Record<string, any> = Record<string, any>>({ router, ...rest }: RouterProps<TRouteTree, TDehydrated>): React.JSX.Element;
33
28
  export declare function getRouteMatch<TRouteTree extends AnyRoute>(state: RouterState<TRouteTree>, id: string): undefined | RouteMatch<TRouteTree>;
34
29
  export declare function useRouterState<TSelected = RouterState<RegisteredRouter['routeTree']>>(opts?: {
@@ -46,8 +46,13 @@ export interface RouterOptions<TRouteTree extends AnyRoute, TDehydrated extends
46
46
  routeTree?: TRouteTree;
47
47
  basepath?: string;
48
48
  context?: TRouteTree['types']['routerContext'];
49
+ dehydrate?: () => TDehydrated;
50
+ hydrate?: (dehydrated: TDehydrated) => void;
49
51
  routeMasks?: RouteMask<TRouteTree>[];
50
52
  unmaskOnReload?: boolean;
53
+ Wrap?: (props: {
54
+ children: any;
55
+ }) => JSX.Element;
51
56
  }
52
57
  export interface RouterState<TRouteTree extends AnyRoute = AnyRoute> {
53
58
  status: 'pending' | 'idle';
@@ -128,8 +133,8 @@ export declare class Router<TRouteTree extends AnyRoute = AnyRoute, TDehydrated
128
133
  flatRoutes: AnyRoute[];
129
134
  constructor(options: RouterConstructorOptions<TRouteTree, TDehydrated>);
130
135
  startReactTransition: (fn: () => void) => void;
131
- setState: (fn: (s: RouterState<TRouteTree>) => RouterState<TRouteTree>) => void;
132
- updateOptions: (newOptions: PickAsRequired<RouterOptions<TRouteTree, TDehydrated>, 'stringifySearch' | 'parseSearch' | 'context'>) => void;
136
+ setState: (updater: NonNullableUpdater<RouterState<TRouteTree>>) => void;
137
+ update: (newOptions: RouterConstructorOptions<TRouteTree, TDehydrated>) => void;
133
138
  buildRouteTree: () => void;
134
139
  subscribe: <TType extends keyof RouterEvents>(eventType: TType, fn: ListenerFn<RouterEvents[TType]>) => () => void;
135
140
  emit: (routerEvent: RouterEvent) => void;
@@ -163,5 +168,12 @@ export declare class Router<TRouteTree extends AnyRoute = AnyRoute, TDehydrated
163
168
  injectHtml: (html: string | (() => Promise<string> | string)) => Promise<void>;
164
169
  dehydrateData: <T>(key: any, getData: T | (() => T | Promise<T>)) => () => T | undefined;
165
170
  hydrateData: <T extends unknown = unknown>(key: any) => T | undefined;
171
+ dehydrate: () => DehydratedRouter;
172
+ hydrate: (__do_not_use_server_ctx?: HydrationCtx) => Promise<void>;
166
173
  }
167
174
  export declare function lazyFn<T extends Record<string, (...args: any[]) => any>, TKey extends keyof T = 'default'>(fn: () => Promise<T>, key?: TKey): (...args: Parameters<T[TKey]>) => Promise<ReturnType<T[TKey]>>;
175
+ export declare class SearchParamError extends Error {
176
+ }
177
+ export declare class PathParamError extends Error {
178
+ }
179
+ export declare function getInitialRouterState(location: ParsedLocation): RouterState<any>;
@@ -1123,24 +1123,12 @@
1123
1123
  if (typeof document !== 'undefined') {
1124
1124
  window.__TSR_ROUTER_CONTEXT__ = routerContext;
1125
1125
  }
1126
- class SearchParamError extends Error {}
1127
- class PathParamError extends Error {}
1128
- function getInitialRouterState(location) {
1129
- return {
1130
- status: 'idle',
1131
- resolvedLocation: location,
1132
- location,
1133
- matches: [],
1134
- pendingMatches: [],
1135
- lastUpdated: Date.now()
1136
- };
1137
- }
1138
1126
  function RouterProvider({
1139
1127
  router,
1140
1128
  ...rest
1141
1129
  }) {
1142
1130
  // Allow the router to update options on the router instance
1143
- router.updateOptions({
1131
+ router.update({
1144
1132
  ...router.options,
1145
1133
  ...rest,
1146
1134
  context: {
@@ -1148,6 +1136,17 @@
1148
1136
  ...rest?.context
1149
1137
  }
1150
1138
  });
1139
+ const inner = /*#__PURE__*/React__namespace.createElement(RouterProviderInner, {
1140
+ router: router
1141
+ });
1142
+ if (router.options.Wrap) {
1143
+ return /*#__PURE__*/React__namespace.createElement(router.options.Wrap, null, inner);
1144
+ }
1145
+ return inner;
1146
+ }
1147
+ function RouterProviderInner({
1148
+ router
1149
+ }) {
1151
1150
  const [preState, setState] = React__namespace.useState(() => router.state);
1152
1151
  const [isTransitioning, startReactTransition] = React__namespace.useTransition();
1153
1152
  const isAnyTransitioning = isTransitioning || preState.matches.some(d => d.status === 'pending');
@@ -1160,18 +1159,21 @@
1160
1159
  router.setState = setState;
1161
1160
  router.state = state;
1162
1161
  router.startReactTransition = startReactTransition;
1163
- React__namespace.useLayoutEffect(() => {
1162
+ const tryLoad = () => {
1163
+ if (state.location !== router.latestLocation) {
1164
+ startReactTransition(() => {
1165
+ try {
1166
+ router.load();
1167
+ } catch (err) {
1168
+ console.error(err);
1169
+ }
1170
+ });
1171
+ }
1172
+ };
1173
+ useLayoutEffect$1(() => {
1164
1174
  const unsub = router.history.subscribe(() => {
1165
1175
  router.latestLocation = router.parseLocation(router.latestLocation);
1166
- if (state.location !== router.latestLocation) {
1167
- startReactTransition(() => {
1168
- try {
1169
- router.load();
1170
- } catch (err) {
1171
- console.error(err);
1172
- }
1173
- });
1174
- }
1176
+ tryLoad();
1175
1177
  });
1176
1178
  const nextLocation = router.buildLocation({
1177
1179
  search: true,
@@ -1189,7 +1191,7 @@
1189
1191
  unsub();
1190
1192
  };
1191
1193
  }, [router.history]);
1192
- React__namespace.useLayoutEffect(() => {
1194
+ useLayoutEffect$1(() => {
1193
1195
  if (!isTransitioning && state.resolvedLocation !== state.location) {
1194
1196
  router.emit({
1195
1197
  type: 'onResolved',
@@ -1204,14 +1206,10 @@
1204
1206
  }));
1205
1207
  }
1206
1208
  });
1207
- React__namespace.useLayoutEffect(() => {
1208
- startReactTransition(() => {
1209
- try {
1210
- router.load();
1211
- } catch (err) {
1212
- console.error(err);
1213
- }
1214
- });
1209
+ useLayoutEffect$1(() => {
1210
+ if (!window.__TSR_DEHYDRATED__) {
1211
+ tryLoad();
1212
+ }
1215
1213
  }, []);
1216
1214
  return /*#__PURE__*/React__namespace.createElement(routerContext.Provider, {
1217
1215
  value: router
@@ -1228,7 +1226,7 @@
1228
1226
  return opts?.select ? opts.select(state) : state;
1229
1227
  }
1230
1228
  function useRouter() {
1231
- const resolvedContext = window.__TSR_ROUTER_CONTEXT__ || routerContext;
1229
+ const resolvedContext = typeof document !== 'undefined' ? window.__TSR_ROUTER_CONTEXT__ || routerContext : routerContext;
1232
1230
  const value = React__namespace.useContext(resolvedContext);
1233
1231
  warning(value, 'useRouter must be used inside a <RouterProvider> component!');
1234
1232
  return value;
@@ -1554,6 +1552,8 @@
1554
1552
  };
1555
1553
  }
1556
1554
 
1555
+ // import warning from 'tiny-warning'
1556
+
1557
1557
  //
1558
1558
 
1559
1559
  const componentTypes = ['component', 'errorComponent', 'pendingComponent'];
@@ -1571,7 +1571,7 @@
1571
1571
  // Must build in constructor
1572
1572
 
1573
1573
  constructor(options) {
1574
- this.updateOptions({
1574
+ this.update({
1575
1575
  defaultPreloadDelay: 50,
1576
1576
  defaultPendingMs: 1000,
1577
1577
  defaultPendingMinMs: 500,
@@ -1581,20 +1581,22 @@
1581
1581
  parseSearch: options?.parseSearch ?? defaultParseSearch
1582
1582
  });
1583
1583
  }
1584
- startReactTransition = () => {
1585
- warning(false, 'startReactTransition implementation is missing. If you see this, please file an issue.');
1586
- };
1587
- setState = () => {
1588
- warning(false, 'setState implementation is missing. If you see this, please file an issue.');
1584
+
1585
+ // These are default implementations that can optionally be overridden
1586
+ // by the router provider once rendered. We provide these so that the
1587
+ // router can be used in a non-react environment if necessary
1588
+ startReactTransition = fn => fn();
1589
+ setState = updater => {
1590
+ this.state = functionalUpdate(updater, this.state);
1589
1591
  };
1590
- updateOptions = newOptions => {
1592
+ update = newOptions => {
1591
1593
  this.options = {
1592
1594
  ...this.options,
1593
1595
  ...newOptions
1594
1596
  };
1595
1597
  this.basepath = `/${trimPath(newOptions.basepath ?? '') ?? ''}`;
1596
1598
  if (!this.history || this.options.history && this.options.history !== this.history) {
1597
- this.history = this.options.history ?? createBrowserHistory();
1599
+ this.history = this.options.history ?? (typeof document !== 'undefined' ? createBrowserHistory() : createMemoryHistory());
1598
1600
  this.latestLocation = this.parseLocation();
1599
1601
  }
1600
1602
  if (this.options.routeTree !== this.routeTree) {
@@ -2352,6 +2354,7 @@
2352
2354
  // ...s,
2353
2355
  // status: 'idle',
2354
2356
  // resolvedLocation: s.location,
2357
+ // matches,
2355
2358
  // }))
2356
2359
 
2357
2360
  //
@@ -2552,63 +2555,42 @@
2552
2555
  }
2553
2556
  return undefined;
2554
2557
  };
2555
-
2556
- // dehydrate = (): DehydratedRouter => {
2557
- // return {
2558
- // state: {
2559
- // dehydratedMatches: this.state.matches.map((d) =>
2560
- // pick(d, ['fetchedAt', 'invalid', 'id', 'status', 'updatedAt']),
2561
- // ),
2562
- // },
2563
- // }
2564
- // }
2565
-
2566
- // hydrate = async (__do_not_use_server_ctx?: HydrationCtx) => {
2567
- // let _ctx = __do_not_use_server_ctx
2568
- // // Client hydrates from window
2569
- // if (typeof document !== 'undefined') {
2570
- // _ctx = window.__TSR_DEHYDRATED__
2571
- // }
2572
-
2573
- // invariant(
2574
- // _ctx,
2575
- // 'Expected to find a __TSR_DEHYDRATED__ property on window... but we did not. Did you forget to render <DehydrateRouter /> in your app?',
2576
- // )
2577
-
2578
- // const ctx = _ctx
2579
- // this.dehydratedData = ctx.payload as any
2580
- // this.options.hydrate?.(ctx.payload as any)
2581
- // const dehydratedState = ctx.router.state
2582
-
2583
- // let matches = this.matchRoutes(
2584
- // this.state.location.pathname,
2585
- // this.state.location.search,
2586
- // ).map((match) => {
2587
- // const dehydratedMatch = dehydratedState.dehydratedMatches.find(
2588
- // (d) => d.id === match.id,
2589
- // )
2590
-
2591
- // invariant(
2592
- // dehydratedMatch,
2593
- // `Could not find a client-side match for dehydrated match with id: ${match.id}!`,
2594
- // )
2595
-
2596
- // if (dehydratedMatch) {
2597
- // return {
2598
- // ...match,
2599
- // ...dehydratedMatch,
2600
- // }
2601
- // }
2602
- // return match
2603
- // })
2604
-
2605
- // this.setState((s) => {
2606
- // return {
2607
- // ...s,
2608
- // matches: dehydratedState.dehydratedMatches as any,
2609
- // }
2610
- // })
2611
- // }
2558
+ dehydrate = () => {
2559
+ return {
2560
+ state: {
2561
+ dehydratedMatches: this.state.matches.map(d => pick(d, ['fetchedAt', 'invalid', 'id', 'status', 'updatedAt', 'loaderData']))
2562
+ }
2563
+ };
2564
+ };
2565
+ hydrate = async __do_not_use_server_ctx => {
2566
+ let _ctx = __do_not_use_server_ctx;
2567
+ // Client hydrates from window
2568
+ if (typeof document !== 'undefined') {
2569
+ _ctx = window.__TSR_DEHYDRATED__;
2570
+ }
2571
+ invariant(_ctx, 'Expected to find a __TSR_DEHYDRATED__ property on window... but we did not. Did you forget to render <DehydrateRouter /> in your app?');
2572
+ const ctx = _ctx;
2573
+ this.dehydratedData = ctx.payload;
2574
+ this.options.hydrate?.(ctx.payload);
2575
+ const dehydratedState = ctx.router.state;
2576
+ let matches = this.matchRoutes(this.state.location.pathname, this.state.location.search).map(match => {
2577
+ const dehydratedMatch = dehydratedState.dehydratedMatches.find(d => d.id === match.id);
2578
+ invariant(dehydratedMatch, `Could not find a client-side match for dehydrated match with id: ${match.id}!`);
2579
+ if (dehydratedMatch) {
2580
+ return {
2581
+ ...match,
2582
+ ...dehydratedMatch
2583
+ };
2584
+ }
2585
+ return match;
2586
+ });
2587
+ this.setState(s => {
2588
+ return {
2589
+ ...s,
2590
+ matches: matches
2591
+ };
2592
+ });
2593
+ };
2612
2594
 
2613
2595
  // resolveMatchPromise = (matchId: string, key: string, value: any) => {
2614
2596
  // state.matches
@@ -2629,6 +2611,18 @@
2629
2611
  function isCtrlEvent(e) {
2630
2612
  return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
2631
2613
  }
2614
+ class SearchParamError extends Error {}
2615
+ class PathParamError extends Error {}
2616
+ function getInitialRouterState(location) {
2617
+ return {
2618
+ status: 'idle',
2619
+ resolvedLocation: location,
2620
+ location,
2621
+ matches: [],
2622
+ pendingMatches: [],
2623
+ lastUpdated: Date.now()
2624
+ };
2625
+ }
2632
2626
 
2633
2627
  const useLayoutEffect = typeof window !== 'undefined' ? React__namespace.useLayoutEffect : React__namespace.useEffect;
2634
2628
  const windowKey = 'window';