@tanstack/react-router 0.0.1-beta.54 → 0.0.1-beta.55

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.
@@ -59,10 +59,56 @@
59
59
  throw new Error(value);
60
60
  }
61
61
 
62
- function n(n){for(var r=arguments.length,t=Array(r>1?r-1:0),e=1;e<r;e++)t[e-1]=arguments[e];{var i=Y[n],o=i?"function"==typeof i?i.apply(null,t):i:"unknown error nr: "+n;throw Error("[Immer] "+o)}}function r(n){return !!n&&!!n[Q]}function t(n){var r;return !!n&&(function(n){if(!n||"object"!=typeof n)return !1;var r=Object.getPrototypeOf(n);if(null===r)return !0;var t=Object.hasOwnProperty.call(r,"constructor")&&r.constructor;return t===Object||"function"==typeof t&&Function.toString.call(t)===Z}(n)||Array.isArray(n)||!!n[L]||!!(null===(r=n.constructor)||void 0===r?void 0:r[L])||s(n)||v(n))}function i(n,r,t){void 0===t&&(t=!1),0===o(n)?(t?Object.keys:nn)(n).forEach((function(e){t&&"symbol"==typeof e||r(e,n[e],n);})):n.forEach((function(t,e){return r(e,t,n)}));}function o(n){var r=n[Q];return r?r.i>3?r.i-4:r.i:Array.isArray(n)?1:s(n)?2:v(n)?3:0}function u(n,r){return 2===o(n)?n.has(r):Object.prototype.hasOwnProperty.call(n,r)}function a(n,r){return 2===o(n)?n.get(r):n[r]}function f(n,r,t){var e=o(n);2===e?n.set(r,t):3===e?(n.delete(r),n.add(t)):n[r]=t;}function c(n,r){return n===r?0!==n||1/n==1/r:n!=n&&r!=r}function s(n){return X&&n instanceof Map}function v(n){return q&&n instanceof Set}function p(n){return n.o||n.t}function l(n){if(Array.isArray(n))return Array.prototype.slice.call(n);var r=rn(n);delete r[Q];for(var t=nn(r),e=0;e<t.length;e++){var i=t[e],o=r[i];!1===o.writable&&(o.writable=!0,o.configurable=!0),(o.get||o.set)&&(r[i]={configurable:!0,writable:!0,enumerable:o.enumerable,value:n[i]});}return Object.create(Object.getPrototypeOf(n),r)}function d(n,e){return void 0===e&&(e=!1),y(n)||r(n)||!t(n)?n:(o(n)>1&&(n.set=n.add=n.clear=n.delete=h),Object.freeze(n),e&&i(n,(function(n,r){return d(r,!0)}),!0),n)}function h(){n(2);}function y(n){return null==n||"object"!=typeof n||Object.isFrozen(n)}function b(r){var t=tn[r];return t||n(18,r),t}function _(){return U||n(0),U}function j(n,r){r&&(b("Patches"),n.u=[],n.s=[],n.v=r);}function O(n){g(n),n.p.forEach(S),n.p=null;}function g(n){n===U&&(U=n.l);}function w(n){return U={p:[],l:U,h:n,m:!0,_:0}}function S(n){var r=n[Q];0===r.i||1===r.i?r.j():r.O=!0;}function P(r,e){e._=e.p.length;var i=e.p[0],o=void 0!==r&&r!==i;return e.h.g||b("ES5").S(e,r,o),o?(i[Q].P&&(O(e),n(4)),t(r)&&(r=M(e,r),e.l||x(e,r)),e.u&&b("Patches").M(i[Q].t,r,e.u,e.s)):r=M(e,i,[]),O(e),e.u&&e.v(e.u,e.s),r!==H?r:void 0}function M(n,r,t){if(y(r))return r;var e=r[Q];if(!e)return i(r,(function(i,o){return A(n,e,r,i,o,t)}),!0),r;if(e.A!==n)return r;if(!e.P)return x(n,e.t,!0),e.t;if(!e.I){e.I=!0,e.A._--;var o=4===e.i||5===e.i?e.o=l(e.k):e.o;i(3===e.i?new Set(o):o,(function(r,i){return A(n,e,o,r,i,t)})),x(n,o,!1),t&&n.u&&b("Patches").R(e,t,n.u,n.s);}return e.o}function A(e,i,o,a,c,s){if(c===o&&n(5),r(c)){var v=M(e,c,s&&i&&3!==i.i&&!u(i.D,a)?s.concat(a):void 0);if(f(o,a,v),!r(v))return;e.m=!1;}if(t(c)&&!y(c)){if(!e.h.F&&e._<1)return;M(e,c),i&&i.A.l||x(e,c);}}function x(n,r,t){void 0===t&&(t=!1),n.h.F&&n.m&&d(r,t);}function z(n,r){var t=n[Q];return (t?p(t):n)[r]}function I(n,r){if(r in n)for(var t=Object.getPrototypeOf(n);t;){var e=Object.getOwnPropertyDescriptor(t,r);if(e)return e;t=Object.getPrototypeOf(t);}}function k(n){n.P||(n.P=!0,n.l&&k(n.l));}function E(n){n.o||(n.o=l(n.t));}function R(n,r,t){var e=s(r)?b("MapSet").N(r,t):v(r)?b("MapSet").T(r,t):n.g?function(n,r){var t=Array.isArray(n),e={i:t?1:0,A:r?r.A:_(),P:!1,I:!1,D:{},l:r,t:n,k:null,o:null,j:null,C:!1},i=e,o=en;t&&(i=[e],o=on);var u=Proxy.revocable(i,o),a=u.revoke,f=u.proxy;return e.k=f,e.j=a,f}(r,t):b("ES5").J(r,t);return (t?t.A:_()).p.push(e),e}function D(e){return r(e)||n(22,e),function n(r){if(!t(r))return r;var e,u=r[Q],c=o(r);if(u){if(!u.P&&(u.i<4||!b("ES5").K(u)))return u.t;u.I=!0,e=F(r,c),u.I=!1;}else e=F(r,c);return i(e,(function(r,t){u&&a(u.t,r)===t||f(e,r,n(t));})),3===c?new Set(e):e}(e)}function F(n,r){switch(r){case 2:return new Map(n);case 3:return Array.from(n)}return l(n)}var G,U,W="undefined"!=typeof Symbol&&"symbol"==typeof Symbol("x"),X="undefined"!=typeof Map,q="undefined"!=typeof Set,B="undefined"!=typeof Proxy&&void 0!==Proxy.revocable&&"undefined"!=typeof Reflect,H=W?Symbol.for("immer-nothing"):((G={})["immer-nothing"]=!0,G),L=W?Symbol.for("immer-draftable"):"__$immer_draftable",Q=W?Symbol.for("immer-state"):"__$immer_state",Y={0:"Illegal state",1:"Immer drafts cannot have computed properties",2:"This object has been frozen and should not be mutated",3:function(n){return "Cannot use a proxy that has been revoked. Did you pass an object from inside an immer function to an async process? "+n},4:"An immer producer returned a new value *and* modified its draft. Either return a new value *or* modify the draft.",5:"Immer forbids circular references",6:"The first or second argument to `produce` must be a function",7:"The third argument to `produce` must be a function or undefined",8:"First argument to `createDraft` must be a plain object, an array, or an immerable object",9:"First argument to `finishDraft` must be a draft returned by `createDraft`",10:"The given draft is already finalized",11:"Object.defineProperty() cannot be used on an Immer draft",12:"Object.setPrototypeOf() cannot be used on an Immer draft",13:"Immer only supports deleting array indices",14:"Immer only supports setting array indices and the 'length' property",15:function(n){return "Cannot apply patch, path doesn't resolve: "+n},16:'Sets cannot have "replace" patches.',17:function(n){return "Unsupported patch operation: "+n},18:function(n){return "The plugin for '"+n+"' has not been loaded into Immer. To enable the plugin, import and call `enable"+n+"()` when initializing your application."},20:"Cannot use proxies if Proxy, Proxy.revocable or Reflect are not available",21:function(n){return "produce can only be called on things that are draftable: plain objects, arrays, Map, Set or classes that are marked with '[immerable]: true'. Got '"+n+"'"},22:function(n){return "'current' expects a draft, got: "+n},23:function(n){return "'original' expects a draft, got: "+n},24:"Patching reserved attributes like __proto__, prototype and constructor is not allowed"},Z=""+Object.prototype.constructor,nn="undefined"!=typeof Reflect&&Reflect.ownKeys?Reflect.ownKeys:void 0!==Object.getOwnPropertySymbols?function(n){return Object.getOwnPropertyNames(n).concat(Object.getOwnPropertySymbols(n))}:Object.getOwnPropertyNames,rn=Object.getOwnPropertyDescriptors||function(n){var r={};return nn(n).forEach((function(t){r[t]=Object.getOwnPropertyDescriptor(n,t);})),r},tn={},en={get:function(n,r){if(r===Q)return n;var e=p(n);if(!u(e,r))return function(n,r,t){var e,i=I(r,t);return i?"value"in i?i.value:null===(e=i.get)||void 0===e?void 0:e.call(n.k):void 0}(n,e,r);var i=e[r];return n.I||!t(i)?i:i===z(n.t,r)?(E(n),n.o[r]=R(n.A.h,i,n)):i},has:function(n,r){return r in p(n)},ownKeys:function(n){return Reflect.ownKeys(p(n))},set:function(n,r,t){var e=I(p(n),r);if(null==e?void 0:e.set)return e.set.call(n.k,t),!0;if(!n.P){var i=z(p(n),r),o=null==i?void 0:i[Q];if(o&&o.t===t)return n.o[r]=t,n.D[r]=!1,!0;if(c(t,i)&&(void 0!==t||u(n.t,r)))return !0;E(n),k(n);}return n.o[r]===t&&"number"!=typeof t&&(void 0!==t||r in n.o)||(n.o[r]=t,n.D[r]=!0,!0)},deleteProperty:function(n,r){return void 0!==z(n.t,r)||r in n.t?(n.D[r]=!1,E(n),k(n)):delete n.D[r],n.o&&delete n.o[r],!0},getOwnPropertyDescriptor:function(n,r){var t=p(n),e=Reflect.getOwnPropertyDescriptor(t,r);return e?{writable:!0,configurable:1!==n.i||"length"!==r,enumerable:e.enumerable,value:t[r]}:e},defineProperty:function(){n(11);},getPrototypeOf:function(n){return Object.getPrototypeOf(n.t)},setPrototypeOf:function(){n(12);}},on={};i(en,(function(n,r){on[n]=function(){return arguments[0]=arguments[0][0],r.apply(this,arguments)};})),on.deleteProperty=function(r,t){return isNaN(parseInt(t))&&n(13),on.set.call(this,r,t,void 0)},on.set=function(r,t,e){return "length"!==t&&isNaN(parseInt(t))&&n(14),en.set.call(this,r[0],t,e,r[0])};var un=function(){function e(r){var e=this;this.g=B,this.F=!0,this.produce=function(r,i,o){if("function"==typeof r&&"function"!=typeof i){var u=i;i=r;var a=e;return function(n){var r=this;void 0===n&&(n=u);for(var t=arguments.length,e=Array(t>1?t-1:0),o=1;o<t;o++)e[o-1]=arguments[o];return a.produce(n,(function(n){var t;return (t=i).call.apply(t,[r,n].concat(e))}))}}var f;if("function"!=typeof i&&n(6),void 0!==o&&"function"!=typeof o&&n(7),t(r)){var c=w(e),s=R(e,r,void 0),v=!0;try{f=i(s),v=!1;}finally{v?O(c):g(c);}return "undefined"!=typeof Promise&&f instanceof Promise?f.then((function(n){return j(c,o),P(n,c)}),(function(n){throw O(c),n})):(j(c,o),P(f,c))}if(!r||"object"!=typeof r){if(void 0===(f=i(r))&&(f=r),f===H&&(f=void 0),e.F&&d(f,!0),o){var p=[],l=[];b("Patches").M(r,f,p,l),o(p,l);}return f}n(21,r);},this.produceWithPatches=function(n,r){if("function"==typeof n)return function(r){for(var t=arguments.length,i=Array(t>1?t-1:0),o=1;o<t;o++)i[o-1]=arguments[o];return e.produceWithPatches(r,(function(r){return n.apply(void 0,[r].concat(i))}))};var t,i,o=e.produce(n,r,(function(n,r){t=n,i=r;}));return "undefined"!=typeof Promise&&o instanceof Promise?o.then((function(n){return [n,t,i]})):[o,t,i]},"boolean"==typeof(null==r?void 0:r.useProxies)&&this.setUseProxies(r.useProxies),"boolean"==typeof(null==r?void 0:r.autoFreeze)&&this.setAutoFreeze(r.autoFreeze);}var i=e.prototype;return i.createDraft=function(e){t(e)||n(8),r(e)&&(e=D(e));var i=w(this),o=R(this,e,void 0);return o[Q].C=!0,g(i),o},i.finishDraft=function(r,t){var e=r&&r[Q];(e&&e.C||n(9),e.I&&n(10));var i=e.A;return j(i,t),P(void 0,i)},i.setAutoFreeze=function(n){this.F=n;},i.setUseProxies=function(r){r&&!B&&n(20),this.g=r;},i.applyPatches=function(n,t){var e;for(e=t.length-1;e>=0;e--){var i=t[e];if(0===i.path.length&&"replace"===i.op){n=i.value;break}}e>-1&&(t=t.slice(e+1));var o=b("Patches").$;return r(n)?o(n,t):this.produce(n,(function(n){return o(n,t)}))},e}(),an=new un,fn=an.produce;an.produceWithPatches.bind(an);var sn=an.setAutoFreeze.bind(an);an.setUseProxies.bind(an);an.applyPatches.bind(an);an.createDraft.bind(an);an.finishDraft.bind(an);
62
+ /**
63
+ * store
64
+ *
65
+ * Copyright (c) TanStack
66
+ *
67
+ * This source code is licensed under the MIT license found in the
68
+ * LICENSE.md file in the root directory of this source tree.
69
+ *
70
+ * @license MIT
71
+ */
72
+ class Store {
73
+ listeners = new Set();
74
+ batching = false;
75
+ queue = [];
76
+ constructor(initialState, options) {
77
+ this.state = initialState;
78
+ this.options = options;
79
+ }
80
+ subscribe = listener => {
81
+ this.listeners.add(listener);
82
+ const unsub = this.options?.onSubscribe?.(listener, this);
83
+ return () => {
84
+ this.listeners.delete(listener);
85
+ unsub?.();
86
+ };
87
+ };
88
+ setState = updater => {
89
+ const previous = this.state;
90
+ this.state = this.options?.updateFn ? this.options.updateFn(previous)(updater) : updater(previous);
91
+ this.queue.push(() => {
92
+ this.listeners.forEach(listener => listener(this.state, previous));
93
+ this.options?.onUpdate?.(this.state, previous);
94
+ });
95
+ this.#flush();
96
+ };
97
+ #flush = () => {
98
+ if (this.batching) return;
99
+ this.queue.forEach(cb => cb());
100
+ this.queue = [];
101
+ };
102
+ batch = cb => {
103
+ this.batching = true;
104
+ cb();
105
+ this.batching = false;
106
+ this.#flush();
107
+ };
108
+ }
63
109
 
64
110
  /**
65
- * router-core
111
+ * router
66
112
  *
67
113
  * Copyright (c) TanStack
68
114
  *
@@ -239,6 +285,66 @@
239
285
  }, {});
240
286
  }
241
287
 
288
+ /**
289
+ * This function returns `a` if `b` is deeply equal.
290
+ * If not, it will replace any deeply equal children of `b` with those of `a`.
291
+ * This can be used for structural sharing between immutable JSON values for example.
292
+ * Do not use this with signals
293
+ */
294
+ function replaceEqualDeep(prev, _next) {
295
+ if (prev === _next) {
296
+ return prev;
297
+ }
298
+ const next = _next;
299
+ const array = Array.isArray(prev) && Array.isArray(next);
300
+ if (array || isPlainObject(prev) && isPlainObject(next)) {
301
+ const prevSize = array ? prev.length : Object.keys(prev).length;
302
+ const nextItems = array ? next : Object.keys(next);
303
+ const nextSize = nextItems.length;
304
+ const copy = array ? [] : {};
305
+ let equalItems = 0;
306
+ for (let i = 0; i < nextSize; i++) {
307
+ const key = array ? i : nextItems[i];
308
+ copy[key] = replaceEqualDeep(prev[key], next[key]);
309
+ if (copy[key] === prev[key]) {
310
+ equalItems++;
311
+ }
312
+ }
313
+ return prevSize === nextSize && equalItems === prevSize ? prev : copy;
314
+ }
315
+ return next;
316
+ }
317
+
318
+ // Copied from: https://github.com/jonschlinkert/is-plain-object
319
+ function isPlainObject(o) {
320
+ if (!hasObjectPrototype(o)) {
321
+ return false;
322
+ }
323
+
324
+ // If has modified constructor
325
+ const ctor = o.constructor;
326
+ if (typeof ctor === 'undefined') {
327
+ return true;
328
+ }
329
+
330
+ // If has modified prototype
331
+ const prot = ctor.prototype;
332
+ if (!hasObjectPrototype(prot)) {
333
+ return false;
334
+ }
335
+
336
+ // If constructor does not have an Object-specific method
337
+ if (!prot.hasOwnProperty('isPrototypeOf')) {
338
+ return false;
339
+ }
340
+
341
+ // Most likely a plain Object
342
+ return true;
343
+ }
344
+ function hasObjectPrototype(o) {
345
+ return Object.prototype.toString.call(o) === '[object Object]';
346
+ }
347
+
242
348
  function joinPaths(paths) {
243
349
  return cleanPath(paths.filter(Boolean).join('/'));
244
350
  }
@@ -515,204 +621,11 @@
515
621
  };
516
622
  };
517
623
 
518
- sn(false);
519
- let queue = [];
520
- let batching = false;
521
- function flush() {
522
- if (batching) return;
523
- queue.forEach(cb => cb());
524
- queue = [];
525
- }
526
- function createStore(initialState, debug) {
527
- const listeners = new Set();
528
- const store = {
529
- state: initialState,
530
- subscribe: listener => {
531
- listeners.add(listener);
532
- return () => listeners.delete(listener);
533
- },
534
- setState: updater => {
535
- const previous = store.state;
536
- store.state = fn(d => {
537
- updater(d);
538
- })(previous);
539
- if (debug) console.log(store.state);
540
- queue.push(() => listeners.forEach(listener => listener(store.state, previous)));
541
- flush();
542
- }
543
- };
544
- return store;
545
- }
546
- function batch(cb) {
547
- batching = true;
548
- cb();
549
- batching = false;
550
- flush();
551
- }
552
-
553
- // /**
554
- // * This function converts a store to an immutable value, which is
555
- // * more complex than you think. On first read, (when prev is undefined)
556
- // * every value must be recursively touched so tracking is "deep".
557
- // * Every object/array structure must also be cloned to
558
- // * have a new reference, otherwise it will get mutated by subsequent
559
- // * store updates.
560
- // *
561
- // * In the case that prev is supplied, we have to do deep comparisons
562
- // * between prev and next objects/array references and if they are deeply
563
- // * equal, we can return the prev version for referential equality.
564
- // */
565
- // export function storeToImmutable<T>(prev: any, next: T): T {
566
- // const cache = new Map()
567
-
568
- // // Visit all nodes
569
- // // clone all next structures
570
- // // from bottom up, if prev === next, return prev
571
-
572
- // function recurse(prev: any, next: any) {
573
- // if (cache.has(next)) {
574
- // return cache.get(next)
575
- // }
576
-
577
- // const prevIsArray = Array.isArray(prev)
578
- // const nextIsArray = Array.isArray(next)
579
- // const prevIsObj = isPlainObject(prev)
580
- // const nextIsObj = isPlainObject(next)
581
- // const nextIsComplex = nextIsArray || nextIsObj
582
-
583
- // const isArray = prevIsArray && nextIsArray
584
- // const isObj = prevIsObj && nextIsObj
585
-
586
- // const isSameStructure = isArray || isObj
587
-
588
- // if (nextIsComplex) {
589
- // const prevSize = isArray
590
- // ? prev.length
591
- // : isObj
592
- // ? Object.keys(prev).length
593
- // : -1
594
- // const nextKeys = isArray ? next : Object.keys(next)
595
- // const nextSize = nextKeys.length
596
-
597
- // let changed = false
598
- // const copy: any = nextIsArray ? [] : {}
599
-
600
- // for (let i = 0; i < nextSize; i++) {
601
- // const key = isArray ? i : nextKeys[i]
602
- // const prevValue = isSameStructure ? prev[key] : undefined
603
- // const nextValue = next[key]
604
-
605
- // // Recurse the new value
606
- // try {
607
- // console.count(key)
608
- // copy[key] = recurse(prevValue, nextValue)
609
- // } catch {}
610
-
611
- // // If the new value has changed reference,
612
- // // mark the obj/array as changed
613
- // if (!changed && copy[key] !== prevValue) {
614
- // changed = true
615
- // }
616
- // }
617
-
618
- // // No items have changed!
619
- // // If something has changed, return a clone of the next obj/array
620
- // if (changed || prevSize !== nextSize) {
621
- // cache.set(next, copy)
622
- // return copy
623
- // }
624
-
625
- // // If they are exactly the same, return the prev obj/array
626
- // cache.set(next, prev)
627
- // return prev
628
- // }
629
-
630
- // cache.set(next, next)
631
- // return next
632
- // }
633
-
634
- // return recurse(prev, next)
635
- // }
636
-
637
- /**
638
- * This function returns `a` if `b` is deeply equal.
639
- * If not, it will replace any deeply equal children of `b` with those of `a`.
640
- * This can be used for structural sharing between immutable JSON values for example.
641
- * Do not use this with signals
642
- */
643
- function replaceEqualDeep(prev, _next) {
644
- if (prev === _next) {
645
- return prev;
646
- }
647
- const next = _next;
648
- const array = Array.isArray(prev) && Array.isArray(next);
649
- if (array || isPlainObject(prev) && isPlainObject(next)) {
650
- const prevSize = array ? prev.length : Object.keys(prev).length;
651
- const nextItems = array ? next : Object.keys(next);
652
- const nextSize = nextItems.length;
653
- const copy = array ? [] : {};
654
- let equalItems = 0;
655
- for (let i = 0; i < nextSize; i++) {
656
- const key = array ? i : nextItems[i];
657
- copy[key] = replaceEqualDeep(prev[key], next[key]);
658
- if (copy[key] === prev[key]) {
659
- equalItems++;
660
- }
661
- }
662
- return prevSize === nextSize && equalItems === prevSize ? prev : copy;
663
- }
664
- return next;
665
- }
666
-
667
- // Copied from: https://github.com/jonschlinkert/is-plain-object
668
- function isPlainObject(o) {
669
- if (!hasObjectPrototype(o)) {
670
- return false;
671
- }
672
-
673
- // If has modified constructor
674
- const ctor = o.constructor;
675
- if (typeof ctor === 'undefined') {
676
- return true;
677
- }
678
-
679
- // If has modified prototype
680
- const prot = ctor.prototype;
681
- if (!hasObjectPrototype(prot)) {
682
- return false;
683
- }
684
-
685
- // If constructor does not have an Object-specific method
686
- if (!prot.hasOwnProperty('isPrototypeOf')) {
687
- return false;
688
- }
689
-
690
- // Most likely a plain Object
691
- return true;
692
- }
693
- function hasObjectPrototype(o) {
694
- return Object.prototype.toString.call(o) === '[object Object]';
695
- }
696
- function trackDeep(obj) {
697
- const seen = new Set();
698
- JSON.stringify(obj, (_, value) => {
699
- if (typeof value === 'function') {
700
- return undefined;
701
- }
702
- if (typeof value === 'object' && value !== null) {
703
- if (seen.has(value)) return;
704
- seen.add(value);
705
- }
706
- return value;
707
- });
708
- return obj;
709
- }
624
+ //
710
625
 
711
626
  const componentTypes = ['component', 'errorComponent', 'pendingComponent'];
712
627
  class RouteMatch {
713
628
  abortController = new AbortController();
714
- #latestId = '';
715
- #resolve = () => {};
716
629
  onLoaderDataListeners = new Set();
717
630
  constructor(router, route, opts) {
718
631
  Object.assign(this, {
@@ -721,80 +634,49 @@
721
634
  id: opts.id,
722
635
  pathname: opts.pathname,
723
636
  params: opts.params,
724
- store: createStore({
637
+ store: new Store({
638
+ updatedAt: 0,
725
639
  routeSearch: {},
726
640
  search: {},
727
- status: 'idle',
728
- routeLoaderData: {},
729
- loaderData: {},
730
- isFetching: false,
731
- invalid: false,
732
- invalidAt: Infinity
641
+ status: 'idle'
733
642
  })
734
643
  });
735
- if (!this.__hasLoaders()) {
736
- this.store.setState(s => s.status = 'success');
644
+ if (!this.#hasLoaders()) {
645
+ this.store.setState(s => ({
646
+ ...s,
647
+ status: 'success'
648
+ }));
737
649
  }
738
650
  }
739
- setLoaderData = loaderData => {
740
- batch(() => {
741
- this.store.setState(s => {
742
- s.routeLoaderData = loaderData;
743
- });
744
- this.#updateLoaderData();
745
- });
746
- };
747
651
  cancel = () => {
748
652
  this.abortController?.abort();
749
653
  };
750
- load = async loaderOpts => {
751
- const now = Date.now();
752
- const minMaxAge = loaderOpts?.preload ? Math.max(loaderOpts?.maxAge, loaderOpts?.gcMaxAge) : 0;
753
-
754
- // If this is a preload, add it to the preload cache
755
- if (loaderOpts?.preload && minMaxAge > 0) {
756
- // If the match is currently active, don't preload it
757
- if (this.router.store.state.currentMatches.find(d => d.id === this.id)) {
758
- return;
759
- }
760
- this.router.store.setState(s => {
761
- s.matchCache[this.id] = {
762
- gc: now + loaderOpts.gcMaxAge,
763
- match: this
764
- };
765
- });
766
- }
767
-
654
+ load = async () => {
768
655
  // If the match is invalid, errored or idle, trigger it to load
769
- if (this.store.state.status === 'success' && this.getIsInvalid() || this.store.state.status === 'error' || this.store.state.status === 'idle') {
770
- const maxAge = loaderOpts?.preload ? loaderOpts?.maxAge : undefined;
771
- await this.fetch({
772
- maxAge
773
- });
656
+ if (this.store.state.status !== 'pending') {
657
+ await this.fetch();
774
658
  }
775
659
  };
776
- fetch = async opts => {
777
- this.__loadPromise = new Promise(async resolve => {
660
+ #latestId = '';
661
+ fetch = async () => {
662
+ this.__loadPromise = Promise.resolve().then(async () => {
778
663
  const loadId = '' + Date.now() + Math.random();
779
664
  this.#latestId = loadId;
780
- const checkLatest = () => loadId !== this.#latestId ? this.__loadPromise?.then(() => resolve()) : undefined;
665
+ const checkLatest = () => {
666
+ return loadId !== this.#latestId ? this.__loadPromise : undefined;
667
+ };
781
668
  let latestPromise;
782
- batch(() => {
669
+ this.store.batch(() => {
783
670
  // If the match was in an error state, set it
784
671
  // to a loading state again. Otherwise, keep it
785
672
  // as loading or resolved
786
673
  if (this.store.state.status === 'idle') {
787
- this.store.setState(s => s.status = 'loading');
674
+ this.store.setState(s => ({
675
+ ...s,
676
+ status: 'pending'
677
+ }));
788
678
  }
789
-
790
- // We started loading the route, so it's no longer invalid
791
- this.store.setState(s => s.invalid = false);
792
679
  });
793
-
794
- // We are now fetching, even if it's in the background of a
795
- // resolved state
796
- this.store.setState(s => s.isFetching = true);
797
- this.#resolve = resolve;
798
680
  const componentsPromise = (async () => {
799
681
  // then run all component and data loaders in parallel
800
682
  // For each component type, potentially load it asynchronously
@@ -806,103 +688,61 @@
806
688
  }
807
689
  }));
808
690
  })();
809
- const dataPromise = Promise.resolve().then(async () => {
810
- try {
811
- if (this.route.options.loader) {
812
- const data = await this.router.loadMatchData(this);
813
- if (latestPromise = checkLatest()) return latestPromise;
814
- this.setLoaderData(data);
815
- }
816
- this.store.setState(s => {
817
- s.error = undefined;
818
- s.status = 'success';
819
- s.updatedAt = Date.now();
820
- s.invalidAt = s.updatedAt + (opts?.maxAge ?? this.route.options.loaderMaxAge ?? this.router.options.defaultLoaderMaxAge ?? 0);
821
- });
822
- return this.store.state.routeLoaderData;
823
- } catch (err) {
824
- if (latestPromise = checkLatest()) return latestPromise;
825
- {
826
- console.error(err);
827
- }
828
- this.store.setState(s => {
829
- s.error = err;
830
- s.status = 'error';
831
- s.updatedAt = Date.now();
691
+ const dataPromise = Promise.resolve().then(() => {
692
+ if (this.route.options.onLoad) {
693
+ return this.route.options.onLoad({
694
+ params: this.params,
695
+ search: this.store.state.search,
696
+ signal: this.abortController.signal
832
697
  });
833
- throw err;
834
698
  }
699
+ return;
835
700
  });
836
- const after = async () => {
837
- if (latestPromise = checkLatest()) return latestPromise;
838
- this.store.setState(s => s.isFetching = false);
839
- this.#resolve();
840
- delete this.__loadPromise;
841
- };
842
701
  try {
843
- await Promise.all([componentsPromise, dataPromise.catch(() => {})]);
844
- after();
845
- } catch {
846
- after();
702
+ await componentsPromise;
703
+ await dataPromise;
704
+ if (latestPromise = checkLatest()) return await latestPromise;
705
+ this.store.setState(s => ({
706
+ ...s,
707
+ error: undefined,
708
+ status: 'success',
709
+ updatedAt: Date.now()
710
+ }));
711
+ } catch (err) {
712
+ this.store.setState(s => ({
713
+ ...s,
714
+ error: err,
715
+ status: 'error',
716
+ updatedAt: Date.now()
717
+ }));
718
+ } finally {
719
+ delete this.__loadPromise;
847
720
  }
848
721
  });
849
722
  return this.__loadPromise;
850
723
  };
851
- invalidate = async () => {
852
- this.store.setState(s => s.invalid = true);
853
- if (this.router.store.state.currentMatches.find(d => d.id === this.id)) {
854
- await this.load();
855
- }
856
- };
857
- __hasLoaders = () => {
858
- return !!(this.route.options.loader || componentTypes.some(d => this.route.options[d]?.preload));
859
- };
860
- getIsInvalid = () => {
861
- const now = Date.now();
862
- return this.store.state.invalid || this.store.state.invalidAt < now;
863
- };
864
- #updateLoaderData = () => {
865
- this.store.setState(s => {
866
- s.loaderData = replaceEqualDeep(s.loaderData, {
867
- ...this.parentMatch?.store.state.loaderData,
868
- ...s.routeLoaderData
869
- });
870
- });
871
- this.onLoaderDataListeners.forEach(listener => listener());
724
+ #hasLoaders = () => {
725
+ return !!(this.route.options.onLoad || componentTypes.some(d => this.route.options[d]?.preload));
872
726
  };
873
727
  __setParentMatch = parentMatch => {
874
728
  if (!this.parentMatch && parentMatch) {
875
729
  this.parentMatch = parentMatch;
876
- this.parentMatch.__onLoaderData(() => {
877
- this.#updateLoaderData();
878
- });
879
730
  }
880
731
  };
881
- __onLoaderData = listener => {
882
- this.onLoaderDataListeners.add(listener);
883
- // return () => this.onLoaderDataListeners.delete(listener)
884
- };
885
-
886
732
  __validate = () => {
887
733
  // Validate the search params and stabilize them
888
734
  const parentSearch = this.parentMatch?.store.state.search ?? this.router.store.state.latestLocation.search;
889
735
  try {
890
- const prevSearch = this.store.state.routeSearch;
891
736
  const validator = typeof this.route.options.validateSearch === 'object' ? this.route.options.validateSearch.parse : this.route.options.validateSearch;
892
737
  let nextSearch = validator?.(parentSearch) ?? {};
893
- batch(() => {
894
- // Invalidate route matches when search param stability changes
895
- if (prevSearch !== nextSearch) {
896
- this.store.setState(s => s.invalid = true);
738
+ this.store.setState(s => ({
739
+ ...s,
740
+ routeSearch: nextSearch,
741
+ search: {
742
+ ...parentSearch,
743
+ ...nextSearch
897
744
  }
898
- this.store.setState(s => {
899
- s.routeSearch = nextSearch;
900
- s.search = {
901
- ...parentSearch,
902
- ...nextSearch
903
- };
904
- });
905
- });
745
+ }));
906
746
  componentTypes.map(async type => {
907
747
  const component = this.route.options[type];
908
748
  if (typeof this[type] !== 'function') {
@@ -915,10 +755,11 @@
915
755
  cause: err
916
756
  });
917
757
  error.code = 'INVALID_SEARCH_PARAMS';
918
- this.store.setState(s => {
919
- s.status = 'error';
920
- s.error = error;
921
- });
758
+ this.store.setState(s => ({
759
+ ...s,
760
+ status: 'error',
761
+ error: error
762
+ }));
922
763
 
923
764
  // Do not proceed with loading the route
924
765
  return;
@@ -1001,9 +842,6 @@
1001
842
  resolveNavigation = () => {};
1002
843
  constructor(options) {
1003
844
  this.options = {
1004
- defaultLoaderGcMaxAge: 5 * 60 * 1000,
1005
- defaultLoaderMaxAge: 0,
1006
- defaultPreloadMaxAge: 2000,
1007
845
  defaultPreloadDelay: 50,
1008
846
  context: undefined,
1009
847
  ...options,
@@ -1011,7 +849,7 @@
1011
849
  parseSearch: options?.parseSearch ?? defaultParseSearch,
1012
850
  fetchServerDataFn: options?.fetchServerDataFn ?? defaultFetchServerDataFn
1013
851
  };
1014
- this.store = createStore(getInitialRouterState());
852
+ this.store = new Store(getInitialRouterState());
1015
853
  this.basepath = '';
1016
854
  this.update(options);
1017
855
 
@@ -1057,10 +895,12 @@
1057
895
  this.#unsubHistory();
1058
896
  }
1059
897
  this.history = this.options.history ?? (isServer ? createMemoryHistory() : createBrowserHistory());
1060
- this.store.setState(s => {
1061
- s.latestLocation = this.#parseLocation();
1062
- s.currentLocation = s.latestLocation;
1063
- });
898
+ const parsedLocation = this.#parseLocation();
899
+ this.store.setState(s => ({
900
+ ...s,
901
+ latestLocation: parsedLocation,
902
+ currentLocation: parsedLocation
903
+ }));
1064
904
  this.#unsubHistory = this.history.listen(() => {
1065
905
  this.load(this.#parseLocation(this.store.state.latestLocation));
1066
906
  });
@@ -1100,23 +940,25 @@
1100
940
  // Cancel any pending matches
1101
941
  this.cancelMatches();
1102
942
  let matches;
1103
- batch(() => {
943
+ this.store.batch(() => {
1104
944
  if (next) {
1105
945
  // Ingest the new location
1106
- this.store.setState(s => {
1107
- s.latestLocation = next;
1108
- });
946
+ this.store.setState(s => ({
947
+ ...s,
948
+ latestLocation: next
949
+ }));
1109
950
  }
1110
951
 
1111
952
  // Match the routes
1112
953
  matches = this.matchRoutes(this.store.state.latestLocation.pathname, {
1113
954
  strictParseParams: true
1114
955
  });
1115
- this.store.setState(s => {
1116
- s.status = 'loading';
1117
- s.pendingMatches = matches;
1118
- s.pendingLocation = this.store.state.latestLocation;
1119
- });
956
+ this.store.setState(s => ({
957
+ ...s,
958
+ status: 'pending',
959
+ pendingMatches: matches,
960
+ pendingLocation: this.store.state.latestLocation
961
+ }));
1120
962
  });
1121
963
 
1122
964
  // Load the matches
@@ -1151,20 +993,12 @@
1151
993
  });
1152
994
 
1153
995
  // Clear non-loading error states when match leaves
1154
- if (d.store.state.status === 'error' && !d.store.state.isFetching) {
1155
- d.store.setState(s => {
1156
- s.status = 'idle';
1157
- s.error = undefined;
1158
- });
1159
- }
1160
- const gc = Math.max(d.route.options.loaderGcMaxAge ?? this.options.defaultLoaderGcMaxAge ?? 0, d.route.options.loaderMaxAge ?? this.options.defaultLoaderMaxAge ?? 0);
1161
- if (gc > 0) {
1162
- this.store.setState(s => {
1163
- s.matchCache[d.id] = {
1164
- gc: gc == Infinity ? Number.MAX_SAFE_INTEGER : now + gc,
1165
- match: d
1166
- };
1167
- });
996
+ if (d.store.state.status === 'error') {
997
+ this.store.setState(s => ({
998
+ ...s,
999
+ status: 'idle',
1000
+ error: undefined
1001
+ }));
1168
1002
  }
1169
1003
  });
1170
1004
  staying.forEach(d => {
@@ -1178,41 +1012,20 @@
1178
1012
  params: d.params,
1179
1013
  search: d.store.state.search
1180
1014
  });
1181
- delete this.store.state.matchCache[d.id];
1182
- });
1183
- this.store.setState(s => {
1184
- Object.assign(s, {
1185
- status: 'idle',
1186
- currentLocation: this.store.state.latestLocation,
1187
- currentMatches: matches,
1188
- pendingLocation: undefined,
1189
- pendingMatches: undefined
1190
- });
1015
+ // delete this.store.state.matchCache[d.id] // TODO:
1191
1016
  });
1017
+
1018
+ this.store.setState(s => ({
1019
+ ...s,
1020
+ status: 'idle',
1021
+ currentLocation: this.store.state.latestLocation,
1022
+ currentMatches: matches,
1023
+ pendingLocation: undefined,
1024
+ pendingMatches: undefined
1025
+ }));
1192
1026
  this.options.onRouteChange?.();
1193
1027
  this.resolveNavigation();
1194
1028
  };
1195
- cleanMatchCache = () => {
1196
- const now = Date.now();
1197
- this.store.setState(s => {
1198
- Object.keys(s.matchCache).forEach(matchId => {
1199
- const entry = s.matchCache[matchId];
1200
-
1201
- // Don't remove loading matches
1202
- if (entry.match.store.state.status === 'loading') {
1203
- return;
1204
- }
1205
-
1206
- // Do not remove successful matches that are still valid
1207
- if (entry.gc > 0 && entry.gc > now) {
1208
- return;
1209
- }
1210
-
1211
- // Everything else gets removed
1212
- delete s.matchCache[matchId];
1213
- });
1214
- });
1215
- };
1216
1029
  getRoute = id => {
1217
1030
  const route = this.routesById[id];
1218
1031
  invariant(route, `Route with id "${id}" not found`);
@@ -1226,15 +1039,13 @@
1226
1039
  await this.loadMatches(matches);
1227
1040
  return matches;
1228
1041
  };
1229
- preloadRoute = async (navigateOpts = this.store.state.latestLocation, loaderOpts) => {
1042
+ preloadRoute = async (navigateOpts = this.store.state.latestLocation) => {
1230
1043
  const next = this.buildNext(navigateOpts);
1231
1044
  const matches = this.matchRoutes(next.pathname, {
1232
1045
  strictParseParams: true
1233
1046
  });
1234
1047
  await this.loadMatches(matches, {
1235
- preload: true,
1236
- maxAge: loaderOpts.maxAge ?? this.options.defaultPreloadMaxAge ?? this.options.defaultLoaderMaxAge ?? 0,
1237
- gcMaxAge: loaderOpts.gcMaxAge ?? this.options.defaultPreloadGcMaxAge ?? this.options.defaultLoaderGcMaxAge ?? 0
1048
+ preload: true
1238
1049
  });
1239
1050
  return matches;
1240
1051
  };
@@ -1288,7 +1099,9 @@
1288
1099
  foundRoutes.forEach(foundRoute => {
1289
1100
  const interpolatedPath = interpolatePath(foundRoute.path, params);
1290
1101
  const matchId = interpolatePath(foundRoute.id, params, true);
1291
- const match = existingMatches.find(d => d.id === matchId) || this.store.state.matchCache[matchId]?.match || new RouteMatch(this, foundRoute, {
1102
+ const match = existingMatches.find(d => d.id === matchId) ||
1103
+ // this.store.state.matchCache[matchId]?.match || // TODO:
1104
+ new RouteMatch(this, foundRoute, {
1292
1105
  id: matchId,
1293
1106
  params,
1294
1107
  pathname: joinPaths([this.basepath, interpolatedPath])
@@ -1305,7 +1118,7 @@
1305
1118
  return matches;
1306
1119
  };
1307
1120
  loadMatches = async (resolvedMatches, loaderOpts) => {
1308
- this.cleanMatchCache();
1121
+ // this.cleanMatchCache()
1309
1122
  resolvedMatches.forEach(async match => {
1310
1123
  // Validate the match (loads search params etc)
1311
1124
  match.__validate();
@@ -1331,7 +1144,7 @@
1331
1144
  if (search.__data?.matchId && search.__data.matchId !== match.id) {
1332
1145
  return;
1333
1146
  }
1334
- match.load(loaderOpts);
1147
+ match.load();
1335
1148
  if (match.store.state.status !== 'success' && match.__loadPromise) {
1336
1149
  // Wait for the first sign of activity from the match
1337
1150
  await match.__loadPromise;
@@ -1342,41 +1155,6 @@
1342
1155
  });
1343
1156
  await Promise.all(matchPromises);
1344
1157
  };
1345
- loadMatchData = async routeMatch => {
1346
- if (isServer || !this.options.useServerData) {
1347
- return (await routeMatch.route.options.loader?.({
1348
- // parentLoaderPromise: routeMatch.parentMatch.dataPromise,
1349
- params: routeMatch.params,
1350
- search: routeMatch.store.state.routeSearch,
1351
- signal: routeMatch.abortController.signal
1352
- })) || {};
1353
- } else {
1354
- // Refresh:
1355
- // '/dashboard'
1356
- // '/dashboard/invoices/'
1357
- // '/dashboard/invoices/123'
1358
-
1359
- // New:
1360
- // '/dashboard/invoices/456'
1361
-
1362
- // TODO: batch requests when possible
1363
-
1364
- const res = await this.options.fetchServerDataFn({
1365
- router: this,
1366
- routeMatch
1367
- });
1368
- return res;
1369
- }
1370
- };
1371
- invalidateRoute = async opts => {
1372
- const next = this.buildNext(opts);
1373
- const unloadedMatchIds = this.matchRoutes(next.pathname).map(d => d.id);
1374
- await Promise.allSettled([...this.store.state.currentMatches, ...(this.store.state.pendingMatches ?? [])].map(async match => {
1375
- if (unloadedMatchIds.includes(match.id)) {
1376
- return match.invalidate();
1377
- }
1378
- }));
1379
- };
1380
1158
  reload = () => {
1381
1159
  this.navigate({
1382
1160
  fromCurrent: true,
@@ -1494,9 +1272,6 @@
1494
1272
  const handleClick = e => {
1495
1273
  if (!disabled && !isCtrlEvent(e) && !e.defaultPrevented && (!target || target === '_self') && e.button === 0) {
1496
1274
  e.preventDefault();
1497
- if (pathIsEqual && !search && !hash) {
1498
- this.invalidateRoute(nextOpts);
1499
- }
1500
1275
 
1501
1276
  // All is well? Navigate!
1502
1277
  this.#commitLocation(nextOpts);
@@ -1506,10 +1281,7 @@
1506
1281
  // The click handler
1507
1282
  const handleFocus = e => {
1508
1283
  if (preload) {
1509
- this.preloadRoute(nextOpts, {
1510
- maxAge: userPreloadMaxAge,
1511
- gcMaxAge: userPreloadGcMaxAge
1512
- }).catch(err => {
1284
+ this.preloadRoute(nextOpts).catch(err => {
1513
1285
  console.warn(err);
1514
1286
  console.warn('Error preloading route! ☝️');
1515
1287
  });
@@ -1523,10 +1295,7 @@
1523
1295
  }
1524
1296
  target.preloadTimeout = setTimeout(() => {
1525
1297
  target.preloadTimeout = null;
1526
- this.preloadRoute(nextOpts, {
1527
- maxAge: userPreloadMaxAge,
1528
- gcMaxAge: userPreloadGcMaxAge
1529
- }).catch(err => {
1298
+ this.preloadRoute(nextOpts).catch(err => {
1530
1299
  console.warn(err);
1531
1300
  console.warn('Error preloading route! ☝️');
1532
1301
  });
@@ -1558,7 +1327,7 @@
1558
1327
  currentMatches: this.store.state.currentMatches.map(match => ({
1559
1328
  id: match.id,
1560
1329
  state: {
1561
- ...pick(match.store.state, ['status', 'routeLoaderData', 'invalidAt', 'invalid'])
1330
+ ...pick(match.store.state, ['status'])
1562
1331
  }
1563
1332
  }))
1564
1333
  },
@@ -1567,7 +1336,6 @@
1567
1336
  };
1568
1337
  hydrate = dehydratedRouter => {
1569
1338
  this.store.setState(s => {
1570
- // Update the context TODO: make this part of state?
1571
1339
  this.options.context = dehydratedRouter.context;
1572
1340
 
1573
1341
  // Match the routes
@@ -1576,54 +1344,20 @@
1576
1344
  });
1577
1345
  currentMatches.forEach((match, index) => {
1578
1346
  const dehydratedMatch = dehydratedRouter.state.currentMatches[index];
1579
- invariant(dehydratedMatch && dehydratedMatch.id === match.id, 'Oh no! There was a hydration mismatch when attempting to rethis.store the state of the router! 😬');
1580
- match.store.setState(s => {
1581
- Object.assign(s, dehydratedMatch.state);
1582
- });
1583
- match.setLoaderData(dehydratedMatch.state.routeLoaderData);
1347
+ invariant(dehydratedMatch && dehydratedMatch.id === match.id, 'Oh no! There was a hydration mismatch when attempting to hydrate the state of the router! 😬');
1348
+ match.store.setState(s => ({
1349
+ ...s,
1350
+ ...dehydratedMatch.state
1351
+ }));
1584
1352
  });
1585
1353
  currentMatches.forEach(match => match.__validate());
1586
- Object.assign(s, {
1354
+ return {
1355
+ ...s,
1587
1356
  ...dehydratedRouter.state,
1588
1357
  currentMatches
1589
- });
1358
+ };
1590
1359
  });
1591
1360
  };
1592
- getLoader = opts => {
1593
- const id = opts.from || '/';
1594
- const route = this.getRoute(id);
1595
- if (!route) return undefined;
1596
- let loader = this.store.state.loaders[id] || (() => {
1597
- this.store.setState(s => {
1598
- s.loaders[id] = {
1599
- pending: [],
1600
- fetch: async loaderContext => {
1601
- if (!route) {
1602
- return;
1603
- }
1604
- const loaderState = {
1605
- loadedAt: Date.now(),
1606
- loaderContext
1607
- };
1608
- this.store.setState(s => {
1609
- s.loaders[id].current = loaderState;
1610
- s.loaders[id].latest = loaderState;
1611
- s.loaders[id].pending.push(loaderState);
1612
- });
1613
- try {
1614
- return await route.options.loader?.(loaderContext);
1615
- } finally {
1616
- this.store.setState(s => {
1617
- s.loaders[id].pending = s.loaders[id].pending.filter(d => d !== loaderState);
1618
- });
1619
- }
1620
- }
1621
- };
1622
- });
1623
- return this.store.state.loaders[id];
1624
- })();
1625
- return loader;
1626
- };
1627
1361
  #buildRouteTree = rootRouteConfig => {
1628
1362
  const recurseRoutes = (routeConfigs, parent) => {
1629
1363
  return routeConfigs.map((routeConfig, i) => {
@@ -1747,17 +1481,24 @@
1747
1481
  latestLocation: null,
1748
1482
  currentLocation: null,
1749
1483
  currentMatches: [],
1750
- loaders: {},
1751
- lastUpdated: Date.now(),
1752
- matchCache: {},
1753
- get isFetching() {
1754
- return this.status === 'loading' || this.currentMatches.some(d => d.store.state.isFetching);
1755
- },
1756
- get isPreloading() {
1757
- return Object.values(this.matchCache).some(d => d.match.store.state.isFetching && !this.currentMatches.find(dd => dd.id === d.match.id));
1758
- }
1484
+ lastUpdated: Date.now()
1485
+ // matchCache: {}, // TODO:
1486
+ // get isFetching() {
1487
+ // return (
1488
+ // this.status === 'loading' ||
1489
+ // this.currentMatches.some((d) => d.store.state.isFetching)
1490
+ // )
1491
+ // },
1492
+ // get isPreloading() {
1493
+ // return Object.values(this.matchCache).some(
1494
+ // (d) =>
1495
+ // d.match.store.state.isFetching &&
1496
+ // !this.currentMatches.find((dd) => dd.id === d.match.id),
1497
+ // )
1498
+ // },
1759
1499
  };
1760
1500
  }
1501
+
1761
1502
  function isCtrlEvent(e) {
1762
1503
  return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
1763
1504
  }
@@ -1770,76 +1511,16 @@
1770
1511
  });
1771
1512
  }
1772
1513
 
1773
- // RouterAction is a constrained identify function that takes options: key, action, onSuccess, onError, onSettled, etc
1774
- function createAction(options) {
1775
- const store = createStore({
1776
- submissions: []
1777
- }, options.debug);
1778
- return {
1779
- options,
1780
- store,
1781
- reset: () => {
1782
- store.setState(s => {
1783
- s.submissions = [];
1784
- });
1785
- },
1786
- submit: async payload => {
1787
- const submission = {
1788
- submittedAt: Date.now(),
1789
- status: 'pending',
1790
- payload: payload,
1791
- invalidate: () => {
1792
- setSubmission(s => {
1793
- s.isInvalid = true;
1794
- });
1795
- },
1796
- getIsLatest: () => store.state.submissions[store.state.submissions.length - 1]?.submittedAt === submission.submittedAt
1797
- };
1798
- const setSubmission = updater => {
1799
- store.setState(s => {
1800
- const a = s.submissions.find(d => d.submittedAt === submission.submittedAt);
1801
- invariant(a, 'Could not find submission in store');
1802
- updater(a);
1803
- });
1804
- };
1805
- store.setState(s => {
1806
- s.submissions.push(submission);
1807
- s.submissions.reverse();
1808
- s.submissions = s.submissions.slice(0, options.maxSubmissions ?? 10);
1809
- s.submissions.reverse();
1810
- });
1811
- const after = async () => {
1812
- options.onEachSettled?.(submission);
1813
- if (submission.getIsLatest()) await options.onLatestSettled?.(submission);
1814
- };
1815
- try {
1816
- const res = await options.action?.(submission.payload);
1817
- setSubmission(s => {
1818
- s.response = res;
1819
- });
1820
- await options.onEachSuccess?.(submission);
1821
- if (submission.getIsLatest()) await options.onLatestSuccess?.(submission);
1822
- await after();
1823
- setSubmission(s => {
1824
- s.status = 'success';
1825
- });
1826
- return res;
1827
- } catch (err) {
1828
- console.error(err);
1829
- setSubmission(s => {
1830
- s.error = err;
1831
- });
1832
- await options.onEachError?.(submission);
1833
- if (submission.getIsLatest()) await options.onLatestError?.(submission);
1834
- await after();
1835
- setSubmission(s => {
1836
- s.status = 'error';
1837
- });
1838
- throw err;
1839
- }
1840
- }
1841
- };
1842
- }
1514
+ /**
1515
+ * react-store
1516
+ *
1517
+ * Copyright (c) TanStack
1518
+ *
1519
+ * This source code is licensed under the MIT license found in the
1520
+ * LICENSE.md file in the root directory of this source tree.
1521
+ *
1522
+ * @license MIT
1523
+ */
1843
1524
 
1844
1525
  function useStore(store, selector = d => d, compareShallow) {
1845
1526
  const slice = withSelector.useSyncExternalStoreWithSelector(store.subscribe, () => store.state, () => store.state, selector, compareShallow ? shallow : undefined);
@@ -2066,12 +1747,6 @@
2066
1747
  invariant(resolvedRoute, `Could not find a route for route "${routeId}"! Did you forget to add it to your route config?`);
2067
1748
  return resolvedRoute;
2068
1749
  }
2069
- function useLoaderData(opts) {
2070
- const match = useMatch(opts);
2071
- invariant(match, `Could not find ${opts?.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`);
2072
- useStore(match.store, d => opts?.track?.(d.loaderData) ?? d.loaderData);
2073
- return match.store.state.loaderData;
2074
- }
2075
1750
  function useSearch(opts) {
2076
1751
  const match = useMatch(opts);
2077
1752
  useStore(match.store, d => opts?.track?.(d.search) ?? d.search);
@@ -2144,7 +1819,7 @@
2144
1819
  if (props.match.store.state.status === 'success') {
2145
1820
  return /*#__PURE__*/React__namespace.createElement(props.match.component ?? router.options.defaultComponent ?? Outlet);
2146
1821
  }
2147
- if (props.match.store.state.status === 'loading') {
1822
+ if (props.match.store.state.status === 'pending') {
2148
1823
  throw props.match.__loadPromise;
2149
1824
  }
2150
1825
  invariant(false, 'Idle routeMatch status encountered during rendering! You should never see this. File an issue!');
@@ -2189,34 +1864,24 @@
2189
1864
  // router's location key changes.
2190
1865
  function CatchBoundaryInner(props) {
2191
1866
  const [activeErrorState, setActiveErrorState] = React__namespace.useState(props.errorState);
2192
- useRouter();
1867
+ const router = useRouter();
2193
1868
  const errorComponent = props.errorComponent ?? DefaultErrorBoundary;
2194
-
2195
- // React.useEffect(() => {
2196
- // if (activeErrorState) {
2197
- // let prevKey = router.store.state.currentLocation.key
2198
- // return createRoot((dispose) => {
2199
- // createEffect(() => {
2200
- // if (router.store.state.currentLocation.key !== prevKey) {
2201
- // prevKey = router.store.state.currentLocation.key
2202
- // setActiveErrorState({} as any)
2203
- // }
2204
- // })
2205
-
2206
- // return dispose
2207
- // })
2208
- // }
2209
-
2210
- // return
2211
- // }, [activeErrorState])
2212
-
1869
+ const prevKeyRef = React__namespace.useRef('');
1870
+ React__namespace.useEffect(() => {
1871
+ if (activeErrorState) {
1872
+ if (router.store.state.currentLocation.key !== prevKeyRef.current) {
1873
+ setActiveErrorState({});
1874
+ }
1875
+ }
1876
+ prevKeyRef.current = router.store.state.currentLocation.key;
1877
+ }, [activeErrorState, router.store.state.currentLocation.key]);
2213
1878
  React__namespace.useEffect(() => {
2214
1879
  if (props.errorState.error) {
2215
1880
  setActiveErrorState(props.errorState);
2216
1881
  }
2217
- props.reset();
1882
+ // props.reset()
2218
1883
  }, [props.errorState.error]);
2219
- if (props.errorState.error) {
1884
+ if (props.errorState.error && activeErrorState.error) {
2220
1885
  return /*#__PURE__*/React__namespace.createElement(errorComponent, activeErrorState);
2221
1886
  }
2222
1887
  return props.children;
@@ -2247,16 +1912,6 @@
2247
1912
  }
2248
1913
  }, error.message) : null)));
2249
1914
  }
2250
- function useAction(action, opts) {
2251
- useStore(action.store, d => opts?.track?.(d) ?? d, true);
2252
- const [ref] = React__namespace.useState({});
2253
- Object.assign(ref, {
2254
- ...action,
2255
- latestSubmission: action.store.state.submissions[action.store.state.submissions.length - 1],
2256
- pendingSubmissions: React__namespace.useMemo(() => action.store.state.submissions.filter(d => d.status === 'pending'), [action.store.state.submissions])
2257
- });
2258
- return ref;
2259
- }
2260
1915
 
2261
1916
  // TODO: While we migrate away from the history package, these need to be disabled
2262
1917
  // export function usePrompt(message: string, when: boolean | any): void {
@@ -2294,14 +1949,11 @@
2294
1949
  exports.RouteMatch = RouteMatch;
2295
1950
  exports.Router = Router;
2296
1951
  exports.RouterProvider = RouterProvider;
2297
- exports.batch = batch;
2298
1952
  exports.cleanPath = cleanPath;
2299
- exports.createAction = createAction;
2300
1953
  exports.createBrowserHistory = createBrowserHistory;
2301
1954
  exports.createHashHistory = createHashHistory;
2302
1955
  exports.createMemoryHistory = createMemoryHistory;
2303
1956
  exports.createRouteConfig = createRouteConfig;
2304
- exports.createStore = createStore;
2305
1957
  exports.decode = decode;
2306
1958
  exports.defaultFetchServerDataFn = defaultFetchServerDataFn;
2307
1959
  exports.defaultParseSearch = defaultParseSearch;
@@ -2310,6 +1962,7 @@
2310
1962
  exports.functionalUpdate = functionalUpdate;
2311
1963
  exports.interpolatePath = interpolatePath;
2312
1964
  exports.invariant = invariant;
1965
+ exports.isPlainObject = isPlainObject;
2313
1966
  exports.joinPaths = joinPaths;
2314
1967
  exports.last = last;
2315
1968
  exports.lazy = lazy;
@@ -2324,13 +1977,10 @@
2324
1977
  exports.rootRouteId = rootRouteId;
2325
1978
  exports.routerContext = routerContext;
2326
1979
  exports.stringifySearchWith = stringifySearchWith;
2327
- exports.trackDeep = trackDeep;
2328
1980
  exports.trimPath = trimPath;
2329
1981
  exports.trimPathLeft = trimPathLeft;
2330
1982
  exports.trimPathRight = trimPathRight;
2331
- exports.useAction = useAction;
2332
1983
  exports.useLinkProps = useLinkProps;
2333
- exports.useLoaderData = useLoaderData;
2334
1984
  exports.useMatch = useMatch;
2335
1985
  exports.useMatchRoute = useMatchRoute;
2336
1986
  exports.useMatches = useMatches;