@tanstack/react-router 0.0.1-beta.21 → 0.0.1-beta.210

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 (102) hide show
  1. package/LICENSE +21 -0
  2. package/build/cjs/CatchBoundary.js +125 -0
  3. package/build/cjs/CatchBoundary.js.map +1 -0
  4. package/build/cjs/Matches.js +223 -0
  5. package/build/cjs/Matches.js.map +1 -0
  6. package/build/cjs/RouterProvider.js +1021 -0
  7. package/build/cjs/RouterProvider.js.map +1 -0
  8. package/build/cjs/_virtual/_rollupPluginBabelHelpers.js +1 -19
  9. package/build/cjs/_virtual/_rollupPluginBabelHelpers.js.map +1 -1
  10. package/build/cjs/fileRoute.js +29 -0
  11. package/build/cjs/fileRoute.js.map +1 -0
  12. package/build/cjs/index.js +124 -0
  13. package/build/cjs/index.js.map +1 -0
  14. package/build/cjs/lazyRouteComponent.js +57 -0
  15. package/build/cjs/lazyRouteComponent.js.map +1 -0
  16. package/build/cjs/link.js +150 -0
  17. package/build/cjs/link.js.map +1 -0
  18. package/build/cjs/path.js +211 -0
  19. package/build/cjs/path.js.map +1 -0
  20. package/build/cjs/qss.js +65 -0
  21. package/build/cjs/qss.js.map +1 -0
  22. package/build/cjs/redirects.js +27 -0
  23. package/build/cjs/redirects.js.map +1 -0
  24. package/build/cjs/route.js +133 -0
  25. package/build/cjs/route.js.map +1 -0
  26. package/build/cjs/router.js +203 -0
  27. package/build/cjs/router.js.map +1 -0
  28. package/build/cjs/searchParams.js +83 -0
  29. package/build/cjs/searchParams.js.map +1 -0
  30. package/build/cjs/useBlocker.js +64 -0
  31. package/build/cjs/useBlocker.js.map +1 -0
  32. package/build/cjs/useNavigate.js +78 -0
  33. package/build/cjs/useNavigate.js.map +1 -0
  34. package/build/cjs/useParams.js +28 -0
  35. package/build/cjs/useParams.js.map +1 -0
  36. package/build/cjs/useSearch.js +27 -0
  37. package/build/cjs/useSearch.js.map +1 -0
  38. package/build/cjs/utils.js +225 -0
  39. package/build/cjs/utils.js.map +1 -0
  40. package/build/esm/index.js +1895 -2565
  41. package/build/esm/index.js.map +1 -1
  42. package/build/stats-html.html +59 -49
  43. package/build/stats-react.json +815 -43
  44. package/build/types/CatchBoundary.d.ts +33 -0
  45. package/build/types/Matches.d.ts +31 -0
  46. package/build/types/RouterProvider.d.ts +78 -0
  47. package/build/types/awaited.d.ts +0 -0
  48. package/build/types/defer.d.ts +0 -0
  49. package/build/types/fileRoute.d.ts +32 -0
  50. package/build/types/history.d.ts +7 -0
  51. package/build/types/index.d.ts +24 -104
  52. package/build/types/injectHtml.d.ts +0 -0
  53. package/build/types/lazyRouteComponent.d.ts +2 -0
  54. package/build/types/link.d.ts +105 -0
  55. package/build/types/location.d.ts +14 -0
  56. package/build/types/path.d.ts +16 -0
  57. package/build/types/qss.d.ts +2 -0
  58. package/build/types/redirects.d.ts +10 -0
  59. package/build/types/route.d.ts +261 -0
  60. package/build/types/routeInfo.d.ts +22 -0
  61. package/build/types/router.d.ts +117 -0
  62. package/build/types/scroll-restoration.d.ts +0 -0
  63. package/build/types/searchParams.d.ts +7 -0
  64. package/build/types/useBlocker.d.ts +8 -0
  65. package/build/types/useNavigate.d.ts +20 -0
  66. package/build/types/useParams.d.ts +7 -0
  67. package/build/types/useSearch.d.ts +7 -0
  68. package/build/types/utils.d.ts +65 -0
  69. package/build/umd/index.development.js +2132 -2469
  70. package/build/umd/index.development.js.map +1 -1
  71. package/build/umd/index.production.js +4 -4
  72. package/build/umd/index.production.js.map +1 -1
  73. package/package.json +9 -10
  74. package/src/CatchBoundary.tsx +97 -0
  75. package/src/Matches.tsx +315 -0
  76. package/src/RouterProvider.tsx +1457 -0
  77. package/src/awaited.tsx +40 -0
  78. package/src/defer.ts +55 -0
  79. package/src/fileRoute.ts +145 -0
  80. package/src/history.ts +8 -0
  81. package/src/index.tsx +28 -693
  82. package/src/injectHtml.ts +28 -0
  83. package/src/lazyRouteComponent.tsx +33 -0
  84. package/src/link.tsx +507 -0
  85. package/src/location.ts +15 -0
  86. package/src/path.ts +256 -0
  87. package/src/qss.ts +53 -0
  88. package/src/redirects.ts +31 -0
  89. package/src/route.ts +786 -0
  90. package/src/routeInfo.ts +68 -0
  91. package/src/router.ts +374 -0
  92. package/src/scroll-restoration.tsx +205 -0
  93. package/src/searchParams.ts +79 -0
  94. package/src/useBlocker.tsx +34 -0
  95. package/src/useNavigate.tsx +109 -0
  96. package/src/useParams.tsx +25 -0
  97. package/src/useSearch.tsx +25 -0
  98. package/src/utils.ts +337 -0
  99. package/build/cjs/react-router/src/index.js +0 -466
  100. package/build/cjs/react-router/src/index.js.map +0 -1
  101. package/build/cjs/router-core/build/esm/index.js +0 -2523
  102. package/build/cjs/router-core/build/esm/index.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * react-router
2
+ * @tanstack/react-router/src/index.tsx
3
3
  *
4
4
  * Copyright (c) TanStack
5
5
  *
@@ -8,979 +8,274 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
+ import { createBrowserHistory } from '@tanstack/history';
12
+ export * from '@tanstack/history';
13
+ import invariant from 'tiny-invariant';
14
+ export { default as invariant } from 'tiny-invariant';
15
+ import warning from 'tiny-warning';
16
+ export { default as warning } from 'tiny-warning';
11
17
  import * as React from 'react';
12
- import { useSyncExternalStore } from 'use-sync-external-store/shim';
13
18
 
14
- function _extends$2() {
15
- _extends$2 = Object.assign ? Object.assign.bind() : function (target) {
16
- for (var i = 1; i < arguments.length; i++) {
17
- var source = arguments[i];
18
-
19
- for (var key in source) {
20
- if (Object.prototype.hasOwnProperty.call(source, key)) {
21
- target[key] = source[key];
22
- }
19
+ function CatchBoundary(props) {
20
+ const errorComponent = props.errorComponent ?? ErrorComponent;
21
+ return /*#__PURE__*/React.createElement(CatchBoundaryImpl, {
22
+ resetKey: props.resetKey,
23
+ onCatch: props.onCatch,
24
+ children: ({
25
+ error
26
+ }) => {
27
+ if (error) {
28
+ return /*#__PURE__*/React.createElement(errorComponent, {
29
+ error
30
+ });
23
31
  }
32
+ return props.children;
24
33
  }
25
-
26
- return target;
27
- };
28
- return _extends$2.apply(this, arguments);
29
- }
30
-
31
- function _objectWithoutPropertiesLoose(source, excluded) {
32
- if (source == null) return {};
33
- var target = {};
34
- var sourceKeys = Object.keys(source);
35
- var key, i;
36
-
37
- for (i = 0; i < sourceKeys.length; i++) {
38
- key = sourceKeys[i];
39
- if (excluded.indexOf(key) >= 0) continue;
40
- target[key] = source[key];
41
- }
42
-
43
- return target;
34
+ });
44
35
  }
45
-
46
- /**
47
- * router-core
48
- *
49
- * Copyright (c) TanStack
50
- *
51
- * This source code is licensed under the MIT license found in the
52
- * LICENSE.md file in the root directory of this source tree.
53
- *
54
- * @license MIT
55
- */
56
- function _extends$1() {
57
- _extends$1 = Object.assign ? Object.assign.bind() : function (target) {
58
- for (var i = 1; i < arguments.length; i++) {
59
- var source = arguments[i];
60
-
61
- for (var key in source) {
62
- if (Object.prototype.hasOwnProperty.call(source, key)) {
63
- target[key] = source[key];
64
- }
65
- }
66
- }
67
-
68
- return target;
36
+ class CatchBoundaryImpl extends React.Component {
37
+ state = {
38
+ error: null
69
39
  };
70
- return _extends$1.apply(this, arguments);
71
- }
72
-
73
- /**
74
- * Actions represent the type of change to a location value.
75
- *
76
- * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#action
77
- */
78
- var Action;
79
-
80
- (function (Action) {
81
- /**
82
- * A POP indicates a change to an arbitrary index in the history stack, such
83
- * as a back or forward navigation. It does not describe the direction of the
84
- * navigation, only that the current index changed.
85
- *
86
- * Note: This is the default action for newly created history objects.
87
- */
88
- Action["Pop"] = "POP";
89
- /**
90
- * A PUSH indicates a new entry being added to the history stack, such as when
91
- * a link is clicked and a new page loads. When this happens, all subsequent
92
- * entries in the stack are lost.
93
- */
94
-
95
- Action["Push"] = "PUSH";
96
- /**
97
- * A REPLACE indicates the entry at the current index in the history stack
98
- * being replaced by a new one.
99
- */
100
-
101
- Action["Replace"] = "REPLACE";
102
- })(Action || (Action = {}));
103
-
104
- var readOnly = process.env.NODE_ENV !== "production" ? function (obj) {
105
- return Object.freeze(obj);
106
- } : function (obj) {
107
- return obj;
108
- };
109
-
110
- function warning$1(cond, message) {
111
- if (!cond) {
112
- // eslint-disable-next-line no-console
113
- if (typeof console !== 'undefined') console.warn(message);
114
-
115
- try {
116
- // Welcome to debugging history!
117
- //
118
- // This error is thrown as a convenience so you can more easily
119
- // find the source for a warning that appears in the console by
120
- // enabling "pause on exceptions" in your JavaScript debugger.
121
- throw new Error(message); // eslint-disable-next-line no-empty
122
- } catch (e) {}
123
- }
124
- }
125
-
126
- var BeforeUnloadEventType = 'beforeunload';
127
- var HashChangeEventType = 'hashchange';
128
- var PopStateEventType = 'popstate';
129
- /**
130
- * Browser history stores the location in regular URLs. This is the standard for
131
- * most web apps, but it requires some configuration on the server to ensure you
132
- * serve the same app at multiple URLs.
133
- *
134
- * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createbrowserhistory
135
- */
136
-
137
- function createBrowserHistory(options) {
138
- if (options === void 0) {
139
- options = {};
140
- }
141
-
142
- var _options = options,
143
- _options$window = _options.window,
144
- window = _options$window === void 0 ? document.defaultView : _options$window;
145
- var globalHistory = window.history;
146
-
147
- function getIndexAndLocation() {
148
- var _window$location = window.location,
149
- pathname = _window$location.pathname,
150
- search = _window$location.search,
151
- hash = _window$location.hash;
152
- var state = globalHistory.state || {};
153
- return [state.idx, readOnly({
154
- pathname: pathname,
155
- search: search,
156
- hash: hash,
157
- state: state.usr || null,
158
- key: state.key || 'default'
159
- })];
160
- }
161
-
162
- var blockedPopTx = null;
163
-
164
- function handlePop() {
165
- if (blockedPopTx) {
166
- blockers.call(blockedPopTx);
167
- blockedPopTx = null;
168
- } else {
169
- var nextAction = Action.Pop;
170
-
171
- var _getIndexAndLocation = getIndexAndLocation(),
172
- nextIndex = _getIndexAndLocation[0],
173
- nextLocation = _getIndexAndLocation[1];
174
-
175
- if (blockers.length) {
176
- if (nextIndex != null) {
177
- var delta = index - nextIndex;
178
-
179
- if (delta) {
180
- // Revert the POP
181
- blockedPopTx = {
182
- action: nextAction,
183
- location: nextLocation,
184
- retry: function retry() {
185
- go(delta * -1);
186
- }
187
- };
188
- go(delta);
189
- }
190
- } else {
191
- // Trying to POP to a location with no index. We did not create
192
- // this location, so we can't effectively block the navigation.
193
- process.env.NODE_ENV !== "production" ? warning$1(false, // TODO: Write up a doc that explains our blocking strategy in
194
- // detail and link to it here so people can understand better what
195
- // is going on and how to avoid it.
196
- "You are trying to block a POP navigation to a location that was not " + "created by the history library. The block will fail silently in " + "production, but in general you should do all navigation with the " + "history library (instead of using window.history.pushState directly) " + "to avoid this situation.") : void 0;
197
- }
198
- } else {
199
- applyTx(nextAction);
200
- }
201
- }
202
- }
203
-
204
- window.addEventListener(PopStateEventType, handlePop);
205
- var action = Action.Pop;
206
-
207
- var _getIndexAndLocation2 = getIndexAndLocation(),
208
- index = _getIndexAndLocation2[0],
209
- location = _getIndexAndLocation2[1];
210
-
211
- var listeners = createEvents();
212
- var blockers = createEvents();
213
-
214
- if (index == null) {
215
- index = 0;
216
- globalHistory.replaceState(_extends$1({}, globalHistory.state, {
217
- idx: index
218
- }), '');
219
- }
220
-
221
- function createHref(to) {
222
- return typeof to === 'string' ? to : createPath(to);
223
- } // state defaults to `null` because `window.history.state` does
224
-
225
-
226
- function getNextLocation(to, state) {
227
- if (state === void 0) {
228
- state = null;
229
- }
230
-
231
- return readOnly(_extends$1({
232
- pathname: location.pathname,
233
- hash: '',
234
- search: ''
235
- }, typeof to === 'string' ? parsePath(to) : to, {
236
- state: state,
237
- key: createKey()
238
- }));
239
- }
240
-
241
- function getHistoryStateAndUrl(nextLocation, index) {
242
- return [{
243
- usr: nextLocation.state,
244
- key: nextLocation.key,
245
- idx: index
246
- }, createHref(nextLocation)];
247
- }
248
-
249
- function allowTx(action, location, retry) {
250
- return !blockers.length || (blockers.call({
251
- action: action,
252
- location: location,
253
- retry: retry
254
- }), false);
255
- }
256
-
257
- function applyTx(nextAction) {
258
- action = nextAction;
259
-
260
- var _getIndexAndLocation3 = getIndexAndLocation();
261
-
262
- index = _getIndexAndLocation3[0];
263
- location = _getIndexAndLocation3[1];
264
- listeners.call({
265
- action: action,
266
- location: location
267
- });
40
+ static getDerivedStateFromError(error) {
41
+ return {
42
+ error
43
+ };
268
44
  }
269
-
270
- function push(to, state) {
271
- var nextAction = Action.Push;
272
- var nextLocation = getNextLocation(to, state);
273
-
274
- function retry() {
275
- push(to, state);
276
- }
277
-
278
- if (allowTx(nextAction, nextLocation, retry)) {
279
- var _getHistoryStateAndUr = getHistoryStateAndUrl(nextLocation, index + 1),
280
- historyState = _getHistoryStateAndUr[0],
281
- url = _getHistoryStateAndUr[1]; // TODO: Support forced reloading
282
- // try...catch because iOS limits us to 100 pushState calls :/
283
-
284
-
285
- try {
286
- globalHistory.pushState(historyState, '', url);
287
- } catch (error) {
288
- // They are going to lose state here, but there is no real
289
- // way to warn them about it since the page will refresh...
290
- window.location.assign(url);
291
- }
292
-
293
- applyTx(nextAction);
45
+ componentDidUpdate(prevProps, prevState) {
46
+ if (prevState.error && prevProps.resetKey !== this.props.resetKey) {
47
+ this.setState({
48
+ error: null
49
+ });
294
50
  }
295
51
  }
296
-
297
- function replace(to, state) {
298
- var nextAction = Action.Replace;
299
- var nextLocation = getNextLocation(to, state);
300
-
301
- function retry() {
302
- replace(to, state);
303
- }
304
-
305
- if (allowTx(nextAction, nextLocation, retry)) {
306
- var _getHistoryStateAndUr2 = getHistoryStateAndUrl(nextLocation, index),
307
- historyState = _getHistoryStateAndUr2[0],
308
- url = _getHistoryStateAndUr2[1]; // TODO: Support forced reloading
309
-
310
-
311
- globalHistory.replaceState(historyState, '', url);
312
- applyTx(nextAction);
313
- }
52
+ componentDidCatch(error) {
53
+ this.props.onCatch?.(error);
314
54
  }
315
-
316
- function go(delta) {
317
- globalHistory.go(delta);
55
+ render() {
56
+ return this.props.children(this.state);
318
57
  }
319
-
320
- var history = {
321
- get action() {
322
- return action;
323
- },
324
-
325
- get location() {
326
- return location;
327
- },
328
-
329
- createHref: createHref,
330
- push: push,
331
- replace: replace,
332
- go: go,
333
- back: function back() {
334
- go(-1);
335
- },
336
- forward: function forward() {
337
- go(1);
338
- },
339
- listen: function listen(listener) {
340
- return listeners.push(listener);
341
- },
342
- block: function block(blocker) {
343
- var unblock = blockers.push(blocker);
344
-
345
- if (blockers.length === 1) {
346
- window.addEventListener(BeforeUnloadEventType, promptBeforeUnload);
347
- }
348
-
349
- return function () {
350
- unblock(); // Remove the beforeunload listener so the document may
351
- // still be salvageable in the pagehide event.
352
- // See https://html.spec.whatwg.org/#unloading-documents
353
-
354
- if (!blockers.length) {
355
- window.removeEventListener(BeforeUnloadEventType, promptBeforeUnload);
356
- }
357
- };
358
- }
359
- };
360
- return history;
361
58
  }
362
- /**
363
- * Hash history stores the location in window.location.hash. This makes it ideal
364
- * for situations where you don't want to send the location to the server for
365
- * some reason, either because you do cannot configure it or the URL space is
366
- * reserved for something else.
367
- *
368
- * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createhashhistory
369
- */
370
-
371
- function createHashHistory(options) {
372
- if (options === void 0) {
373
- options = {};
374
- }
375
-
376
- var _options2 = options,
377
- _options2$window = _options2.window,
378
- window = _options2$window === void 0 ? document.defaultView : _options2$window;
379
- var globalHistory = window.history;
380
-
381
- function getIndexAndLocation() {
382
- var _parsePath = parsePath(window.location.hash.substr(1)),
383
- _parsePath$pathname = _parsePath.pathname,
384
- pathname = _parsePath$pathname === void 0 ? '/' : _parsePath$pathname,
385
- _parsePath$search = _parsePath.search,
386
- search = _parsePath$search === void 0 ? '' : _parsePath$search,
387
- _parsePath$hash = _parsePath.hash,
388
- hash = _parsePath$hash === void 0 ? '' : _parsePath$hash;
389
-
390
- var state = globalHistory.state || {};
391
- return [state.idx, readOnly({
392
- pathname: pathname,
393
- search: search,
394
- hash: hash,
395
- state: state.usr || null,
396
- key: state.key || 'default'
397
- })];
398
- }
399
-
400
- var blockedPopTx = null;
401
-
402
- function handlePop() {
403
- if (blockedPopTx) {
404
- blockers.call(blockedPopTx);
405
- blockedPopTx = null;
406
- } else {
407
- var nextAction = Action.Pop;
408
-
409
- var _getIndexAndLocation4 = getIndexAndLocation(),
410
- nextIndex = _getIndexAndLocation4[0],
411
- nextLocation = _getIndexAndLocation4[1];
412
-
413
- if (blockers.length) {
414
- if (nextIndex != null) {
415
- var delta = index - nextIndex;
416
-
417
- if (delta) {
418
- // Revert the POP
419
- blockedPopTx = {
420
- action: nextAction,
421
- location: nextLocation,
422
- retry: function retry() {
423
- go(delta * -1);
424
- }
425
- };
426
- go(delta);
427
- }
428
- } else {
429
- // Trying to POP to a location with no index. We did not create
430
- // this location, so we can't effectively block the navigation.
431
- process.env.NODE_ENV !== "production" ? warning$1(false, // TODO: Write up a doc that explains our blocking strategy in
432
- // detail and link to it here so people can understand better
433
- // what is going on and how to avoid it.
434
- "You are trying to block a POP navigation to a location that was not " + "created by the history library. The block will fail silently in " + "production, but in general you should do all navigation with the " + "history library (instead of using window.history.pushState directly) " + "to avoid this situation.") : void 0;
435
- }
436
- } else {
437
- applyTx(nextAction);
438
- }
439
- }
440
- }
441
-
442
- window.addEventListener(PopStateEventType, handlePop); // popstate does not fire on hashchange in IE 11 and old (trident) Edge
443
- // https://developer.mozilla.org/de/docs/Web/API/Window/popstate_event
444
-
445
- window.addEventListener(HashChangeEventType, function () {
446
- var _getIndexAndLocation5 = getIndexAndLocation(),
447
- nextLocation = _getIndexAndLocation5[1]; // Ignore extraneous hashchange events.
448
-
449
-
450
- if (createPath(nextLocation) !== createPath(location)) {
451
- handlePop();
452
- }
453
- });
454
- var action = Action.Pop;
455
-
456
- var _getIndexAndLocation6 = getIndexAndLocation(),
457
- index = _getIndexAndLocation6[0],
458
- location = _getIndexAndLocation6[1];
459
-
460
- var listeners = createEvents();
461
- var blockers = createEvents();
462
-
463
- if (index == null) {
464
- index = 0;
465
- globalHistory.replaceState(_extends$1({}, globalHistory.state, {
466
- idx: index
467
- }), '');
468
- }
469
-
470
- function getBaseHref() {
471
- var base = document.querySelector('base');
472
- var href = '';
473
-
474
- if (base && base.getAttribute('href')) {
475
- var url = window.location.href;
476
- var hashIndex = url.indexOf('#');
477
- href = hashIndex === -1 ? url : url.slice(0, hashIndex);
478
- }
479
-
480
- return href;
481
- }
482
-
483
- function createHref(to) {
484
- return getBaseHref() + '#' + (typeof to === 'string' ? to : createPath(to));
485
- }
486
-
487
- function getNextLocation(to, state) {
488
- if (state === void 0) {
489
- state = null;
490
- }
491
-
492
- return readOnly(_extends$1({
493
- pathname: location.pathname,
494
- hash: '',
495
- search: ''
496
- }, typeof to === 'string' ? parsePath(to) : to, {
497
- state: state,
498
- key: createKey()
499
- }));
500
- }
501
-
502
- function getHistoryStateAndUrl(nextLocation, index) {
503
- return [{
504
- usr: nextLocation.state,
505
- key: nextLocation.key,
506
- idx: index
507
- }, createHref(nextLocation)];
508
- }
509
-
510
- function allowTx(action, location, retry) {
511
- return !blockers.length || (blockers.call({
512
- action: action,
513
- location: location,
514
- retry: retry
515
- }), false);
516
- }
517
-
518
- function applyTx(nextAction) {
519
- action = nextAction;
520
-
521
- var _getIndexAndLocation7 = getIndexAndLocation();
522
-
523
- index = _getIndexAndLocation7[0];
524
- location = _getIndexAndLocation7[1];
525
- listeners.call({
526
- action: action,
527
- location: location
528
- });
529
- }
530
-
531
- function push(to, state) {
532
- var nextAction = Action.Push;
533
- var nextLocation = getNextLocation(to, state);
534
-
535
- function retry() {
536
- push(to, state);
537
- }
538
-
539
- process.env.NODE_ENV !== "production" ? warning$1(nextLocation.pathname.charAt(0) === '/', "Relative pathnames are not supported in hash history.push(" + JSON.stringify(to) + ")") : void 0;
540
-
541
- if (allowTx(nextAction, nextLocation, retry)) {
542
- var _getHistoryStateAndUr3 = getHistoryStateAndUrl(nextLocation, index + 1),
543
- historyState = _getHistoryStateAndUr3[0],
544
- url = _getHistoryStateAndUr3[1]; // TODO: Support forced reloading
545
- // try...catch because iOS limits us to 100 pushState calls :/
546
-
547
-
548
- try {
549
- globalHistory.pushState(historyState, '', url);
550
- } catch (error) {
551
- // They are going to lose state here, but there is no real
552
- // way to warn them about it since the page will refresh...
553
- window.location.assign(url);
554
- }
555
-
556
- applyTx(nextAction);
59
+ function ErrorComponent({
60
+ error
61
+ }) {
62
+ const [show, setShow] = React.useState(process.env.NODE_ENV !== 'production');
63
+ return /*#__PURE__*/React.createElement("div", {
64
+ style: {
65
+ padding: '.5rem',
66
+ maxWidth: '100%'
557
67
  }
558
- }
559
-
560
- function replace(to, state) {
561
- var nextAction = Action.Replace;
562
- var nextLocation = getNextLocation(to, state);
563
-
564
- function retry() {
565
- replace(to, state);
68
+ }, /*#__PURE__*/React.createElement("div", {
69
+ style: {
70
+ display: 'flex',
71
+ alignItems: 'center',
72
+ gap: '.5rem'
566
73
  }
567
-
568
- process.env.NODE_ENV !== "production" ? warning$1(nextLocation.pathname.charAt(0) === '/', "Relative pathnames are not supported in hash history.replace(" + JSON.stringify(to) + ")") : void 0;
569
-
570
- if (allowTx(nextAction, nextLocation, retry)) {
571
- var _getHistoryStateAndUr4 = getHistoryStateAndUrl(nextLocation, index),
572
- historyState = _getHistoryStateAndUr4[0],
573
- url = _getHistoryStateAndUr4[1]; // TODO: Support forced reloading
574
-
575
-
576
- globalHistory.replaceState(historyState, '', url);
577
- applyTx(nextAction);
74
+ }, /*#__PURE__*/React.createElement("strong", {
75
+ style: {
76
+ fontSize: '1rem'
578
77
  }
579
- }
580
-
581
- function go(delta) {
582
- globalHistory.go(delta);
583
- }
584
-
585
- var history = {
586
- get action() {
587
- return action;
588
- },
589
-
590
- get location() {
591
- return location;
592
- },
593
-
594
- createHref: createHref,
595
- push: push,
596
- replace: replace,
597
- go: go,
598
- back: function back() {
599
- go(-1);
600
- },
601
- forward: function forward() {
602
- go(1);
603
- },
604
- listen: function listen(listener) {
605
- return listeners.push(listener);
78
+ }, "Something went wrong!"), /*#__PURE__*/React.createElement("button", {
79
+ style: {
80
+ appearance: 'none',
81
+ fontSize: '.6em',
82
+ border: '1px solid currentColor',
83
+ padding: '.1rem .2rem',
84
+ fontWeight: 'bold',
85
+ borderRadius: '.25rem'
606
86
  },
607
- block: function block(blocker) {
608
- var unblock = blockers.push(blocker);
609
-
610
- if (blockers.length === 1) {
611
- window.addEventListener(BeforeUnloadEventType, promptBeforeUnload);
612
- }
613
-
614
- return function () {
615
- unblock(); // Remove the beforeunload listener so the document may
616
- // still be salvageable in the pagehide event.
617
- // See https://html.spec.whatwg.org/#unloading-documents
618
-
619
- if (!blockers.length) {
620
- window.removeEventListener(BeforeUnloadEventType, promptBeforeUnload);
621
- }
622
- };
623
- }
624
- };
625
- return history;
626
- }
627
- /**
628
- * Memory history stores the current location in memory. It is designed for use
629
- * in stateful non-browser environments like tests and React Native.
630
- *
631
- * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#creatememoryhistory
632
- */
633
-
634
- function createMemoryHistory(options) {
635
- if (options === void 0) {
636
- options = {};
637
- }
638
-
639
- var _options3 = options,
640
- _options3$initialEntr = _options3.initialEntries,
641
- initialEntries = _options3$initialEntr === void 0 ? ['/'] : _options3$initialEntr,
642
- initialIndex = _options3.initialIndex;
643
- var entries = initialEntries.map(function (entry) {
644
- var location = readOnly(_extends$1({
645
- pathname: '/',
646
- search: '',
647
- hash: '',
648
- state: null,
649
- key: createKey()
650
- }, typeof entry === 'string' ? parsePath(entry) : entry));
651
- process.env.NODE_ENV !== "production" ? warning$1(location.pathname.charAt(0) === '/', "Relative pathnames are not supported in createMemoryHistory({ initialEntries }) (invalid entry: " + JSON.stringify(entry) + ")") : void 0;
652
- return location;
653
- });
654
- var index = clamp(initialIndex == null ? entries.length - 1 : initialIndex, 0, entries.length - 1);
655
- var action = Action.Pop;
656
- var location = entries[index];
657
- var listeners = createEvents();
658
- var blockers = createEvents();
659
-
660
- function createHref(to) {
661
- return typeof to === 'string' ? to : createPath(to);
662
- }
663
-
664
- function getNextLocation(to, state) {
665
- if (state === void 0) {
666
- state = null;
667
- }
668
-
669
- return readOnly(_extends$1({
670
- pathname: location.pathname,
671
- search: '',
672
- hash: ''
673
- }, typeof to === 'string' ? parsePath(to) : to, {
674
- state: state,
675
- key: createKey()
676
- }));
677
- }
678
-
679
- function allowTx(action, location, retry) {
680
- return !blockers.length || (blockers.call({
681
- action: action,
682
- location: location,
683
- retry: retry
684
- }), false);
685
- }
686
-
687
- function applyTx(nextAction, nextLocation) {
688
- action = nextAction;
689
- location = nextLocation;
690
- listeners.call({
691
- action: action,
692
- location: location
693
- });
694
- }
695
-
696
- function push(to, state) {
697
- var nextAction = Action.Push;
698
- var nextLocation = getNextLocation(to, state);
699
-
700
- function retry() {
701
- push(to, state);
702
- }
703
-
704
- process.env.NODE_ENV !== "production" ? warning$1(location.pathname.charAt(0) === '/', "Relative pathnames are not supported in memory history.push(" + JSON.stringify(to) + ")") : void 0;
705
-
706
- if (allowTx(nextAction, nextLocation, retry)) {
707
- index += 1;
708
- entries.splice(index, entries.length, nextLocation);
709
- applyTx(nextAction, nextLocation);
710
- }
711
- }
712
-
713
- function replace(to, state) {
714
- var nextAction = Action.Replace;
715
- var nextLocation = getNextLocation(to, state);
716
-
717
- function retry() {
718
- replace(to, state);
719
- }
720
-
721
- process.env.NODE_ENV !== "production" ? warning$1(location.pathname.charAt(0) === '/', "Relative pathnames are not supported in memory history.replace(" + JSON.stringify(to) + ")") : void 0;
722
-
723
- if (allowTx(nextAction, nextLocation, retry)) {
724
- entries[index] = nextLocation;
725
- applyTx(nextAction, nextLocation);
726
- }
727
- }
728
-
729
- function go(delta) {
730
- var nextIndex = clamp(index + delta, 0, entries.length - 1);
731
- var nextAction = Action.Pop;
732
- var nextLocation = entries[nextIndex];
733
-
734
- function retry() {
735
- go(delta);
736
- }
737
-
738
- if (allowTx(nextAction, nextLocation, retry)) {
739
- index = nextIndex;
740
- applyTx(nextAction, nextLocation);
87
+ onClick: () => setShow(d => !d)
88
+ }, show ? 'Hide Error' : 'Show Error')), /*#__PURE__*/React.createElement("div", {
89
+ style: {
90
+ height: '.25rem'
741
91
  }
742
- }
743
-
744
- var history = {
745
- get index() {
746
- return index;
747
- },
748
-
749
- get action() {
750
- return action;
751
- },
752
-
753
- get location() {
754
- return location;
755
- },
756
-
757
- createHref: createHref,
758
- push: push,
759
- replace: replace,
760
- go: go,
761
- back: function back() {
762
- go(-1);
763
- },
764
- forward: function forward() {
765
- go(1);
766
- },
767
- listen: function listen(listener) {
768
- return listeners.push(listener);
769
- },
770
- block: function block(blocker) {
771
- return blockers.push(blocker);
92
+ }), show ? /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("pre", {
93
+ style: {
94
+ fontSize: '.7em',
95
+ border: '1px solid red',
96
+ borderRadius: '.25rem',
97
+ padding: '.3rem',
98
+ color: 'red',
99
+ overflow: 'auto'
772
100
  }
773
- };
774
- return history;
775
- } ////////////////////////////////////////////////////////////////////////////////
776
- // UTILS
777
- ////////////////////////////////////////////////////////////////////////////////
778
-
779
- function clamp(n, lowerBound, upperBound) {
780
- return Math.min(Math.max(n, lowerBound), upperBound);
781
- }
782
-
783
- function promptBeforeUnload(event) {
784
- // Cancel the event.
785
- event.preventDefault(); // Chrome (and legacy IE) requires returnValue to be set.
786
-
787
- event.returnValue = '';
101
+ }, error.message ? /*#__PURE__*/React.createElement("code", null, error.message) : null)) : null);
788
102
  }
789
103
 
790
- function createEvents() {
791
- var handlers = [];
792
- return {
793
- get length() {
794
- return handlers.length;
795
- },
796
-
797
- push: function push(fn) {
798
- handlers.push(fn);
799
- return function () {
800
- handlers = handlers.filter(function (handler) {
801
- return handler !== fn;
802
- });
803
- };
804
- },
805
- call: function call(arg) {
806
- handlers.forEach(function (fn) {
807
- return fn && fn(arg);
808
- });
809
- }
810
- };
811
- }
104
+ // export type Expand<T> = T
105
+
106
+ // type Compute<T> = { [K in keyof T]: T[K] } | never
107
+
108
+ // type AllKeys<T> = T extends any ? keyof T : never
109
+
110
+ // export type MergeUnion<T, Keys extends keyof T = keyof T> = Compute<
111
+ // {
112
+ // [K in Keys]: T[Keys]
113
+ // } & {
114
+ // [K in AllKeys<T>]?: T extends any
115
+ // ? K extends keyof T
116
+ // ? T[K]
117
+ // : never
118
+ // : never
119
+ // }
120
+ // >
121
+ // // Sample types to merge
122
+ // type TypeA = {
123
+ // shared: string
124
+ // onlyInA: string
125
+ // nested: {
126
+ // shared: string
127
+ // aProp: string
128
+ // }
129
+ // array: string[]
130
+ // }
131
+ // type TypeB = {
132
+ // shared: number
133
+ // onlyInB: number
134
+ // nested: {
135
+ // shared: number
136
+ // bProp: number
137
+ // }
138
+ // array: number[]
139
+ // }
140
+ // type TypeC = {
141
+ // shared: boolean
142
+ // onlyInC: boolean
143
+ // nested: {
144
+ // shared: boolean
145
+ // cProp: boolean
146
+ // }
147
+ // array: boolean[]
148
+ // }
149
+ // type Test = Expand<Assign<TypeA, TypeB>>
150
+ // // Using DeepMerge to merge TypeA and TypeB
151
+ // type MergedType = Expand<AssignAll<[TypeA, TypeB, TypeC]>>
152
+ //
812
153
 
813
- function createKey() {
814
- return Math.random().toString(36).substr(2, 8);
154
+ const isServer = typeof document === 'undefined';
155
+ function last(arr) {
156
+ return arr[arr.length - 1];
815
157
  }
816
- /**
817
- * Creates a string URL path from the given pathname, search, and hash components.
818
- *
819
- * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createpath
820
- */
821
-
822
-
823
- function createPath(_ref) {
824
- var _ref$pathname = _ref.pathname,
825
- pathname = _ref$pathname === void 0 ? '/' : _ref$pathname,
826
- _ref$search = _ref.search,
827
- search = _ref$search === void 0 ? '' : _ref$search,
828
- _ref$hash = _ref.hash,
829
- hash = _ref$hash === void 0 ? '' : _ref$hash;
830
- if (search && search !== '?') pathname += search.charAt(0) === '?' ? search : '?' + search;
831
- if (hash && hash !== '#') pathname += hash.charAt(0) === '#' ? hash : '#' + hash;
832
- return pathname;
158
+ function isFunction(d) {
159
+ return typeof d === 'function';
833
160
  }
834
- /**
835
- * Parses a string URL path into its separate pathname, search, and hash components.
836
- *
837
- * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#parsepath
838
- */
839
-
840
- function parsePath(path) {
841
- var parsedPath = {};
842
-
843
- if (path) {
844
- var hashIndex = path.indexOf('#');
845
-
846
- if (hashIndex >= 0) {
847
- parsedPath.hash = path.substr(hashIndex);
848
- path = path.substr(0, hashIndex);
849
- }
850
-
851
- var searchIndex = path.indexOf('?');
852
-
853
- if (searchIndex >= 0) {
854
- parsedPath.search = path.substr(searchIndex);
855
- path = path.substr(0, searchIndex);
856
- }
857
-
858
- if (path) {
859
- parsedPath.pathname = path;
860
- }
161
+ function functionalUpdate(updater, previous) {
162
+ if (isFunction(updater)) {
163
+ return updater(previous);
861
164
  }
862
-
863
- return parsedPath;
165
+ return updater;
864
166
  }
865
-
866
- var isProduction = process.env.NODE_ENV === 'production';
867
- var prefix = 'Invariant failed';
868
- function invariant(condition, message) {
869
- if (condition) {
870
- return;
871
- }
872
- if (isProduction) {
873
- throw new Error(prefix);
874
- }
875
- var provided = typeof message === 'function' ? message() : message;
876
- var value = provided ? "".concat(prefix, ": ").concat(provided) : prefix;
877
- throw new Error(value);
167
+ function pick(parent, keys) {
168
+ return keys.reduce((obj, key) => {
169
+ obj[key] = parent[key];
170
+ return obj;
171
+ }, {});
878
172
  }
879
173
 
880
- // type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
881
- // k: infer I,
882
- // ) => any
883
- // ? I
884
- // : never
885
-
886
174
  /**
887
175
  * This function returns `a` if `b` is deeply equal.
888
176
  * If not, it will replace any deeply equal children of `b` with those of `a`.
889
- * This can be used for structural sharing between JSON values for example.
177
+ * This can be used for structural sharing between immutable JSON values for example.
178
+ * Do not use this with signals
890
179
  */
891
- function replaceEqualDeep(prev, next) {
892
- if (prev === next) {
180
+ function replaceEqualDeep(prev, _next) {
181
+ if (prev === _next) {
893
182
  return prev;
894
183
  }
895
-
184
+ const next = _next;
896
185
  const array = Array.isArray(prev) && Array.isArray(next);
897
-
898
186
  if (array || isPlainObject(prev) && isPlainObject(next)) {
899
- const aSize = array ? prev.length : Object.keys(prev).length;
900
- const bItems = array ? next : Object.keys(next);
901
- const bSize = bItems.length;
187
+ const prevSize = array ? prev.length : Object.keys(prev).length;
188
+ const nextItems = array ? next : Object.keys(next);
189
+ const nextSize = nextItems.length;
902
190
  const copy = array ? [] : {};
903
191
  let equalItems = 0;
904
-
905
- for (let i = 0; i < bSize; i++) {
906
- const key = array ? i : bItems[i];
192
+ for (let i = 0; i < nextSize; i++) {
193
+ const key = array ? i : nextItems[i];
907
194
  copy[key] = replaceEqualDeep(prev[key], next[key]);
908
-
909
195
  if (copy[key] === prev[key]) {
910
196
  equalItems++;
911
197
  }
912
198
  }
913
-
914
- return aSize === bSize && equalItems === aSize ? prev : copy;
199
+ return prevSize === nextSize && equalItems === prevSize ? prev : copy;
915
200
  }
916
-
917
201
  return next;
918
- } // Copied from: https://github.com/jonschlinkert/is-plain-object
202
+ }
919
203
 
204
+ // Copied from: https://github.com/jonschlinkert/is-plain-object
920
205
  function isPlainObject(o) {
921
206
  if (!hasObjectPrototype(o)) {
922
207
  return false;
923
- } // If has modified constructor
924
-
208
+ }
925
209
 
210
+ // If has modified constructor
926
211
  const ctor = o.constructor;
927
-
928
212
  if (typeof ctor === 'undefined') {
929
213
  return true;
930
- } // If has modified prototype
931
-
214
+ }
932
215
 
216
+ // If has modified prototype
933
217
  const prot = ctor.prototype;
934
-
935
218
  if (!hasObjectPrototype(prot)) {
936
219
  return false;
937
- } // If constructor does not have an Object-specific method
938
-
220
+ }
939
221
 
222
+ // If constructor does not have an Object-specific method
940
223
  if (!prot.hasOwnProperty('isPrototypeOf')) {
941
224
  return false;
942
- } // Most likely a plain Object
943
-
225
+ }
944
226
 
227
+ // Most likely a plain Object
945
228
  return true;
946
229
  }
947
-
948
230
  function hasObjectPrototype(o) {
949
231
  return Object.prototype.toString.call(o) === '[object Object]';
950
232
  }
951
-
952
- function last(arr) {
953
- return arr[arr.length - 1];
954
- }
955
- function warning(cond, message) {
956
- if (cond) {
957
- if (typeof console !== 'undefined') console.warn(message);
958
-
959
- try {
960
- throw new Error(message);
961
- } catch (_unused) {}
233
+ function partialDeepEqual(a, b) {
234
+ if (a === b) {
235
+ return true;
962
236
  }
963
-
964
- return true;
237
+ if (typeof a !== typeof b) {
238
+ return false;
239
+ }
240
+ if (isPlainObject(a) && isPlainObject(b)) {
241
+ return !Object.keys(b).some(key => !partialDeepEqual(a[key], b[key]));
242
+ }
243
+ if (Array.isArray(a) && Array.isArray(b)) {
244
+ return !(a.length !== b.length || a.some((item, index) => !partialDeepEqual(item, b[index])));
245
+ }
246
+ return false;
965
247
  }
966
-
967
- function isFunction(d) {
968
- return typeof d === 'function';
248
+ function useStableCallback(fn) {
249
+ const fnRef = React.useRef(fn);
250
+ fnRef.current = fn;
251
+ const ref = React.useRef((...args) => fnRef.current(...args));
252
+ return ref.current;
969
253
  }
970
-
971
- function functionalUpdate(updater, previous) {
972
- if (isFunction(updater)) {
973
- return updater(previous);
254
+ function shallow(objA, objB) {
255
+ if (Object.is(objA, objB)) {
256
+ return true;
974
257
  }
975
-
976
- return updater;
258
+ if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
259
+ return false;
260
+ }
261
+ const keysA = Object.keys(objA);
262
+ if (keysA.length !== Object.keys(objB).length) {
263
+ return false;
264
+ }
265
+ for (let i = 0; i < keysA.length; i++) {
266
+ if (!Object.prototype.hasOwnProperty.call(objB, keysA[i]) || !Object.is(objA[keysA[i]], objB[keysA[i]])) {
267
+ return false;
268
+ }
269
+ }
270
+ return true;
977
271
  }
978
- function pick(parent, keys) {
979
- return keys.reduce((obj, key) => {
980
- obj[key] = parent[key];
981
- return obj;
982
- }, {});
272
+ function useRouteContext(opts) {
273
+ return useMatch({
274
+ ...opts,
275
+ select: match => opts?.select ? opts.select(match.context) : match.context
276
+ });
983
277
  }
278
+ const useLayoutEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
984
279
 
985
280
  function joinPaths(paths) {
986
281
  return cleanPath(paths.filter(Boolean).join('/'));
@@ -999,8 +294,8 @@ function trimPath(path) {
999
294
  return trimPathRight(trimPathLeft(path));
1000
295
  }
1001
296
  function resolvePath(basepath, base, to) {
1002
- base = base.replace(new RegExp("^" + basepath), '/');
1003
- to = to.replace(new RegExp("^" + basepath), '/');
297
+ base = base.replace(new RegExp(`^${basepath}`), '/');
298
+ to = to.replace(new RegExp(`^${basepath}`), '/');
1004
299
  let baseSegments = parsePathname(base);
1005
300
  const toSegments = parsePathname(to);
1006
301
  toSegments.forEach((toSegment, index) => {
@@ -1013,13 +308,10 @@ function resolvePath(basepath, base, to) {
1013
308
  baseSegments.push(toSegment);
1014
309
  } else ;
1015
310
  } else if (toSegment.value === '..') {
1016
- var _last;
1017
-
1018
311
  // Extra trailing slash? pop it off
1019
- if (baseSegments.length > 1 && ((_last = last(baseSegments)) == null ? void 0 : _last.value) === '/') {
312
+ if (baseSegments.length > 1 && last(baseSegments)?.value === '/') {
1020
313
  baseSegments.pop();
1021
314
  }
1022
-
1023
315
  baseSegments.pop();
1024
316
  } else if (toSegment.value === '.') {
1025
317
  return;
@@ -1034,10 +326,8 @@ function parsePathname(pathname) {
1034
326
  if (!pathname) {
1035
327
  return [];
1036
328
  }
1037
-
1038
329
  pathname = cleanPath(pathname);
1039
330
  const segments = [];
1040
-
1041
331
  if (pathname.slice(0, 1) === '/') {
1042
332
  pathname = pathname.substring(1);
1043
333
  segments.push({
@@ -1045,34 +335,30 @@ function parsePathname(pathname) {
1045
335
  value: '/'
1046
336
  });
1047
337
  }
1048
-
1049
338
  if (!pathname) {
1050
339
  return segments;
1051
- } // Remove empty segments and '.' segments
1052
-
340
+ }
1053
341
 
342
+ // Remove empty segments and '.' segments
1054
343
  const split = pathname.split('/').filter(Boolean);
1055
344
  segments.push(...split.map(part => {
1056
- if (part.startsWith('*')) {
345
+ if (part === '$' || part === '*') {
1057
346
  return {
1058
347
  type: 'wildcard',
1059
348
  value: part
1060
349
  };
1061
350
  }
1062
-
1063
- if (part.charAt(0) === ':') {
351
+ if (part.charAt(0) === '$') {
1064
352
  return {
1065
353
  type: 'param',
1066
354
  value: part
1067
355
  };
1068
356
  }
1069
-
1070
357
  return {
1071
358
  type: 'pathname',
1072
359
  value: part
1073
360
  };
1074
361
  }));
1075
-
1076
362
  if (pathname.slice(-1) === '/') {
1077
363
  pathname = pathname.substring(1);
1078
364
  segments.push({
@@ -1080,1824 +366,1868 @@ function parsePathname(pathname) {
1080
366
  value: '/'
1081
367
  });
1082
368
  }
1083
-
1084
369
  return segments;
1085
370
  }
1086
- function interpolatePath(path, params, leaveWildcard) {
371
+ function interpolatePath(path, params, leaveWildcards = false) {
1087
372
  const interpolatedPathSegments = parsePathname(path);
1088
373
  return joinPaths(interpolatedPathSegments.map(segment => {
1089
- if (segment.value === '*' && !leaveWildcard) {
1090
- return '';
374
+ if (segment.type === 'wildcard') {
375
+ const value = params[segment.value];
376
+ if (leaveWildcards) return `${segment.value}${value ?? ''}`;
377
+ return value;
1091
378
  }
1092
-
1093
379
  if (segment.type === 'param') {
1094
- var _segment$value$substr;
1095
-
1096
- return (_segment$value$substr = params[segment.value.substring(1)]) != null ? _segment$value$substr : '';
380
+ return params[segment.value.substring(1)] ?? '';
1097
381
  }
1098
-
1099
382
  return segment.value;
1100
383
  }));
1101
384
  }
1102
- function matchPathname(currentPathname, matchLocation) {
1103
- const pathParams = matchByPath(currentPathname, matchLocation); // const searchMatched = matchBySearch(currentLocation.search, matchLocation)
385
+ function matchPathname(basepath, currentPathname, matchLocation) {
386
+ const pathParams = matchByPath(basepath, currentPathname, matchLocation);
387
+ // const searchMatched = matchBySearch(location.search, matchLocation)
1104
388
 
1105
389
  if (matchLocation.to && !pathParams) {
1106
390
  return;
1107
- } // if (matchLocation.search && !searchMatched) {
1108
- // return
1109
- // }
1110
-
1111
-
1112
- return pathParams != null ? pathParams : {};
1113
- }
1114
- function matchByPath(from, matchLocation) {
1115
- var _matchLocation$to;
1116
-
1117
- const baseSegments = parsePathname(from);
1118
- const routeSegments = parsePathname("" + ((_matchLocation$to = matchLocation.to) != null ? _matchLocation$to : '*'));
1119
- const params = {};
1120
-
1121
- let isMatch = (() => {
1122
- for (let i = 0; i < Math.max(baseSegments.length, routeSegments.length); i++) {
1123
- const baseSegment = baseSegments[i];
1124
- const routeSegment = routeSegments[i];
1125
- const isLastRouteSegment = i === routeSegments.length - 1;
1126
- const isLastBaseSegment = i === baseSegments.length - 1;
1127
-
1128
- if (routeSegment) {
1129
- if (routeSegment.type === 'wildcard') {
1130
- if (baseSegment != null && baseSegment.value) {
1131
- params['*'] = joinPaths(baseSegments.slice(i).map(d => d.value));
1132
- return true;
1133
- }
1134
-
1135
- return false;
1136
- }
1137
-
1138
- if (routeSegment.type === 'pathname') {
1139
- if (routeSegment.value === '/' && !(baseSegment != null && baseSegment.value)) {
1140
- return true;
1141
- }
1142
-
1143
- if (baseSegment) {
1144
- if (matchLocation.caseSensitive) {
1145
- if (routeSegment.value !== baseSegment.value) {
1146
- return false;
1147
- }
1148
- } else if (routeSegment.value.toLowerCase() !== baseSegment.value.toLowerCase()) {
1149
- return false;
1150
- }
1151
- }
1152
- }
1153
-
1154
- if (!baseSegment) {
1155
- return false;
1156
- }
1157
-
1158
- if (routeSegment.type === 'param') {
1159
- if ((baseSegment == null ? void 0 : baseSegment.value) === '/') {
1160
- return false;
1161
- }
1162
-
1163
- if (!baseSegment.value.startsWith(':')) {
1164
- params[routeSegment.value.substring(1)] = baseSegment.value;
1165
- }
1166
- }
1167
- }
1168
-
1169
- if (isLastRouteSegment && !isLastBaseSegment) {
1170
- return !!matchLocation.fuzzy;
1171
- }
1172
- }
1173
-
1174
- return true;
1175
- })();
1176
-
1177
- return isMatch ? params : undefined;
1178
- }
1179
-
1180
- // @ts-nocheck
1181
- // 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.
1182
- function encode(obj, pfx) {
1183
- var k,
1184
- i,
1185
- tmp,
1186
- str = '';
1187
-
1188
- for (k in obj) {
1189
- if ((tmp = obj[k]) !== void 0) {
1190
- if (Array.isArray(tmp)) {
1191
- for (i = 0; i < tmp.length; i++) {
1192
- str && (str += '&');
1193
- str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp[i]);
1194
- }
1195
- } else {
1196
- str && (str += '&');
1197
- str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp);
1198
- }
1199
- }
1200
- }
1201
-
1202
- return (pfx || '') + str;
1203
- }
1204
-
1205
- function toValue(mix) {
1206
- if (!mix) return '';
1207
- var str = decodeURIComponent(mix);
1208
- if (str === 'false') return false;
1209
- if (str === 'true') return true;
1210
- if (str.charAt(0) === '0') return str;
1211
- return +str * 0 === 0 ? +str : str;
1212
- }
1213
-
1214
- function decode(str) {
1215
- var tmp,
1216
- k,
1217
- out = {},
1218
- arr = str.split('&');
1219
-
1220
- while (tmp = arr.shift()) {
1221
- tmp = tmp.split('=');
1222
- k = tmp.shift();
1223
-
1224
- if (out[k] !== void 0) {
1225
- out[k] = [].concat(out[k], toValue(tmp.shift()));
1226
- } else {
1227
- out[k] = toValue(tmp.shift());
1228
- }
1229
391
  }
1230
-
1231
- return out;
1232
- }
1233
-
1234
- function _extends() {
1235
- _extends = Object.assign ? Object.assign.bind() : function (target) {
1236
- for (var i = 1; i < arguments.length; i++) {
1237
- var source = arguments[i];
1238
-
1239
- for (var key in source) {
1240
- if (Object.prototype.hasOwnProperty.call(source, key)) {
1241
- target[key] = source[key];
1242
- }
1243
- }
1244
- }
1245
-
1246
- return target;
1247
- };
1248
- return _extends.apply(this, arguments);
1249
- }
1250
-
1251
- function createRoute(routeConfig, options, parent, router) {
1252
- const {
1253
- id,
1254
- routeId,
1255
- path: routePath,
1256
- fullPath
1257
- } = routeConfig;
1258
-
1259
- const action = router.state.actions[id] || (() => {
1260
- router.state.actions[id] = {
1261
- submissions: [],
1262
- submit: async (submission, actionOpts) => {
1263
- var _actionOpts$invalidat;
1264
-
1265
- if (!route) {
1266
- return;
1267
- }
1268
-
1269
- const invalidate = (_actionOpts$invalidat = actionOpts == null ? void 0 : actionOpts.invalidate) != null ? _actionOpts$invalidat : true;
1270
-
1271
- if (!(actionOpts != null && actionOpts.multi)) {
1272
- action.submissions = action.submissions.filter(d => d.isMulti);
1273
- }
1274
-
1275
- const actionState = {
1276
- submittedAt: Date.now(),
1277
- status: 'pending',
1278
- submission,
1279
- isMulti: !!(actionOpts != null && actionOpts.multi)
1280
- };
1281
- action.current = actionState;
1282
- action.latest = actionState;
1283
- action.submissions.push(actionState);
1284
- router.notify();
1285
-
1286
- try {
1287
- const res = await (route.options.action == null ? void 0 : route.options.action(submission));
1288
- actionState.data = res;
1289
-
1290
- if (invalidate) {
1291
- router.invalidateRoute({
1292
- to: '.',
1293
- fromCurrent: true
1294
- });
1295
- await router.reload();
1296
- }
1297
-
1298
- actionState.status = 'success';
1299
- return res;
1300
- } catch (err) {
1301
- console.error(err);
1302
- actionState.error = err;
1303
- actionState.status = 'error';
1304
- } finally {
1305
- router.notify();
1306
- }
1307
- }
1308
- };
1309
- return router.state.actions[id];
1310
- })();
1311
-
1312
- const loader = router.state.loaders[id] || (() => {
1313
- router.state.loaders[id] = {
1314
- pending: [],
1315
- fetch: async loaderContext => {
1316
- if (!route) {
1317
- return;
1318
- }
1319
-
1320
- const loaderState = {
1321
- loadedAt: Date.now(),
1322
- loaderContext
1323
- };
1324
- loader.current = loaderState;
1325
- loader.latest = loaderState;
1326
- loader.pending.push(loaderState); // router.state = {
1327
- // ...router.state,
1328
- // currentAction: loaderState,
1329
- // latestAction: loaderState,
1330
- // }
1331
-
1332
- router.notify();
1333
-
1334
- try {
1335
- return await (route.options.loader == null ? void 0 : route.options.loader(loaderContext));
1336
- } finally {
1337
- loader.pending = loader.pending.filter(d => d !== loaderState); // router.removeActionQueue.push({ loader, loaderState })
1338
-
1339
- router.notify();
1340
- }
1341
- }
1342
- };
1343
- return router.state.loaders[id];
1344
- })();
1345
-
1346
- let route = {
1347
- routeId: id,
1348
- routeRouteId: routeId,
1349
- routePath,
1350
- fullPath,
1351
- options,
1352
- router,
1353
- childRoutes: undefined,
1354
- parentRoute: parent,
1355
- action,
1356
- loader: loader,
1357
- buildLink: options => {
1358
- return router.buildLink(_extends({}, options, {
1359
- from: fullPath
1360
- }));
1361
- },
1362
- navigate: options => {
1363
- return router.navigate(_extends({}, options, {
1364
- from: fullPath
1365
- }));
1366
- },
1367
- matchRoute: (matchLocation, opts) => {
1368
- return router.matchRoute(_extends({}, matchLocation, {
1369
- from: fullPath
1370
- }), opts);
1371
- }
1372
- };
1373
- router.options.createRoute == null ? void 0 : router.options.createRoute({
1374
- router,
1375
- route
1376
- });
1377
- return route;
392
+ return pathParams ?? {};
1378
393
  }
1379
-
1380
- const rootRouteId = '__root__';
1381
- const createRouteConfig = function createRouteConfig(options, children, isRoot, parentId, parentPath) {
1382
- if (options === void 0) {
1383
- options = {};
1384
- }
1385
-
1386
- if (isRoot === void 0) {
1387
- isRoot = true;
1388
- }
1389
-
1390
- if (isRoot) {
1391
- options.path = rootRouteId;
1392
- } // Strip the root from parentIds
1393
-
1394
-
1395
- if (parentId === rootRouteId) {
1396
- parentId = '';
1397
- }
1398
-
1399
- let path = isRoot ? rootRouteId : options.path; // If the path is anything other than an index path, trim it up
1400
-
1401
- if (path && path !== '/') {
1402
- path = trimPath(path);
1403
- }
1404
-
1405
- const routeId = path || options.id;
1406
- let id = joinPaths([parentId, routeId]);
1407
-
1408
- if (path === rootRouteId) {
1409
- path = '/';
394
+ function matchByPath(basepath, from, matchLocation) {
395
+ // Remove the base path from the pathname
396
+ from = basepath != '/' ? from.substring(basepath.length) : from;
397
+ // Default to to $ (wildcard)
398
+ const to = `${matchLocation.to ?? '$'}`;
399
+ // Parse the from and to
400
+ const baseSegments = parsePathname(from);
401
+ const routeSegments = parsePathname(to);
402
+ if (!from.startsWith('/')) {
403
+ baseSegments.unshift({
404
+ type: 'pathname',
405
+ value: '/'
406
+ });
1410
407
  }
1411
-
1412
- if (id !== rootRouteId) {
1413
- id = joinPaths(['/', id]);
408
+ if (!to.startsWith('/')) {
409
+ routeSegments.unshift({
410
+ type: 'pathname',
411
+ value: '/'
412
+ });
1414
413
  }
1415
-
1416
- const fullPath = id === rootRouteId ? '/' : trimPathRight(joinPaths([parentPath, path]));
1417
- return {
1418
- id: id,
1419
- routeId: routeId,
1420
- path: path,
1421
- fullPath: fullPath,
1422
- options: options,
1423
- children,
1424
- createChildren: cb => createRouteConfig(options, cb(childOptions => createRouteConfig(childOptions, undefined, false, id, fullPath)), false, parentId, parentPath),
1425
- addChildren: children => createRouteConfig(options, children, false, parentId, parentPath),
1426
- createRoute: childOptions => createRouteConfig(childOptions, undefined, false, id, fullPath)
1427
- };
1428
- };
1429
-
1430
- const componentTypes = ['component', 'errorComponent', 'pendingComponent'];
1431
- function createRouteMatch(router, route, opts) {
1432
- const routeMatch = _extends({}, route, opts, {
1433
- router,
1434
- routeSearch: {},
1435
- search: {},
1436
- childMatches: [],
1437
- status: 'idle',
1438
- routeLoaderData: {},
1439
- loaderData: {},
1440
- isFetching: false,
1441
- isInvalid: false,
1442
- invalidAt: Infinity,
1443
- // pendingActions: [],
1444
- getIsInvalid: () => {
1445
- const now = Date.now();
1446
- return routeMatch.isInvalid || routeMatch.invalidAt < now;
1447
- },
1448
- __: {
1449
- abortController: new AbortController(),
1450
- latestId: '',
1451
- resolve: () => {},
1452
- notify: () => {
1453
- routeMatch.__.resolve();
1454
-
1455
- routeMatch.router.notify();
1456
- },
1457
- validate: () => {
1458
- var _routeMatch$parentMat, _routeMatch$parentMat2;
1459
-
1460
- // Validate the search params and stabilize them
1461
- const parentSearch = (_routeMatch$parentMat = (_routeMatch$parentMat2 = routeMatch.parentMatch) == null ? void 0 : _routeMatch$parentMat2.search) != null ? _routeMatch$parentMat : router.location.search;
1462
-
1463
- try {
1464
- var _validator;
1465
-
1466
- const prevSearch = routeMatch.routeSearch;
1467
- const validator = typeof routeMatch.options.validateSearch === 'object' ? routeMatch.options.validateSearch.parse : routeMatch.options.validateSearch;
1468
- let nextSearch = replaceEqualDeep(prevSearch, (_validator = validator == null ? void 0 : validator(parentSearch)) != null ? _validator : {}); // Invalidate route matches when search param stability changes
1469
-
1470
- if (prevSearch !== nextSearch) {
1471
- routeMatch.isInvalid = true;
414
+ const params = {};
415
+ let isMatch = (() => {
416
+ for (let i = 0; i < Math.max(baseSegments.length, routeSegments.length); i++) {
417
+ const baseSegment = baseSegments[i];
418
+ const routeSegment = routeSegments[i];
419
+ const isLastBaseSegment = i >= baseSegments.length - 1;
420
+ const isLastRouteSegment = i >= routeSegments.length - 1;
421
+ if (routeSegment) {
422
+ if (routeSegment.type === 'wildcard') {
423
+ if (baseSegment?.value) {
424
+ params['*'] = joinPaths(baseSegments.slice(i).map(d => d.value));
425
+ return true;
1472
426
  }
1473
-
1474
- routeMatch.routeSearch = nextSearch;
1475
- routeMatch.search = replaceEqualDeep(parentSearch, _extends({}, parentSearch, nextSearch));
1476
- componentTypes.map(async type => {
1477
- const component = routeMatch.options[type];
1478
-
1479
- if (typeof routeMatch.__[type] !== 'function') {
1480
- routeMatch.__[type] = component;
427
+ return false;
428
+ }
429
+ if (routeSegment.type === 'pathname') {
430
+ if (routeSegment.value === '/' && !baseSegment?.value) {
431
+ return true;
432
+ }
433
+ if (baseSegment) {
434
+ if (matchLocation.caseSensitive) {
435
+ if (routeSegment.value !== baseSegment.value) {
436
+ return false;
437
+ }
438
+ } else if (routeSegment.value.toLowerCase() !== baseSegment.value.toLowerCase()) {
439
+ return false;
1481
440
  }
1482
- });
1483
- } catch (err) {
1484
- console.error(err);
1485
- const error = new Error('Invalid search params found', {
1486
- cause: err
1487
- });
1488
- error.code = 'INVALID_SEARCH_PARAMS';
1489
- routeMatch.status = 'error';
1490
- routeMatch.error = error; // Do not proceed with loading the route
1491
-
1492
- return;
441
+ }
1493
442
  }
1494
- }
1495
- },
1496
- cancel: () => {
1497
- var _routeMatch$__$abortC;
1498
-
1499
- (_routeMatch$__$abortC = routeMatch.__.abortController) == null ? void 0 : _routeMatch$__$abortC.abort();
1500
- },
1501
- invalidate: () => {
1502
- routeMatch.isInvalid = true;
1503
- },
1504
- hasLoaders: () => {
1505
- return !!(route.options.loader || componentTypes.some(d => {
1506
- var _route$options$d;
1507
-
1508
- return (_route$options$d = route.options[d]) == null ? void 0 : _route$options$d.preload;
1509
- }));
1510
- },
1511
- load: async loaderOpts => {
1512
- const now = Date.now();
1513
- const minMaxAge = loaderOpts != null && loaderOpts.preload ? Math.max(loaderOpts == null ? void 0 : loaderOpts.maxAge, loaderOpts == null ? void 0 : loaderOpts.gcMaxAge) : 0; // If this is a preload, add it to the preload cache
1514
-
1515
- if (loaderOpts != null && loaderOpts.preload && minMaxAge > 0) {
1516
- // If the match is currently active, don't preload it
1517
- if (router.state.matches.find(d => d.matchId === routeMatch.matchId)) {
1518
- return;
443
+ if (!baseSegment) {
444
+ return false;
1519
445
  }
1520
-
1521
- router.matchCache[routeMatch.matchId] = {
1522
- gc: now + loaderOpts.gcMaxAge,
1523
- match: routeMatch
1524
- };
1525
- } // If the match is invalid, errored or idle, trigger it to load
1526
-
1527
-
1528
- if (routeMatch.status === 'success' && routeMatch.getIsInvalid() || routeMatch.status === 'error' || routeMatch.status === 'idle') {
1529
- const maxAge = loaderOpts != null && loaderOpts.preload ? loaderOpts == null ? void 0 : loaderOpts.maxAge : undefined;
1530
- await routeMatch.fetch({
1531
- maxAge
1532
- });
1533
- }
1534
- },
1535
- fetch: async opts => {
1536
- const loadId = '' + Date.now() + Math.random();
1537
- routeMatch.__.latestId = loadId;
1538
-
1539
- const checkLatest = async () => {
1540
- if (loadId !== routeMatch.__.latestId) {
1541
- // warning(true, 'Data loader is out of date!')
1542
- return new Promise(() => {});
446
+ if (routeSegment.type === 'param') {
447
+ if (baseSegment?.value === '/') {
448
+ return false;
449
+ }
450
+ if (baseSegment.value.charAt(0) !== '$') {
451
+ params[routeSegment.value.substring(1)] = baseSegment.value;
452
+ }
1543
453
  }
1544
- }; // If the match was in an error state, set it
1545
- // to a loading state again. Otherwise, keep it
1546
- // as loading or resolved
1547
-
1548
-
1549
- if (routeMatch.status === 'idle') {
1550
- routeMatch.status = 'loading';
1551
- } // We started loading the route, so it's no longer invalid
1552
-
1553
-
1554
- routeMatch.isInvalid = false;
1555
- routeMatch.__.loadPromise = new Promise(async resolve => {
1556
- // We are now fetching, even if it's in the background of a
1557
- // resolved state
1558
- routeMatch.isFetching = true;
1559
- routeMatch.__.resolve = resolve;
1560
-
1561
- routeMatch.__.componentsPromise = (async () => {
1562
- // then run all component and data loaders in parallel
1563
- // For each component type, potentially load it asynchronously
1564
- await Promise.all(componentTypes.map(async type => {
1565
- var _routeMatch$__$type;
1566
-
1567
- const component = routeMatch.options[type];
1568
-
1569
- if ((_routeMatch$__$type = routeMatch.__[type]) != null && _routeMatch$__$type.preload) {
1570
- routeMatch.__[type] = await router.options.loadComponent(component);
1571
- }
1572
- }));
1573
- })();
1574
-
1575
- routeMatch.__.dataPromise = Promise.resolve().then(async () => {
1576
- try {
1577
- var _ref, _ref2, _opts$maxAge;
1578
-
1579
- if (routeMatch.options.loader) {
1580
- const data = await router.loadMatchData(routeMatch);
1581
- await checkLatest();
1582
- routeMatch.routeLoaderData = replaceEqualDeep(routeMatch.routeLoaderData, data);
1583
- }
1584
-
1585
- routeMatch.error = undefined;
1586
- routeMatch.status = 'success';
1587
- routeMatch.updatedAt = Date.now();
1588
- routeMatch.invalidAt = routeMatch.updatedAt + ((_ref = (_ref2 = (_opts$maxAge = opts == null ? void 0 : opts.maxAge) != null ? _opts$maxAge : routeMatch.options.loaderMaxAge) != null ? _ref2 : router.options.defaultLoaderMaxAge) != null ? _ref : 0);
1589
- return routeMatch.routeLoaderData;
1590
- } catch (err) {
1591
- await checkLatest();
454
+ }
455
+ if (!isLastBaseSegment && isLastRouteSegment) {
456
+ return !!matchLocation.fuzzy;
457
+ }
458
+ }
459
+ return true;
460
+ })();
461
+ return isMatch ? params : undefined;
462
+ }
1592
463
 
1593
- if (process.env.NODE_ENV !== 'production') {
1594
- console.error(err);
1595
- }
464
+ // Detect if we're in the DOM
1596
465
 
1597
- routeMatch.error = err;
1598
- routeMatch.status = 'error';
1599
- routeMatch.updatedAt = Date.now();
1600
- throw err;
1601
- }
1602
- });
466
+ function redirect(opts) {
467
+ opts.isRedirect = true;
468
+ return opts;
469
+ }
470
+ function isRedirect(obj) {
471
+ return !!obj?.isRedirect;
472
+ }
1603
473
 
1604
- const after = async () => {
1605
- await checkLatest();
1606
- routeMatch.isFetching = false;
1607
- delete routeMatch.__.loadPromise;
474
+ // @ts-nocheck
1608
475
 
1609
- routeMatch.__.notify();
1610
- };
476
+ // 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.
1611
477
 
1612
- try {
1613
- await Promise.all([routeMatch.__.componentsPromise, routeMatch.__.dataPromise.catch(() => {})]);
1614
- after();
1615
- } catch (_unused) {
1616
- after();
478
+ function encode(obj, pfx) {
479
+ var k,
480
+ i,
481
+ tmp,
482
+ str = '';
483
+ for (k in obj) {
484
+ if ((tmp = obj[k]) !== void 0) {
485
+ if (Array.isArray(tmp)) {
486
+ for (i = 0; i < tmp.length; i++) {
487
+ str && (str += '&');
488
+ str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp[i]);
1617
489
  }
1618
- });
1619
- await routeMatch.__.loadPromise;
1620
- await checkLatest();
490
+ } else {
491
+ str && (str += '&');
492
+ str += encodeURIComponent(k) + '=' + encodeURIComponent(tmp);
493
+ }
1621
494
  }
1622
- });
1623
-
1624
- if (!routeMatch.hasLoaders()) {
1625
- routeMatch.status = 'success';
1626
495
  }
1627
-
1628
- return routeMatch;
496
+ return (pfx || '') + str;
497
+ }
498
+ function toValue(mix) {
499
+ if (!mix) return '';
500
+ var str = decodeURIComponent(mix);
501
+ if (str === 'false') return false;
502
+ if (str === 'true') return true;
503
+ return +str * 0 === 0 && +str + '' === str ? +str : str;
504
+ }
505
+ function decode(str) {
506
+ var tmp,
507
+ k,
508
+ out = {},
509
+ arr = str.split('&');
510
+ while (tmp = arr.shift()) {
511
+ tmp = tmp.split('=');
512
+ k = tmp.shift();
513
+ if (out[k] !== void 0) {
514
+ out[k] = [].concat(out[k], toValue(tmp.shift()));
515
+ } else {
516
+ out[k] = toValue(tmp.shift());
517
+ }
518
+ }
519
+ return out;
1629
520
  }
1630
521
 
1631
522
  const defaultParseSearch = parseSearchWith(JSON.parse);
1632
- const defaultStringifySearch = stringifySearchWith(JSON.stringify);
523
+ const defaultStringifySearch = stringifySearchWith(JSON.stringify, JSON.parse);
1633
524
  function parseSearchWith(parser) {
1634
525
  return searchStr => {
1635
526
  if (searchStr.substring(0, 1) === '?') {
1636
527
  searchStr = searchStr.substring(1);
1637
528
  }
529
+ let query = decode(searchStr);
1638
530
 
1639
- let query = decode(searchStr); // Try to parse any query params that might be json
1640
-
531
+ // Try to parse any query params that might be json
1641
532
  for (let key in query) {
1642
533
  const value = query[key];
1643
-
1644
534
  if (typeof value === 'string') {
1645
535
  try {
1646
536
  query[key] = parser(value);
1647
- } catch (err) {//
537
+ } catch (err) {
538
+ //
1648
539
  }
1649
540
  }
1650
541
  }
1651
-
1652
542
  return query;
1653
543
  };
1654
544
  }
1655
- function stringifySearchWith(stringify) {
545
+ function stringifySearchWith(stringify, parser) {
546
+ function stringifyValue(val) {
547
+ if (typeof val === 'object' && val !== null) {
548
+ try {
549
+ return stringify(val);
550
+ } catch (err) {
551
+ // silent
552
+ }
553
+ } else if (typeof val === 'string' && typeof parser === 'function') {
554
+ try {
555
+ // Check if it's a valid parseable string.
556
+ // If it is, then stringify it again.
557
+ parser(val);
558
+ return stringify(val);
559
+ } catch (err) {
560
+ // silent
561
+ }
562
+ }
563
+ return val;
564
+ }
1656
565
  return search => {
1657
- search = _extends({}, search);
1658
-
566
+ search = {
567
+ ...search
568
+ };
1659
569
  if (search) {
1660
570
  Object.keys(search).forEach(key => {
1661
571
  const val = search[key];
1662
-
1663
572
  if (typeof val === 'undefined' || val === undefined) {
1664
573
  delete search[key];
1665
- } else if (val && typeof val === 'object' && val !== null) {
1666
- try {
1667
- search[key] = stringify(val);
1668
- } catch (err) {// silent
1669
- }
574
+ } else {
575
+ search[key] = stringifyValue(val);
1670
576
  }
1671
577
  });
1672
578
  }
1673
-
1674
579
  const searchStr = encode(search).toString();
1675
- return searchStr ? "?" + searchStr : '';
1676
- };
1677
- }
1678
-
1679
- var _window$document;
1680
- // Detect if we're in the DOM
1681
- const isServer = typeof window === 'undefined' || !((_window$document = window.document) != null && _window$document.createElement); // This is the default history object if none is defined
1682
-
1683
- const createDefaultHistory = () => isServer ? createMemoryHistory() : createBrowserHistory();
1684
-
1685
- function getInitialRouterState() {
1686
- return {
1687
- status: 'idle',
1688
- location: null,
1689
- matches: [],
1690
- actions: {},
1691
- loaders: {},
1692
- lastUpdated: Date.now(),
1693
- isFetching: false,
1694
- isPreloading: false
580
+ return searchStr ? `?${searchStr}` : '';
1695
581
  };
1696
582
  }
1697
583
 
1698
- function createRouter(userOptions) {
1699
- var _userOptions$stringif, _userOptions$parseSea;
1700
-
1701
- const history = (userOptions == null ? void 0 : userOptions.history) || createDefaultHistory();
1702
-
1703
- const originalOptions = _extends({
1704
- defaultLoaderGcMaxAge: 5 * 60 * 1000,
1705
- defaultLoaderMaxAge: 0,
1706
- defaultPreloadMaxAge: 2000,
1707
- defaultPreloadDelay: 50
1708
- }, userOptions, {
1709
- stringifySearch: (_userOptions$stringif = userOptions == null ? void 0 : userOptions.stringifySearch) != null ? _userOptions$stringif : defaultStringifySearch,
1710
- parseSearch: (_userOptions$parseSea = userOptions == null ? void 0 : userOptions.parseSearch) != null ? _userOptions$parseSea : defaultParseSearch
1711
- });
1712
-
1713
- let router = {
1714
- types: undefined,
1715
- // public api
1716
- history,
1717
- options: originalOptions,
1718
- listeners: [],
1719
- // Resolved after construction
1720
- basepath: '',
1721
- routeTree: undefined,
1722
- routesById: {},
1723
- location: undefined,
1724
- //
1725
- navigationPromise: Promise.resolve(),
1726
- resolveNavigation: () => {},
1727
- matchCache: {},
1728
- state: getInitialRouterState(),
1729
- reset: () => {
1730
- router.state = getInitialRouterState();
1731
- router.notify();
1732
- },
1733
- startedLoadingAt: Date.now(),
1734
- subscribe: listener => {
1735
- router.listeners.push(listener);
1736
- return () => {
1737
- router.listeners = router.listeners.filter(x => x !== listener);
1738
- };
1739
- },
1740
- getRoute: id => {
1741
- return router.routesById[id];
1742
- },
1743
- notify: () => {
1744
- const isFetching = router.state.status === 'loading' || router.state.matches.some(d => d.isFetching);
1745
- const isPreloading = Object.values(router.matchCache).some(d => d.match.isFetching && !router.state.matches.find(dd => dd.matchId === d.match.matchId));
1746
-
1747
- if (router.state.isFetching !== isFetching || router.state.isPreloading !== isPreloading) {
1748
- router.state = _extends({}, router.state, {
1749
- isFetching,
1750
- isPreloading
1751
- });
1752
- }
1753
-
1754
- cascadeLoaderData(router.state.matches);
1755
- router.listeners.forEach(listener => listener(router));
1756
- },
1757
- dehydrateState: () => {
1758
- return _extends({}, pick(router.state, ['status', 'location', 'lastUpdated']), {
1759
- matches: router.state.matches.map(match => pick(match, ['matchId', 'status', 'routeLoaderData', 'loaderData', 'isInvalid', 'invalidAt']))
1760
- });
1761
- },
1762
- hydrateState: dehydratedState => {
1763
- // Match the routes
1764
- const matches = router.matchRoutes(router.location.pathname, {
1765
- strictParseParams: true
1766
- });
1767
- matches.forEach((match, index) => {
1768
- const dehydratedMatch = dehydratedState.matches[index];
1769
- invariant(dehydratedMatch, 'Oh no! Dehydrated route matches did not match the active state of the router 😬');
1770
- Object.assign(match, dehydratedMatch);
1771
- });
1772
- matches.forEach(match => match.__.validate());
1773
- router.state = _extends({}, router.state, dehydratedState, {
1774
- matches
1775
- });
1776
- },
1777
- mount: () => {
1778
- const next = router.__.buildLocation({
1779
- to: '.',
1780
- search: true,
1781
- hash: true
1782
- }); // If the current location isn't updated, trigger a navigation
1783
- // to the current location. Otherwise, load the current location.
1784
-
1785
-
1786
- if (next.href !== router.location.href) {
1787
- router.__.commitLocation(next, true);
1788
- }
1789
-
1790
- if (!router.state.matches.length) {
1791
- router.load();
1792
- }
1793
-
1794
- const unsub = router.history.listen(event => {
1795
- router.load(router.__.parseLocation(event.location, router.location));
1796
- }); // addEventListener does not exist in React Native, but window does
1797
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1798
-
1799
- if (!isServer && window.addEventListener) {
1800
- // Listen to visibillitychange and focus
1801
- window.addEventListener('visibilitychange', router.onFocus, false);
1802
- window.addEventListener('focus', router.onFocus, false);
1803
- }
1804
-
1805
- return () => {
1806
- unsub();
1807
-
1808
- if (!isServer && window.removeEventListener) {
1809
- // Be sure to unsubscribe if a new handler is set
1810
- window.removeEventListener('visibilitychange', router.onFocus);
1811
- window.removeEventListener('focus', router.onFocus);
1812
- }
1813
- };
1814
- },
1815
- onFocus: () => {
1816
- router.load();
1817
- },
1818
- update: opts => {
1819
- const newHistory = (opts == null ? void 0 : opts.history) !== router.history;
1820
-
1821
- if (!router.location || newHistory) {
1822
- if (opts != null && opts.history) {
1823
- router.history = opts.history;
1824
- }
1825
-
1826
- router.location = router.__.parseLocation(router.history.location);
1827
- router.state.location = router.location;
1828
- }
1829
-
1830
- Object.assign(router.options, opts);
1831
- const {
1832
- basepath,
1833
- routeConfig
1834
- } = router.options;
1835
- router.basepath = cleanPath("/" + (basepath != null ? basepath : ''));
1836
-
1837
- if (routeConfig) {
1838
- router.routesById = {};
1839
- router.routeTree = router.__.buildRouteTree(routeConfig);
1840
- }
1841
-
1842
- return router;
1843
- },
1844
- cancelMatches: () => {
1845
- var _router$state$pending, _router$state$pending2;
1846
- [...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 => {
1847
- match.cancel();
1848
- });
1849
- },
1850
- load: async next => {
1851
- const id = Math.random();
1852
- router.startedLoadingAt = id;
1853
-
1854
- if (next) {
1855
- // Ingest the new location
1856
- router.location = next;
1857
- } // Cancel any pending matches
1858
-
1859
-
1860
- router.cancelMatches(); // Match the routes
1861
-
1862
- const matches = router.matchRoutes(router.location.pathname, {
1863
- strictParseParams: true
1864
- });
1865
-
1866
- if (typeof document !== 'undefined') {
1867
- router.state = _extends({}, router.state, {
1868
- pending: {
1869
- matches: matches,
1870
- location: router.location
1871
- },
1872
- status: 'loading'
1873
- });
1874
- } else {
1875
- router.state = _extends({}, router.state, {
1876
- matches: matches,
1877
- location: router.location,
1878
- status: 'loading'
1879
- });
1880
- }
1881
-
1882
- router.notify(); // Load the matches
1883
-
1884
- await router.loadMatches(matches);
1885
-
1886
- if (router.startedLoadingAt !== id) {
1887
- // Ignore side-effects of match loading
1888
- return router.navigationPromise;
1889
- }
1890
-
1891
- const previousMatches = router.state.matches;
1892
- const exiting = [],
1893
- staying = [];
1894
- previousMatches.forEach(d => {
1895
- if (matches.find(dd => dd.matchId === d.matchId)) {
1896
- staying.push(d);
1897
- } else {
1898
- exiting.push(d);
1899
- }
1900
- });
1901
- const entering = matches.filter(d => {
1902
- return !previousMatches.find(dd => dd.matchId === d.matchId);
1903
- });
1904
- const now = Date.now();
1905
- exiting.forEach(d => {
1906
- var _ref, _d$options$loaderGcMa, _ref2, _d$options$loaderMaxA;
1907
-
1908
- d.__.onExit == null ? void 0 : d.__.onExit({
1909
- params: d.params,
1910
- search: d.routeSearch
1911
- }); // Clear idle error states when match leaves
1912
-
1913
- if (d.status === 'error' && !d.isFetching) {
1914
- d.status = 'idle';
1915
- d.error = undefined;
1916
- }
1917
-
1918
- const gc = Math.max((_ref = (_d$options$loaderGcMa = d.options.loaderGcMaxAge) != null ? _d$options$loaderGcMa : router.options.defaultLoaderGcMaxAge) != null ? _ref : 0, (_ref2 = (_d$options$loaderMaxA = d.options.loaderMaxAge) != null ? _d$options$loaderMaxA : router.options.defaultLoaderMaxAge) != null ? _ref2 : 0);
1919
-
1920
- if (gc > 0) {
1921
- router.matchCache[d.matchId] = {
1922
- gc: gc == Infinity ? Number.MAX_SAFE_INTEGER : now + gc,
1923
- match: d
1924
- };
1925
- }
1926
- });
1927
- staying.forEach(d => {
1928
- d.options.onTransition == null ? void 0 : d.options.onTransition({
1929
- params: d.params,
1930
- search: d.routeSearch
1931
- });
1932
- });
1933
- entering.forEach(d => {
1934
- d.__.onExit = d.options.onMatch == null ? void 0 : d.options.onMatch({
1935
- params: d.params,
1936
- search: d.search
1937
- });
1938
- delete router.matchCache[d.matchId];
1939
- });
1940
-
1941
- if (router.startedLoadingAt !== id) {
1942
- // Ignore side-effects of match loading
1943
- return;
1944
- }
1945
-
1946
- matches.forEach(match => {
1947
- // Clear actions
1948
- if (match.action) {
1949
- match.action.current = undefined;
1950
- match.action.submissions = [];
1951
- }
1952
- });
1953
- router.state = _extends({}, router.state, {
1954
- location: router.location,
1955
- matches,
1956
- pending: undefined,
1957
- status: 'idle'
1958
- });
1959
- router.notify();
1960
- router.resolveNavigation();
1961
- },
1962
- cleanMatchCache: () => {
1963
- const now = Date.now();
1964
- Object.keys(router.matchCache).forEach(matchId => {
1965
- const entry = router.matchCache[matchId]; // Don't remove loading matches
1966
-
1967
- if (entry.match.status === 'loading') {
1968
- return;
1969
- } // Do not remove successful matches that are still valid
1970
-
1971
-
1972
- if (entry.gc > 0 && entry.gc > now) {
1973
- return;
1974
- } // Everything else gets removed
1975
-
1976
-
1977
- delete router.matchCache[matchId];
1978
- });
1979
- },
1980
- loadRoute: async function loadRoute(navigateOpts) {
1981
- if (navigateOpts === void 0) {
1982
- navigateOpts = router.location;
1983
- }
1984
-
1985
- const next = router.buildNext(navigateOpts);
1986
- const matches = router.matchRoutes(next.pathname, {
1987
- strictParseParams: true
1988
- });
1989
- await router.loadMatches(matches);
1990
- return matches;
1991
- },
1992
- preloadRoute: async function preloadRoute(navigateOpts, loaderOpts) {
1993
- var _ref3, _ref4, _loaderOpts$maxAge, _ref5, _ref6, _loaderOpts$gcMaxAge;
1994
-
1995
- if (navigateOpts === void 0) {
1996
- navigateOpts = router.location;
1997
- }
1998
-
1999
- const next = router.buildNext(navigateOpts);
2000
- const matches = router.matchRoutes(next.pathname, {
2001
- strictParseParams: true
2002
- });
2003
- await router.loadMatches(matches, {
2004
- preload: true,
2005
- maxAge: (_ref3 = (_ref4 = (_loaderOpts$maxAge = loaderOpts.maxAge) != null ? _loaderOpts$maxAge : router.options.defaultPreloadMaxAge) != null ? _ref4 : router.options.defaultLoaderMaxAge) != null ? _ref3 : 0,
2006
- gcMaxAge: (_ref5 = (_ref6 = (_loaderOpts$gcMaxAge = loaderOpts.gcMaxAge) != null ? _loaderOpts$gcMaxAge : router.options.defaultPreloadGcMaxAge) != null ? _ref6 : router.options.defaultLoaderGcMaxAge) != null ? _ref5 : 0
2007
- });
2008
- return matches;
2009
- },
2010
- matchRoutes: (pathname, opts) => {
2011
- var _router$state$pending3, _router$state$pending4;
2012
-
2013
- router.cleanMatchCache();
2014
- const matches = [];
2015
-
2016
- if (!router.routeTree) {
2017
- return matches;
2018
- }
2019
-
2020
- 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 : [])];
2021
-
2022
- const recurse = async routes => {
2023
- var _parentMatch$params, _router$options$filte, _foundRoute$childRout;
584
+ //
2024
585
 
2025
- const parentMatch = last(matches);
2026
- let params = (_parentMatch$params = parentMatch == null ? void 0 : parentMatch.params) != null ? _parentMatch$params : {};
2027
- const filteredRoutes = (_router$options$filte = router.options.filterRoutes == null ? void 0 : router.options.filterRoutes(routes)) != null ? _router$options$filte : routes;
2028
- let foundRoutes = [];
586
+ //
2029
587
 
2030
- const findMatchInRoutes = (parentRoutes, routes) => {
2031
- routes.some(route => {
2032
- var _route$childRoutes, _route$childRoutes2, _route$options$caseSe;
588
+ const componentTypes = ['component', 'errorComponent', 'pendingComponent'];
589
+ class Router {
590
+ // dehydratedData?: TDehydrated
591
+ // resetNextScroll = false
592
+ // tempLocationKey = `${Math.round(Math.random() * 10000000)}`
593
+ constructor(options) {
594
+ this.options = {
595
+ defaultPreloadDelay: 50,
596
+ context: undefined,
597
+ ...options,
598
+ stringifySearch: options?.stringifySearch ?? defaultStringifySearch,
599
+ parseSearch: options?.parseSearch ?? defaultParseSearch
600
+ };
601
+ this.routeTree = this.options.routeTree;
602
+ }
603
+ subscribers = new Set();
604
+ subscribe = (eventType, fn) => {
605
+ const listener = {
606
+ eventType,
607
+ fn
608
+ };
609
+ this.subscribers.add(listener);
610
+ return () => {
611
+ this.subscribers.delete(listener);
612
+ };
613
+ };
614
+ emit = routerEvent => {
615
+ this.subscribers.forEach(listener => {
616
+ if (listener.eventType === routerEvent.type) {
617
+ listener.fn(routerEvent);
618
+ }
619
+ });
620
+ };
2033
621
 
2034
- if (!route.routePath && (_route$childRoutes = route.childRoutes) != null && _route$childRoutes.length) {
2035
- return findMatchInRoutes([...foundRoutes, route], route.childRoutes);
2036
- }
622
+ // dehydrate = (): DehydratedRouter => {
623
+ // return {
624
+ // state: {
625
+ // dehydratedMatches: state.matches.map((d) =>
626
+ // pick(d, ['fetchedAt', 'invalid', 'id', 'status', 'updatedAt']),
627
+ // ),
628
+ // },
629
+ // }
630
+ // }
2037
631
 
2038
- const fuzzy = !!(route.routePath !== '/' || (_route$childRoutes2 = route.childRoutes) != null && _route$childRoutes2.length);
2039
- const matchParams = matchPathname(pathname, {
2040
- to: route.fullPath,
2041
- fuzzy,
2042
- caseSensitive: (_route$options$caseSe = route.options.caseSensitive) != null ? _route$options$caseSe : router.options.caseSensitive
2043
- });
632
+ // hydrate = async (__do_not_use_server_ctx?: HydrationCtx) => {
633
+ // let _ctx = __do_not_use_server_ctx
634
+ // // Client hydrates from window
635
+ // if (typeof document !== 'undefined') {
636
+ // _ctx = window.__TSR_DEHYDRATED__
637
+ // }
638
+
639
+ // invariant(
640
+ // _ctx,
641
+ // 'Expected to find a __TSR_DEHYDRATED__ property on window... but we did not. Did you forget to render <DehydrateRouter /> in your app?',
642
+ // )
643
+
644
+ // const ctx = _ctx
645
+ // this.dehydratedData = ctx.payload as any
646
+ // this.options.hydrate?.(ctx.payload as any)
647
+ // const dehydratedState = ctx.router.state
648
+
649
+ // let matches = this.matchRoutes(
650
+ // state.location.pathname,
651
+ // state.location.search,
652
+ // ).map((match) => {
653
+ // const dehydratedMatch = dehydratedState.dehydratedMatches.find(
654
+ // (d) => d.id === match.id,
655
+ // )
656
+
657
+ // invariant(
658
+ // dehydratedMatch,
659
+ // `Could not find a client-side match for dehydrated match with id: ${match.id}!`,
660
+ // )
661
+
662
+ // if (dehydratedMatch) {
663
+ // return {
664
+ // ...match,
665
+ // ...dehydratedMatch,
666
+ // }
667
+ // }
668
+ // return match
669
+ // })
670
+
671
+ // this.setState((s) => {
672
+ // return {
673
+ // ...s,
674
+ // matches: dehydratedState.dehydratedMatches as any,
675
+ // }
676
+ // })
677
+ // }
2044
678
 
2045
- if (matchParams) {
2046
- let parsedParams;
679
+ // TODO:
680
+ // injectedHtml: (string | (() => Promise<string> | string))[] = []
2047
681
 
2048
- try {
2049
- var _route$options$parseP;
682
+ // TODO:
683
+ // injectHtml = async (html: string | (() => Promise<string> | string)) => {
684
+ // this.injectedHtml.push(html)
685
+ // }
2050
686
 
2051
- parsedParams = (_route$options$parseP = route.options.parseParams == null ? void 0 : route.options.parseParams(matchParams)) != null ? _route$options$parseP : matchParams;
2052
- } catch (err) {
2053
- if (opts != null && opts.strictParseParams) {
2054
- throw err;
2055
- }
2056
- }
687
+ // TODO:
688
+ // dehydrateData = <T>(key: any, getData: T | (() => Promise<T> | T)) => {
689
+ // if (typeof document === 'undefined') {
690
+ // const strKey = typeof key === 'string' ? key : JSON.stringify(key)
691
+
692
+ // this.injectHtml(async () => {
693
+ // const id = `__TSR_DEHYDRATED__${strKey}`
694
+ // const data =
695
+ // typeof getData === 'function' ? await (getData as any)() : getData
696
+ // return `<script id='${id}' suppressHydrationWarning>window["__TSR_DEHYDRATED__${escapeJSON(
697
+ // strKey,
698
+ // )}"] = ${JSON.stringify(data)}
699
+ // ;(() => {
700
+ // var el = document.getElementById('${id}')
701
+ // el.parentElement.removeChild(el)
702
+ // })()
703
+ // </script>`
704
+ // })
705
+
706
+ // return () => this.hydrateData<T>(key)
707
+ // }
708
+
709
+ // return () => undefined
710
+ // }
2057
711
 
2058
- params = _extends({}, params, parsedParams);
2059
- }
712
+ // hydrateData = <T = unknown>(key: any) => {
713
+ // if (typeof document !== 'undefined') {
714
+ // const strKey = typeof key === 'string' ? key : JSON.stringify(key)
2060
715
 
2061
- if (!!matchParams) {
2062
- foundRoutes = [...parentRoutes, route];
2063
- }
716
+ // return window[`__TSR_DEHYDRATED__${strKey}` as any] as T
717
+ // }
2064
718
 
2065
- return !!foundRoutes.length;
2066
- });
2067
- return !!foundRoutes.length;
2068
- };
719
+ // return undefined
720
+ // }
2069
721
 
2070
- findMatchInRoutes([], filteredRoutes);
722
+ // resolveMatchPromise = (matchId: string, key: string, value: any) => {
723
+ // state.matches
724
+ // .find((d) => d.id === matchId)
725
+ // ?.__promisesByKey[key]?.resolve(value)
726
+ // }
2071
727
 
2072
- if (!foundRoutes.length) {
2073
- return;
2074
- }
728
+ // setRouteMatch = (
729
+ // id: string,
730
+ // pending: boolean,
731
+ // updater: NonNullableUpdater<RouteMatch<TRouteTree>>,
732
+ // ) => {
733
+ // const key = pending ? 'pendingMatches' : 'matches'
734
+
735
+ // this.setState((prev) => {
736
+ // return {
737
+ // ...prev,
738
+ // [key]: prev[key].map((d) => {
739
+ // if (d.id === id) {
740
+ // return functionalUpdate(updater, d)
741
+ // }
742
+
743
+ // return d
744
+ // }),
745
+ // }
746
+ // })
747
+ // }
2075
748
 
2076
- foundRoutes.forEach(foundRoute => {
2077
- var _router$matchCache$ma;
749
+ // setPendingRouteMatch = (
750
+ // id: string,
751
+ // updater: NonNullableUpdater<RouteMatch<TRouteTree>>,
752
+ // ) => {
753
+ // this.setRouteMatch(id, true, updater)
754
+ // }
755
+ }
2078
756
 
2079
- const interpolatedPath = interpolatePath(foundRoute.routePath, params);
2080
- const matchId = interpolatePath(foundRoute.routeId, params, true);
2081
- const match = existingMatches.find(d => d.matchId === matchId) || ((_router$matchCache$ma = router.matchCache[matchId]) == null ? void 0 : _router$matchCache$ma.match) || createRouteMatch(router, foundRoute, {
2082
- parentMatch,
2083
- matchId,
2084
- params,
2085
- pathname: joinPaths([pathname, interpolatedPath])
2086
- });
2087
- matches.push(match);
2088
- });
2089
- const foundRoute = last(foundRoutes);
757
+ // A function that takes an import() argument which is a function and returns a new function that will
758
+ // proxy arguments from the caller to the imported function, retaining all type
759
+ // information along the way
760
+ function lazyFn(fn, key) {
761
+ return async (...args) => {
762
+ const imported = await fn();
763
+ return imported[key || 'default'](...args);
764
+ };
765
+ }
2090
766
 
2091
- if ((_foundRoute$childRout = foundRoute.childRoutes) != null && _foundRoute$childRout.length) {
2092
- recurse(foundRoute.childRoutes);
2093
- }
767
+ const routerContext = /*#__PURE__*/React.createContext(null);
768
+ if (typeof document !== 'undefined') {
769
+ window.__TSR_ROUTER_CONTEXT__ = routerContext;
770
+ }
771
+ const preloadWarning = 'Error preloading route! ☝️';
772
+ function isCtrlEvent(e) {
773
+ return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
774
+ }
775
+ class SearchParamError extends Error {}
776
+ class PathParamError extends Error {}
777
+ function getInitialRouterState(location) {
778
+ return {
779
+ status: 'idle',
780
+ resolvedLocation: undefined,
781
+ location: location,
782
+ matches: [],
783
+ pendingMatches: [],
784
+ lastUpdated: Date.now()
785
+ };
786
+ }
787
+ function RouterProvider({
788
+ router,
789
+ ...rest
790
+ }) {
791
+ const options = {
792
+ ...router.options,
793
+ ...rest,
794
+ context: {
795
+ ...router.options.context,
796
+ ...rest?.context
797
+ }
798
+ };
799
+ const history = React.useState(() => options.history ?? createBrowserHistory())[0];
800
+ const tempLocationKeyRef = React.useRef(`${Math.round(Math.random() * 10000000)}`);
801
+ const resetNextScrollRef = React.useRef(false);
802
+ const navigateTimeoutRef = React.useRef(null);
803
+ const latestLoadPromiseRef = React.useRef(Promise.resolve());
804
+ const checkLatest = promise => {
805
+ return latestLoadPromiseRef.current !== promise ? latestLoadPromiseRef.current : undefined;
806
+ };
807
+ const parseLocation = useStableCallback(previousLocation => {
808
+ const parse = ({
809
+ pathname,
810
+ search,
811
+ hash,
812
+ state
813
+ }) => {
814
+ const parsedSearch = options.parseSearch(search);
815
+ return {
816
+ pathname: pathname,
817
+ searchStr: search,
818
+ search: replaceEqualDeep(previousLocation?.search, parsedSearch),
819
+ hash: hash.split('#').reverse()[0] ?? '',
820
+ href: `${pathname}${search}${hash}`,
821
+ state: replaceEqualDeep(previousLocation?.state, state)
2094
822
  };
2095
-
2096
- recurse([router.routeTree]);
2097
- cascadeLoaderData(matches);
2098
- return matches;
2099
- },
2100
- loadMatches: async (resolvedMatches, loaderOpts) => {
2101
- const matchPromises = resolvedMatches.map(async match => {
2102
- // Validate the match (loads search params etc)
2103
- match.__.validate();
2104
-
2105
- match.load(loaderOpts);
2106
- const search = match.search;
2107
-
2108
- if (search.__data && search.__data.matchId !== match.matchId) {
2109
- return;
823
+ };
824
+ const location = parse(history.location);
825
+ let {
826
+ __tempLocation,
827
+ __tempKey
828
+ } = location.state;
829
+ if (__tempLocation && (!__tempKey || __tempKey === tempLocationKeyRef.current)) {
830
+ // Sync up the location keys
831
+ const parsedTempLocation = parse(__tempLocation);
832
+ parsedTempLocation.state.key = location.state.key;
833
+ delete parsedTempLocation.state.__tempLocation;
834
+ return {
835
+ ...parsedTempLocation,
836
+ maskedLocation: location
837
+ };
838
+ }
839
+ return location;
840
+ });
841
+ const [preState, setState] = React.useState(() => getInitialRouterState(parseLocation()));
842
+ const [isTransitioning, startReactTransition] = React.useTransition();
843
+ const state = React.useMemo(() => ({
844
+ ...preState,
845
+ status: isTransitioning ? 'pending' : 'idle'
846
+ }), [preState, isTransitioning]);
847
+ React.useLayoutEffect(() => {
848
+ if (!isTransitioning && state.resolvedLocation !== state.location) {
849
+ setState(s => ({
850
+ ...s,
851
+ resolvedLocation: s.location
852
+ }));
853
+ }
854
+ });
855
+ const basepath = `/${trimPath(options.basepath ?? '') ?? ''}`;
856
+ const resolvePathWithBase = useStableCallback((from, path) => {
857
+ return resolvePath(basepath, from, cleanPath(path));
858
+ });
859
+ const [routesById, routesByPath] = React.useMemo(() => {
860
+ const routesById = {};
861
+ const routesByPath = {};
862
+ const recurseRoutes = routes => {
863
+ routes.forEach((route, i) => {
864
+ route.init({
865
+ originalIndex: i
866
+ });
867
+ const existingRoute = routesById[route.id];
868
+ invariant(!existingRoute, `Duplicate routes found with id: ${String(route.id)}`);
869
+ routesById[route.id] = route;
870
+ if (!route.isRoot && route.path) {
871
+ const trimmedFullPath = trimPathRight(route.fullPath);
872
+ if (!routesByPath[trimmedFullPath] || route.fullPath.endsWith('/')) {
873
+ routesByPath[trimmedFullPath] = route;
874
+ }
2110
875
  }
2111
-
2112
- if (match.__.loadPromise) {
2113
- // Wait for the first sign of activity from the match
2114
- await match.__.loadPromise;
876
+ const children = route.children;
877
+ if (children?.length) {
878
+ recurseRoutes(children);
2115
879
  }
2116
880
  });
2117
- router.notify();
2118
- await Promise.all(matchPromises);
2119
- },
2120
- loadMatchData: async routeMatch => {
2121
- if (isServer || !router.options.useServerData) {
2122
- var _await$routeMatch$opt;
2123
-
2124
- return (_await$routeMatch$opt = await (routeMatch.options.loader == null ? void 0 : routeMatch.options.loader({
2125
- // parentLoaderPromise: routeMatch.parentMatch?.__.dataPromise,
2126
- params: routeMatch.params,
2127
- search: routeMatch.routeSearch,
2128
- signal: routeMatch.__.abortController.signal
2129
- }))) != null ? _await$routeMatch$opt : {};
2130
- } else {
2131
- const next = router.buildNext({
2132
- to: '.',
2133
- search: d => _extends({}, d != null ? d : {}, {
2134
- __data: {
2135
- matchId: routeMatch.matchId
2136
- }
2137
- })
2138
- });
2139
- const res = await fetch(next.href, {
2140
- method: 'GET' // signal: routeMatch.__.abortController.signal,
2141
-
2142
- });
881
+ };
882
+ recurseRoutes([router.routeTree]);
883
+ return [routesById, routesByPath];
884
+ }, []);
885
+ const looseRoutesById = routesById;
886
+ const flatRoutes = React.useMemo(() => Object.values(routesByPath).map((d, i) => {
887
+ const trimmed = trimPath(d.fullPath);
888
+ const parsed = parsePathname(trimmed);
889
+ while (parsed.length > 1 && parsed[0]?.value === '/') {
890
+ parsed.shift();
891
+ }
892
+ const score = parsed.map(d => {
893
+ if (d.type === 'param') {
894
+ return 0.5;
895
+ }
896
+ if (d.type === 'wildcard') {
897
+ return 0.25;
898
+ }
899
+ return 1;
900
+ });
901
+ return {
902
+ child: d,
903
+ trimmed,
904
+ parsed,
905
+ index: i,
906
+ score
907
+ };
908
+ }).sort((a, b) => {
909
+ let isIndex = a.trimmed === '/' ? 1 : b.trimmed === '/' ? -1 : 0;
910
+ if (isIndex !== 0) return isIndex;
911
+ const length = Math.min(a.score.length, b.score.length);
912
+
913
+ // Sort by length of score
914
+ if (a.score.length !== b.score.length) {
915
+ return b.score.length - a.score.length;
916
+ }
2143
917
 
2144
- if (res.ok) {
2145
- return res.json();
2146
- }
918
+ // Sort by min available score
919
+ for (let i = 0; i < length; i++) {
920
+ if (a.score[i] !== b.score[i]) {
921
+ return b.score[i] - a.score[i];
922
+ }
923
+ }
2147
924
 
2148
- throw new Error('Failed to fetch match data');
925
+ // Sort by min available parsed value
926
+ for (let i = 0; i < length; i++) {
927
+ if (a.parsed[i].value !== b.parsed[i].value) {
928
+ return a.parsed[i].value > b.parsed[i].value ? 1 : -1;
2149
929
  }
2150
- },
2151
- invalidateRoute: opts => {
2152
- var _router$state$pending5, _router$state$pending6;
2153
-
2154
- const next = router.buildNext(opts);
2155
- const unloadedMatchIds = router.matchRoutes(next.pathname).map(d => d.matchId);
2156
- [...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 => {
2157
- if (unloadedMatchIds.includes(match.matchId)) {
2158
- match.invalidate();
2159
- }
2160
- });
2161
- },
2162
- reload: () => router.__.navigate({
2163
- fromCurrent: true,
2164
- replace: true,
2165
- search: true
2166
- }),
2167
- resolvePath: (from, path) => {
2168
- return resolvePath(router.basepath, from, cleanPath(path));
2169
- },
2170
- matchRoute: (location, opts) => {
2171
- var _location$from;
930
+ }
931
+
932
+ // Sort by length of trimmed full path
933
+ if (a.trimmed !== b.trimmed) {
934
+ return a.trimmed > b.trimmed ? 1 : -1;
935
+ }
2172
936
 
2173
- // const location = router.buildNext(opts)
2174
- location = _extends({}, location, {
2175
- to: location.to ? router.resolvePath((_location$from = location.from) != null ? _location$from : '', location.to) : undefined
937
+ // Sort by original index
938
+ return a.index - b.index;
939
+ }).map((d, i) => {
940
+ d.child.rank = i;
941
+ return d.child;
942
+ }), [routesByPath]);
943
+ const matchRoutes = useStableCallback((pathname, locationSearch, opts) => {
944
+ let routeParams = {};
945
+ let foundRoute = flatRoutes.find(route => {
946
+ const matchedParams = matchPathname(basepath, trimPathRight(pathname), {
947
+ to: route.fullPath,
948
+ caseSensitive: route.options.caseSensitive ?? options.caseSensitive,
949
+ fuzzy: false
2176
950
  });
2177
- const next = router.buildNext(location);
951
+ if (matchedParams) {
952
+ routeParams = matchedParams;
953
+ return true;
954
+ }
955
+ return false;
956
+ });
957
+ let routeCursor = foundRoute || routesById['__root__'];
958
+ let matchedRoutes = [routeCursor];
959
+ // let includingLayouts = true
960
+ while (routeCursor?.parentRoute) {
961
+ routeCursor = routeCursor.parentRoute;
962
+ if (routeCursor) matchedRoutes.unshift(routeCursor);
963
+ }
2178
964
 
2179
- if (opts != null && opts.pending) {
2180
- var _router$state$pending7;
965
+ // Existing matches are matches that are already loaded along with
966
+ // pending matches that are still loading
2181
967
 
2182
- if (!((_router$state$pending7 = router.state.pending) != null && _router$state$pending7.location)) {
2183
- return false;
968
+ const parseErrors = matchedRoutes.map(route => {
969
+ let parsedParamsError;
970
+ if (route.options.parseParams) {
971
+ try {
972
+ const parsedParams = route.options.parseParams(routeParams);
973
+ // Add the parsed params to the accumulated params bag
974
+ Object.assign(routeParams, parsedParams);
975
+ } catch (err) {
976
+ parsedParamsError = new PathParamError(err.message, {
977
+ cause: err
978
+ });
979
+ if (opts?.throwOnError) {
980
+ throw parsedParamsError;
981
+ }
982
+ return parsedParamsError;
2184
983
  }
2185
-
2186
- return !!matchPathname(router.state.pending.location.pathname, _extends({}, opts, {
2187
- to: next.pathname
2188
- }));
2189
984
  }
2190
-
2191
- return !!matchPathname(router.state.location.pathname, _extends({}, opts, {
2192
- to: next.pathname
2193
- }));
2194
- },
2195
- navigate: async _ref7 => {
2196
- let {
2197
- from,
2198
- to = '.',
2199
- search,
2200
- hash,
2201
- replace,
2202
- params
2203
- } = _ref7;
2204
- // If this link simply reloads the current route,
2205
- // make sure it has a new key so it will trigger a data refresh
2206
- // If this `to` is a valid external URL, return
2207
- // null for LinkUtils
2208
- const toString = String(to);
2209
- const fromString = String(from);
2210
- let isExternal;
2211
-
2212
- try {
2213
- new URL("" + toString);
2214
- isExternal = true;
2215
- } catch (e) {}
2216
-
2217
- invariant(!isExternal, 'Attempting to navigate to external url with router.navigate!');
2218
- return router.__.navigate({
2219
- from: fromString,
2220
- to: toString,
2221
- search,
2222
- hash,
2223
- replace,
2224
- params
2225
- });
2226
- },
2227
- buildLink: _ref8 => {
2228
- var _preload, _ref9;
2229
-
2230
- let {
2231
- from,
2232
- to = '.',
2233
- search,
2234
- params,
2235
- hash,
2236
- target,
2237
- replace,
2238
- activeOptions,
2239
- preload,
2240
- preloadMaxAge: userPreloadMaxAge,
2241
- preloadGcMaxAge: userPreloadGcMaxAge,
2242
- preloadDelay: userPreloadDelay,
2243
- disabled
2244
- } = _ref8;
2245
-
2246
- // If this link simply reloads the current route,
2247
- // make sure it has a new key so it will trigger a data refresh
2248
- // If this `to` is a valid external URL, return
2249
- // null for LinkUtils
2250
- try {
2251
- new URL("" + to);
985
+ return;
986
+ });
987
+ const matches = matchedRoutes.map((route, index) => {
988
+ const interpolatedPath = interpolatePath(route.path, routeParams);
989
+ const matchId = interpolatePath(route.id, routeParams, true);
990
+
991
+ // Waste not, want not. If we already have a match for this route,
992
+ // reuse it. This is important for layout routes, which might stick
993
+ // around between navigation actions that only change leaf routes.
994
+ const existingMatch = getRouteMatch(state, matchId);
995
+ if (existingMatch) {
2252
996
  return {
2253
- type: 'external',
2254
- href: to
997
+ ...existingMatch
2255
998
  };
2256
- } catch (e) {}
999
+ }
2257
1000
 
2258
- const nextOpts = {
2259
- from,
2260
- to,
2261
- search,
2262
- params,
2263
- hash,
2264
- replace
1001
+ // Create a fresh route match
1002
+ const hasLoaders = !!(route.options.load || componentTypes.some(d => route.options[d]?.preload));
1003
+ const routeMatch = {
1004
+ id: matchId,
1005
+ routeId: route.id,
1006
+ params: routeParams,
1007
+ pathname: joinPaths([basepath, interpolatedPath]),
1008
+ updatedAt: Date.now(),
1009
+ routeSearch: {},
1010
+ search: {},
1011
+ status: hasLoaders ? 'pending' : 'success',
1012
+ isFetching: false,
1013
+ invalid: false,
1014
+ error: undefined,
1015
+ paramsError: parseErrors[index],
1016
+ searchError: undefined,
1017
+ loadPromise: Promise.resolve(),
1018
+ context: undefined,
1019
+ abortController: new AbortController(),
1020
+ fetchedAt: 0
2265
1021
  };
2266
- const next = router.buildNext(nextOpts);
2267
- preload = (_preload = preload) != null ? _preload : router.options.defaultPreload;
2268
- const preloadDelay = (_ref9 = userPreloadDelay != null ? userPreloadDelay : router.options.defaultPreloadDelay) != null ? _ref9 : 0; // Compare path/hash for matches
2269
-
2270
- const pathIsEqual = router.state.location.pathname === next.pathname;
2271
- const currentPathSplit = router.state.location.pathname.split('/');
2272
- const nextPathSplit = next.pathname.split('/');
2273
- const pathIsFuzzyEqual = nextPathSplit.every((d, i) => d === currentPathSplit[i]);
2274
- const hashIsEqual = router.state.location.hash === next.hash; // Combine the matches based on user options
2275
-
2276
- const pathTest = activeOptions != null && activeOptions.exact ? pathIsEqual : pathIsFuzzyEqual;
2277
- const hashTest = activeOptions != null && activeOptions.includeHash ? hashIsEqual : true; // The final "active" test
2278
-
2279
- const isActive = pathTest && hashTest; // The click handler
2280
-
2281
- const handleClick = e => {
2282
- if (!disabled && !isCtrlEvent(e) && !e.defaultPrevented && (!target || target === '_self') && e.button === 0) {
2283
- e.preventDefault();
2284
-
2285
- if (pathIsEqual && !search && !hash) {
2286
- router.invalidateRoute(nextOpts);
2287
- } // All is well? Navigate!)
2288
-
2289
-
2290
- router.__.navigate(nextOpts);
2291
- }
2292
- }; // The click handler
2293
-
1022
+ return routeMatch;
1023
+ });
2294
1024
 
2295
- const handleFocus = e => {
2296
- if (preload) {
2297
- router.preloadRoute(nextOpts, {
2298
- maxAge: userPreloadMaxAge,
2299
- gcMaxAge: userPreloadGcMaxAge
1025
+ // Take each match and resolve its search params and context
1026
+ // This has to happen after the matches are created or found
1027
+ // so that we can use the parent match's search params and context
1028
+ matches.forEach((match, i) => {
1029
+ const parentMatch = matches[i - 1];
1030
+ const route = looseRoutesById[match.routeId];
1031
+ const searchInfo = (() => {
1032
+ // Validate the search params and stabilize them
1033
+ const parentSearchInfo = {
1034
+ search: parentMatch?.search ?? locationSearch,
1035
+ routeSearch: parentMatch?.routeSearch ?? locationSearch
1036
+ };
1037
+ try {
1038
+ const validator = typeof route.options.validateSearch === 'object' ? route.options.validateSearch.parse : route.options.validateSearch;
1039
+ let routeSearch = validator?.(parentSearchInfo.search) ?? {};
1040
+ let search = {
1041
+ ...parentSearchInfo.search,
1042
+ ...routeSearch
1043
+ };
1044
+ routeSearch = replaceEqualDeep(match.routeSearch, routeSearch);
1045
+ search = replaceEqualDeep(match.search, search);
1046
+ return {
1047
+ routeSearch,
1048
+ search,
1049
+ searchDidChange: match.routeSearch !== routeSearch
1050
+ };
1051
+ } catch (err) {
1052
+ match.searchError = new SearchParamError(err.message, {
1053
+ cause: err
2300
1054
  });
2301
- }
2302
- };
2303
-
2304
- const handleEnter = e => {
2305
- const target = e.target || {};
2306
-
2307
- if (preload) {
2308
- if (target.preloadTimeout) {
2309
- return;
1055
+ if (opts?.throwOnError) {
1056
+ throw match.searchError;
2310
1057
  }
2311
-
2312
- target.preloadTimeout = setTimeout(() => {
2313
- target.preloadTimeout = null;
2314
- router.preloadRoute(nextOpts, {
2315
- maxAge: userPreloadMaxAge,
2316
- gcMaxAge: userPreloadGcMaxAge
2317
- });
2318
- }, preloadDelay);
2319
- }
2320
- };
2321
-
2322
- const handleLeave = e => {
2323
- const target = e.target || {};
2324
-
2325
- if (target.preloadTimeout) {
2326
- clearTimeout(target.preloadTimeout);
2327
- target.preloadTimeout = null;
1058
+ return parentSearchInfo;
2328
1059
  }
1060
+ })();
1061
+ Object.assign(match, searchInfo);
1062
+ });
1063
+ return matches;
1064
+ });
1065
+ const cancelMatch = useStableCallback(id => {
1066
+ getRouteMatch(state, id)?.abortController?.abort();
1067
+ });
1068
+ const cancelMatches = useStableCallback(state => {
1069
+ state.matches.forEach(match => {
1070
+ cancelMatch(match.id);
1071
+ });
1072
+ });
1073
+ const buildLocation = useStableCallback(opts => {
1074
+ const build = (dest = {}, matches) => {
1075
+ const from = latestLocationRef.current;
1076
+ const fromPathname = dest.from ?? from.pathname;
1077
+ let pathname = resolvePathWithBase(fromPathname, `${dest.to ?? ''}`);
1078
+ const fromMatches = matchRoutes(fromPathname, from.search);
1079
+ const stayingMatches = matches?.filter(d => fromMatches?.find(e => e.routeId === d.routeId));
1080
+ const prevParams = {
1081
+ ...last(fromMatches)?.params
2329
1082
  };
2330
-
1083
+ let nextParams = (dest.params ?? true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
1084
+ if (nextParams) {
1085
+ matches?.map(d => looseRoutesById[d.routeId].options.stringifyParams).filter(Boolean).forEach(fn => {
1086
+ nextParams = {
1087
+ ...nextParams,
1088
+ ...fn(nextParams)
1089
+ };
1090
+ });
1091
+ }
1092
+ pathname = interpolatePath(pathname, nextParams ?? {});
1093
+ const preSearchFilters = stayingMatches?.map(match => looseRoutesById[match.routeId].options.preSearchFilters ?? []).flat().filter(Boolean) ?? [];
1094
+ const postSearchFilters = stayingMatches?.map(match => looseRoutesById[match.routeId].options.postSearchFilters ?? []).flat().filter(Boolean) ?? [];
1095
+
1096
+ // Pre filters first
1097
+ const preFilteredSearch = preSearchFilters?.length ? preSearchFilters?.reduce((prev, next) => next(prev), from.search) : from.search;
1098
+
1099
+ // Then the link/navigate function
1100
+ const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
1101
+ : dest.search ? functionalUpdate(dest.search, preFilteredSearch) ?? {} // Updater
1102
+ : preSearchFilters?.length ? preFilteredSearch // Preserve resolvedFrom filters
1103
+ : {};
1104
+
1105
+ // Then post filters
1106
+ const postFilteredSearch = postSearchFilters?.length ? postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
1107
+ const search = replaceEqualDeep(from.search, postFilteredSearch);
1108
+ const searchStr = options.stringifySearch(search);
1109
+ const hash = dest.hash === true ? from.hash : dest.hash ? functionalUpdate(dest.hash, from.hash) : from.hash;
1110
+ const hashStr = hash ? `#${hash}` : '';
1111
+ let nextState = dest.state === true ? from.state : dest.state ? functionalUpdate(dest.state, from.state) : from.state;
1112
+ nextState = replaceEqualDeep(from.state, nextState);
2331
1113
  return {
2332
- type: 'internal',
2333
- next,
2334
- handleFocus,
2335
- handleClick,
2336
- handleEnter,
2337
- handleLeave,
2338
- isActive,
2339
- disabled
1114
+ pathname,
1115
+ search,
1116
+ searchStr,
1117
+ state: nextState,
1118
+ hash,
1119
+ href: history.createHref(`${pathname}${searchStr}${hashStr}`),
1120
+ unmaskOnReload: dest.unmaskOnReload
2340
1121
  };
2341
- },
2342
- buildNext: opts => {
2343
- const next = router.__.buildLocation(opts);
2344
-
2345
- const matches = router.matchRoutes(next.pathname);
2346
-
2347
- const __preSearchFilters = matches.map(match => {
2348
- var _match$options$preSea;
2349
-
2350
- return (_match$options$preSea = match.options.preSearchFilters) != null ? _match$options$preSea : [];
2351
- }).flat().filter(Boolean);
2352
-
2353
- const __postSearchFilters = matches.map(match => {
2354
- var _match$options$postSe;
2355
-
2356
- return (_match$options$postSe = match.options.postSearchFilters) != null ? _match$options$postSe : [];
2357
- }).flat().filter(Boolean);
2358
-
2359
- return router.__.buildLocation(_extends({}, opts, {
2360
- __preSearchFilters,
2361
- __postSearchFilters
2362
- }));
2363
- },
2364
- __: {
2365
- buildRouteTree: rootRouteConfig => {
2366
- const recurseRoutes = (routeConfigs, parent) => {
2367
- return routeConfigs.map(routeConfig => {
2368
- const routeOptions = routeConfig.options;
2369
- const route = createRoute(routeConfig, routeOptions, parent, router);
2370
- const existingRoute = router.routesById[route.routeId];
2371
-
2372
- if (existingRoute) {
2373
- if (process.env.NODE_ENV !== 'production') {
2374
- console.warn("Duplicate routes found with id: " + String(route.routeId), router.routesById, route);
1122
+ };
1123
+ const buildWithMatches = (dest = {}, maskedDest) => {
1124
+ let next = build(dest);
1125
+ let maskedNext = maskedDest ? build(maskedDest) : undefined;
1126
+ if (!maskedNext) {
1127
+ let params = {};
1128
+ let foundMask = options.routeMasks?.find(d => {
1129
+ const match = matchPathname(basepath, next.pathname, {
1130
+ to: d.from,
1131
+ caseSensitive: false,
1132
+ fuzzy: false
1133
+ });
1134
+ if (match) {
1135
+ params = match;
1136
+ return true;
1137
+ }
1138
+ return false;
1139
+ });
1140
+ if (foundMask) {
1141
+ foundMask = {
1142
+ ...foundMask,
1143
+ from: interpolatePath(foundMask.from, params)
1144
+ };
1145
+ maskedDest = foundMask;
1146
+ maskedNext = build(maskedDest);
1147
+ }
1148
+ }
1149
+ const nextMatches = matchRoutes(next.pathname, next.search);
1150
+ const maskedMatches = maskedNext ? matchRoutes(maskedNext.pathname, maskedNext.search) : undefined;
1151
+ const maskedFinal = maskedNext ? build(maskedDest, maskedMatches) : undefined;
1152
+ const final = build(dest, nextMatches);
1153
+ if (maskedFinal) {
1154
+ final.maskedLocation = maskedFinal;
1155
+ }
1156
+ return final;
1157
+ };
1158
+ if (opts.mask) {
1159
+ return buildWithMatches(opts, {
1160
+ ...pick(opts, ['from']),
1161
+ ...opts.mask
1162
+ });
1163
+ }
1164
+ return buildWithMatches(opts);
1165
+ });
1166
+ const commitLocation = useStableCallback(async ({
1167
+ startTransition,
1168
+ ...next
1169
+ }) => {
1170
+ if (navigateTimeoutRef.current) clearTimeout(navigateTimeoutRef.current);
1171
+ const isSameUrl = latestLocationRef.current.href === next.href;
1172
+
1173
+ // If the next urls are the same and we're not replacing,
1174
+ // do nothing
1175
+ if (!isSameUrl || !next.replace) {
1176
+ let {
1177
+ maskedLocation,
1178
+ ...nextHistory
1179
+ } = next;
1180
+ if (maskedLocation) {
1181
+ nextHistory = {
1182
+ ...maskedLocation,
1183
+ state: {
1184
+ ...maskedLocation.state,
1185
+ __tempKey: undefined,
1186
+ __tempLocation: {
1187
+ ...nextHistory,
1188
+ search: nextHistory.searchStr,
1189
+ state: {
1190
+ ...nextHistory.state,
1191
+ __tempKey: undefined,
1192
+ __tempLocation: undefined,
1193
+ key: undefined
2375
1194
  }
2376
-
2377
- throw new Error();
2378
1195
  }
2379
- router.routesById[route.routeId] = route;
2380
- const children = routeConfig.children;
2381
- route.childRoutes = children != null && children.length ? recurseRoutes(children, route) : undefined;
2382
- return route;
2383
- });
1196
+ }
2384
1197
  };
2385
-
2386
- const routes = recurseRoutes([rootRouteConfig]);
2387
- return routes[0];
2388
- },
2389
- parseLocation: (location, previousLocation) => {
2390
- var _location$hash$split$;
2391
-
2392
- const parsedSearch = router.options.parseSearch(location.search);
2393
- return {
2394
- pathname: location.pathname,
2395
- searchStr: location.search,
2396
- search: replaceEqualDeep(previousLocation == null ? void 0 : previousLocation.search, parsedSearch),
2397
- hash: (_location$hash$split$ = location.hash.split('#').reverse()[0]) != null ? _location$hash$split$ : '',
2398
- href: "" + location.pathname + location.search + location.hash,
2399
- state: location.state,
2400
- key: location.key
1198
+ if (nextHistory.unmaskOnReload ?? options.unmaskOnReload ?? false) {
1199
+ nextHistory.state.__tempKey = tempLocationKeyRef.current;
1200
+ }
1201
+ }
1202
+ const apply = () => {
1203
+ history[next.replace ? 'replace' : 'push'](nextHistory.href, nextHistory.state);
1204
+ };
1205
+ if (startTransition ?? true) {
1206
+ startReactTransition(apply);
1207
+ } else {
1208
+ apply();
1209
+ }
1210
+ }
1211
+ resetNextScrollRef.current = next.resetScroll ?? true;
1212
+ return latestLoadPromiseRef.current;
1213
+ });
1214
+ const buildAndCommitLocation = useStableCallback(({
1215
+ replace,
1216
+ resetScroll,
1217
+ startTransition,
1218
+ ...rest
1219
+ } = {}) => {
1220
+ const location = buildLocation(rest);
1221
+ return commitLocation({
1222
+ ...location,
1223
+ startTransition,
1224
+ replace,
1225
+ resetScroll
1226
+ });
1227
+ });
1228
+ const navigate = useStableCallback(({
1229
+ from,
1230
+ to = '',
1231
+ ...rest
1232
+ }) => {
1233
+ // If this link simply reloads the current route,
1234
+ // make sure it has a new key so it will trigger a data refresh
1235
+
1236
+ // If this `to` is a valid external URL, return
1237
+ // null for LinkUtils
1238
+ const toString = String(to);
1239
+ const fromString = typeof from === 'undefined' ? from : String(from);
1240
+ let isExternal;
1241
+ try {
1242
+ new URL(`${toString}`);
1243
+ isExternal = true;
1244
+ } catch (e) {}
1245
+ invariant(!isExternal, 'Attempting to navigate to external url with this.navigate!');
1246
+ return buildAndCommitLocation({
1247
+ ...rest,
1248
+ from: fromString,
1249
+ to: toString
1250
+ });
1251
+ });
1252
+ const loadMatches = useStableCallback(async ({
1253
+ checkLatest,
1254
+ matches,
1255
+ preload
1256
+ }) => {
1257
+ let latestPromise;
1258
+ let firstBadMatchIndex;
1259
+
1260
+ // Check each match middleware to see if the route can be accessed
1261
+ try {
1262
+ for (let [index, match] of matches.entries()) {
1263
+ const parentMatch = matches[index - 1];
1264
+ const route = looseRoutesById[match.routeId];
1265
+ const handleError = (err, code) => {
1266
+ err.routerCode = code;
1267
+ firstBadMatchIndex = firstBadMatchIndex ?? index;
1268
+ if (isRedirect(err)) {
1269
+ throw err;
1270
+ }
1271
+ try {
1272
+ route.options.onError?.(err);
1273
+ } catch (errorHandlerErr) {
1274
+ err = errorHandlerErr;
1275
+ if (isRedirect(errorHandlerErr)) {
1276
+ throw errorHandlerErr;
1277
+ }
1278
+ }
1279
+ matches[index] = match = {
1280
+ ...match,
1281
+ error: err,
1282
+ status: 'error',
1283
+ updatedAt: Date.now()
1284
+ };
2401
1285
  };
2402
- },
2403
- navigate: location => {
2404
- const next = router.buildNext(location);
2405
- return router.__.commitLocation(next, location.replace);
2406
- },
2407
- buildLocation: function buildLocation(dest) {
2408
- var _dest$from, _router$basepath, _dest$to, _last, _dest$params, _dest$__preSearchFilt, _functionalUpdate, _dest$__preSearchFilt2, _dest$__postSearchFil;
2409
-
2410
- if (dest === void 0) {
2411
- dest = {};
1286
+ try {
1287
+ if (match.paramsError) {
1288
+ handleError(match.paramsError, 'PARSE_PARAMS');
1289
+ }
1290
+ if (match.searchError) {
1291
+ handleError(match.searchError, 'VALIDATE_SEARCH');
1292
+ }
1293
+ const parentContext = parentMatch?.context ?? options.context ?? {};
1294
+ const beforeLoadContext = (await route.options.beforeLoad?.({
1295
+ search: match.search,
1296
+ abortController: match.abortController,
1297
+ params: match.params,
1298
+ preload: !!preload,
1299
+ context: parentContext,
1300
+ location: state.location,
1301
+ // TODO: This might need to be latestLocationRef.current...?
1302
+ navigate: opts => navigate({
1303
+ ...opts,
1304
+ from: match.pathname
1305
+ }),
1306
+ buildLocation
1307
+ })) ?? {};
1308
+ const context = {
1309
+ ...parentContext,
1310
+ ...beforeLoadContext
1311
+ };
1312
+ matches[index] = match = {
1313
+ ...match,
1314
+ context: replaceEqualDeep(match.context, context)
1315
+ };
1316
+ } catch (err) {
1317
+ handleError(err, 'BEFORE_LOAD');
1318
+ break;
2412
1319
  }
1320
+ }
1321
+ } catch (err) {
1322
+ if (isRedirect(err)) {
1323
+ if (!preload) navigate(err);
1324
+ return matches;
1325
+ }
1326
+ throw err;
1327
+ }
1328
+ const validResolvedMatches = matches.slice(0, firstBadMatchIndex);
1329
+ const matchPromises = [];
1330
+ validResolvedMatches.forEach((match, index) => {
1331
+ matchPromises.push((async () => {
1332
+ const parentMatchPromise = matchPromises[index - 1];
1333
+ const route = looseRoutesById[match.routeId];
1334
+ if (match.isFetching) {
1335
+ return getRouteMatch(state, match.id)?.loadPromise;
1336
+ }
1337
+ const handleIfRedirect = err => {
1338
+ if (isRedirect(err)) {
1339
+ if (!preload) {
1340
+ navigate(err);
1341
+ }
1342
+ return true;
1343
+ }
1344
+ return false;
1345
+ };
1346
+ const load = async () => {
1347
+ try {
1348
+ const componentsPromise = Promise.all(componentTypes.map(async type => {
1349
+ const component = route.options[type];
1350
+ if (component?.preload) {
1351
+ await component.preload();
1352
+ }
1353
+ }));
1354
+ const loaderPromise = route.options.load?.({
1355
+ params: match.params,
1356
+ search: match.search,
1357
+ preload: !!preload,
1358
+ parentMatchPromise,
1359
+ abortController: match.abortController,
1360
+ context: match.context,
1361
+ location: state.location,
1362
+ navigate: opts => navigate({
1363
+ ...opts,
1364
+ from: match.pathname
1365
+ })
1366
+ });
1367
+ const [_, loaderContext] = await Promise.all([componentsPromise, loaderPromise]);
1368
+ if (latestPromise = checkLatest()) return await latestPromise;
1369
+ matches[index] = match = {
1370
+ ...match,
1371
+ error: undefined,
1372
+ status: 'success',
1373
+ isFetching: false,
1374
+ updatedAt: Date.now()
1375
+ };
1376
+ } catch (error) {
1377
+ if (latestPromise = checkLatest()) return await latestPromise;
1378
+ if (handleIfRedirect(error)) return;
1379
+ try {
1380
+ route.options.onError?.(error);
1381
+ } catch (onErrorError) {
1382
+ error = onErrorError;
1383
+ if (handleIfRedirect(onErrorError)) return;
1384
+ }
1385
+ matches[index] = match = {
1386
+ ...match,
1387
+ error,
1388
+ status: 'error',
1389
+ isFetching: false,
1390
+ updatedAt: Date.now()
1391
+ };
1392
+ }
1393
+ if (!preload) {
1394
+ setState(s => ({
1395
+ ...s,
1396
+ matches: s.matches.map(d => d.id === match.id ? match : d)
1397
+ }));
1398
+ }
1399
+ };
1400
+ let loadPromise;
1401
+ matches[index] = match = {
1402
+ ...match,
1403
+ isFetching: true,
1404
+ fetchedAt: Date.now(),
1405
+ invalid: false
1406
+ };
1407
+ loadPromise = load();
1408
+ matches[index] = match = {
1409
+ ...match,
1410
+ loadPromise
1411
+ };
1412
+ await loadPromise;
1413
+ })());
1414
+ });
1415
+ await Promise.all(matchPromises);
1416
+ return matches;
1417
+ });
1418
+ const load = useStableCallback(async () => {
1419
+ const promise = new Promise(async (resolve, reject) => {
1420
+ const next = latestLocationRef.current;
1421
+ const prevLocation = state.resolvedLocation || state.location;
1422
+ const pathDidChange = !!(next && prevLocation.href !== next.href);
1423
+ let latestPromise;
1424
+
1425
+ // Cancel any pending matches
1426
+ cancelMatches(state);
1427
+ router.emit({
1428
+ type: 'onBeforeLoad',
1429
+ from: prevLocation,
1430
+ to: next ?? state.location,
1431
+ pathChanged: pathDidChange
1432
+ });
2413
1433
 
2414
- // const resolvedFrom: Location = {
2415
- // ...router.location,
2416
- const fromPathname = dest.fromCurrent ? router.location.pathname : (_dest$from = dest.from) != null ? _dest$from : router.location.pathname;
2417
-
2418
- let pathname = resolvePath((_router$basepath = router.basepath) != null ? _router$basepath : '/', fromPathname, "" + ((_dest$to = dest.to) != null ? _dest$to : '.'));
2419
-
2420
- const fromMatches = router.matchRoutes(router.location.pathname, {
2421
- strictParseParams: true
2422
- });
2423
- const toMatches = router.matchRoutes(pathname);
2424
-
2425
- const prevParams = _extends({}, (_last = last(fromMatches)) == null ? void 0 : _last.params);
2426
-
2427
- let nextParams = ((_dest$params = dest.params) != null ? _dest$params : true) === true ? prevParams : functionalUpdate(dest.params, prevParams);
1434
+ // Match the routes
1435
+ let matches = matchRoutes(next.pathname, next.search, {
1436
+ debug: true
1437
+ });
2428
1438
 
2429
- if (nextParams) {
2430
- toMatches.map(d => d.options.stringifyParams).filter(Boolean).forEach(fn => {
2431
- Object.assign({}, nextParams, fn(nextParams));
1439
+ // Ingest the new matches
1440
+ setState(s => ({
1441
+ ...s,
1442
+ matches
1443
+ }));
1444
+ try {
1445
+ try {
1446
+ // Load the matches
1447
+ await loadMatches({
1448
+ matches,
1449
+ checkLatest: () => checkLatest(promise)
2432
1450
  });
1451
+ } catch (err) {
1452
+ // swallow this error, since we'll display the
1453
+ // errors on the route components
2433
1454
  }
2434
1455
 
2435
- pathname = interpolatePath(pathname, nextParams != null ? nextParams : {}); // Pre filters first
2436
-
2437
- 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
2438
-
2439
- const destSearch = dest.search === true ? preFilteredSearch // Preserve resolvedFrom true
2440
- : dest.search ? (_functionalUpdate = functionalUpdate(dest.search, preFilteredSearch)) != null ? _functionalUpdate : {} // Updater
2441
- : (_dest$__preSearchFilt2 = dest.__preSearchFilters) != null && _dest$__preSearchFilt2.length ? preFilteredSearch // Preserve resolvedFrom filters
2442
- : {}; // Then post filters
2443
-
2444
- const postFilteredSearch = (_dest$__postSearchFil = dest.__postSearchFilters) != null && _dest$__postSearchFil.length ? dest.__postSearchFilters.reduce((prev, next) => next(prev), destSearch) : destSearch;
2445
- const search = replaceEqualDeep(router.location.search, postFilteredSearch);
2446
- const searchStr = router.options.stringifySearch(search);
2447
- let hash = dest.hash === true ? router.location.hash : functionalUpdate(dest.hash, router.location.hash);
2448
- hash = hash ? "#" + hash : '';
2449
- return {
2450
- pathname,
2451
- search,
2452
- searchStr,
2453
- state: router.location.state,
2454
- hash,
2455
- href: "" + pathname + searchStr + hash,
2456
- key: dest.key
2457
- };
2458
- },
2459
- commitLocation: (next, replace) => {
2460
- const id = '' + Date.now() + Math.random();
2461
- if (router.navigateTimeout) clearTimeout(router.navigateTimeout);
2462
- let nextAction = 'replace';
2463
-
2464
- if (!replace) {
2465
- nextAction = 'push';
1456
+ // Only apply the latest transition
1457
+ if (latestPromise = checkLatest(promise)) {
1458
+ return latestPromise;
2466
1459
  }
2467
1460
 
2468
- const isSameUrl = router.__.parseLocation(history.location).href === next.href;
2469
-
2470
- if (isSameUrl && !next.key) {
2471
- nextAction = 'replace';
1461
+ // TODO:
1462
+ // const exitingMatchIds = previousMatches.filter(
1463
+ // (id) => !state.pendingMatches.includes(id),
1464
+ // )
1465
+ // const enteringMatchIds = state.pendingMatches.filter(
1466
+ // (id) => !previousMatches.includes(id),
1467
+ // )
1468
+ // const stayingMatchIds = previousMatches.filter((id) =>
1469
+ // state.pendingMatches.includes(id),
1470
+ // )
1471
+
1472
+ // setState((s) => ({
1473
+ // ...s,
1474
+ // status: 'idle',
1475
+ // resolvedLocation: s.location,
1476
+ // }))
1477
+
1478
+ // TODO:
1479
+ // ;(
1480
+ // [
1481
+ // [exitingMatchIds, 'onLeave'],
1482
+ // [enteringMatchIds, 'onEnter'],
1483
+ // [stayingMatchIds, 'onTransition'],
1484
+ // ] as const
1485
+ // ).forEach(([matches, hook]) => {
1486
+ // matches.forEach((match) => {
1487
+ // const route = this.getRoute(match.routeId)
1488
+ // route.options[hook]?.(match)
1489
+ // })
1490
+ // })
1491
+ router.emit({
1492
+ type: 'onLoad',
1493
+ from: prevLocation,
1494
+ to: next,
1495
+ pathChanged: pathDidChange
1496
+ });
1497
+ resolve();
1498
+ } catch (err) {
1499
+ // Only apply the latest transition
1500
+ if (latestPromise = checkLatest(promise)) {
1501
+ return latestPromise;
2472
1502
  }
1503
+ reject(err);
1504
+ }
1505
+ });
1506
+ latestLoadPromiseRef.current = promise;
1507
+ return latestLoadPromiseRef.current;
1508
+ });
1509
+ const preloadRoute = useStableCallback(async (navigateOpts = state.location) => {
1510
+ let next = buildLocation(navigateOpts);
1511
+ let matches = matchRoutes(next.pathname, next.search, {
1512
+ throwOnError: true
1513
+ });
1514
+ await loadMatches({
1515
+ matches,
1516
+ preload: true,
1517
+ checkLatest: () => undefined
1518
+ });
1519
+ return [last(matches), matches];
1520
+ });
1521
+ const buildLink = useStableCallback(dest => {
1522
+ // If this link simply reloads the current route,
1523
+ // make sure it has a new key so it will trigger a data refresh
1524
+
1525
+ // If this `to` is a valid external URL, return
1526
+ // null for LinkUtils
1527
+
1528
+ const {
1529
+ to,
1530
+ preload: userPreload,
1531
+ preloadDelay: userPreloadDelay,
1532
+ activeOptions,
1533
+ disabled,
1534
+ target,
1535
+ replace,
1536
+ resetScroll,
1537
+ startTransition
1538
+ } = dest;
1539
+ try {
1540
+ new URL(`${to}`);
1541
+ return {
1542
+ type: 'external',
1543
+ href: to
1544
+ };
1545
+ } catch (e) {}
1546
+ const nextOpts = dest;
1547
+ const next = buildLocation(nextOpts);
1548
+ const preload = userPreload ?? options.defaultPreload;
1549
+ const preloadDelay = userPreloadDelay ?? options.defaultPreloadDelay ?? 0;
1550
+
1551
+ // Compare path/hash for matches
1552
+ const currentPathSplit = latestLocationRef.current.pathname.split('/');
1553
+ const nextPathSplit = next.pathname.split('/');
1554
+ const pathIsFuzzyEqual = nextPathSplit.every((d, i) => d === currentPathSplit[i]);
1555
+ // Combine the matches based on user options
1556
+ const pathTest = activeOptions?.exact ? latestLocationRef.current.pathname === next.pathname : pathIsFuzzyEqual;
1557
+ const hashTest = activeOptions?.includeHash ? latestLocationRef.current.hash === next.hash : true;
1558
+ const searchTest = activeOptions?.includeSearch ?? true ? partialDeepEqual(latestLocationRef.current.search, next.search) : true;
1559
+
1560
+ // The final "active" test
1561
+ const isActive = pathTest && hashTest && searchTest;
1562
+
1563
+ // The click handler
1564
+ const handleClick = e => {
1565
+ if (!disabled && !isCtrlEvent(e) && !e.defaultPrevented && (!target || target === '_self') && e.button === 0) {
1566
+ e.preventDefault();
1567
+
1568
+ // All is well? Navigate!
1569
+ commitLocation({
1570
+ ...next,
1571
+ replace,
1572
+ resetScroll,
1573
+ startTransition
1574
+ });
1575
+ }
1576
+ };
2473
1577
 
2474
- if (nextAction === 'replace') {
2475
- history.replace({
2476
- pathname: next.pathname,
2477
- hash: next.hash,
2478
- search: next.searchStr
2479
- }, _extends({
2480
- id
2481
- }, next.state));
2482
- } else {
2483
- history.push({
2484
- pathname: next.pathname,
2485
- hash: next.hash,
2486
- search: next.searchStr
2487
- }, {
2488
- id
1578
+ // The click handler
1579
+ const handleFocus = e => {
1580
+ if (preload) {
1581
+ preloadRoute(nextOpts).catch(err => {
1582
+ console.warn(err);
1583
+ console.warn(preloadWarning);
1584
+ });
1585
+ }
1586
+ };
1587
+ const handleTouchStart = e => {
1588
+ preloadRoute(nextOpts).catch(err => {
1589
+ console.warn(err);
1590
+ console.warn(preloadWarning);
1591
+ });
1592
+ };
1593
+ const handleEnter = e => {
1594
+ const target = e.target || {};
1595
+ if (preload) {
1596
+ if (target.preloadTimeout) {
1597
+ return;
1598
+ }
1599
+ target.preloadTimeout = setTimeout(() => {
1600
+ target.preloadTimeout = null;
1601
+ preloadRoute(nextOpts).catch(err => {
1602
+ console.warn(err);
1603
+ console.warn(preloadWarning);
2489
1604
  });
1605
+ }, preloadDelay);
1606
+ }
1607
+ };
1608
+ const handleLeave = e => {
1609
+ const target = e.target || {};
1610
+ if (target.preloadTimeout) {
1611
+ clearTimeout(target.preloadTimeout);
1612
+ target.preloadTimeout = null;
1613
+ }
1614
+ };
1615
+ return {
1616
+ type: 'internal',
1617
+ next,
1618
+ handleFocus,
1619
+ handleClick,
1620
+ handleEnter,
1621
+ handleLeave,
1622
+ handleTouchStart,
1623
+ isActive,
1624
+ disabled
1625
+ };
1626
+ });
1627
+ const latestLocationRef = React.useRef(state.location);
1628
+ React.useLayoutEffect(() => {
1629
+ const unsub = history.subscribe(() => {
1630
+ latestLocationRef.current = parseLocation(latestLocationRef.current);
1631
+ setState(s => ({
1632
+ ...s,
1633
+ status: 'pending'
1634
+ }));
1635
+ if (state.location !== latestLocationRef.current) {
1636
+ try {
1637
+ load();
1638
+ } catch (err) {
1639
+ console.error(err);
2490
1640
  }
1641
+ }
1642
+ });
1643
+ const nextLocation = buildLocation({
1644
+ search: true,
1645
+ params: true,
1646
+ hash: true,
1647
+ state: true
1648
+ });
1649
+ if (state.location.href !== nextLocation.href) {
1650
+ commitLocation({
1651
+ ...nextLocation,
1652
+ replace: true
1653
+ });
1654
+ }
1655
+ return () => {
1656
+ unsub();
1657
+ };
1658
+ }, [history]);
1659
+ const initialLoad = React.useRef(true);
1660
+ if (initialLoad.current) {
1661
+ initialLoad.current = false;
1662
+ startReactTransition(() => {
1663
+ try {
1664
+ load();
1665
+ } catch (err) {
1666
+ console.error(err);
1667
+ }
1668
+ });
1669
+ }
1670
+ const matchRoute = useStableCallback((location, opts) => {
1671
+ location = {
1672
+ ...location,
1673
+ to: location.to ? resolvePathWithBase(location.from || '', location.to) : undefined
1674
+ };
1675
+ const next = buildLocation(location);
1676
+ if (opts?.pending && state.status !== 'pending') {
1677
+ return false;
1678
+ }
1679
+ const baseLocation = opts?.pending ? latestLocationRef.current : state.resolvedLocation;
2491
1680
 
2492
- router.navigationPromise = new Promise(resolve => {
2493
- const previousNavigationResolve = router.resolveNavigation;
1681
+ // const baseLocation = state.resolvedLocation
2494
1682
 
2495
- router.resolveNavigation = () => {
2496
- previousNavigationResolve();
2497
- resolve();
2498
- };
2499
- });
2500
- return router.navigationPromise;
2501
- }
1683
+ if (!baseLocation) {
1684
+ return false;
1685
+ }
1686
+ const match = matchPathname(basepath, baseLocation.pathname, {
1687
+ ...opts,
1688
+ to: next.pathname
1689
+ });
1690
+ if (!match) {
1691
+ return false;
1692
+ }
1693
+ if (match && (opts?.includeSearch ?? true)) {
1694
+ return partialDeepEqual(baseLocation.search, next.search) ? match : false;
2502
1695
  }
1696
+ return match;
1697
+ });
1698
+ const routerContextValue = {
1699
+ routeTree: router.routeTree,
1700
+ navigate,
1701
+ buildLink,
1702
+ state,
1703
+ matchRoute,
1704
+ routesById,
1705
+ options,
1706
+ history,
1707
+ load,
1708
+ buildLocation
2503
1709
  };
2504
- router.update(userOptions); // Allow frameworks to hook into the router creation
2505
-
2506
- router.options.createRouter == null ? void 0 : router.options.createRouter(router);
2507
- return router;
1710
+ return /*#__PURE__*/React.createElement(routerContext.Provider, {
1711
+ value: routerContextValue
1712
+ }, /*#__PURE__*/React.createElement(Matches, null));
2508
1713
  }
2509
-
2510
- function isCtrlEvent(e) {
2511
- return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
1714
+ function getRouteMatch(state, id) {
1715
+ return [...state.pendingMatches, ...state.matches].find(d => d.id === id);
1716
+ }
1717
+ function useRouterState(opts) {
1718
+ const {
1719
+ state
1720
+ } = useRouter();
1721
+ // return useStore(router.__store, opts?.select as any)
1722
+ return opts?.select ? opts.select(state) : state;
1723
+ }
1724
+ function useRouter() {
1725
+ const resolvedContext = window.__TSR_ROUTER_CONTEXT__ || routerContext;
1726
+ const value = React.useContext(resolvedContext);
1727
+ warning(value, 'useRouter must be used inside a <RouterProvider> component!');
1728
+ return value;
2512
1729
  }
2513
1730
 
2514
- function cascadeLoaderData(matches) {
2515
- matches.forEach((match, index) => {
2516
- const parent = matches[index - 1];
2517
-
2518
- if (parent) {
2519
- match.loaderData = replaceEqualDeep(match.loaderData, _extends({}, parent.loaderData, match.routeLoaderData));
1731
+ function Matches() {
1732
+ const {
1733
+ routesById,
1734
+ state
1735
+ } = useRouter();
1736
+ const {
1737
+ matches
1738
+ } = state;
1739
+ const locationKey = useRouterState().location.state.key;
1740
+ const route = routesById[rootRouteId];
1741
+ const errorComponent = React.useCallback(props => {
1742
+ return /*#__PURE__*/React.createElement(ErrorComponent, {
1743
+ ...props,
1744
+ useMatch: route.useMatch,
1745
+ useRouteContext: route.useRouteContext,
1746
+ useSearch: route.useSearch,
1747
+ useParams: route.useParams
1748
+ });
1749
+ }, [route]);
1750
+ return /*#__PURE__*/React.createElement(matchesContext.Provider, {
1751
+ value: matches
1752
+ }, /*#__PURE__*/React.createElement(CatchBoundary, {
1753
+ resetKey: locationKey,
1754
+ errorComponent: errorComponent,
1755
+ onCatch: () => {
1756
+ warning(false, `Error in router! Consider setting an 'errorComponent' in your RootRoute! 👍`);
2520
1757
  }
2521
- });
1758
+ }, matches.length ? /*#__PURE__*/React.createElement(Match, {
1759
+ matches: matches
1760
+ }) : null));
2522
1761
  }
2523
-
2524
- const _excluded = ["type", "children", "target", "activeProps", "inactiveProps", "activeOptions", "disabled", "hash", "search", "params", "to", "preload", "preloadDelay", "preloadMaxAge", "replace", "style", "className", "onClick", "onFocus", "onMouseEnter", "onMouseLeave", "onTouchStart", "onTouchEnd"],
2525
- _excluded2 = ["pending", "caseSensitive", "children"],
2526
- _excluded3 = ["children", "router"];
2527
- function lazy(importer) {
2528
- const lazyComp = /*#__PURE__*/React.lazy(importer);
2529
- let promise;
2530
- let resolvedComp;
2531
- const forwardedComp = /*#__PURE__*/React.forwardRef((props, ref) => {
2532
- const resolvedCompRef = React.useRef(resolvedComp || lazyComp);
2533
- return /*#__PURE__*/React.createElement(resolvedCompRef.current, _extends$2({}, ref ? {
2534
- ref
2535
- } : {}, props));
2536
- });
2537
- const finalComp = forwardedComp;
2538
-
2539
- finalComp.preload = () => {
2540
- if (!promise) {
2541
- promise = importer().then(module => {
2542
- resolvedComp = module.default;
2543
- return resolvedComp;
1762
+ const defaultPending = () => null;
1763
+ function Match({
1764
+ matches
1765
+ }) {
1766
+ const {
1767
+ options,
1768
+ routesById
1769
+ } = useRouter();
1770
+ const match = matches[0];
1771
+ const routeId = match?.routeId;
1772
+ const route = routesById[routeId];
1773
+ const locationKey = useRouterState().location.state?.key;
1774
+ const PendingComponent = route.options.pendingComponent ?? options.defaultPendingComponent ?? defaultPending;
1775
+ const routeErrorComponent = route.options.errorComponent ?? options.defaultErrorComponent ?? ErrorComponent;
1776
+ const ResolvedSuspenseBoundary = route.options.wrapInSuspense ?? React.Suspense;
1777
+ // const ResolvedSuspenseBoundary = SafeFragment
1778
+
1779
+ const errorComponent = React.useCallback(props => {
1780
+ return /*#__PURE__*/React.createElement(routeErrorComponent, {
1781
+ ...props,
1782
+ useMatch: route.useMatch,
1783
+ useRouteContext: route.useRouteContext,
1784
+ useSearch: route.useSearch,
1785
+ useParams: route.useParams
1786
+ });
1787
+ }, [route]);
1788
+ return /*#__PURE__*/React.createElement(matchesContext.Provider, {
1789
+ value: matches
1790
+ }, /*#__PURE__*/React.createElement(ResolvedSuspenseBoundary, {
1791
+ fallback: /*#__PURE__*/React.createElement(PendingComponent, {
1792
+ useMatch: route.useMatch,
1793
+ useRouteContext: route.useRouteContext,
1794
+ useSearch: route.useSearch,
1795
+ useParams: route.useParams
1796
+ })
1797
+ }, /*#__PURE__*/React.createElement(CatchBoundary, {
1798
+ resetKey: locationKey,
1799
+ errorComponent: errorComponent,
1800
+ onCatch: () => {
1801
+ warning(false, `Error in route match: ${match.id}`);
1802
+ }
1803
+ }, /*#__PURE__*/React.createElement(MatchInner, {
1804
+ match: match
1805
+ }))));
1806
+ }
1807
+ function MatchInner({
1808
+ match
1809
+ }) {
1810
+ const {
1811
+ options,
1812
+ routesById
1813
+ } = useRouter();
1814
+ const route = routesById[match.routeId];
1815
+ if (match.status === 'error') {
1816
+ throw match.error;
1817
+ }
1818
+ if (match.status === 'pending') {
1819
+ throw match.loadPromise;
1820
+ }
1821
+ if (match.status === 'success') {
1822
+ let comp = route.options.component ?? options.defaultComponent;
1823
+ if (comp) {
1824
+ return /*#__PURE__*/React.createElement(comp, {
1825
+ useMatch: route.useMatch,
1826
+ useRouteContext: route.useRouteContext,
1827
+ useSearch: route.useSearch,
1828
+ useParams: route.useParams
2544
1829
  });
2545
1830
  }
2546
-
2547
- return promise;
2548
- };
2549
-
2550
- return finalComp;
1831
+ return /*#__PURE__*/React.createElement(Outlet, null);
1832
+ }
1833
+ invariant(false, 'Idle routeMatch status encountered during rendering! You should never see this. File an issue!');
2551
1834
  }
2552
- //
2553
- function Link(props) {
2554
- const router = useRouter();
2555
- return /*#__PURE__*/React.createElement(router.Link, props);
1835
+ function Outlet() {
1836
+ const matches = React.useContext(matchesContext).slice(1);
1837
+ if (!matches[0]) {
1838
+ return null;
1839
+ }
1840
+ return /*#__PURE__*/React.createElement(Match, {
1841
+ matches: matches
1842
+ });
1843
+ }
1844
+ function useMatchRoute() {
1845
+ const {
1846
+ matchRoute
1847
+ } = useRouter();
1848
+ return React.useCallback(opts => {
1849
+ const {
1850
+ pending,
1851
+ caseSensitive,
1852
+ ...rest
1853
+ } = opts;
1854
+ return matchRoute(rest, {
1855
+ pending,
1856
+ caseSensitive
1857
+ });
1858
+ }, []);
1859
+ }
1860
+ function MatchRoute(props) {
1861
+ const matchRoute = useMatchRoute();
1862
+ const params = matchRoute(props);
1863
+ if (typeof props.children === 'function') {
1864
+ return props.children(params);
1865
+ }
1866
+ return !!params ? props.children : null;
1867
+ }
1868
+ function useMatch(opts) {
1869
+ const nearestMatch = React.useContext(matchesContext)[0];
1870
+ const nearestMatchRouteId = nearestMatch?.routeId;
1871
+ const matchRouteId = useRouterState({
1872
+ select: state => {
1873
+ const match = opts?.from ? state.matches.find(d => d.routeId === opts?.from) : state.matches.find(d => d.id === nearestMatch.id);
1874
+ return match.routeId;
1875
+ }
1876
+ });
1877
+ if (opts?.strict ?? true) {
1878
+ 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?`);
1879
+ }
1880
+ const matchSelection = useRouterState({
1881
+ select: state => {
1882
+ const match = opts?.from ? state.matches.find(d => d.routeId === opts?.from) : state.matches.find(d => d.id === nearestMatch.id);
1883
+ invariant(match, `Could not find ${opts?.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`);
1884
+ return opts?.select ? opts.select(match) : match;
1885
+ }
1886
+ });
1887
+ return matchSelection;
2556
1888
  }
2557
1889
  const matchesContext = /*#__PURE__*/React.createContext(null);
2558
- const routerContext = /*#__PURE__*/React.createContext(null);
2559
- function MatchesProvider(props) {
2560
- return /*#__PURE__*/React.createElement(matchesContext.Provider, props);
1890
+ function useMatches(opts) {
1891
+ const contextMatches = React.useContext(matchesContext);
1892
+ return useRouterState({
1893
+ select: state => {
1894
+ const matches = state.matches.slice(state.matches.findIndex(d => d.id === contextMatches[0]?.id));
1895
+ return opts?.select ? opts.select(matches) : matches;
1896
+ }
1897
+ });
2561
1898
  }
2562
1899
 
2563
- const useRouterSubscription = router => {
2564
- useSyncExternalStore(cb => router.subscribe(() => cb()), () => router.state, () => router.state);
2565
- };
2566
-
2567
- function createReactRouter(opts) {
2568
- const makeRouteExt = (route, router) => {
2569
- return {
2570
- useRoute: function useRoute(subRouteId) {
2571
- if (subRouteId === void 0) {
2572
- subRouteId = '.';
2573
- }
2574
-
2575
- const resolvedRouteId = router.resolvePath(route.routeId, subRouteId);
2576
- const resolvedRoute = router.getRoute(resolvedRouteId);
2577
- useRouterSubscription(router);
2578
- invariant(resolvedRoute, "Could not find a route for route \"" + resolvedRouteId + "\"! Did you forget to add it to your route config?");
2579
- return resolvedRoute;
2580
- },
2581
- linkProps: options => {
2582
- var _functionalUpdate, _functionalUpdate2;
2583
-
2584
- const {
2585
- // custom props
2586
- target,
2587
- activeProps = () => ({
2588
- className: 'active'
2589
- }),
2590
- inactiveProps = () => ({}),
2591
- disabled,
2592
- // element props
2593
- style,
2594
- className,
2595
- onClick,
2596
- onFocus,
2597
- onMouseEnter,
2598
- onMouseLeave
2599
- } = options,
2600
- rest = _objectWithoutPropertiesLoose(options, _excluded);
2601
-
2602
- const linkInfo = route.buildLink(options);
2603
-
2604
- if (linkInfo.type === 'external') {
2605
- const {
2606
- href
2607
- } = linkInfo;
2608
- return {
2609
- href
2610
- };
2611
- }
1900
+ function useParams(opts) {
1901
+ return useRouterState({
1902
+ select: state => {
1903
+ const params = last(state.matches)?.params;
1904
+ return opts?.select ? opts.select(params) : params;
1905
+ }
1906
+ });
1907
+ }
2612
1908
 
2613
- const {
2614
- handleClick,
2615
- handleFocus,
2616
- handleEnter,
2617
- handleLeave,
2618
- isActive,
2619
- next
2620
- } = linkInfo;
2621
-
2622
- const reactHandleClick = e => {
2623
- React.startTransition(() => {
2624
- handleClick(e);
2625
- });
2626
- };
1909
+ function useSearch(opts) {
1910
+ return useMatch({
1911
+ ...opts,
1912
+ select: match => {
1913
+ return opts?.select ? opts.select(match.search) : match.search;
1914
+ }
1915
+ });
1916
+ }
2627
1917
 
2628
- const composeHandlers = handlers => e => {
2629
- e.persist();
2630
- handlers.forEach(handler => {
2631
- if (handler) handler(e);
2632
- });
2633
- }; // Get the active props
2634
-
2635
-
2636
- const resolvedActiveProps = isActive ? (_functionalUpdate = functionalUpdate(activeProps, {})) != null ? _functionalUpdate : {} : {}; // Get the inactive props
2637
-
2638
- const resolvedInactiveProps = isActive ? {} : (_functionalUpdate2 = functionalUpdate(inactiveProps, {})) != null ? _functionalUpdate2 : {};
2639
- return _extends$2({}, resolvedActiveProps, resolvedInactiveProps, rest, {
2640
- href: disabled ? undefined : next.href,
2641
- onClick: composeHandlers([reactHandleClick, onClick]),
2642
- onFocus: composeHandlers([handleFocus, onFocus]),
2643
- onMouseEnter: composeHandlers([handleEnter, onMouseEnter]),
2644
- onMouseLeave: composeHandlers([handleLeave, onMouseLeave]),
2645
- target,
2646
- style: _extends$2({}, style, resolvedActiveProps.style, resolvedInactiveProps.style),
2647
- className: [className, resolvedActiveProps.className, resolvedInactiveProps.className].filter(Boolean).join(' ') || undefined
2648
- }, disabled ? {
2649
- role: 'link',
2650
- 'aria-disabled': true
2651
- } : undefined, {
2652
- ['data-status']: isActive ? 'active' : undefined
2653
- });
2654
- },
2655
- Link: /*#__PURE__*/React.forwardRef((props, ref) => {
2656
- const linkProps = route.linkProps(props);
2657
- useRouterSubscription(router);
2658
- return /*#__PURE__*/React.createElement("a", _extends$2({
2659
- ref: ref
2660
- }, linkProps, {
2661
- children: typeof props.children === 'function' ? props.children({
2662
- isActive: linkProps['data-status'] === 'active'
2663
- }) : props.children
2664
- }));
2665
- }),
2666
- MatchRoute: opts => {
2667
- const {
2668
- pending,
2669
- caseSensitive
2670
- } = opts,
2671
- rest = _objectWithoutPropertiesLoose(opts, _excluded2);
2672
-
2673
- const params = route.matchRoute(rest, {
2674
- pending,
2675
- caseSensitive
2676
- });
1918
+ const rootRouteId = '__root__';
2677
1919
 
2678
- if (!params) {
2679
- return null;
2680
- }
1920
+ // The parse type here allows a zod schema to be passed directly to the validator
2681
1921
 
2682
- return typeof opts.children === 'function' ? opts.children(params) : opts.children;
2683
- }
2684
- };
2685
- };
1922
+ class Route {
1923
+ // Set up in this.init()
2686
1924
 
2687
- const coreRouter = createRouter(_extends$2({}, opts, {
2688
- createRouter: router => {
2689
- const routerExt = {
2690
- useState: () => {
2691
- useRouterSubscription(router);
2692
- return router.state;
2693
- },
2694
- useMatch: (routeId, opts) => {
2695
- var _useMatches, _opts$strict;
2696
-
2697
- useRouterSubscription(router);
2698
- invariant(routeId !== rootRouteId, "\"" + rootRouteId + "\" cannot be used with useMatch! Did you mean to useRoute(\"" + rootRouteId + "\")?");
2699
- const runtimeMatch = (_useMatches = useMatches()) == null ? void 0 : _useMatches[0];
2700
- const match = router.state.matches.find(d => d.routeId === routeId);
2701
-
2702
- if ((_opts$strict = opts == null ? void 0 : opts.strict) != null ? _opts$strict : true) {
2703
- invariant(match, "Could not find an active match for \"" + routeId + "\"!");
2704
- invariant(runtimeMatch.routeId == (match == null ? void 0 : match.routeId), "useMatch(\"" + (match == null ? void 0 : match.routeId) + "\") is being called in a component that is meant to render the '" + runtimeMatch.routeId + "' route. Did you mean to 'useMatch(\"" + (match == null ? void 0 : match.routeId) + "\", { strict: false })' or 'useRoute(\"" + (match == null ? void 0 : match.routeId) + "\")' instead?");
2705
- }
1925
+ // customId!: TCustomId
2706
1926
 
2707
- return match;
2708
- }
2709
- };
2710
- const routeExt = makeRouteExt(router.getRoute('/'), router);
2711
- Object.assign(router, routerExt, routeExt);
2712
- },
2713
- createRoute: _ref => {
2714
- let {
2715
- router,
2716
- route
2717
- } = _ref;
2718
- const routeExt = makeRouteExt(route, router);
2719
- Object.assign(route, routeExt);
2720
- },
2721
- loadComponent: async component => {
2722
- if (component.preload && typeof document !== 'undefined') {
2723
- component.preload(); // return await component.preload()
2724
- }
1927
+ // Optional
2725
1928
 
2726
- return component;
1929
+ constructor(options) {
1930
+ this.options = options || {};
1931
+ this.isRoot = !options?.getParentRoute;
1932
+ Route.__onInit(this);
1933
+ }
1934
+ init = opts => {
1935
+ this.originalIndex = opts.originalIndex;
1936
+ const options = this.options;
1937
+ const isRoot = !options?.path && !options?.id;
1938
+ this.parentRoute = this.options?.getParentRoute?.();
1939
+ if (isRoot) {
1940
+ this.path = rootRouteId;
1941
+ } else {
1942
+ invariant(this.parentRoute, `Child Route instances must pass a 'getParentRoute: () => ParentRoute' option that returns a Route instance.`);
2727
1943
  }
2728
- }));
2729
- return coreRouter;
2730
- }
2731
- function RouterProvider(_ref2) {
2732
- let {
2733
- children,
2734
- router
2735
- } = _ref2,
2736
- rest = _objectWithoutPropertiesLoose(_ref2, _excluded3);
1944
+ let path = isRoot ? rootRouteId : options.path;
2737
1945
 
2738
- router.update(rest);
2739
- useRouterSubscription(router);
2740
- React.useEffect(() => {
2741
- console.log('hello');
2742
- return router.mount();
2743
- }, [router]);
2744
- return /*#__PURE__*/React.createElement(routerContext.Provider, {
2745
- value: {
2746
- router: router
1946
+ // If the path is anything other than an index path, trim it up
1947
+ if (path && path !== '/') {
1948
+ path = trimPath(path);
2747
1949
  }
2748
- }, /*#__PURE__*/React.createElement(MatchesProvider, {
2749
- value: router.state.matches
2750
- }, children != null ? children : /*#__PURE__*/React.createElement(Outlet, null)));
2751
- }
2752
- function useRouter() {
2753
- const value = React.useContext(routerContext);
2754
- warning(!value, 'useRouter must be used inside a <Router> component!');
2755
- useRouterSubscription(value.router);
2756
- return value.router;
2757
- }
2758
- function useMatches() {
2759
- return React.useContext(matchesContext);
2760
- }
2761
- function useMatch(routeId, opts) {
2762
- const router = useRouter();
2763
- return router.useMatch(routeId, opts);
2764
- }
2765
- function useNearestMatch() {
2766
- var _useMatches2;
1950
+ const customId = options?.id || path;
2767
1951
 
2768
- const runtimeMatch = (_useMatches2 = useMatches()) == null ? void 0 : _useMatches2[0];
2769
- invariant(runtimeMatch, "Could not find a nearest match!");
2770
- return runtimeMatch;
1952
+ // Strip the parentId prefix from the first level of children
1953
+ let id = isRoot ? rootRouteId : joinPaths([this.parentRoute.id === rootRouteId ? '' : this.parentRoute.id, customId]);
1954
+ if (path === rootRouteId) {
1955
+ path = '/';
1956
+ }
1957
+ if (id !== rootRouteId) {
1958
+ id = joinPaths(['/', id]);
1959
+ }
1960
+ const fullPath = id === rootRouteId ? '/' : joinPaths([this.parentRoute.fullPath, path]);
1961
+ this.path = path;
1962
+ this.id = id;
1963
+ // this.customId = customId as TCustomId
1964
+ this.fullPath = fullPath;
1965
+ this.to = fullPath;
1966
+ };
1967
+ addChildren = children => {
1968
+ this.children = children;
1969
+ return this;
1970
+ };
1971
+ update = options => {
1972
+ Object.assign(this.options, options);
1973
+ return this;
1974
+ };
1975
+ static __onInit = route => {
1976
+ // This is a dummy static method that should get
1977
+ // replaced by a framework specific implementation if necessary
1978
+ };
1979
+ useMatch = opts => {
1980
+ return useMatch({
1981
+ ...opts,
1982
+ from: this.id
1983
+ });
1984
+ };
1985
+ useRouteContext = opts => {
1986
+ return useMatch({
1987
+ ...opts,
1988
+ from: this.id,
1989
+ select: d => opts?.select ? opts.select(d.context) : d.context
1990
+ });
1991
+ };
1992
+ useSearch = opts => {
1993
+ return useSearch({
1994
+ ...opts,
1995
+ from: this.id
1996
+ });
1997
+ };
1998
+ useParams = opts => {
1999
+ return useParams({
2000
+ ...opts,
2001
+ from: this.id
2002
+ });
2003
+ };
2771
2004
  }
2772
- function useRoute(routeId) {
2773
- const router = useRouter();
2774
- return router.useRoute(routeId);
2005
+ function rootRouteWithContext() {
2006
+ return options => {
2007
+ return new RootRoute(options);
2008
+ };
2775
2009
  }
2776
- function linkProps(props) {
2777
- const router = useRouter();
2778
- return router.linkProps(props);
2010
+ class RootRoute extends Route {
2011
+ constructor(options) {
2012
+ super(options);
2013
+ }
2779
2014
  }
2780
- function MatchRoute(props) {
2781
- const router = useRouter();
2782
- return /*#__PURE__*/React.createElement(router.MatchRoute, props);
2015
+ function createRouteMask(opts) {
2016
+ return opts;
2783
2017
  }
2784
- function Outlet() {
2785
- var _ref3, _match$__$pendingComp, _match$__$errorCompon;
2786
2018
 
2787
- const router = useRouter();
2788
- const matches = useMatches().slice(1);
2789
- const match = matches[0];
2790
- const defaultPending = React.useCallback(() => null, []);
2019
+ //
2791
2020
 
2792
- if (!match) {
2793
- return null;
2021
+ class FileRoute {
2022
+ constructor(path) {
2023
+ this.path = path;
2794
2024
  }
2025
+ createRoute = options => {
2026
+ const route = new Route(options);
2027
+ route.isRoot = false;
2028
+ return route;
2029
+ };
2030
+ }
2795
2031
 
2796
- const PendingComponent = (_ref3 = (_match$__$pendingComp = match.__.pendingComponent) != null ? _match$__$pendingComp : router.options.defaultPendingComponent) != null ? _ref3 : defaultPending;
2797
- const errorComponent = (_match$__$errorCompon = match.__.errorComponent) != null ? _match$__$errorCompon : router.options.defaultErrorComponent;
2798
- return /*#__PURE__*/React.createElement(MatchesProvider, {
2799
- value: matches
2800
- }, /*#__PURE__*/React.createElement(React.Suspense, {
2801
- fallback: /*#__PURE__*/React.createElement(PendingComponent, null)
2802
- }, /*#__PURE__*/React.createElement(CatchBoundary, {
2803
- errorComponent: errorComponent
2804
- }, (() => {
2805
- if (match.status === 'error') {
2806
- throw match.error;
2032
+ function lazyRouteComponent(importer, exportName) {
2033
+ let loadPromise;
2034
+ const load = () => {
2035
+ if (!loadPromise) {
2036
+ loadPromise = importer();
2807
2037
  }
2038
+ return loadPromise;
2039
+ };
2040
+ const lazyComp = /*#__PURE__*/React.lazy(async () => {
2041
+ const moduleExports = await load();
2042
+ const comp = moduleExports[exportName ?? 'default'];
2043
+ return {
2044
+ default: comp
2045
+ };
2046
+ });
2047
+ lazyComp.preload = load;
2048
+ return lazyComp;
2049
+ }
2808
2050
 
2809
- if (match.status === 'success') {
2810
- var _ref4, _ref5;
2811
-
2812
- return /*#__PURE__*/React.createElement((_ref4 = (_ref5 = match.__.component) != null ? _ref5 : router.options.defaultComponent) != null ? _ref4 : Outlet);
2051
+ function _extends() {
2052
+ _extends = Object.assign ? Object.assign.bind() : function (target) {
2053
+ for (var i = 1; i < arguments.length; i++) {
2054
+ var source = arguments[i];
2055
+ for (var key in source) {
2056
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
2057
+ target[key] = source[key];
2058
+ }
2059
+ }
2813
2060
  }
2814
-
2815
- console.log(match.matchId, 'suspend');
2816
- throw match.__.loadPromise;
2817
- })())));
2061
+ return target;
2062
+ };
2063
+ return _extends.apply(this, arguments);
2818
2064
  }
2819
2065
 
2820
- class CatchBoundary extends React.Component {
2821
- constructor() {
2822
- super(...arguments);
2823
- this.state = {
2824
- error: false
2066
+ function useLinkProps(options) {
2067
+ const {
2068
+ buildLink
2069
+ } = useRouter();
2070
+ const match = useMatch({
2071
+ strict: false
2072
+ });
2073
+ const {
2074
+ // custom props
2075
+ type,
2076
+ children,
2077
+ target,
2078
+ activeProps = () => ({
2079
+ className: 'active'
2080
+ }),
2081
+ inactiveProps = () => ({}),
2082
+ activeOptions,
2083
+ disabled,
2084
+ hash,
2085
+ search,
2086
+ params,
2087
+ to,
2088
+ state,
2089
+ mask,
2090
+ preload,
2091
+ preloadDelay,
2092
+ replace,
2093
+ startTransition,
2094
+ // element props
2095
+ style,
2096
+ className,
2097
+ onClick,
2098
+ onFocus,
2099
+ onMouseEnter,
2100
+ onMouseLeave,
2101
+ onTouchStart,
2102
+ ...rest
2103
+ } = options;
2104
+ const linkInfo = buildLink({
2105
+ from: options.to ? match.pathname : undefined,
2106
+ ...options
2107
+ });
2108
+ if (linkInfo.type === 'external') {
2109
+ const {
2110
+ href
2111
+ } = linkInfo;
2112
+ return {
2113
+ href
2825
2114
  };
2826
2115
  }
2827
-
2828
- componentDidCatch(error, info) {
2829
- console.error(error);
2830
- this.setState({
2831
- error,
2832
- info
2116
+ const {
2117
+ handleClick,
2118
+ handleFocus,
2119
+ handleEnter,
2120
+ handleLeave,
2121
+ handleTouchStart,
2122
+ isActive,
2123
+ next
2124
+ } = linkInfo;
2125
+ const composeHandlers = handlers => e => {
2126
+ if (e.persist) e.persist();
2127
+ handlers.filter(Boolean).forEach(handler => {
2128
+ if (e.defaultPrevented) return;
2129
+ handler(e);
2833
2130
  });
2834
- }
2835
-
2836
- render() {
2837
- var _this$props$errorComp;
2838
-
2839
- const errorComponent = (_this$props$errorComp = this.props.errorComponent) != null ? _this$props$errorComp : DefaultErrorBoundary;
2840
-
2841
- if (this.state.error) {
2842
- return /*#__PURE__*/React.createElement(errorComponent, this.state);
2843
- }
2844
-
2845
- return this.props.children;
2846
- }
2131
+ };
2847
2132
 
2848
- }
2133
+ // Get the active props
2134
+ const resolvedActiveProps = isActive ? functionalUpdate(activeProps, {}) ?? {} : {};
2849
2135
 
2850
- function DefaultErrorBoundary(_ref6) {
2851
- let {
2852
- error
2853
- } = _ref6;
2854
- return /*#__PURE__*/React.createElement("div", {
2855
- style: {
2856
- padding: '.5rem',
2857
- maxWidth: '100%'
2858
- }
2859
- }, /*#__PURE__*/React.createElement("strong", {
2860
- style: {
2861
- fontSize: '1.2rem'
2862
- }
2863
- }, "Something went wrong!"), /*#__PURE__*/React.createElement("div", {
2864
- style: {
2865
- height: '.5rem'
2866
- }
2867
- }), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("pre", null, error.message ? /*#__PURE__*/React.createElement("code", {
2136
+ // Get the inactive props
2137
+ const resolvedInactiveProps = isActive ? {} : functionalUpdate(inactiveProps, {}) ?? {};
2138
+ return {
2139
+ ...resolvedActiveProps,
2140
+ ...resolvedInactiveProps,
2141
+ ...rest,
2142
+ href: disabled ? undefined : next.maskedLocation ? next.maskedLocation.href : next.href,
2143
+ onClick: composeHandlers([onClick, handleClick]),
2144
+ onFocus: composeHandlers([onFocus, handleFocus]),
2145
+ onMouseEnter: composeHandlers([onMouseEnter, handleEnter]),
2146
+ onMouseLeave: composeHandlers([onMouseLeave, handleLeave]),
2147
+ onTouchStart: composeHandlers([onTouchStart, handleTouchStart]),
2148
+ target,
2868
2149
  style: {
2869
- fontSize: '.7em',
2870
- border: '1px solid red',
2871
- borderRadius: '.25rem',
2872
- padding: '.5rem',
2873
- color: 'red'
2874
- }
2875
- }, error.message) : null)));
2150
+ ...style,
2151
+ ...resolvedActiveProps.style,
2152
+ ...resolvedInactiveProps.style
2153
+ },
2154
+ className: [className, resolvedActiveProps.className, resolvedInactiveProps.className].filter(Boolean).join(' ') || undefined,
2155
+ ...(disabled ? {
2156
+ role: 'link',
2157
+ 'aria-disabled': true
2158
+ } : undefined),
2159
+ ['data-status']: isActive ? 'active' : undefined
2160
+ };
2876
2161
  }
2877
- function usePrompt(message, when) {
2878
- const router = useRouter();
2162
+ const Link = /*#__PURE__*/React.forwardRef((props, ref) => {
2163
+ const linkProps = useLinkProps(props);
2164
+ return /*#__PURE__*/React.createElement("a", _extends({
2165
+ ref: ref
2166
+ }, linkProps, {
2167
+ children: typeof props.children === 'function' ? props.children({
2168
+ isActive: linkProps['data-status'] === 'active'
2169
+ }) : props.children
2170
+ }));
2171
+ });
2172
+
2173
+ function useBlocker(message, condition = true) {
2174
+ const {
2175
+ history
2176
+ } = useRouter();
2879
2177
  React.useEffect(() => {
2880
- if (!when) return;
2881
- let unblock = router.history.block(transition => {
2178
+ if (!condition) return;
2179
+ let unblock = history.block((retry, cancel) => {
2882
2180
  if (window.confirm(message)) {
2883
2181
  unblock();
2884
- transition.retry();
2885
- } else {
2886
- router.location.pathname = window.location.pathname;
2182
+ retry();
2887
2183
  }
2888
2184
  });
2889
2185
  return unblock;
2890
- }, [when, location, message]);
2186
+ });
2187
+ }
2188
+ function Block({
2189
+ message,
2190
+ condition,
2191
+ children
2192
+ }) {
2193
+ useBlocker(message, condition);
2194
+ return children ?? null;
2195
+ }
2196
+
2197
+ function useNavigate(defaultOpts) {
2198
+ const {
2199
+ navigate
2200
+ } = useRouter();
2201
+ const match = useMatch({
2202
+ strict: false
2203
+ });
2204
+ return React.useCallback(opts => {
2205
+ return navigate({
2206
+ from: opts?.to ? match.pathname : undefined,
2207
+ ...defaultOpts,
2208
+ ...opts
2209
+ });
2210
+ }, []);
2891
2211
  }
2892
- function Prompt(_ref7) {
2893
- let {
2894
- message,
2895
- when,
2896
- children
2897
- } = _ref7;
2898
- usePrompt(message, when != null ? when : true);
2899
- return children != null ? children : null;
2212
+ function typedNavigate(navigate) {
2213
+ return navigate;
2214
+ } //
2215
+
2216
+ function Navigate(props) {
2217
+ const {
2218
+ navigate
2219
+ } = useRouter();
2220
+ const match = useMatch({
2221
+ strict: false
2222
+ });
2223
+ useLayoutEffect(() => {
2224
+ navigate({
2225
+ from: props.to ? match.pathname : undefined,
2226
+ ...props
2227
+ });
2228
+ }, []);
2229
+ return null;
2900
2230
  }
2901
2231
 
2902
- export { DefaultErrorBoundary, Link, MatchRoute, MatchesProvider, Outlet, Prompt, RouterProvider, cleanPath, createBrowserHistory, createHashHistory, createMemoryHistory, createReactRouter, createRoute, createRouteConfig, createRouteMatch, createRouter, decode, defaultParseSearch, defaultStringifySearch, encode, functionalUpdate, interpolatePath, invariant, joinPaths, last, lazy, linkProps, matchByPath, matchPathname, matchesContext, parsePathname, parseSearchWith, pick, replaceEqualDeep, resolvePath, rootRouteId, routerContext, stringifySearchWith, trimPath, trimPathLeft, trimPathRight, useMatch, useMatches, useNearestMatch, usePrompt, useRoute, useRouter, warning };
2232
+ export { Block, CatchBoundary, CatchBoundaryImpl, ErrorComponent, FileRoute, Link, Match, MatchRoute, Matches, Navigate, Outlet, PathParamError, RootRoute, Route, Router, RouterProvider, SearchParamError, cleanPath, componentTypes, createRouteMask, decode, defaultParseSearch, defaultStringifySearch, encode, functionalUpdate, getInitialRouterState, getRouteMatch, interpolatePath, isPlainObject, isRedirect, isServer, joinPaths, last, lazyFn, lazyRouteComponent, matchByPath, matchPathname, matchesContext, parsePathname, parseSearchWith, partialDeepEqual, pick, redirect, replaceEqualDeep, resolvePath, rootRouteId, rootRouteWithContext, routerContext, shallow, stringifySearchWith, trimPath, trimPathLeft, trimPathRight, typedNavigate, useBlocker, useLayoutEffect, useLinkProps, useMatch, useMatchRoute, useMatches, useNavigate, useParams, useRouteContext, useRouter, useRouterState, useSearch, useStableCallback };
2903
2233
  //# sourceMappingURL=index.js.map