@tanstack/react-router 0.0.1-beta.219 → 0.0.1-beta.220
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/build/cjs/Matches.js.map +1 -1
- package/build/cjs/RouterProvider.js +51 -17
- package/build/cjs/RouterProvider.js.map +1 -1
- package/build/cjs/awaited.js +45 -0
- package/build/cjs/awaited.js.map +1 -0
- package/build/cjs/defer.js +39 -0
- package/build/cjs/defer.js.map +1 -0
- package/build/cjs/index.js +7 -0
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/router.js +0 -43
- package/build/cjs/router.js.map +1 -1
- package/build/cjs/utils.js +6 -0
- package/build/cjs/utils.js.map +1 -1
- package/build/esm/index.js +602 -559
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +392 -329
- package/build/types/RouterProvider.d.ts +5 -0
- package/build/types/awaited.d.ts +8 -0
- package/build/types/defer.d.ts +19 -0
- package/build/types/index.d.ts +2 -0
- package/build/types/utils.d.ts +1 -0
- package/build/umd/index.development.js +606 -558
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js +1 -1
- package/build/umd/index.production.js.map +1 -1
- package/package.json +2 -2
- package/src/Matches.tsx +1 -1
- package/src/RouterProvider.tsx +85 -24
- package/src/awaited.tsx +40 -40
- package/src/defer.ts +48 -48
- package/src/index.tsx +2 -2
- package/src/router.ts +0 -50
- package/src/utils.ts +7 -0
package/build/esm/index.js
CHANGED
|
@@ -282,6 +282,11 @@ function useRouteContext(opts) {
|
|
|
282
282
|
});
|
|
283
283
|
}
|
|
284
284
|
const useLayoutEffect$1 = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
|
|
285
|
+
function escapeJSON(jsonString) {
|
|
286
|
+
return jsonString.replace(/\\/g, '\\\\') // Escape backslashes
|
|
287
|
+
.replace(/'/g, "\\'") // Escape single quotes
|
|
288
|
+
.replace(/"/g, '\\"'); // Escape double quotes
|
|
289
|
+
}
|
|
285
290
|
|
|
286
291
|
function joinPaths(paths) {
|
|
287
292
|
return cleanPath(paths.filter(Boolean).join('/'));
|
|
@@ -467,173 +472,480 @@ function matchByPath(basepath, from, matchLocation) {
|
|
|
467
472
|
return isMatch ? params : undefined;
|
|
468
473
|
}
|
|
469
474
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
+
function useParams(opts) {
|
|
476
|
+
return useRouterState({
|
|
477
|
+
select: state => {
|
|
478
|
+
const params = last(state.matches)?.params;
|
|
479
|
+
return opts?.select ? opts.select(params) : params;
|
|
480
|
+
}
|
|
481
|
+
});
|
|
475
482
|
}
|
|
476
|
-
|
|
477
|
-
|
|
483
|
+
|
|
484
|
+
function useSearch(opts) {
|
|
485
|
+
return useMatch({
|
|
486
|
+
...opts,
|
|
487
|
+
select: match => {
|
|
488
|
+
return opts?.select ? opts.select(match.search) : match.search;
|
|
489
|
+
}
|
|
490
|
+
});
|
|
478
491
|
}
|
|
479
492
|
|
|
480
|
-
|
|
493
|
+
const rootRouteId = '__root__';
|
|
481
494
|
|
|
482
|
-
//
|
|
495
|
+
// The parse type here allows a zod schema to be passed directly to the validator
|
|
483
496
|
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
}
|
|
496
|
-
} else {
|
|
497
|
-
str && (str += '&');
|
|
498
|
-
str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp);
|
|
499
|
-
}
|
|
500
|
-
}
|
|
497
|
+
class Route {
|
|
498
|
+
// Set up in this.init()
|
|
499
|
+
|
|
500
|
+
// customId!: TCustomId
|
|
501
|
+
|
|
502
|
+
// Optional
|
|
503
|
+
|
|
504
|
+
constructor(options) {
|
|
505
|
+
this.options = options || {};
|
|
506
|
+
this.isRoot = !options?.getParentRoute;
|
|
507
|
+
Route.__onInit(this);
|
|
501
508
|
}
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
return +str * 0 === 0 && +str + '' === str ? +str : str;
|
|
510
|
-
}
|
|
511
|
-
function decode(str) {
|
|
512
|
-
var tmp,
|
|
513
|
-
k,
|
|
514
|
-
out = {},
|
|
515
|
-
arr = str.split('&');
|
|
516
|
-
while (tmp = arr.shift()) {
|
|
517
|
-
tmp = tmp.split('=');
|
|
518
|
-
k = tmp.shift();
|
|
519
|
-
if (out[k] !== void 0) {
|
|
520
|
-
out[k] = [].concat(out[k], toValue(tmp.shift()));
|
|
509
|
+
init = opts => {
|
|
510
|
+
this.originalIndex = opts.originalIndex;
|
|
511
|
+
const options = this.options;
|
|
512
|
+
const isRoot = !options?.path && !options?.id;
|
|
513
|
+
this.parentRoute = this.options?.getParentRoute?.();
|
|
514
|
+
if (isRoot) {
|
|
515
|
+
this.path = rootRouteId;
|
|
521
516
|
} else {
|
|
522
|
-
|
|
517
|
+
invariant(this.parentRoute, `Child Route instances must pass a 'getParentRoute: () => ParentRoute' option that returns a Route instance.`);
|
|
523
518
|
}
|
|
524
|
-
|
|
525
|
-
return out;
|
|
526
|
-
}
|
|
519
|
+
let path = isRoot ? rootRouteId : options.path;
|
|
527
520
|
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
return searchStr => {
|
|
532
|
-
if (searchStr.substring(0, 1) === '?') {
|
|
533
|
-
searchStr = searchStr.substring(1);
|
|
521
|
+
// If the path is anything other than an index path, trim it up
|
|
522
|
+
if (path && path !== '/') {
|
|
523
|
+
path = trimPath(path);
|
|
534
524
|
}
|
|
535
|
-
|
|
525
|
+
const customId = options?.id || path;
|
|
536
526
|
|
|
537
|
-
//
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
try {
|
|
542
|
-
query[key] = parser(value);
|
|
543
|
-
} catch (err) {
|
|
544
|
-
//
|
|
545
|
-
}
|
|
546
|
-
}
|
|
527
|
+
// Strip the parentId prefix from the first level of children
|
|
528
|
+
let id = isRoot ? rootRouteId : joinPaths([this.parentRoute.id === rootRouteId ? '' : this.parentRoute.id, customId]);
|
|
529
|
+
if (path === rootRouteId) {
|
|
530
|
+
path = '/';
|
|
547
531
|
}
|
|
548
|
-
|
|
532
|
+
if (id !== rootRouteId) {
|
|
533
|
+
id = joinPaths(['/', id]);
|
|
534
|
+
}
|
|
535
|
+
const fullPath = id === rootRouteId ? '/' : joinPaths([this.parentRoute.fullPath, path]);
|
|
536
|
+
this.path = path;
|
|
537
|
+
this.id = id;
|
|
538
|
+
// this.customId = customId as TCustomId
|
|
539
|
+
this.fullPath = fullPath;
|
|
540
|
+
this.to = fullPath;
|
|
541
|
+
};
|
|
542
|
+
addChildren = children => {
|
|
543
|
+
this.children = children;
|
|
544
|
+
return this;
|
|
545
|
+
};
|
|
546
|
+
update = options => {
|
|
547
|
+
Object.assign(this.options, options);
|
|
548
|
+
return this;
|
|
549
|
+
};
|
|
550
|
+
static __onInit = route => {
|
|
551
|
+
// This is a dummy static method that should get
|
|
552
|
+
// replaced by a framework specific implementation if necessary
|
|
553
|
+
};
|
|
554
|
+
useMatch = opts => {
|
|
555
|
+
return useMatch({
|
|
556
|
+
...opts,
|
|
557
|
+
from: this.id
|
|
558
|
+
});
|
|
559
|
+
};
|
|
560
|
+
useRouteContext = opts => {
|
|
561
|
+
return useMatch({
|
|
562
|
+
...opts,
|
|
563
|
+
from: this.id,
|
|
564
|
+
select: d => opts?.select ? opts.select(d.context) : d.context
|
|
565
|
+
});
|
|
566
|
+
};
|
|
567
|
+
useSearch = opts => {
|
|
568
|
+
return useSearch({
|
|
569
|
+
...opts,
|
|
570
|
+
from: this.id
|
|
571
|
+
});
|
|
572
|
+
};
|
|
573
|
+
useParams = opts => {
|
|
574
|
+
return useParams({
|
|
575
|
+
...opts,
|
|
576
|
+
from: this.id
|
|
577
|
+
});
|
|
578
|
+
};
|
|
579
|
+
useLoaderData = opts => {
|
|
580
|
+
return useLoaderData({
|
|
581
|
+
...opts,
|
|
582
|
+
from: this.id
|
|
583
|
+
});
|
|
549
584
|
};
|
|
550
585
|
}
|
|
551
|
-
function
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
try {
|
|
555
|
-
return stringify(val);
|
|
556
|
-
} catch (err) {
|
|
557
|
-
// silent
|
|
558
|
-
}
|
|
559
|
-
} else if (typeof val === 'string' && typeof parser === 'function') {
|
|
560
|
-
try {
|
|
561
|
-
// Check if it's a valid parseable string.
|
|
562
|
-
// If it is, then stringify it again.
|
|
563
|
-
parser(val);
|
|
564
|
-
return stringify(val);
|
|
565
|
-
} catch (err) {
|
|
566
|
-
// silent
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
return val;
|
|
570
|
-
}
|
|
571
|
-
return search => {
|
|
572
|
-
search = {
|
|
573
|
-
...search
|
|
574
|
-
};
|
|
575
|
-
if (search) {
|
|
576
|
-
Object.keys(search).forEach(key => {
|
|
577
|
-
const val = search[key];
|
|
578
|
-
if (typeof val === 'undefined' || val === undefined) {
|
|
579
|
-
delete search[key];
|
|
580
|
-
} else {
|
|
581
|
-
search[key] = stringifyValue(val);
|
|
582
|
-
}
|
|
583
|
-
});
|
|
584
|
-
}
|
|
585
|
-
const searchStr = encode(search).toString();
|
|
586
|
-
return searchStr ? `?${searchStr}` : '';
|
|
586
|
+
function rootRouteWithContext() {
|
|
587
|
+
return options => {
|
|
588
|
+
return new RootRoute(options);
|
|
587
589
|
};
|
|
588
590
|
}
|
|
589
|
-
|
|
590
|
-
//
|
|
591
|
-
|
|
592
|
-
//
|
|
593
|
-
|
|
594
|
-
const componentTypes = ['component', 'errorComponent', 'pendingComponent'];
|
|
595
|
-
class Router {
|
|
596
|
-
// dehydratedData?: TDehydrated
|
|
597
|
-
// resetNextScroll = false
|
|
598
|
-
// tempLocationKey = `${Math.round(Math.random() * 10000000)}`
|
|
591
|
+
class RootRoute extends Route {
|
|
599
592
|
constructor(options) {
|
|
600
|
-
|
|
601
|
-
defaultPreloadDelay: 50,
|
|
602
|
-
context: undefined,
|
|
603
|
-
...options,
|
|
604
|
-
stringifySearch: options?.stringifySearch ?? defaultStringifySearch,
|
|
605
|
-
parseSearch: options?.parseSearch ?? defaultParseSearch
|
|
606
|
-
};
|
|
607
|
-
this.routeTree = this.options.routeTree;
|
|
593
|
+
super(options);
|
|
608
594
|
}
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
fn
|
|
614
|
-
};
|
|
615
|
-
this.subscribers.add(listener);
|
|
616
|
-
return () => {
|
|
617
|
-
this.subscribers.delete(listener);
|
|
618
|
-
};
|
|
619
|
-
};
|
|
620
|
-
emit = routerEvent => {
|
|
621
|
-
this.subscribers.forEach(listener => {
|
|
622
|
-
if (listener.eventType === routerEvent.type) {
|
|
623
|
-
listener.fn(routerEvent);
|
|
624
|
-
}
|
|
625
|
-
});
|
|
626
|
-
};
|
|
595
|
+
}
|
|
596
|
+
function createRouteMask(opts) {
|
|
597
|
+
return opts;
|
|
598
|
+
}
|
|
627
599
|
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
600
|
+
//
|
|
601
|
+
|
|
602
|
+
function Matches() {
|
|
603
|
+
const {
|
|
604
|
+
routesById,
|
|
605
|
+
state
|
|
606
|
+
} = useRouter();
|
|
607
|
+
const {
|
|
608
|
+
matches
|
|
609
|
+
} = state;
|
|
610
|
+
const locationKey = useRouterState().location.state.key;
|
|
611
|
+
const route = routesById[rootRouteId];
|
|
612
|
+
const errorComponent = React.useCallback(props => {
|
|
613
|
+
return /*#__PURE__*/React.createElement(ErrorComponent, {
|
|
614
|
+
...props,
|
|
615
|
+
useMatch: route.useMatch,
|
|
616
|
+
useRouteContext: route.useRouteContext,
|
|
617
|
+
useSearch: route.useSearch,
|
|
618
|
+
useParams: route.useParams
|
|
619
|
+
});
|
|
620
|
+
}, [route]);
|
|
621
|
+
return /*#__PURE__*/React.createElement(matchesContext.Provider, {
|
|
622
|
+
value: matches
|
|
623
|
+
}, /*#__PURE__*/React.createElement(CatchBoundary, {
|
|
624
|
+
resetKey: locationKey,
|
|
625
|
+
errorComponent: errorComponent,
|
|
626
|
+
onCatch: () => {
|
|
627
|
+
warning(false, `Error in router! Consider setting an 'errorComponent' in your RootRoute! 👍`);
|
|
628
|
+
}
|
|
629
|
+
}, matches.length ? /*#__PURE__*/React.createElement(Match, {
|
|
630
|
+
matches: matches
|
|
631
|
+
}) : null));
|
|
632
|
+
}
|
|
633
|
+
const defaultPending = () => null;
|
|
634
|
+
function SafeFragment(props) {
|
|
635
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, props.children);
|
|
636
|
+
}
|
|
637
|
+
function Match({
|
|
638
|
+
matches
|
|
639
|
+
}) {
|
|
640
|
+
const {
|
|
641
|
+
options,
|
|
642
|
+
routesById
|
|
643
|
+
} = useRouter();
|
|
644
|
+
const match = matches[0];
|
|
645
|
+
const routeId = match?.routeId;
|
|
646
|
+
const route = routesById[routeId];
|
|
647
|
+
const locationKey = useRouterState().location.state?.key;
|
|
648
|
+
const PendingComponent = route.options.pendingComponent ?? options.defaultPendingComponent ?? defaultPending;
|
|
649
|
+
const routeErrorComponent = route.options.errorComponent ?? options.defaultErrorComponent ?? ErrorComponent;
|
|
650
|
+
const ResolvedSuspenseBoundary = route.options.wrapInSuspense ? React.Suspense : SafeFragment;
|
|
651
|
+
const errorComponent = routeErrorComponent ? React.useCallback(props => {
|
|
652
|
+
return /*#__PURE__*/React.createElement(routeErrorComponent, {
|
|
653
|
+
...props,
|
|
654
|
+
useMatch: route.useMatch,
|
|
655
|
+
useRouteContext: route.useRouteContext,
|
|
656
|
+
useSearch: route.useSearch,
|
|
657
|
+
useParams: route.useParams
|
|
658
|
+
});
|
|
659
|
+
}, [route]) : undefined;
|
|
660
|
+
return /*#__PURE__*/React.createElement(matchesContext.Provider, {
|
|
661
|
+
value: matches
|
|
662
|
+
}, /*#__PURE__*/React.createElement(ResolvedSuspenseBoundary, {
|
|
663
|
+
fallback: /*#__PURE__*/React.createElement(PendingComponent, {
|
|
664
|
+
useMatch: route.useMatch,
|
|
665
|
+
useRouteContext: route.useRouteContext,
|
|
666
|
+
useSearch: route.useSearch,
|
|
667
|
+
useParams: route.useParams
|
|
668
|
+
})
|
|
669
|
+
}, errorComponent ? /*#__PURE__*/React.createElement(CatchBoundary, {
|
|
670
|
+
resetKey: locationKey,
|
|
671
|
+
errorComponent: errorComponent,
|
|
672
|
+
onCatch: () => {
|
|
673
|
+
warning(false, `Error in route match: ${match.id}`);
|
|
674
|
+
}
|
|
675
|
+
}, /*#__PURE__*/React.createElement(MatchInner, {
|
|
676
|
+
match: match
|
|
677
|
+
})) : /*#__PURE__*/React.createElement(SafeFragment, null, /*#__PURE__*/React.createElement(MatchInner, {
|
|
678
|
+
match: match
|
|
679
|
+
}))));
|
|
680
|
+
}
|
|
681
|
+
function MatchInner({
|
|
682
|
+
match
|
|
683
|
+
}) {
|
|
684
|
+
const {
|
|
685
|
+
options,
|
|
686
|
+
routesById
|
|
687
|
+
} = useRouter();
|
|
688
|
+
const route = routesById[match.routeId];
|
|
689
|
+
if (match.status === 'error') {
|
|
690
|
+
throw match.error;
|
|
691
|
+
}
|
|
692
|
+
if (match.status === 'pending') {
|
|
693
|
+
throw match.loadPromise;
|
|
694
|
+
}
|
|
695
|
+
if (match.status === 'success') {
|
|
696
|
+
let comp = route.options.component ?? options.defaultComponent;
|
|
697
|
+
if (comp) {
|
|
698
|
+
return /*#__PURE__*/React.createElement(comp, {
|
|
699
|
+
useMatch: route.useMatch,
|
|
700
|
+
useRouteContext: route.useRouteContext,
|
|
701
|
+
useSearch: route.useSearch,
|
|
702
|
+
useParams: route.useParams,
|
|
703
|
+
useLoaderData: route.useLoaderData
|
|
704
|
+
});
|
|
705
|
+
}
|
|
706
|
+
return /*#__PURE__*/React.createElement(Outlet, null);
|
|
707
|
+
}
|
|
708
|
+
invariant(false, 'Idle routeMatch status encountered during rendering! You should never see this. File an issue!');
|
|
709
|
+
}
|
|
710
|
+
function Outlet() {
|
|
711
|
+
const matches = React.useContext(matchesContext).slice(1);
|
|
712
|
+
if (!matches[0]) {
|
|
713
|
+
return null;
|
|
714
|
+
}
|
|
715
|
+
return /*#__PURE__*/React.createElement(Match, {
|
|
716
|
+
matches: matches
|
|
717
|
+
});
|
|
718
|
+
}
|
|
719
|
+
function useMatchRoute() {
|
|
720
|
+
const {
|
|
721
|
+
matchRoute
|
|
722
|
+
} = useRouter();
|
|
723
|
+
return React.useCallback(opts => {
|
|
724
|
+
const {
|
|
725
|
+
pending,
|
|
726
|
+
caseSensitive,
|
|
727
|
+
...rest
|
|
728
|
+
} = opts;
|
|
729
|
+
return matchRoute(rest, {
|
|
730
|
+
pending,
|
|
731
|
+
caseSensitive
|
|
732
|
+
});
|
|
733
|
+
}, []);
|
|
734
|
+
}
|
|
735
|
+
function MatchRoute(props) {
|
|
736
|
+
const matchRoute = useMatchRoute();
|
|
737
|
+
const params = matchRoute(props);
|
|
738
|
+
if (typeof props.children === 'function') {
|
|
739
|
+
return props.children(params);
|
|
740
|
+
}
|
|
741
|
+
return !!params ? props.children : null;
|
|
742
|
+
}
|
|
743
|
+
function useMatch(opts) {
|
|
744
|
+
const nearestMatch = React.useContext(matchesContext)[0];
|
|
745
|
+
const nearestMatchRouteId = nearestMatch?.routeId;
|
|
746
|
+
const matchRouteId = useRouterState({
|
|
747
|
+
select: state => {
|
|
748
|
+
const match = opts?.from ? state.matches.find(d => d.routeId === opts?.from) : state.matches.find(d => d.id === nearestMatch.id);
|
|
749
|
+
return match.routeId;
|
|
750
|
+
}
|
|
751
|
+
});
|
|
752
|
+
if (opts?.strict ?? true) {
|
|
753
|
+
invariant(nearestMatchRouteId == matchRouteId, `useMatch("${matchRouteId}") is being called in a component that is meant to render the '${nearestMatchRouteId}' route. Did you mean to 'useMatch("${matchRouteId}", { strict: false })' or 'useRoute("${matchRouteId}")' instead?`);
|
|
754
|
+
}
|
|
755
|
+
const matchSelection = useRouterState({
|
|
756
|
+
select: state => {
|
|
757
|
+
const match = opts?.from ? state.matches.find(d => d.routeId === opts?.from) : state.matches.find(d => d.id === nearestMatch.id);
|
|
758
|
+
invariant(match, `Could not find ${opts?.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`);
|
|
759
|
+
return opts?.select ? opts.select(match) : match;
|
|
760
|
+
}
|
|
761
|
+
});
|
|
762
|
+
return matchSelection;
|
|
763
|
+
}
|
|
764
|
+
const matchesContext = /*#__PURE__*/React.createContext(null);
|
|
765
|
+
function useMatches(opts) {
|
|
766
|
+
const contextMatches = React.useContext(matchesContext);
|
|
767
|
+
return useRouterState({
|
|
768
|
+
select: state => {
|
|
769
|
+
const matches = state.matches.slice(state.matches.findIndex(d => d.id === contextMatches[0]?.id));
|
|
770
|
+
return opts?.select ? opts.select(matches) : matches;
|
|
771
|
+
}
|
|
772
|
+
});
|
|
773
|
+
}
|
|
774
|
+
function useLoaderData(opts) {
|
|
775
|
+
const match = useMatch({
|
|
776
|
+
...opts,
|
|
777
|
+
select: undefined
|
|
778
|
+
});
|
|
779
|
+
return typeof opts.select === 'function' ? opts.select(match?.loaderData) : match?.loaderData;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
// Detect if we're in the DOM
|
|
783
|
+
|
|
784
|
+
function redirect(opts) {
|
|
785
|
+
opts.isRedirect = true;
|
|
786
|
+
return opts;
|
|
787
|
+
}
|
|
788
|
+
function isRedirect(obj) {
|
|
789
|
+
return !!obj?.isRedirect;
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
// @ts-nocheck
|
|
793
|
+
|
|
794
|
+
// qss has been slightly modified and inlined here for our use cases (and compression's sake). We've included it as a hard dependency for MIT license attribution.
|
|
795
|
+
|
|
796
|
+
function encode(obj, pfx) {
|
|
797
|
+
var k,
|
|
798
|
+
i,
|
|
799
|
+
tmp,
|
|
800
|
+
str = '';
|
|
801
|
+
for (k in obj) {
|
|
802
|
+
if ((tmp = obj[k]) !== void 0) {
|
|
803
|
+
if (Array.isArray(tmp)) {
|
|
804
|
+
for (i = 0; i < tmp.length; i++) {
|
|
805
|
+
str && (str += '&');
|
|
806
|
+
str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp[i]);
|
|
807
|
+
}
|
|
808
|
+
} else {
|
|
809
|
+
str && (str += '&');
|
|
810
|
+
str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp);
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
return (pfx || '') + str;
|
|
815
|
+
}
|
|
816
|
+
function toValue(mix) {
|
|
817
|
+
if (!mix) return '';
|
|
818
|
+
var str = decodeURIComponent(mix);
|
|
819
|
+
if (str === 'false') return false;
|
|
820
|
+
if (str === 'true') return true;
|
|
821
|
+
return +str * 0 === 0 && +str + '' === str ? +str : str;
|
|
822
|
+
}
|
|
823
|
+
function decode(str) {
|
|
824
|
+
var tmp,
|
|
825
|
+
k,
|
|
826
|
+
out = {},
|
|
827
|
+
arr = str.split('&');
|
|
828
|
+
while (tmp = arr.shift()) {
|
|
829
|
+
tmp = tmp.split('=');
|
|
830
|
+
k = tmp.shift();
|
|
831
|
+
if (out[k] !== void 0) {
|
|
832
|
+
out[k] = [].concat(out[k], toValue(tmp.shift()));
|
|
833
|
+
} else {
|
|
834
|
+
out[k] = toValue(tmp.shift());
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
return out;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
const defaultParseSearch = parseSearchWith(JSON.parse);
|
|
841
|
+
const defaultStringifySearch = stringifySearchWith(JSON.stringify, JSON.parse);
|
|
842
|
+
function parseSearchWith(parser) {
|
|
843
|
+
return searchStr => {
|
|
844
|
+
if (searchStr.substring(0, 1) === '?') {
|
|
845
|
+
searchStr = searchStr.substring(1);
|
|
846
|
+
}
|
|
847
|
+
let query = decode(searchStr);
|
|
848
|
+
|
|
849
|
+
// Try to parse any query params that might be json
|
|
850
|
+
for (let key in query) {
|
|
851
|
+
const value = query[key];
|
|
852
|
+
if (typeof value === 'string') {
|
|
853
|
+
try {
|
|
854
|
+
query[key] = parser(value);
|
|
855
|
+
} catch (err) {
|
|
856
|
+
//
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
return query;
|
|
861
|
+
};
|
|
862
|
+
}
|
|
863
|
+
function stringifySearchWith(stringify, parser) {
|
|
864
|
+
function stringifyValue(val) {
|
|
865
|
+
if (typeof val === 'object' && val !== null) {
|
|
866
|
+
try {
|
|
867
|
+
return stringify(val);
|
|
868
|
+
} catch (err) {
|
|
869
|
+
// silent
|
|
870
|
+
}
|
|
871
|
+
} else if (typeof val === 'string' && typeof parser === 'function') {
|
|
872
|
+
try {
|
|
873
|
+
// Check if it's a valid parseable string.
|
|
874
|
+
// If it is, then stringify it again.
|
|
875
|
+
parser(val);
|
|
876
|
+
return stringify(val);
|
|
877
|
+
} catch (err) {
|
|
878
|
+
// silent
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
return val;
|
|
882
|
+
}
|
|
883
|
+
return search => {
|
|
884
|
+
search = {
|
|
885
|
+
...search
|
|
886
|
+
};
|
|
887
|
+
if (search) {
|
|
888
|
+
Object.keys(search).forEach(key => {
|
|
889
|
+
const val = search[key];
|
|
890
|
+
if (typeof val === 'undefined' || val === undefined) {
|
|
891
|
+
delete search[key];
|
|
892
|
+
} else {
|
|
893
|
+
search[key] = stringifyValue(val);
|
|
894
|
+
}
|
|
895
|
+
});
|
|
896
|
+
}
|
|
897
|
+
const searchStr = encode(search).toString();
|
|
898
|
+
return searchStr ? `?${searchStr}` : '';
|
|
899
|
+
};
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
//
|
|
903
|
+
|
|
904
|
+
//
|
|
905
|
+
|
|
906
|
+
const componentTypes = ['component', 'errorComponent', 'pendingComponent'];
|
|
907
|
+
class Router {
|
|
908
|
+
// dehydratedData?: TDehydrated
|
|
909
|
+
// resetNextScroll = false
|
|
910
|
+
// tempLocationKey = `${Math.round(Math.random() * 10000000)}`
|
|
911
|
+
constructor(options) {
|
|
912
|
+
this.options = {
|
|
913
|
+
defaultPreloadDelay: 50,
|
|
914
|
+
context: undefined,
|
|
915
|
+
...options,
|
|
916
|
+
stringifySearch: options?.stringifySearch ?? defaultStringifySearch,
|
|
917
|
+
parseSearch: options?.parseSearch ?? defaultParseSearch
|
|
918
|
+
};
|
|
919
|
+
this.routeTree = this.options.routeTree;
|
|
920
|
+
}
|
|
921
|
+
subscribers = new Set();
|
|
922
|
+
subscribe = (eventType, fn) => {
|
|
923
|
+
const listener = {
|
|
924
|
+
eventType,
|
|
925
|
+
fn
|
|
926
|
+
};
|
|
927
|
+
this.subscribers.add(listener);
|
|
928
|
+
return () => {
|
|
929
|
+
this.subscribers.delete(listener);
|
|
930
|
+
};
|
|
931
|
+
};
|
|
932
|
+
emit = routerEvent => {
|
|
933
|
+
this.subscribers.forEach(listener => {
|
|
934
|
+
if (listener.eventType === routerEvent.type) {
|
|
935
|
+
listener.fn(routerEvent);
|
|
936
|
+
}
|
|
937
|
+
});
|
|
938
|
+
};
|
|
939
|
+
|
|
940
|
+
// dehydrate = (): DehydratedRouter => {
|
|
941
|
+
// return {
|
|
942
|
+
// state: {
|
|
943
|
+
// dehydratedMatches: state.matches.map((d) =>
|
|
944
|
+
// pick(d, ['fetchedAt', 'invalid', 'id', 'status', 'updatedAt']),
|
|
945
|
+
// ),
|
|
946
|
+
// },
|
|
947
|
+
// }
|
|
948
|
+
// }
|
|
637
949
|
|
|
638
950
|
// hydrate = async (__do_not_use_server_ctx?: HydrationCtx) => {
|
|
639
951
|
// let _ctx = __do_not_use_server_ctx
|
|
@@ -682,49 +994,6 @@ class Router {
|
|
|
682
994
|
// })
|
|
683
995
|
// }
|
|
684
996
|
|
|
685
|
-
// TODO:
|
|
686
|
-
// injectedHtml: (string | (() => Promise<string> | string))[] = []
|
|
687
|
-
|
|
688
|
-
// TODO:
|
|
689
|
-
// injectHtml = async (html: string | (() => Promise<string> | string)) => {
|
|
690
|
-
// this.injectedHtml.push(html)
|
|
691
|
-
// }
|
|
692
|
-
|
|
693
|
-
// TODO:
|
|
694
|
-
// dehydrateData = <T>(key: any, getData: T | (() => Promise<T> | T)) => {
|
|
695
|
-
// if (typeof document === 'undefined') {
|
|
696
|
-
// const strKey = typeof key === 'string' ? key : JSON.stringify(key)
|
|
697
|
-
|
|
698
|
-
// this.injectHtml(async () => {
|
|
699
|
-
// const id = `__TSR_DEHYDRATED__${strKey}`
|
|
700
|
-
// const data =
|
|
701
|
-
// typeof getData === 'function' ? await (getData as any)() : getData
|
|
702
|
-
// return `<script id='${id}' suppressHydrationWarning>window["__TSR_DEHYDRATED__${escapeJSON(
|
|
703
|
-
// strKey,
|
|
704
|
-
// )}"] = ${JSON.stringify(data)}
|
|
705
|
-
// ;(() => {
|
|
706
|
-
// var el = document.getElementById('${id}')
|
|
707
|
-
// el.parentElement.removeChild(el)
|
|
708
|
-
// })()
|
|
709
|
-
// </script>`
|
|
710
|
-
// })
|
|
711
|
-
|
|
712
|
-
// return () => this.hydrateData<T>(key)
|
|
713
|
-
// }
|
|
714
|
-
|
|
715
|
-
// return () => undefined
|
|
716
|
-
// }
|
|
717
|
-
|
|
718
|
-
// hydrateData = <T = unknown>(key: any) => {
|
|
719
|
-
// if (typeof document !== 'undefined') {
|
|
720
|
-
// const strKey = typeof key === 'string' ? key : JSON.stringify(key)
|
|
721
|
-
|
|
722
|
-
// return window[`__TSR_DEHYDRATED__${strKey}` as any] as T
|
|
723
|
-
// }
|
|
724
|
-
|
|
725
|
-
// return undefined
|
|
726
|
-
// }
|
|
727
|
-
|
|
728
997
|
// resolveMatchPromise = (matchId: string, key: string, value: any) => {
|
|
729
998
|
// state.matches
|
|
730
999
|
// .find((d) => d.id === matchId)
|
|
@@ -1384,13 +1653,15 @@ function RouterProvider({
|
|
|
1384
1653
|
|
|
1385
1654
|
// Default to reloading the route all the time
|
|
1386
1655
|
let shouldReload = true;
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1656
|
+
if (cause !== 'enter') {
|
|
1657
|
+
let shouldReloadDeps = typeof route.options.shouldReload === 'function' ? route.options.shouldReload?.(loaderContext) : !!(route.options.shouldReload ?? true);
|
|
1658
|
+
if (typeof shouldReloadDeps === 'object') {
|
|
1659
|
+
// compare the deps to see if they've changed
|
|
1660
|
+
shouldReload = !deepEqual(shouldReloadDeps, match.shouldReloadDeps);
|
|
1661
|
+
match.shouldReloadDeps = shouldReloadDeps;
|
|
1662
|
+
} else {
|
|
1663
|
+
shouldReload = !!shouldReloadDeps;
|
|
1664
|
+
}
|
|
1394
1665
|
}
|
|
1395
1666
|
|
|
1396
1667
|
// If the user doesn't want the route to reload, just
|
|
@@ -1691,386 +1962,158 @@ function RouterProvider({
|
|
|
1691
1962
|
return () => {
|
|
1692
1963
|
unsub();
|
|
1693
1964
|
};
|
|
1694
|
-
}, [history]);
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
}, []);
|
|
1704
|
-
const matchRoute = useStableCallback((location, opts) => {
|
|
1705
|
-
location = {
|
|
1706
|
-
...location,
|
|
1707
|
-
to: location.to ? resolvePathWithBase(location.from || '', location.to) : undefined
|
|
1708
|
-
};
|
|
1709
|
-
const next = buildLocation(location);
|
|
1710
|
-
if (opts?.pending && state.status !== 'pending') {
|
|
1711
|
-
return false;
|
|
1712
|
-
}
|
|
1713
|
-
const baseLocation = opts?.pending ? latestLocationRef.current : state.resolvedLocation;
|
|
1714
|
-
|
|
1715
|
-
// const baseLocation = state.resolvedLocation
|
|
1716
|
-
|
|
1717
|
-
if (!baseLocation) {
|
|
1718
|
-
return false;
|
|
1719
|
-
}
|
|
1720
|
-
const match = matchPathname(basepath, baseLocation.pathname, {
|
|
1721
|
-
...opts,
|
|
1722
|
-
to: next.pathname
|
|
1723
|
-
});
|
|
1724
|
-
if (!match) {
|
|
1725
|
-
return false;
|
|
1726
|
-
}
|
|
1727
|
-
if (match && (opts?.includeSearch ?? true)) {
|
|
1728
|
-
return deepEqual(baseLocation.search, next.search, true) ? match : false;
|
|
1729
|
-
}
|
|
1730
|
-
return match;
|
|
1731
|
-
});
|
|
1732
|
-
const routerContextValue = {
|
|
1733
|
-
routeTree: router.routeTree,
|
|
1734
|
-
navigate,
|
|
1735
|
-
buildLink,
|
|
1736
|
-
state,
|
|
1737
|
-
matchRoute,
|
|
1738
|
-
routesById,
|
|
1739
|
-
options,
|
|
1740
|
-
history,
|
|
1741
|
-
load,
|
|
1742
|
-
buildLocation,
|
|
1743
|
-
subscribe: router.subscribe,
|
|
1744
|
-
resetNextScrollRef
|
|
1745
|
-
};
|
|
1746
|
-
return /*#__PURE__*/React.createElement(routerContext.Provider, {
|
|
1747
|
-
value: routerContextValue
|
|
1748
|
-
}, /*#__PURE__*/React.createElement(Matches, null));
|
|
1749
|
-
}
|
|
1750
|
-
function getRouteMatch(state, id) {
|
|
1751
|
-
return [...state.pendingMatches, ...state.matches].find(d => d.id === id);
|
|
1752
|
-
}
|
|
1753
|
-
function useRouterState(opts) {
|
|
1754
|
-
const {
|
|
1755
|
-
state
|
|
1756
|
-
} = useRouter();
|
|
1757
|
-
// return useStore(router.__store, opts?.select as any)
|
|
1758
|
-
return opts?.select ? opts.select(state) : state;
|
|
1759
|
-
}
|
|
1760
|
-
function useRouter() {
|
|
1761
|
-
const resolvedContext = window.__TSR_ROUTER_CONTEXT__ || routerContext;
|
|
1762
|
-
const value = React.useContext(resolvedContext);
|
|
1763
|
-
warning(value, 'useRouter must be used inside a <RouterProvider> component!');
|
|
1764
|
-
return value;
|
|
1765
|
-
}
|
|
1766
|
-
|
|
1767
|
-
function Matches() {
|
|
1768
|
-
const {
|
|
1769
|
-
routesById,
|
|
1770
|
-
state
|
|
1771
|
-
} = useRouter();
|
|
1772
|
-
const {
|
|
1773
|
-
matches
|
|
1774
|
-
} = state;
|
|
1775
|
-
const locationKey = useRouterState().location.state.key;
|
|
1776
|
-
const route = routesById[rootRouteId];
|
|
1777
|
-
const errorComponent = React.useCallback(props => {
|
|
1778
|
-
return /*#__PURE__*/React.createElement(ErrorComponent, {
|
|
1779
|
-
...props,
|
|
1780
|
-
useMatch: route.useMatch,
|
|
1781
|
-
useRouteContext: route.useRouteContext,
|
|
1782
|
-
useSearch: route.useSearch,
|
|
1783
|
-
useParams: route.useParams
|
|
1784
|
-
});
|
|
1785
|
-
}, [route]);
|
|
1786
|
-
return /*#__PURE__*/React.createElement(matchesContext.Provider, {
|
|
1787
|
-
value: matches
|
|
1788
|
-
}, /*#__PURE__*/React.createElement(CatchBoundary, {
|
|
1789
|
-
resetKey: locationKey,
|
|
1790
|
-
errorComponent: errorComponent,
|
|
1791
|
-
onCatch: () => {
|
|
1792
|
-
warning(false, `Error in router! Consider setting an 'errorComponent' in your RootRoute! 👍`);
|
|
1793
|
-
}
|
|
1794
|
-
}, matches.length ? /*#__PURE__*/React.createElement(Match, {
|
|
1795
|
-
matches: matches
|
|
1796
|
-
}) : null));
|
|
1797
|
-
}
|
|
1798
|
-
const defaultPending = () => null;
|
|
1799
|
-
function SafeFragment(props) {
|
|
1800
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, props.children);
|
|
1801
|
-
}
|
|
1802
|
-
function Match({
|
|
1803
|
-
matches
|
|
1804
|
-
}) {
|
|
1805
|
-
const {
|
|
1806
|
-
options,
|
|
1807
|
-
routesById
|
|
1808
|
-
} = useRouter();
|
|
1809
|
-
const match = matches[0];
|
|
1810
|
-
const routeId = match?.routeId;
|
|
1811
|
-
const route = routesById[routeId];
|
|
1812
|
-
const locationKey = useRouterState().location.state?.key;
|
|
1813
|
-
const PendingComponent = route.options.pendingComponent ?? options.defaultPendingComponent ?? defaultPending;
|
|
1814
|
-
const routeErrorComponent = route.options.errorComponent ?? options.defaultErrorComponent ?? ErrorComponent;
|
|
1815
|
-
const ResolvedSuspenseBoundary = route.options.wrapInSuspense ? React.Suspense : SafeFragment;
|
|
1816
|
-
const errorComponent = routeErrorComponent ? React.useCallback(props => {
|
|
1817
|
-
return /*#__PURE__*/React.createElement(routeErrorComponent, {
|
|
1818
|
-
...props,
|
|
1819
|
-
useMatch: route.useMatch,
|
|
1820
|
-
useRouteContext: route.useRouteContext,
|
|
1821
|
-
useSearch: route.useSearch,
|
|
1822
|
-
useParams: route.useParams
|
|
1823
|
-
});
|
|
1824
|
-
}, [route]) : undefined;
|
|
1825
|
-
return /*#__PURE__*/React.createElement(matchesContext.Provider, {
|
|
1826
|
-
value: matches
|
|
1827
|
-
}, /*#__PURE__*/React.createElement(ResolvedSuspenseBoundary, {
|
|
1828
|
-
fallback: /*#__PURE__*/React.createElement(PendingComponent, {
|
|
1829
|
-
useMatch: route.useMatch,
|
|
1830
|
-
useRouteContext: route.useRouteContext,
|
|
1831
|
-
useSearch: route.useSearch,
|
|
1832
|
-
useParams: route.useParams
|
|
1833
|
-
})
|
|
1834
|
-
}, errorComponent ? /*#__PURE__*/React.createElement(CatchBoundary, {
|
|
1835
|
-
resetKey: locationKey,
|
|
1836
|
-
errorComponent: errorComponent,
|
|
1837
|
-
onCatch: () => {
|
|
1838
|
-
warning(false, `Error in route match: ${match.id}`);
|
|
1839
|
-
}
|
|
1840
|
-
}, /*#__PURE__*/React.createElement(MatchInner, {
|
|
1841
|
-
match: match
|
|
1842
|
-
})) : /*#__PURE__*/React.createElement(SafeFragment, null, /*#__PURE__*/React.createElement(MatchInner, {
|
|
1843
|
-
match: match
|
|
1844
|
-
}))));
|
|
1845
|
-
}
|
|
1846
|
-
function MatchInner({
|
|
1847
|
-
match
|
|
1848
|
-
}) {
|
|
1849
|
-
const {
|
|
1850
|
-
options,
|
|
1851
|
-
routesById
|
|
1852
|
-
} = useRouter();
|
|
1853
|
-
const route = routesById[match.routeId];
|
|
1854
|
-
if (match.status === 'error') {
|
|
1855
|
-
throw match.error;
|
|
1856
|
-
}
|
|
1857
|
-
if (match.status === 'pending') {
|
|
1858
|
-
throw match.loadPromise;
|
|
1859
|
-
}
|
|
1860
|
-
if (match.status === 'success') {
|
|
1861
|
-
let comp = route.options.component ?? options.defaultComponent;
|
|
1862
|
-
if (comp) {
|
|
1863
|
-
return /*#__PURE__*/React.createElement(comp, {
|
|
1864
|
-
useMatch: route.useMatch,
|
|
1865
|
-
useRouteContext: route.useRouteContext,
|
|
1866
|
-
useSearch: route.useSearch,
|
|
1867
|
-
useParams: route.useParams,
|
|
1868
|
-
useLoaderData: route.useLoaderData
|
|
1869
|
-
});
|
|
1965
|
+
}, [history]);
|
|
1966
|
+
const matchRoute = useStableCallback((location, opts) => {
|
|
1967
|
+
location = {
|
|
1968
|
+
...location,
|
|
1969
|
+
to: location.to ? resolvePathWithBase(location.from || '', location.to) : undefined
|
|
1970
|
+
};
|
|
1971
|
+
const next = buildLocation(location);
|
|
1972
|
+
if (opts?.pending && state.status !== 'pending') {
|
|
1973
|
+
return false;
|
|
1870
1974
|
}
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
matches: matches
|
|
1882
|
-
});
|
|
1883
|
-
}
|
|
1884
|
-
function useMatchRoute() {
|
|
1885
|
-
const {
|
|
1886
|
-
matchRoute
|
|
1887
|
-
} = useRouter();
|
|
1888
|
-
return React.useCallback(opts => {
|
|
1889
|
-
const {
|
|
1890
|
-
pending,
|
|
1891
|
-
caseSensitive,
|
|
1892
|
-
...rest
|
|
1893
|
-
} = opts;
|
|
1894
|
-
return matchRoute(rest, {
|
|
1895
|
-
pending,
|
|
1896
|
-
caseSensitive
|
|
1975
|
+
const baseLocation = opts?.pending ? latestLocationRef.current : state.resolvedLocation;
|
|
1976
|
+
|
|
1977
|
+
// const baseLocation = state.resolvedLocation
|
|
1978
|
+
|
|
1979
|
+
if (!baseLocation) {
|
|
1980
|
+
return false;
|
|
1981
|
+
}
|
|
1982
|
+
const match = matchPathname(basepath, baseLocation.pathname, {
|
|
1983
|
+
...opts,
|
|
1984
|
+
to: next.pathname
|
|
1897
1985
|
});
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
function MatchRoute(props) {
|
|
1901
|
-
const matchRoute = useMatchRoute();
|
|
1902
|
-
const params = matchRoute(props);
|
|
1903
|
-
if (typeof props.children === 'function') {
|
|
1904
|
-
return props.children(params);
|
|
1905
|
-
}
|
|
1906
|
-
return !!params ? props.children : null;
|
|
1907
|
-
}
|
|
1908
|
-
function useMatch(opts) {
|
|
1909
|
-
const nearestMatch = React.useContext(matchesContext)[0];
|
|
1910
|
-
const nearestMatchRouteId = nearestMatch?.routeId;
|
|
1911
|
-
const matchRouteId = useRouterState({
|
|
1912
|
-
select: state => {
|
|
1913
|
-
const match = opts?.from ? state.matches.find(d => d.routeId === opts?.from) : state.matches.find(d => d.id === nearestMatch.id);
|
|
1914
|
-
return match.routeId;
|
|
1986
|
+
if (!match) {
|
|
1987
|
+
return false;
|
|
1915
1988
|
}
|
|
1989
|
+
if (match && (opts?.includeSearch ?? true)) {
|
|
1990
|
+
return deepEqual(baseLocation.search, next.search, true) ? match : false;
|
|
1991
|
+
}
|
|
1992
|
+
return match;
|
|
1916
1993
|
});
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1994
|
+
const injectedHtmlRef = React.useRef([]);
|
|
1995
|
+
const injectHtml = useStableCallback(async html => {
|
|
1996
|
+
injectedHtmlRef.current.push(html);
|
|
1997
|
+
});
|
|
1998
|
+
const dehydrateData = useStableCallback((key, getData) => {
|
|
1999
|
+
if (typeof document === 'undefined') {
|
|
2000
|
+
const strKey = typeof key === 'string' ? key : JSON.stringify(key);
|
|
2001
|
+
injectHtml(async () => {
|
|
2002
|
+
const id = `__TSR_DEHYDRATED__${strKey}`;
|
|
2003
|
+
const data = typeof getData === 'function' ? await getData() : getData;
|
|
2004
|
+
return `<script id='${id}' suppressHydrationWarning>window["__TSR_DEHYDRATED__${escapeJSON(strKey)}"] = ${JSON.stringify(data)}
|
|
2005
|
+
;(() => {
|
|
2006
|
+
var el = document.getElementById('${id}')
|
|
2007
|
+
el.parentElement.removeChild(el)
|
|
2008
|
+
})()
|
|
2009
|
+
</script>`;
|
|
2010
|
+
});
|
|
2011
|
+
return () => hydrateData(key);
|
|
1925
2012
|
}
|
|
2013
|
+
return () => undefined;
|
|
1926
2014
|
});
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
const
|
|
1930
|
-
|
|
1931
|
-
const contextMatches = React.useContext(matchesContext);
|
|
1932
|
-
return useRouterState({
|
|
1933
|
-
select: state => {
|
|
1934
|
-
const matches = state.matches.slice(state.matches.findIndex(d => d.id === contextMatches[0]?.id));
|
|
1935
|
-
return opts?.select ? opts.select(matches) : matches;
|
|
2015
|
+
const hydrateData = useStableCallback(key => {
|
|
2016
|
+
if (typeof document !== 'undefined') {
|
|
2017
|
+
const strKey = typeof key === 'string' ? key : JSON.stringify(key);
|
|
2018
|
+
return window[`__TSR_DEHYDRATED__${strKey}`];
|
|
1936
2019
|
}
|
|
2020
|
+
return undefined;
|
|
1937
2021
|
});
|
|
2022
|
+
React.useLayoutEffect(() => {
|
|
2023
|
+
startReactTransition(() => {
|
|
2024
|
+
try {
|
|
2025
|
+
load();
|
|
2026
|
+
} catch (err) {
|
|
2027
|
+
console.error(err);
|
|
2028
|
+
}
|
|
2029
|
+
});
|
|
2030
|
+
}, []);
|
|
2031
|
+
const routerContextValue = {
|
|
2032
|
+
routeTree: router.routeTree,
|
|
2033
|
+
navigate,
|
|
2034
|
+
buildLink,
|
|
2035
|
+
state,
|
|
2036
|
+
matchRoute,
|
|
2037
|
+
routesById,
|
|
2038
|
+
options,
|
|
2039
|
+
history,
|
|
2040
|
+
load,
|
|
2041
|
+
buildLocation,
|
|
2042
|
+
subscribe: router.subscribe,
|
|
2043
|
+
resetNextScrollRef,
|
|
2044
|
+
injectedHtmlRef,
|
|
2045
|
+
injectHtml,
|
|
2046
|
+
dehydrateData,
|
|
2047
|
+
hydrateData
|
|
2048
|
+
};
|
|
2049
|
+
return /*#__PURE__*/React.createElement(routerContext.Provider, {
|
|
2050
|
+
value: routerContextValue
|
|
2051
|
+
}, /*#__PURE__*/React.createElement(Matches, null));
|
|
1938
2052
|
}
|
|
1939
|
-
function
|
|
1940
|
-
|
|
1941
|
-
...opts,
|
|
1942
|
-
select: undefined
|
|
1943
|
-
});
|
|
1944
|
-
return typeof opts.select === 'function' ? opts.select(match?.loaderData) : match?.loaderData;
|
|
2053
|
+
function getRouteMatch(state, id) {
|
|
2054
|
+
return [...state.pendingMatches, ...state.matches].find(d => d.id === id);
|
|
1945
2055
|
}
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
}
|
|
1953
|
-
});
|
|
2056
|
+
function useRouterState(opts) {
|
|
2057
|
+
const {
|
|
2058
|
+
state
|
|
2059
|
+
} = useRouter();
|
|
2060
|
+
// return useStore(router.__store, opts?.select as any)
|
|
2061
|
+
return opts?.select ? opts.select(state) : state;
|
|
1954
2062
|
}
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
return opts?.select ? opts.select(match.search) : match.search;
|
|
1961
|
-
}
|
|
1962
|
-
});
|
|
2063
|
+
function useRouter() {
|
|
2064
|
+
const resolvedContext = window.__TSR_ROUTER_CONTEXT__ || routerContext;
|
|
2065
|
+
const value = React.useContext(resolvedContext);
|
|
2066
|
+
warning(value, 'useRouter must be used inside a <RouterProvider> component!');
|
|
2067
|
+
return value;
|
|
1963
2068
|
}
|
|
1964
2069
|
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
Route.__onInit(this);
|
|
1980
|
-
}
|
|
1981
|
-
init = opts => {
|
|
1982
|
-
this.originalIndex = opts.originalIndex;
|
|
1983
|
-
const options = this.options;
|
|
1984
|
-
const isRoot = !options?.path && !options?.id;
|
|
1985
|
-
this.parentRoute = this.options?.getParentRoute?.();
|
|
1986
|
-
if (isRoot) {
|
|
1987
|
-
this.path = rootRouteId;
|
|
1988
|
-
} else {
|
|
1989
|
-
invariant(this.parentRoute, `Child Route instances must pass a 'getParentRoute: () => ParentRoute' option that returns a Route instance.`);
|
|
1990
|
-
}
|
|
1991
|
-
let path = isRoot ? rootRouteId : options.path;
|
|
1992
|
-
|
|
1993
|
-
// If the path is anything other than an index path, trim it up
|
|
1994
|
-
if (path && path !== '/') {
|
|
1995
|
-
path = trimPath(path);
|
|
1996
|
-
}
|
|
1997
|
-
const customId = options?.id || path;
|
|
1998
|
-
|
|
1999
|
-
// Strip the parentId prefix from the first level of children
|
|
2000
|
-
let id = isRoot ? rootRouteId : joinPaths([this.parentRoute.id === rootRouteId ? '' : this.parentRoute.id, customId]);
|
|
2001
|
-
if (path === rootRouteId) {
|
|
2002
|
-
path = '/';
|
|
2003
|
-
}
|
|
2004
|
-
if (id !== rootRouteId) {
|
|
2005
|
-
id = joinPaths(['/', id]);
|
|
2006
|
-
}
|
|
2007
|
-
const fullPath = id === rootRouteId ? '/' : joinPaths([this.parentRoute.fullPath, path]);
|
|
2008
|
-
this.path = path;
|
|
2009
|
-
this.id = id;
|
|
2010
|
-
// this.customId = customId as TCustomId
|
|
2011
|
-
this.fullPath = fullPath;
|
|
2012
|
-
this.to = fullPath;
|
|
2013
|
-
};
|
|
2014
|
-
addChildren = children => {
|
|
2015
|
-
this.children = children;
|
|
2016
|
-
return this;
|
|
2017
|
-
};
|
|
2018
|
-
update = options => {
|
|
2019
|
-
Object.assign(this.options, options);
|
|
2020
|
-
return this;
|
|
2021
|
-
};
|
|
2022
|
-
static __onInit = route => {
|
|
2023
|
-
// This is a dummy static method that should get
|
|
2024
|
-
// replaced by a framework specific implementation if necessary
|
|
2025
|
-
};
|
|
2026
|
-
useMatch = opts => {
|
|
2027
|
-
return useMatch({
|
|
2028
|
-
...opts,
|
|
2029
|
-
from: this.id
|
|
2030
|
-
});
|
|
2031
|
-
};
|
|
2032
|
-
useRouteContext = opts => {
|
|
2033
|
-
return useMatch({
|
|
2034
|
-
...opts,
|
|
2035
|
-
from: this.id,
|
|
2036
|
-
select: d => opts?.select ? opts.select(d.context) : d.context
|
|
2037
|
-
});
|
|
2038
|
-
};
|
|
2039
|
-
useSearch = opts => {
|
|
2040
|
-
return useSearch({
|
|
2041
|
-
...opts,
|
|
2042
|
-
from: this.id
|
|
2043
|
-
});
|
|
2044
|
-
};
|
|
2045
|
-
useParams = opts => {
|
|
2046
|
-
return useParams({
|
|
2047
|
-
...opts,
|
|
2048
|
-
from: this.id
|
|
2049
|
-
});
|
|
2050
|
-
};
|
|
2051
|
-
useLoaderData = opts => {
|
|
2052
|
-
return useLoaderData({
|
|
2053
|
-
...opts,
|
|
2054
|
-
from: this.id
|
|
2070
|
+
function defer(_promise) {
|
|
2071
|
+
const promise = _promise;
|
|
2072
|
+
if (!promise.__deferredState) {
|
|
2073
|
+
promise.__deferredState = {
|
|
2074
|
+
uid: Math.random().toString(36).slice(2),
|
|
2075
|
+
status: 'pending'
|
|
2076
|
+
};
|
|
2077
|
+
const state = promise.__deferredState;
|
|
2078
|
+
promise.then(data => {
|
|
2079
|
+
state.status = 'success';
|
|
2080
|
+
state.data = data;
|
|
2081
|
+
}).catch(error => {
|
|
2082
|
+
state.status = 'error';
|
|
2083
|
+
state.error = error;
|
|
2055
2084
|
});
|
|
2056
|
-
}
|
|
2085
|
+
}
|
|
2086
|
+
return promise;
|
|
2057
2087
|
}
|
|
2058
|
-
function
|
|
2059
|
-
return
|
|
2060
|
-
return new RootRoute(options);
|
|
2061
|
-
};
|
|
2088
|
+
function isDehydratedDeferred(obj) {
|
|
2089
|
+
return typeof obj === 'object' && obj !== null && !(obj instanceof Promise) && !obj.then && '__deferredState' in obj;
|
|
2062
2090
|
}
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2091
|
+
|
|
2092
|
+
function useAwaited({
|
|
2093
|
+
promise
|
|
2094
|
+
}) {
|
|
2095
|
+
const router = useRouter();
|
|
2096
|
+
let state = promise.__deferredState;
|
|
2097
|
+
const key = `__TSR__DEFERRED__${state.uid}`;
|
|
2098
|
+
if (isDehydratedDeferred(promise)) {
|
|
2099
|
+
state = router.hydrateData(key);
|
|
2100
|
+
promise = Promise.resolve(state.data);
|
|
2101
|
+
promise.__deferredState = state;
|
|
2102
|
+
}
|
|
2103
|
+
if (state.status === 'pending') {
|
|
2104
|
+
throw promise;
|
|
2105
|
+
}
|
|
2106
|
+
if (state.status === 'error') {
|
|
2107
|
+
throw state.error;
|
|
2066
2108
|
}
|
|
2109
|
+
router.dehydrateData(key, state);
|
|
2110
|
+
return [state.data];
|
|
2067
2111
|
}
|
|
2068
|
-
function
|
|
2069
|
-
|
|
2112
|
+
function Await(props) {
|
|
2113
|
+
const awaited = useAwaited(props);
|
|
2114
|
+
return props.children(...awaited);
|
|
2070
2115
|
}
|
|
2071
2116
|
|
|
2072
|
-
//
|
|
2073
|
-
|
|
2074
2117
|
class FileRoute {
|
|
2075
2118
|
constructor(path) {
|
|
2076
2119
|
this.path = path;
|
|
@@ -2428,5 +2471,5 @@ function Navigate(props) {
|
|
|
2428
2471
|
return null;
|
|
2429
2472
|
}
|
|
2430
2473
|
|
|
2431
|
-
export { Block, CatchBoundary, CatchBoundaryImpl, ErrorComponent, FileRoute, Link, Match, MatchRoute, Matches, Navigate, Outlet, PathParamError, RootRoute, Route, Router, RouterProvider, ScrollRestoration, SearchParamError, cleanPath, componentTypes, createRouteMask, decode, deepEqual, defaultParseSearch, defaultStringifySearch, encode, functionalUpdate, getInitialRouterState, getRouteMatch, interpolatePath, isPlainObject, isRedirect, isServer, joinPaths, last, lazyFn, lazyRouteComponent, matchByPath, matchPathname, matchesContext, parsePathname, parseSearchWith, pick, redirect, replaceEqualDeep, resolvePath, rootRouteId, rootRouteWithContext, routerContext, shallow, stringifySearchWith, trimPath, trimPathLeft, trimPathRight, typedNavigate, useBlocker, useLayoutEffect$1 as useLayoutEffect, useLinkProps, useLoaderData, useMatch, useMatchRoute, useMatches, useNavigate, useParams, useRouteContext, useRouter, useRouterState, useScrollRestoration, useSearch, useStableCallback };
|
|
2474
|
+
export { Await, Block, CatchBoundary, CatchBoundaryImpl, ErrorComponent, FileRoute, Link, Match, MatchRoute, Matches, Navigate, Outlet, PathParamError, RootRoute, Route, Router, RouterProvider, ScrollRestoration, SearchParamError, cleanPath, componentTypes, createRouteMask, decode, deepEqual, defaultParseSearch, defaultStringifySearch, defer, encode, escapeJSON, functionalUpdate, getInitialRouterState, getRouteMatch, interpolatePath, isDehydratedDeferred, isPlainObject, isRedirect, isServer, joinPaths, last, lazyFn, lazyRouteComponent, matchByPath, matchPathname, matchesContext, parsePathname, parseSearchWith, pick, redirect, replaceEqualDeep, resolvePath, rootRouteId, rootRouteWithContext, routerContext, shallow, stringifySearchWith, trimPath, trimPathLeft, trimPathRight, typedNavigate, useAwaited, useBlocker, useLayoutEffect$1 as useLayoutEffect, useLinkProps, useLoaderData, useMatch, useMatchRoute, useMatches, useNavigate, useParams, useRouteContext, useRouter, useRouterState, useScrollRestoration, useSearch, useStableCallback };
|
|
2432
2475
|
//# sourceMappingURL=index.js.map
|