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