@tanstack/router-core 0.0.1-alpha.6 → 0.0.1-alpha.8

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.
Files changed (40) hide show
  1. package/build/cjs/packages/router-core/src/index.js +33 -1456
  2. package/build/cjs/packages/router-core/src/index.js.map +1 -1
  3. package/build/cjs/packages/router-core/src/path.js +222 -0
  4. package/build/cjs/packages/router-core/src/path.js.map +1 -0
  5. package/build/cjs/packages/router-core/src/qss.js +1 -1
  6. package/build/cjs/packages/router-core/src/qss.js.map +1 -1
  7. package/build/cjs/packages/router-core/src/route.js +126 -0
  8. package/build/cjs/packages/router-core/src/route.js.map +1 -0
  9. package/build/cjs/packages/router-core/src/routeConfig.js +69 -0
  10. package/build/cjs/packages/router-core/src/routeConfig.js.map +1 -0
  11. package/build/cjs/packages/router-core/src/routeMatch.js +260 -0
  12. package/build/cjs/packages/router-core/src/routeMatch.js.map +1 -0
  13. package/build/cjs/packages/router-core/src/router.js +786 -0
  14. package/build/cjs/packages/router-core/src/router.js.map +1 -0
  15. package/build/cjs/packages/router-core/src/searchParams.js +70 -0
  16. package/build/cjs/packages/router-core/src/searchParams.js.map +1 -0
  17. package/build/cjs/packages/router-core/src/utils.js +118 -0
  18. package/build/cjs/packages/router-core/src/utils.js.map +1 -0
  19. package/build/esm/index.js +1306 -1246
  20. package/build/esm/index.js.map +1 -1
  21. package/build/stats-html.html +1 -1
  22. package/build/stats-react.json +374 -57
  23. package/build/types/index.d.ts +361 -336
  24. package/build/umd/index.development.js +1315 -1246
  25. package/build/umd/index.development.js.map +1 -1
  26. package/build/umd/index.production.js +1 -1
  27. package/build/umd/index.production.js.map +1 -1
  28. package/package.json +2 -3
  29. package/src/frameworks.ts +13 -0
  30. package/src/index.ts +15 -3060
  31. package/src/link.ts +289 -0
  32. package/src/path.ts +236 -0
  33. package/src/qss.ts +1 -1
  34. package/src/route.ts +181 -0
  35. package/src/routeConfig.ts +523 -0
  36. package/src/routeInfo.ts +228 -0
  37. package/src/routeMatch.ts +357 -0
  38. package/src/router.ts +1184 -0
  39. package/src/searchParams.ts +54 -0
  40. package/src/utils.ts +157 -0
@@ -0,0 +1,786 @@
1
+ /**
2
+ * router-core
3
+ *
4
+ * Copyright (c) TanStack
5
+ *
6
+ * This source code is licensed under the MIT license found in the
7
+ * LICENSE.md file in the root directory of this source tree.
8
+ *
9
+ * @license MIT
10
+ */
11
+ 'use strict';
12
+
13
+ Object.defineProperty(exports, '__esModule', { value: true });
14
+
15
+ var _rollupPluginBabelHelpers = require('../../../_virtual/_rollupPluginBabelHelpers.js');
16
+ var index = require('../../../node_modules/history/index.js');
17
+ var tinyInvariant = require('../../../node_modules/tiny-invariant/dist/esm/tiny-invariant.js');
18
+ var path = require('./path.js');
19
+ var route = require('./route.js');
20
+ var routeMatch = require('./routeMatch.js');
21
+ var searchParams = require('./searchParams.js');
22
+ var utils = require('./utils.js');
23
+
24
+ var _window$document;
25
+ // Detect if we're in the DOM
26
+ const isServer = Boolean(typeof window === 'undefined' || !((_window$document = window.document) != null && _window$document.createElement)); // This is the default history object if none is defined
27
+
28
+ const createDefaultHistory = () => !isServer ? index.createBrowserHistory() : index.createMemoryHistory();
29
+
30
+ function createRouter(userOptions) {
31
+ var _userOptions$stringif, _userOptions$parseSea;
32
+
33
+ const history = (userOptions == null ? void 0 : userOptions.history) || createDefaultHistory();
34
+
35
+ const originalOptions = _rollupPluginBabelHelpers["extends"]({
36
+ defaultLoaderGcMaxAge: 5 * 60 * 1000,
37
+ defaultLoaderMaxAge: 0,
38
+ defaultLinkPreloadDelay: 50
39
+ }, userOptions, {
40
+ stringifySearch: (_userOptions$stringif = userOptions == null ? void 0 : userOptions.stringifySearch) != null ? _userOptions$stringif : searchParams.defaultStringifySearch,
41
+ parseSearch: (_userOptions$parseSea = userOptions == null ? void 0 : userOptions.parseSearch) != null ? _userOptions$parseSea : searchParams.defaultParseSearch
42
+ });
43
+
44
+ let router = {
45
+ options: originalOptions,
46
+ listeners: [],
47
+ removeActionQueue: [],
48
+ // Resolved after construction
49
+ basepath: '',
50
+ routeTree: undefined,
51
+ routesById: {},
52
+ location: undefined,
53
+ allRouteInfo: undefined,
54
+ //
55
+ navigationPromise: Promise.resolve(),
56
+ resolveNavigation: () => {},
57
+ matchCache: {},
58
+ state: {
59
+ status: 'idle',
60
+ location: null,
61
+ matches: [],
62
+ actions: {},
63
+ loaderData: {},
64
+ lastUpdated: Date.now(),
65
+ isFetching: false,
66
+ isPreloading: false
67
+ },
68
+ startedLoadingAt: Date.now(),
69
+ subscribe: listener => {
70
+ router.listeners.push(listener);
71
+ return () => {
72
+ router.listeners = router.listeners.filter(x => x !== listener);
73
+ };
74
+ },
75
+ getRoute: id => {
76
+ return router.routesById[id];
77
+ },
78
+ notify: () => {
79
+ router.state = _rollupPluginBabelHelpers["extends"]({}, router.state, {
80
+ isFetching: router.state.status === 'loading' || router.state.matches.some(d => d.isFetching),
81
+ isPreloading: Object.values(router.matchCache).some(d => d.match.isFetching && !router.state.matches.find(dd => dd.matchId === d.match.matchId))
82
+ });
83
+ route.cascadeLoaderData(router.state.matches);
84
+ router.listeners.forEach(listener => listener());
85
+ },
86
+ mount: () => {
87
+ const next = router.buildLocation({
88
+ to: '.',
89
+ search: true,
90
+ hash: true
91
+ }); // If the current location isn't updated, trigger a navigation
92
+ // to the current location. Otherwise, load the current location.
93
+
94
+ if (next.href !== router.location.href) {
95
+ router.commitLocation(next, true);
96
+ } else {
97
+ router.loadLocation();
98
+ }
99
+
100
+ const unsub = history.listen(event => {
101
+ router.loadLocation(router.parseLocation(event.location, router.location));
102
+ }); // addEventListener does not exist in React Native, but window does
103
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
104
+
105
+ if (!isServer && window.addEventListener) {
106
+ // Listen to visibillitychange and focus
107
+ window.addEventListener('visibilitychange', router.onFocus, false);
108
+ window.addEventListener('focus', router.onFocus, false);
109
+ }
110
+
111
+ return () => {
112
+ unsub(); // Be sure to unsubscribe if a new handler is set
113
+
114
+ window.removeEventListener('visibilitychange', router.onFocus);
115
+ window.removeEventListener('focus', router.onFocus);
116
+ };
117
+ },
118
+ onFocus: () => {
119
+ router.loadLocation();
120
+ },
121
+ update: opts => {
122
+ Object.assign(router.options, opts);
123
+ const {
124
+ basepath,
125
+ routeConfig
126
+ } = router.options;
127
+ router.basepath = path.cleanPath("/" + (basepath != null ? basepath : ''));
128
+
129
+ if (routeConfig) {
130
+ router.routesById = {};
131
+ router.routeTree = router.buildRouteTree(routeConfig);
132
+ }
133
+
134
+ return router;
135
+ },
136
+ buildRouteTree: rootRouteConfig => {
137
+ const recurseRoutes = (routeConfigs, parent) => {
138
+ return routeConfigs.map(routeConfig => {
139
+ const routeOptions = routeConfig.options;
140
+ const route$1 = route.createRoute(routeConfig, routeOptions, parent, router); // {
141
+ // pendingMs: routeOptions.pendingMs ?? router.defaultPendingMs,
142
+ // pendingMinMs: routeOptions.pendingMinMs ?? router.defaultPendingMinMs,
143
+ // }
144
+
145
+ const existingRoute = router.routesById[route$1.routeId];
146
+
147
+ if (existingRoute) {
148
+ if (process.env.NODE_ENV !== 'production') {
149
+ console.warn("Duplicate routes found with id: " + String(route$1.routeId), router.routesById, route$1);
150
+ }
151
+
152
+ throw new Error();
153
+ }
154
+ router.routesById[route$1.routeId] = route$1;
155
+ const children = routeConfig.children;
156
+ route$1.childRoutes = children != null && children.length ? recurseRoutes(children, route$1) : undefined;
157
+ return route$1;
158
+ });
159
+ };
160
+
161
+ const routes = recurseRoutes([rootRouteConfig]);
162
+ return routes[0];
163
+ },
164
+ parseLocation: (location, previousLocation) => {
165
+ var _location$hash$split$;
166
+
167
+ const parsedSearch = router.options.parseSearch(location.search);
168
+ return {
169
+ pathname: location.pathname,
170
+ searchStr: location.search,
171
+ search: utils.replaceEqualDeep(previousLocation == null ? void 0 : previousLocation.search, parsedSearch),
172
+ hash: (_location$hash$split$ = location.hash.split('#').reverse()[0]) != null ? _location$hash$split$ : '',
173
+ href: "" + location.pathname + location.search + location.hash,
174
+ state: location.state,
175
+ key: location.key
176
+ };
177
+ },
178
+ buildLocation: function buildLocation(dest) {
179
+ var _dest$from, _router$basepath, _dest$to, _last, _dest$params, _dest$__preSearchFilt, _functionalUpdate, _dest$__preSearchFilt2, _dest$__postSearchFil;
180
+
181
+ if (dest === void 0) {
182
+ dest = {};
183
+ }
184
+
185
+ // const resolvedFrom: Location = {
186
+ // ...router.location,
187
+ const fromPathname = dest.fromCurrent ? router.location.pathname : (_dest$from = dest.from) != null ? _dest$from : router.location.pathname;
188
+
189
+ let pathname = path.resolvePath((_router$basepath = router.basepath) != null ? _router$basepath : '/', fromPathname, "" + ((_dest$to = dest.to) != null ? _dest$to : '.'));
190
+
191
+ const fromMatches = router.matchRoutes(router.location.pathname, {
192
+ strictParseParams: true
193
+ });
194
+ const toMatches = router.matchRoutes(pathname);
195
+
196
+ const prevParams = _rollupPluginBabelHelpers["extends"]({}, (_last = utils.last(fromMatches)) == null ? void 0 : _last.params);
197
+
198
+ let nextParams = ((_dest$params = dest.params) != null ? _dest$params : true) === true ? prevParams : utils.functionalUpdate(dest.params, prevParams);
199
+
200
+ if (nextParams) {
201
+ toMatches.map(d => d.options.stringifyParams).filter(Boolean).forEach(fn => {
202
+ Object.assign({}, nextParams, fn(nextParams));
203
+ });
204
+ }
205
+
206
+ pathname = path.interpolatePath(pathname, nextParams != null ? nextParams : {}); // Pre filters first
207
+
208
+ const preFilteredSearch = (_dest$__preSearchFilt = dest.__preSearchFilters) != null && _dest$__preSearchFilt.length ? dest.__preSearchFilters.reduce((prev, next) => next(prev), router.location.search) : router.location.search; // Then the link/navigate function
209
+
210
+ const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
211
+ : dest.search ? (_functionalUpdate = utils.functionalUpdate(dest.search, preFilteredSearch)) != null ? _functionalUpdate : {} // Updater
212
+ : (_dest$__preSearchFilt2 = dest.__preSearchFilters) != null && _dest$__preSearchFilt2.length ? preFilteredSearch // Preserve resolvedFrom filters
213
+ : {}; // Then post filters
214
+
215
+ const postFilteredSearch = (_dest$__postSearchFil = dest.__postSearchFilters) != null && _dest$__postSearchFil.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
216
+ const search = utils.replaceEqualDeep(router.location.search, postFilteredSearch);
217
+ const searchStr = router.options.stringifySearch(search);
218
+ let hash = dest.hash === true ? router.location.hash : utils.functionalUpdate(dest.hash, router.location.hash);
219
+ hash = hash ? "#" + hash : '';
220
+ return {
221
+ pathname,
222
+ search,
223
+ searchStr,
224
+ state: router.location.state,
225
+ hash,
226
+ href: "" + pathname + searchStr + hash,
227
+ key: dest.key
228
+ };
229
+ },
230
+ commitLocation: (next, replace) => {
231
+ const id = '' + Date.now() + Math.random();
232
+ if (router.navigateTimeout) clearTimeout(router.navigateTimeout);
233
+ let nextAction = 'replace';
234
+
235
+ if (!replace) {
236
+ nextAction = 'push';
237
+ }
238
+
239
+ const isSameUrl = router.parseLocation(history.location).href === next.href;
240
+
241
+ if (isSameUrl && !next.key) {
242
+ nextAction = 'replace';
243
+ }
244
+
245
+ if (nextAction === 'replace') {
246
+ history.replace({
247
+ pathname: next.pathname,
248
+ hash: next.hash,
249
+ search: next.searchStr
250
+ }, {
251
+ id
252
+ });
253
+ } else {
254
+ history.push({
255
+ pathname: next.pathname,
256
+ hash: next.hash,
257
+ search: next.searchStr
258
+ }, {
259
+ id
260
+ });
261
+ }
262
+
263
+ router.navigationPromise = new Promise(resolve => {
264
+ const previousNavigationResolve = router.resolveNavigation;
265
+
266
+ router.resolveNavigation = () => {
267
+ previousNavigationResolve();
268
+ resolve();
269
+ };
270
+ });
271
+ return router.navigationPromise;
272
+ },
273
+ buildNext: opts => {
274
+ const next = router.buildLocation(opts);
275
+ const matches = router.matchRoutes(next.pathname);
276
+
277
+ const __preSearchFilters = matches.map(match => {
278
+ var _match$options$preSea;
279
+
280
+ return (_match$options$preSea = match.options.preSearchFilters) != null ? _match$options$preSea : [];
281
+ }).flat().filter(Boolean);
282
+
283
+ const __postSearchFilters = matches.map(match => {
284
+ var _match$options$postSe;
285
+
286
+ return (_match$options$postSe = match.options.postSearchFilters) != null ? _match$options$postSe : [];
287
+ }).flat().filter(Boolean);
288
+
289
+ return router.buildLocation(_rollupPluginBabelHelpers["extends"]({}, opts, {
290
+ __preSearchFilters,
291
+ __postSearchFilters
292
+ }));
293
+ },
294
+ cancelMatches: () => {
295
+ var _router$state$pending, _router$state$pending2;
296
+ [...router.state.matches, ...((_router$state$pending = (_router$state$pending2 = router.state.pending) == null ? void 0 : _router$state$pending2.matches) != null ? _router$state$pending : [])].forEach(match => {
297
+ match.cancel();
298
+ });
299
+ },
300
+ loadLocation: async next => {
301
+ const id = Math.random();
302
+ router.startedLoadingAt = id;
303
+
304
+ if (next) {
305
+ // Ingest the new location
306
+ router.location = next;
307
+ } // Clear out old actions
308
+
309
+
310
+ router.removeActionQueue.forEach(_ref => {
311
+ let {
312
+ action,
313
+ actionState
314
+ } = _ref;
315
+
316
+ if (router.state.currentAction === actionState) {
317
+ router.state.currentAction = undefined;
318
+ }
319
+
320
+ if (action.current === actionState) {
321
+ action.current = undefined;
322
+ }
323
+ });
324
+ router.removeActionQueue = []; // Cancel any pending matches
325
+
326
+ router.cancelMatches(); // Match the routes
327
+
328
+ const matches = router.matchRoutes(location.pathname, {
329
+ strictParseParams: true
330
+ });
331
+ router.state = _rollupPluginBabelHelpers["extends"]({}, router.state, {
332
+ pending: {
333
+ matches: matches,
334
+ location: router.location
335
+ },
336
+ status: 'loading'
337
+ });
338
+ router.notify(); // Load the matches
339
+
340
+ await router.loadMatches(matches, {
341
+ withPending: true
342
+ });
343
+
344
+ if (router.startedLoadingAt !== id) {
345
+ // Ignore side-effects of match loading
346
+ return router.navigationPromise;
347
+ }
348
+
349
+ const previousMatches = router.state.matches;
350
+ const exiting = [],
351
+ staying = [];
352
+ previousMatches.forEach(d => {
353
+ if (matches.find(dd => dd.matchId === d.matchId)) {
354
+ staying.push(d);
355
+ } else {
356
+ exiting.push(d);
357
+ }
358
+ });
359
+ const now = Date.now();
360
+ exiting.forEach(d => {
361
+ var _ref2, _d$options$loaderGcMa, _ref3, _d$options$loaderMaxA;
362
+
363
+ d.__.onExit == null ? void 0 : d.__.onExit({
364
+ params: d.params,
365
+ search: d.routeSearch
366
+ }); // Clear idle error states when match leaves
367
+
368
+ if (d.status === 'error' && !d.isFetching) {
369
+ d.status = 'idle';
370
+ d.error = undefined;
371
+ }
372
+
373
+ const gc = Math.max((_ref2 = (_d$options$loaderGcMa = d.options.loaderGcMaxAge) != null ? _d$options$loaderGcMa : router.options.defaultLoaderGcMaxAge) != null ? _ref2 : 0, (_ref3 = (_d$options$loaderMaxA = d.options.loaderMaxAge) != null ? _d$options$loaderMaxA : router.options.defaultLoaderMaxAge) != null ? _ref3 : 0);
374
+
375
+ if (gc > 0) {
376
+ router.matchCache[d.matchId] = {
377
+ gc: gc == Infinity ? Number.MAX_SAFE_INTEGER : now + gc,
378
+ match: d
379
+ };
380
+ }
381
+ });
382
+ staying.forEach(d => {
383
+ d.options.onTransition == null ? void 0 : d.options.onTransition({
384
+ params: d.params,
385
+ search: d.routeSearch
386
+ });
387
+ });
388
+ const entering = matches.filter(d => {
389
+ return !previousMatches.find(dd => dd.matchId === d.matchId);
390
+ });
391
+ entering.forEach(d => {
392
+ d.__.onExit = d.options.onMatch == null ? void 0 : d.options.onMatch({
393
+ params: d.params,
394
+ search: d.search
395
+ });
396
+ });
397
+
398
+ if (matches.some(d => d.status === 'loading')) {
399
+ router.notify();
400
+ await Promise.all(matches.map(d => d.__.loaderPromise || Promise.resolve()));
401
+ }
402
+
403
+ if (router.startedLoadingAt !== id) {
404
+ // Ignore side-effects of match loading
405
+ return;
406
+ }
407
+
408
+ router.state = _rollupPluginBabelHelpers["extends"]({}, router.state, {
409
+ location: router.location,
410
+ matches,
411
+ pending: undefined,
412
+ status: 'idle'
413
+ });
414
+ router.notify();
415
+ router.resolveNavigation();
416
+ },
417
+ cleanMatchCache: () => {
418
+ const now = Date.now();
419
+ Object.keys(router.matchCache).forEach(matchId => {
420
+ const entry = router.matchCache[matchId]; // Don't remove loading matches
421
+
422
+ if (entry.match.status === 'loading') {
423
+ return;
424
+ } // Do not remove successful matches that are still valid
425
+
426
+
427
+ if (entry.gc > 0 && entry.gc > now) {
428
+ return;
429
+ } // Everything else gets removed
430
+
431
+
432
+ delete router.matchCache[matchId];
433
+ });
434
+ },
435
+ loadRoute: async function loadRoute(navigateOpts, loaderOpts) {
436
+ if (navigateOpts === void 0) {
437
+ navigateOpts = router.location;
438
+ }
439
+
440
+ const next = router.buildNext(navigateOpts);
441
+ const matches = router.matchRoutes(next.pathname, {
442
+ strictParseParams: true
443
+ });
444
+ await router.loadMatches(matches, {
445
+ preload: true,
446
+ maxAge: loaderOpts.maxAge
447
+ });
448
+ return matches;
449
+ },
450
+ matchRoutes: (pathname, opts) => {
451
+ var _router$state$pending3, _router$state$pending4;
452
+
453
+ router.cleanMatchCache();
454
+ const matches = [];
455
+
456
+ if (!router.routeTree) {
457
+ return matches;
458
+ }
459
+
460
+ const existingMatches = [...router.state.matches, ...((_router$state$pending3 = (_router$state$pending4 = router.state.pending) == null ? void 0 : _router$state$pending4.matches) != null ? _router$state$pending3 : [])];
461
+
462
+ const recurse = async routes => {
463
+ var _parentMatch$params, _router$options$filte, _foundRoute$childRout;
464
+
465
+ const parentMatch = utils.last(matches);
466
+ let params = (_parentMatch$params = parentMatch == null ? void 0 : parentMatch.params) != null ? _parentMatch$params : {};
467
+ const filteredRoutes = (_router$options$filte = router.options.filterRoutes == null ? void 0 : router.options.filterRoutes(routes)) != null ? _router$options$filte : routes;
468
+ let foundRoutes = [];
469
+
470
+ const findMatchInRoutes = (parentRoutes, routes) => {
471
+ routes.some(route => {
472
+ var _route$childRoutes, _route$childRoutes2, _route$options$caseSe;
473
+
474
+ if (!route.routePath && (_route$childRoutes = route.childRoutes) != null && _route$childRoutes.length) {
475
+ return findMatchInRoutes([...foundRoutes, route], route.childRoutes);
476
+ }
477
+
478
+ const fuzzy = !!(route.routePath !== '/' || (_route$childRoutes2 = route.childRoutes) != null && _route$childRoutes2.length);
479
+ const matchParams = path.matchPathname(pathname, {
480
+ to: route.fullPath,
481
+ fuzzy,
482
+ caseSensitive: (_route$options$caseSe = route.options.caseSensitive) != null ? _route$options$caseSe : router.options.caseSensitive
483
+ });
484
+
485
+ if (matchParams) {
486
+ let parsedParams;
487
+
488
+ try {
489
+ var _route$options$parseP;
490
+
491
+ parsedParams = (_route$options$parseP = route.options.parseParams == null ? void 0 : route.options.parseParams(matchParams)) != null ? _route$options$parseP : matchParams;
492
+ } catch (err) {
493
+ if (opts != null && opts.strictParseParams) {
494
+ throw err;
495
+ }
496
+ }
497
+
498
+ params = _rollupPluginBabelHelpers["extends"]({}, params, parsedParams);
499
+ }
500
+
501
+ if (!!matchParams) {
502
+ foundRoutes = [...parentRoutes, route];
503
+ }
504
+
505
+ return !!foundRoutes.length;
506
+ });
507
+ return !!foundRoutes.length;
508
+ };
509
+
510
+ findMatchInRoutes([], filteredRoutes);
511
+
512
+ if (!foundRoutes.length) {
513
+ return;
514
+ }
515
+
516
+ foundRoutes.forEach(foundRoute => {
517
+ var _router$matchCache$ma;
518
+
519
+ const interpolatedPath = path.interpolatePath(foundRoute.routePath, params);
520
+ const matchId = path.interpolatePath(foundRoute.routeId, params, true);
521
+ const match = existingMatches.find(d => d.matchId === matchId) || ((_router$matchCache$ma = router.matchCache[matchId]) == null ? void 0 : _router$matchCache$ma.match) || routeMatch.createRouteMatch(router, foundRoute, {
522
+ matchId,
523
+ params,
524
+ pathname: path.joinPaths([pathname, interpolatedPath])
525
+ });
526
+ matches.push(match);
527
+ });
528
+ const foundRoute = utils.last(foundRoutes);
529
+
530
+ if ((_foundRoute$childRout = foundRoute.childRoutes) != null && _foundRoute$childRout.length) {
531
+ recurse(foundRoute.childRoutes);
532
+ }
533
+ };
534
+
535
+ recurse([router.routeTree]);
536
+ route.cascadeLoaderData(matches);
537
+ return matches;
538
+ },
539
+ loadMatches: async (resolvedMatches, loaderOpts) => {
540
+ const now = Date.now();
541
+ const matchPromises = resolvedMatches.map(async match => {
542
+ // Validate the match (loads search params etc)
543
+ match.__.validate(); // // If the match doesn't have a loader, don't attempt to load it
544
+ // if (!match.hasLoaders()) {
545
+ // return
546
+ // }
547
+ // If this is a preload, add it to the preload cache
548
+
549
+
550
+ if (loaderOpts != null && loaderOpts.preload && (loaderOpts == null ? void 0 : loaderOpts.maxAge) > 0) {
551
+ // If the match is currently active, don't preload it
552
+ if (router.state.matches.find(d => d.matchId === match.matchId)) {
553
+ return;
554
+ }
555
+
556
+ router.matchCache[match.matchId] = {
557
+ gc: now + loaderOpts.maxAge,
558
+ // TODO: Should this use the route's maxAge?
559
+ match
560
+ };
561
+ } // If the match is invalid, errored or idle, trigger it to load
562
+
563
+
564
+ if (match.status === 'success' && match.getIsInvalid() || match.status === 'error' || match.status === 'idle') {
565
+ match.load();
566
+ }
567
+
568
+ if (match.status === 'loading') {
569
+ // If requested, start the pending timers
570
+ if (loaderOpts != null && loaderOpts.withPending) match.__.startPending(); // Wait for the first sign of activity from the match
571
+ // This might be completion, error, or a pending state
572
+
573
+ await match.__.loadPromise;
574
+ }
575
+ });
576
+ router.notify();
577
+ await Promise.all(matchPromises);
578
+ },
579
+ invalidateRoute: opts => {
580
+ var _router$state$pending5, _router$state$pending6;
581
+
582
+ const next = router.buildNext(opts);
583
+ const unloadedMatchIds = router.matchRoutes(next.pathname).map(d => d.matchId);
584
+ [...router.state.matches, ...((_router$state$pending5 = (_router$state$pending6 = router.state.pending) == null ? void 0 : _router$state$pending6.matches) != null ? _router$state$pending5 : [])].forEach(match => {
585
+ if (unloadedMatchIds.includes(match.matchId)) {
586
+ match.invalidate();
587
+ }
588
+ });
589
+ },
590
+ reload: () => router._navigate({
591
+ fromCurrent: true,
592
+ replace: true,
593
+ search: true
594
+ }),
595
+ resolvePath: (from, path$1) => {
596
+ return path.resolvePath(router.basepath, from, path.cleanPath(path$1));
597
+ },
598
+ matchRoute: (location, opts) => {
599
+ var _location$from;
600
+
601
+ // const location = router.buildNext(opts)
602
+ location = _rollupPluginBabelHelpers["extends"]({}, location, {
603
+ to: location.to ? router.resolvePath((_location$from = location.from) != null ? _location$from : '', location.to) : undefined
604
+ });
605
+ const next = router.buildNext(location);
606
+
607
+ if (opts != null && opts.pending) {
608
+ var _router$state$pending7;
609
+
610
+ if (!((_router$state$pending7 = router.state.pending) != null && _router$state$pending7.location)) {
611
+ return false;
612
+ }
613
+
614
+ return !!path.matchPathname(router.state.pending.location.pathname, _rollupPluginBabelHelpers["extends"]({}, opts, {
615
+ to: next.pathname
616
+ }));
617
+ }
618
+
619
+ return !!path.matchPathname(router.state.location.pathname, _rollupPluginBabelHelpers["extends"]({}, opts, {
620
+ to: next.pathname
621
+ }));
622
+ },
623
+ _navigate: location => {
624
+ const next = router.buildNext(location);
625
+ return router.commitLocation(next, location.replace);
626
+ },
627
+ navigate: async _ref4 => {
628
+ let {
629
+ from,
630
+ to = '.',
631
+ search,
632
+ hash,
633
+ replace,
634
+ params
635
+ } = _ref4;
636
+ // If this link simply reloads the current route,
637
+ // make sure it has a new key so it will trigger a data refresh
638
+ // If this `to` is a valid external URL, return
639
+ // null for LinkUtils
640
+ const toString = String(to);
641
+ const fromString = String(from);
642
+ let isExternal;
643
+
644
+ try {
645
+ new URL("" + toString);
646
+ isExternal = true;
647
+ } catch (e) {}
648
+
649
+ tinyInvariant["default"](!isExternal, 'Attempting to navigate to external url with router.navigate!');
650
+ return router._navigate({
651
+ from: fromString,
652
+ to: toString,
653
+ search,
654
+ hash,
655
+ replace,
656
+ params
657
+ });
658
+ },
659
+ buildLink: _ref5 => {
660
+ var _preload, _ref6, _ref7, _ref8;
661
+
662
+ let {
663
+ from,
664
+ to = '.',
665
+ search,
666
+ params,
667
+ hash,
668
+ target,
669
+ replace,
670
+ activeOptions,
671
+ preload,
672
+ preloadMaxAge: userPreloadMaxAge,
673
+ preloadDelay: userPreloadDelay,
674
+ disabled
675
+ } = _ref5;
676
+
677
+ // If this link simply reloads the current route,
678
+ // make sure it has a new key so it will trigger a data refresh
679
+ // If this `to` is a valid external URL, return
680
+ // null for LinkUtils
681
+ try {
682
+ new URL("" + to);
683
+ return {
684
+ type: 'external',
685
+ href: to
686
+ };
687
+ } catch (e) {}
688
+
689
+ const nextOpts = {
690
+ from,
691
+ to,
692
+ search,
693
+ params,
694
+ hash,
695
+ replace
696
+ };
697
+ const next = router.buildNext(nextOpts);
698
+ preload = (_preload = preload) != null ? _preload : router.options.defaultLinkPreload;
699
+ const preloadMaxAge = (_ref6 = (_ref7 = userPreloadMaxAge != null ? userPreloadMaxAge : router.options.defaultLinkPreloadMaxAge) != null ? _ref7 : router.options.defaultLoaderGcMaxAge) != null ? _ref6 : 0;
700
+ const preloadDelay = (_ref8 = userPreloadDelay != null ? userPreloadDelay : router.options.defaultLinkPreloadDelay) != null ? _ref8 : 0; // Compare path/hash for matches
701
+
702
+ const pathIsEqual = router.state.location.pathname === next.pathname;
703
+ const currentPathSplit = router.state.location.pathname.split('/');
704
+ const nextPathSplit = next.pathname.split('/');
705
+ const pathIsFuzzyEqual = nextPathSplit.every((d, i) => d === currentPathSplit[i]);
706
+ const hashIsEqual = router.state.location.hash === next.hash; // Combine the matches based on user options
707
+
708
+ const pathTest = activeOptions != null && activeOptions.exact ? pathIsEqual : pathIsFuzzyEqual;
709
+ const hashTest = activeOptions != null && activeOptions.includeHash ? hashIsEqual : true; // The final "active" test
710
+
711
+ const isActive = pathTest && hashTest; // The click handler
712
+
713
+ const handleClick = e => {
714
+ if (!disabled && !isCtrlEvent(e) && !e.defaultPrevented && (!target || target === '_self') && e.button === 0) {
715
+ e.preventDefault();
716
+
717
+ if (pathIsEqual && !search && !hash) {
718
+ router.invalidateRoute(nextOpts);
719
+ } // All is well? Navigate!)
720
+
721
+
722
+ router._navigate(nextOpts);
723
+ }
724
+ }; // The click handler
725
+
726
+
727
+ const handleFocus = e => {
728
+ if (preload && preloadMaxAge > 0) {
729
+ router.loadRoute(nextOpts, {
730
+ maxAge: preloadMaxAge
731
+ });
732
+ }
733
+ };
734
+
735
+ const handleEnter = e => {
736
+ const target = e.target || {};
737
+
738
+ if (preload && preloadMaxAge > 0) {
739
+ if (target.preloadTimeout) {
740
+ return;
741
+ }
742
+
743
+ target.preloadTimeout = setTimeout(() => {
744
+ target.preloadTimeout = null;
745
+ router.loadRoute(nextOpts, {
746
+ maxAge: preloadMaxAge
747
+ });
748
+ }, preloadDelay);
749
+ }
750
+ };
751
+
752
+ const handleLeave = e => {
753
+ const target = e.target || {};
754
+
755
+ if (target.preloadTimeout) {
756
+ clearTimeout(target.preloadTimeout);
757
+ target.preloadTimeout = null;
758
+ }
759
+ };
760
+
761
+ return {
762
+ type: 'internal',
763
+ next,
764
+ handleFocus,
765
+ handleClick,
766
+ handleEnter,
767
+ handleLeave,
768
+ isActive,
769
+ disabled
770
+ };
771
+ }
772
+ };
773
+ router.location = router.parseLocation(history.location);
774
+ router.state.location = router.location;
775
+ router.update(userOptions); // Allow frameworks to hook into the router creation
776
+
777
+ router.options.createRouter == null ? void 0 : router.options.createRouter(router);
778
+ return router;
779
+ }
780
+
781
+ function isCtrlEvent(e) {
782
+ return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
783
+ }
784
+
785
+ exports.createRouter = createRouter;
786
+ //# sourceMappingURL=router.js.map