@tanstack/router-core 0.0.1-alpha.1 → 0.0.1-alpha.10

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