reactive-route 0.0.1-alpha.0 → 0.0.1-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/adapters/kr-observable/index.js +40 -0
- package/dist/cjs/adapters/kr-observable/package.json +1 -0
- package/dist/cjs/adapters/mobx/index.js +44 -0
- package/dist/cjs/adapters/mobx/package.json +1 -0
- package/dist/cjs/adapters/solid/index.js +48 -0
- package/dist/cjs/adapters/solid/package.json +1 -0
- package/dist/cjs/index.js +204 -13
- package/dist/cjs/react/index.js +56 -98
- package/dist/cjs/solid/index.js +38 -97
- package/dist/esm/adapters/kr-observable/index.js +19 -0
- package/dist/esm/adapters/kr-observable/package.json +1 -0
- package/dist/esm/adapters/mobx/index.js +23 -0
- package/dist/esm/adapters/mobx/package.json +1 -0
- package/dist/esm/adapters/solid/index.js +27 -0
- package/dist/esm/adapters/solid/package.json +1 -0
- package/dist/esm/index.js +204 -13
- package/dist/esm/react/index.js +56 -98
- package/dist/esm/solid/index.js +37 -96
- package/dist/types/adapters/kr-observable.d.ts +3 -0
- package/dist/types/adapters/kr-observable.d.ts.map +1 -0
- package/dist/types/adapters/mobx.d.ts +3 -0
- package/dist/types/adapters/mobx.d.ts.map +1 -0
- package/dist/types/adapters/solid.d.ts +3 -0
- package/dist/types/adapters/solid.d.ts.map +1 -0
- package/dist/types/core/createRouterConfig.d.ts +2 -6
- package/dist/types/core/createRouterConfig.d.ts.map +1 -1
- package/dist/types/core/createRouterStore.d.ts +2 -11
- package/dist/types/core/createRouterStore.d.ts.map +1 -1
- package/dist/types/core/index.d.ts +3 -1
- package/dist/types/core/index.d.ts.map +1 -1
- package/dist/types/core/types/InterfaceRouterStore.d.ts +22 -1
- package/dist/types/core/types/InterfaceRouterStore.d.ts.map +1 -1
- package/dist/types/core/types/TypeLifecycleConfig.d.ts +13 -0
- package/dist/types/core/types/TypeLifecycleConfig.d.ts.map +1 -0
- package/dist/types/core/types/TypePropsRouter.d.ts +10 -0
- package/dist/types/core/types/TypePropsRouter.d.ts.map +1 -0
- package/dist/types/core/types/TypeRouteRaw.d.ts +3 -24
- package/dist/types/core/types/TypeRouteRaw.d.ts.map +1 -1
- package/dist/types/react/Router.d.ts +3 -11
- package/dist/types/react/Router.d.ts.map +1 -1
- package/dist/types/solid/Router.d.ts +2 -10
- package/dist/types/solid/Router.d.ts.map +1 -1
- package/dist/types/tsconfig.types.react.tsbuildinfo +1 -0
- package/dist/types/tsconfig.types.solid.tsbuildinfo +1 -0
- package/package.json +48 -21
- package/tsconfig.solid.json +9 -0
- package/tsconfig.types.react.json +11 -0
- package/tsconfig.types.solid.json +14 -0
- package/dist/types/react/useStore.d.ts +0 -8
- package/dist/types/react/useStore.d.ts.map +0 -1
- package/dist/types/solid/replaceObject.d.ts +0 -2
- package/dist/types/solid/replaceObject.d.ts.map +0 -1
- package/dist/types/solid/useStore.d.ts +0 -7
- package/dist/types/solid/useStore.d.ts.map +0 -1
- package/dist/types/tsconfig.types.tsbuildinfo +0 -1
package/dist/cjs/solid/index.js
CHANGED
|
@@ -28,133 +28,74 @@ module.exports = __toCommonJS(solid_exports);
|
|
|
28
28
|
var import_web = require("solid-js/web");
|
|
29
29
|
var import_web2 = require("solid-js/web");
|
|
30
30
|
var import_reactive_route = require("reactive-route");
|
|
31
|
-
var import_solid_js2 = require("solid-js");
|
|
32
|
-
var import_store2 = require("solid-js/store");
|
|
33
|
-
var import_web3 = require("solid-js/web");
|
|
34
|
-
|
|
35
|
-
// packages/solid/replaceObject.ts
|
|
36
|
-
var import_store = require("solid-js/store");
|
|
37
|
-
function replaceObject(obj, newObj) {
|
|
38
|
-
(0, import_store.modifyMutable)(obj, (0, import_store.produce)((state) => {
|
|
39
|
-
if (typeof state === "object" && state != null) {
|
|
40
|
-
for (const variableKey in state) {
|
|
41
|
-
delete state[variableKey];
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
Object.assign(state || {}, newObj);
|
|
45
|
-
}));
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// packages/solid/useStore.ts
|
|
49
31
|
var import_solid_js = require("solid-js");
|
|
50
|
-
var
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
} while ((object = Reflect.getPrototypeOf(object)) && object !== Object.prototype);
|
|
57
|
-
return properties;
|
|
58
|
-
};
|
|
59
|
-
function autoBind(self) {
|
|
60
|
-
for (const [object, key] of getAllProperties(self.constructor.prototype)) {
|
|
61
|
-
if (key === "constructor") continue;
|
|
62
|
-
const descriptor = Reflect.getOwnPropertyDescriptor(object, key);
|
|
63
|
-
if (descriptor && typeof descriptor.value === "function") {
|
|
64
|
-
self[key] = self[key].bind(self);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
return self;
|
|
68
|
-
}
|
|
69
|
-
function useStore(ViewModel, props) {
|
|
70
|
-
const vm = new ViewModel(props);
|
|
71
|
-
autoBind(vm);
|
|
72
|
-
vm.beforeMount?.();
|
|
73
|
-
(0, import_solid_js.onMount)(() => {
|
|
74
|
-
vm.afterMount?.();
|
|
32
|
+
var import_web3 = require("solid-js/web");
|
|
33
|
+
function Router(props) {
|
|
34
|
+
const config = props.routerStore.adapters.makeObservable({
|
|
35
|
+
loadedComponentName: void 0,
|
|
36
|
+
loadedComponentPage: void 0,
|
|
37
|
+
currentProps: {}
|
|
75
38
|
});
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// packages/solid/Router.tsx
|
|
80
|
-
var VM = class {
|
|
81
|
-
constructor(props) {
|
|
82
|
-
this.props = props;
|
|
83
|
-
return (0, import_store2.createMutable)(this);
|
|
84
|
-
}
|
|
85
|
-
loadedComponentName = void 0;
|
|
86
|
-
loadedComponentPage = void 0;
|
|
87
|
-
currentProps = {};
|
|
88
|
-
beforeMount() {
|
|
89
|
-
this.props.beforeMount?.();
|
|
90
|
-
this.redirectOnHistoryPop();
|
|
91
|
-
(0, import_solid_js2.createRenderEffect)(() => this.setLoadedComponent());
|
|
92
|
-
}
|
|
93
|
-
redirectOnHistoryPop() {
|
|
39
|
+
function redirectOnHistoryPop() {
|
|
94
40
|
if (!import_reactive_route.history) return;
|
|
95
41
|
import_reactive_route.history.listen((params) => {
|
|
96
42
|
if (params.action !== "POP") return;
|
|
97
|
-
const previousRoutePathname =
|
|
43
|
+
const previousRoutePathname = props.routerStore.routesHistory[props.routerStore.routesHistory.length - 2];
|
|
98
44
|
if (previousRoutePathname === params.location.pathname) {
|
|
99
|
-
|
|
45
|
+
props.routerStore.routesHistory.pop();
|
|
100
46
|
}
|
|
101
|
-
void
|
|
47
|
+
void props.routerStore.redirectTo({
|
|
102
48
|
noHistoryPush: true,
|
|
103
49
|
...(0, import_reactive_route.getInitialRoute)({
|
|
104
|
-
routes:
|
|
50
|
+
routes: props.routes,
|
|
105
51
|
pathname: import_reactive_route.history.location.pathname,
|
|
106
52
|
fallback: "error404"
|
|
107
53
|
})
|
|
108
54
|
});
|
|
109
55
|
});
|
|
110
56
|
}
|
|
111
|
-
setLoadedComponent() {
|
|
112
|
-
const currentRouteName =
|
|
113
|
-
const currentRoutePage =
|
|
57
|
+
function setLoadedComponent() {
|
|
58
|
+
const currentRouteName = props.routerStore.currentRoute.name;
|
|
59
|
+
const currentRoutePage = props.routerStore.currentRoute.pageName;
|
|
60
|
+
const componentConfig = props.routes[currentRouteName];
|
|
114
61
|
let preventRedirect = false;
|
|
115
|
-
if (
|
|
116
|
-
else if (
|
|
62
|
+
if (props.routerStore.isRedirecting) preventRedirect = true;
|
|
63
|
+
else if (config.loadedComponentName === currentRouteName) {
|
|
117
64
|
preventRedirect = true;
|
|
118
|
-
} else if (
|
|
119
|
-
if (
|
|
120
|
-
|
|
121
|
-
replaceObject(this.currentProps, "props" in componentConfig ? componentConfig.props : {});
|
|
65
|
+
} else if (config.loadedComponentPage != null && currentRouteName != null) {
|
|
66
|
+
if (config.loadedComponentPage === currentRoutePage) {
|
|
67
|
+
props.routerStore.adapters.replaceObject(config.currentProps, "props" in componentConfig ? componentConfig.props : {});
|
|
122
68
|
preventRedirect = true;
|
|
123
69
|
}
|
|
124
70
|
}
|
|
125
71
|
if (preventRedirect) return;
|
|
126
|
-
|
|
127
|
-
if (
|
|
128
|
-
|
|
129
|
-
} else {
|
|
130
|
-
this.props.beforeUpdatePageComponent?.();
|
|
131
|
-
this.setComponent();
|
|
72
|
+
props.routerStore.adapters.batch(() => {
|
|
73
|
+
if (config.loadedComponentName) {
|
|
74
|
+
props.beforeUpdatePageComponent?.();
|
|
132
75
|
}
|
|
76
|
+
props.beforeSetPageComponent?.(componentConfig);
|
|
77
|
+
props.routerStore.adapters.batch(() => {
|
|
78
|
+
props.routerStore.adapters.replaceObject(config.currentProps, "props" in componentConfig ? componentConfig.props : {});
|
|
79
|
+
config.loadedComponentName = currentRouteName;
|
|
80
|
+
config.loadedComponentPage = componentConfig.pageName;
|
|
81
|
+
config[Symbol.for("$adm")]?.batch();
|
|
82
|
+
});
|
|
133
83
|
});
|
|
134
84
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
replaceObject(this.currentProps, "props" in componentConfig ? componentConfig.props : {});
|
|
141
|
-
this.loadedComponentName = currentRouteName;
|
|
142
|
-
this.loadedComponentPage = componentConfig.pageName;
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
};
|
|
146
|
-
function Router(props) {
|
|
147
|
-
const vm = useStore(VM, props);
|
|
148
|
-
return (0, import_web.createComponent)(import_solid_js2.Show, {
|
|
85
|
+
props.beforeMount?.();
|
|
86
|
+
redirectOnHistoryPop();
|
|
87
|
+
setLoadedComponent();
|
|
88
|
+
props.routerStore.adapters.autorun(() => setLoadedComponent());
|
|
89
|
+
return (0, import_web.createComponent)(import_solid_js.Show, {
|
|
149
90
|
get when() {
|
|
150
|
-
return
|
|
91
|
+
return config.loadedComponentName;
|
|
151
92
|
},
|
|
152
93
|
get children() {
|
|
153
94
|
return (0, import_web.createComponent)(import_web3.Dynamic, (0, import_web2.mergeProps)({
|
|
154
95
|
get component() {
|
|
155
|
-
return props.routes[
|
|
96
|
+
return props.routes[config.loadedComponentName]?.component || void 0;
|
|
156
97
|
}
|
|
157
|
-
}, () =>
|
|
98
|
+
}, () => config.currentProps));
|
|
158
99
|
}
|
|
159
100
|
});
|
|
160
101
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// packages/adapters/kr-observable.ts
|
|
2
|
+
import { autorun, makeObservable } from "kr-observable";
|
|
3
|
+
import { observer } from "kr-observable/react";
|
|
4
|
+
var adapters = {
|
|
5
|
+
batch: (cb) => cb(),
|
|
6
|
+
autorun,
|
|
7
|
+
replaceObject: (obj, newObj) => {
|
|
8
|
+
for (const variableKey in obj) {
|
|
9
|
+
delete obj[variableKey];
|
|
10
|
+
}
|
|
11
|
+
Object.assign(obj, newObj);
|
|
12
|
+
},
|
|
13
|
+
makeObservable,
|
|
14
|
+
makeAutoObservable: makeObservable,
|
|
15
|
+
observer
|
|
16
|
+
};
|
|
17
|
+
export {
|
|
18
|
+
adapters
|
|
19
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type": "module"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// packages/adapters/mobx.ts
|
|
2
|
+
import { autorun, makeAutoObservable, observable, runInAction } from "mobx";
|
|
3
|
+
import { observer } from "mobx-react-lite";
|
|
4
|
+
var adapters = {
|
|
5
|
+
batch: runInAction,
|
|
6
|
+
autorun,
|
|
7
|
+
observer,
|
|
8
|
+
replaceObject: (obj, newObj) => {
|
|
9
|
+
runInAction(() => {
|
|
10
|
+
for (const variableKey in obj) {
|
|
11
|
+
if (obj.hasOwnProperty(variableKey)) {
|
|
12
|
+
delete obj[variableKey];
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
Object.assign(obj, newObj);
|
|
16
|
+
});
|
|
17
|
+
},
|
|
18
|
+
makeObservable: observable,
|
|
19
|
+
makeAutoObservable
|
|
20
|
+
};
|
|
21
|
+
export {
|
|
22
|
+
adapters
|
|
23
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type": "module"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// packages/adapters/solid.ts
|
|
2
|
+
import { batch, createRenderEffect } from "solid-js";
|
|
3
|
+
import { createMutable, modifyMutable, produce } from "solid-js/store";
|
|
4
|
+
var adapters = {
|
|
5
|
+
batch,
|
|
6
|
+
autorun: createRenderEffect,
|
|
7
|
+
replaceObject: (obj, newObj) => {
|
|
8
|
+
modifyMutable(
|
|
9
|
+
obj,
|
|
10
|
+
produce((state) => {
|
|
11
|
+
if (typeof state === "object" && state != null) {
|
|
12
|
+
for (const variableKey in state) {
|
|
13
|
+
if (state.hasOwnProperty(variableKey)) {
|
|
14
|
+
delete state[variableKey];
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
Object.assign(state || {}, newObj);
|
|
19
|
+
})
|
|
20
|
+
);
|
|
21
|
+
},
|
|
22
|
+
makeObservable: createMutable,
|
|
23
|
+
makeAutoObservable: createMutable
|
|
24
|
+
};
|
|
25
|
+
export {
|
|
26
|
+
adapters
|
|
27
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type": "module"}
|
package/dist/esm/index.js
CHANGED
|
@@ -11,6 +11,9 @@ function createRouterConfig(config) {
|
|
|
11
11
|
return addNames(config);
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
// packages/core/createRouterStore.ts
|
|
15
|
+
import queryString2 from "query-string";
|
|
16
|
+
|
|
14
17
|
// packages/core/utils/constants.ts
|
|
15
18
|
var constants = {
|
|
16
19
|
dynamicSeparator: ":",
|
|
@@ -31,6 +34,19 @@ function isDynamicRoute(route) {
|
|
|
31
34
|
return "params" in route;
|
|
32
35
|
}
|
|
33
36
|
|
|
37
|
+
// packages/core/utils/getDynamicValues.ts
|
|
38
|
+
function getDynamicValues(params) {
|
|
39
|
+
const { route, pathname } = params;
|
|
40
|
+
const pathnameArray = pathname.replace(/\?.+$/, "").split(constants.pathPartSeparator).filter(Boolean).map((str) => decodeURIComponent(str));
|
|
41
|
+
const routePathnameArray = route.path.split(constants.pathPartSeparator).filter(Boolean);
|
|
42
|
+
const dynamicParams = {};
|
|
43
|
+
for (let i = 0; i < routePathnameArray.length; i++) {
|
|
44
|
+
const paramName = routePathnameArray[i];
|
|
45
|
+
if (isDynamic(paramName)) dynamicParams[clearDynamic(paramName)] = pathnameArray[i];
|
|
46
|
+
}
|
|
47
|
+
return dynamicParams;
|
|
48
|
+
}
|
|
49
|
+
|
|
34
50
|
// packages/core/utils/findRouteByPathname.ts
|
|
35
51
|
function completeStaticMatch(pathname, path) {
|
|
36
52
|
return !path.includes(constants.dynamicSeparator) && (pathname === path || pathname === `${path}${constants.pathPartSeparator}`);
|
|
@@ -62,19 +78,6 @@ function findRouteByPathname({
|
|
|
62
78
|
return dynamicRouteMatch;
|
|
63
79
|
}
|
|
64
80
|
|
|
65
|
-
// packages/core/utils/getDynamicValues.ts
|
|
66
|
-
function getDynamicValues(params) {
|
|
67
|
-
const { route, pathname } = params;
|
|
68
|
-
const pathnameArray = pathname.replace(/\?.+$/, "").split(constants.pathPartSeparator).filter(Boolean).map((str) => decodeURIComponent(str));
|
|
69
|
-
const routePathnameArray = route.path.split(constants.pathPartSeparator).filter(Boolean);
|
|
70
|
-
const dynamicParams = {};
|
|
71
|
-
for (let i = 0; i < routePathnameArray.length; i++) {
|
|
72
|
-
const paramName = routePathnameArray[i];
|
|
73
|
-
if (isDynamic(paramName)) dynamicParams[clearDynamic(paramName)] = pathnameArray[i];
|
|
74
|
-
}
|
|
75
|
-
return dynamicParams;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
81
|
// packages/core/utils/getQueryValues.ts
|
|
79
82
|
import queryString from "query-string";
|
|
80
83
|
|
|
@@ -142,8 +145,196 @@ function replaceDynamicValues({
|
|
|
142
145
|
return encodeURIComponent(value);
|
|
143
146
|
});
|
|
144
147
|
}
|
|
148
|
+
|
|
149
|
+
// packages/core/createRouterStore.ts
|
|
150
|
+
function createRouterStore({
|
|
151
|
+
adapters,
|
|
152
|
+
routes,
|
|
153
|
+
routeError500,
|
|
154
|
+
lifecycleParams
|
|
155
|
+
}) {
|
|
156
|
+
const routerStore = adapters.makeObservable({
|
|
157
|
+
routesHistory: [],
|
|
158
|
+
currentRoute: {},
|
|
159
|
+
isRedirecting: false,
|
|
160
|
+
redirectTo: void 0,
|
|
161
|
+
restoreFromURL: void 0,
|
|
162
|
+
restoreFromServer: void 0,
|
|
163
|
+
adapters
|
|
164
|
+
});
|
|
165
|
+
routerStore.restoreFromServer = function restoreFromServer(obj) {
|
|
166
|
+
adapters.batch(() => {
|
|
167
|
+
routerStore.routesHistory.push(...obj.routesHistory || []);
|
|
168
|
+
Object.assign(routerStore.currentRoute, obj.currentRoute);
|
|
169
|
+
});
|
|
170
|
+
const preloadedRouteName = Object.keys(routes).find(
|
|
171
|
+
(routeName) => routerStore.currentRoute.name === routeName
|
|
172
|
+
);
|
|
173
|
+
return loadComponentToConfig({ route: routes[preloadedRouteName] });
|
|
174
|
+
};
|
|
175
|
+
routerStore.restoreFromURL = function restoreFromURL(params) {
|
|
176
|
+
return routerStore.redirectTo(getInitialRoute({ routes, ...params }));
|
|
177
|
+
};
|
|
178
|
+
routerStore.redirectTo = async function redirectTo(config) {
|
|
179
|
+
const { route: routeName, noHistoryPush, asClient } = config;
|
|
180
|
+
const isClient = typeof asClient === "boolean" ? asClient : constants.isClient;
|
|
181
|
+
let currentRoute;
|
|
182
|
+
let currentPathname;
|
|
183
|
+
let currentUrl;
|
|
184
|
+
let currentSearch;
|
|
185
|
+
let currentQuery;
|
|
186
|
+
if (routerStore.currentRoute?.name) {
|
|
187
|
+
currentRoute = routes[routerStore.currentRoute.name];
|
|
188
|
+
currentPathname = replaceDynamicValues({
|
|
189
|
+
route: currentRoute,
|
|
190
|
+
params: routerStore.currentRoute.params
|
|
191
|
+
});
|
|
192
|
+
currentUrl = queryString2.stringifyUrl({
|
|
193
|
+
url: currentPathname,
|
|
194
|
+
query: routerStore.currentRoute.query
|
|
195
|
+
});
|
|
196
|
+
currentQuery = routerStore.currentRoute.query;
|
|
197
|
+
currentSearch = queryString2.stringify(routerStore.currentRoute.query);
|
|
198
|
+
}
|
|
199
|
+
const nextRoute = routes[routeName];
|
|
200
|
+
const nextPathname = replaceDynamicValues({
|
|
201
|
+
route: nextRoute,
|
|
202
|
+
params: "params" in config ? config.params : void 0
|
|
203
|
+
});
|
|
204
|
+
let nextQuery;
|
|
205
|
+
let nextUrl = nextPathname;
|
|
206
|
+
let nextSearch;
|
|
207
|
+
if ("query" in config && config.query) {
|
|
208
|
+
const clearedQuery = getQueryValues({
|
|
209
|
+
route: nextRoute,
|
|
210
|
+
pathname: `${nextPathname}?${queryString2.stringify(config.query)}`
|
|
211
|
+
});
|
|
212
|
+
if (Object.keys(clearedQuery).length > 0) {
|
|
213
|
+
nextQuery = clearedQuery;
|
|
214
|
+
nextSearch = queryString2.stringify(clearedQuery);
|
|
215
|
+
nextUrl = queryString2.stringifyUrl({ url: nextPathname, query: clearedQuery });
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
if (currentUrl === nextUrl) return Promise.resolve();
|
|
219
|
+
if (currentPathname === nextPathname) {
|
|
220
|
+
if (currentSearch !== nextSearch) {
|
|
221
|
+
adapters.batch(() => {
|
|
222
|
+
adapters.replaceObject(routerStore.currentRoute.query, nextQuery || {});
|
|
223
|
+
routerStore.routesHistory.push(nextUrl);
|
|
224
|
+
});
|
|
225
|
+
if (history && !noHistoryPush) {
|
|
226
|
+
history.push({
|
|
227
|
+
hash: history.location.hash,
|
|
228
|
+
search: nextSearch,
|
|
229
|
+
pathname: nextPathname
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return Promise.resolve();
|
|
234
|
+
}
|
|
235
|
+
adapters.batch(() => {
|
|
236
|
+
routerStore.isRedirecting = true;
|
|
237
|
+
});
|
|
238
|
+
try {
|
|
239
|
+
await currentRoute?.beforeLeave?.(
|
|
240
|
+
{
|
|
241
|
+
nextUrl,
|
|
242
|
+
nextRoute,
|
|
243
|
+
nextQuery,
|
|
244
|
+
nextSearch,
|
|
245
|
+
nextPathname,
|
|
246
|
+
currentUrl,
|
|
247
|
+
currentQuery,
|
|
248
|
+
currentRoute,
|
|
249
|
+
currentSearch,
|
|
250
|
+
currentPathname
|
|
251
|
+
},
|
|
252
|
+
...lifecycleParams || []
|
|
253
|
+
);
|
|
254
|
+
const redirectConfig = await nextRoute.beforeEnter?.(
|
|
255
|
+
{
|
|
256
|
+
nextUrl,
|
|
257
|
+
nextRoute,
|
|
258
|
+
nextQuery,
|
|
259
|
+
nextSearch,
|
|
260
|
+
nextPathname,
|
|
261
|
+
currentUrl,
|
|
262
|
+
currentQuery,
|
|
263
|
+
currentRoute,
|
|
264
|
+
currentSearch,
|
|
265
|
+
currentPathname
|
|
266
|
+
},
|
|
267
|
+
...lifecycleParams || []
|
|
268
|
+
);
|
|
269
|
+
if (typeof redirectConfig === "object") {
|
|
270
|
+
if (isClient) return redirectTo({ ...redirectConfig, asClient });
|
|
271
|
+
const redirectRoute = routes[redirectConfig.route];
|
|
272
|
+
const redirectParams = "params" in redirectConfig && redirectConfig.params ? redirectConfig.params : void 0;
|
|
273
|
+
let redirectUrl = replaceDynamicValues({
|
|
274
|
+
params: redirectParams,
|
|
275
|
+
route: redirectRoute
|
|
276
|
+
});
|
|
277
|
+
if ("query" in redirectConfig && redirectConfig.query) {
|
|
278
|
+
const clearedQuery = getQueryValues({
|
|
279
|
+
route: nextRoute,
|
|
280
|
+
pathname: `${nextPathname}?${queryString2.stringify(redirectConfig.query)}`
|
|
281
|
+
});
|
|
282
|
+
if (Object.keys(clearedQuery).length > 0) {
|
|
283
|
+
redirectUrl = queryString2.stringifyUrl({ url: redirectUrl, query: clearedQuery });
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
throw Object.assign(new Error(redirectUrl), { name: constants.errorRedirect });
|
|
287
|
+
}
|
|
288
|
+
await loadComponentToConfig({ route: routes[nextRoute.name] });
|
|
289
|
+
} catch (error) {
|
|
290
|
+
if (error?.name === constants.errorPrevent) return Promise.resolve();
|
|
291
|
+
if (error?.name === constants.errorRedirect) {
|
|
292
|
+
throw error;
|
|
293
|
+
}
|
|
294
|
+
console.error(error);
|
|
295
|
+
await loadComponentToConfig({ route: routeError500 });
|
|
296
|
+
adapters.batch(() => {
|
|
297
|
+
adapters.replaceObject(routerStore.currentRoute, {
|
|
298
|
+
name: routeError500.name,
|
|
299
|
+
path: routeError500.path,
|
|
300
|
+
props: routes[routeError500.name].props,
|
|
301
|
+
query: {},
|
|
302
|
+
params: {},
|
|
303
|
+
pageName: routes[routeError500.name].pageName
|
|
304
|
+
});
|
|
305
|
+
routerStore.isRedirecting = false;
|
|
306
|
+
});
|
|
307
|
+
return Promise.resolve();
|
|
308
|
+
}
|
|
309
|
+
adapters.batch(() => {
|
|
310
|
+
adapters.replaceObject(routerStore.currentRoute, {
|
|
311
|
+
name: nextRoute.name,
|
|
312
|
+
path: nextRoute.path,
|
|
313
|
+
props: routes[nextRoute.name].props,
|
|
314
|
+
query: getQueryValues({ route: nextRoute, pathname: nextUrl }),
|
|
315
|
+
params: getDynamicValues({ route: nextRoute, pathname: nextUrl }),
|
|
316
|
+
pageName: routes[nextRoute.name].pageName
|
|
317
|
+
});
|
|
318
|
+
const lastUrl = routerStore.routesHistory[routerStore.routesHistory.length - 1];
|
|
319
|
+
if (lastUrl !== nextUrl) {
|
|
320
|
+
routerStore.routesHistory.push(nextUrl);
|
|
321
|
+
}
|
|
322
|
+
if (history && !noHistoryPush) {
|
|
323
|
+
history.push({
|
|
324
|
+
hash: history.location.hash,
|
|
325
|
+
search: "query" in config ? `?${queryString2.stringify(config.query)}` : "",
|
|
326
|
+
pathname: nextPathname
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
routerStore.isRedirecting = false;
|
|
330
|
+
});
|
|
331
|
+
return Promise.resolve();
|
|
332
|
+
};
|
|
333
|
+
return routerStore;
|
|
334
|
+
}
|
|
145
335
|
export {
|
|
146
336
|
createRouterConfig,
|
|
337
|
+
createRouterStore,
|
|
147
338
|
findRouteByPathname,
|
|
148
339
|
getInitialRoute,
|
|
149
340
|
history,
|
package/dist/esm/react/index.js
CHANGED
|
@@ -1,125 +1,83 @@
|
|
|
1
1
|
// packages/react/Router.tsx
|
|
2
|
-
import {
|
|
3
|
-
import { observer } from "mobx-react-lite";
|
|
2
|
+
import { memo, useCallback, useEffect, useRef, useState } from "react";
|
|
4
3
|
import { getInitialRoute, history } from "reactive-route";
|
|
5
|
-
|
|
6
|
-
// packages/react/useStore.ts
|
|
7
|
-
import { runInAction } from "mobx";
|
|
8
|
-
import { useEffect, useRef, useState } from "react";
|
|
9
|
-
function useStore(ViewModel, props) {
|
|
10
|
-
const isFirstRenderRef = useRef(true);
|
|
11
|
-
const [vm] = useState(() => {
|
|
12
|
-
const instance = new ViewModel(props || {});
|
|
13
|
-
runInAction(() => {
|
|
14
|
-
instance.beforeMount?.();
|
|
15
|
-
});
|
|
16
|
-
return instance;
|
|
17
|
-
});
|
|
18
|
-
useEffect(() => {
|
|
19
|
-
if (isFirstRenderRef.current) {
|
|
20
|
-
isFirstRenderRef.current = false;
|
|
21
|
-
} else if (props) {
|
|
22
|
-
runInAction(() => {
|
|
23
|
-
vm.props = props || {};
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
}, [props]);
|
|
27
|
-
useEffect(() => {
|
|
28
|
-
vm.afterMount?.();
|
|
29
|
-
return () => {
|
|
30
|
-
vm.autorunDisposers?.forEach((disposer) => disposer());
|
|
31
|
-
};
|
|
32
|
-
}, []);
|
|
33
|
-
return vm;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// packages/react/Router.tsx
|
|
37
4
|
import { jsx } from "react/jsx-runtime";
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
makeAutoObservable(
|
|
42
|
-
this,
|
|
43
|
-
{ loadedComponent: false, setLoadedComponent: false, props: false },
|
|
44
|
-
{ autoBind: true }
|
|
45
|
-
);
|
|
46
|
-
}
|
|
47
|
-
autorunDisposers = [];
|
|
48
|
-
loadedComponentName = void 0;
|
|
49
|
-
loadedComponentPage = void 0;
|
|
50
|
-
loadedComponent;
|
|
51
|
-
currentProps = {};
|
|
52
|
-
beforeMount() {
|
|
53
|
-
this.props.beforeMount?.();
|
|
54
|
-
this.redirectOnHistoryPop();
|
|
55
|
-
this.setLoadedComponent();
|
|
56
|
-
this.autorunDisposers.push(autorun(this.setLoadedComponent));
|
|
57
|
-
}
|
|
58
|
-
redirectOnHistoryPop() {
|
|
5
|
+
function RouterInner(props) {
|
|
6
|
+
const disposerRef = useRef(null);
|
|
7
|
+
const redirectOnHistoryPop = useCallback(() => {
|
|
59
8
|
if (!history) return;
|
|
60
9
|
history.listen((params) => {
|
|
61
10
|
if (params.action !== "POP") return;
|
|
62
|
-
const previousRoutePathname =
|
|
11
|
+
const previousRoutePathname = props.routerStore.routesHistory[props.routerStore.routesHistory.length - 2];
|
|
63
12
|
if (previousRoutePathname === params.location.pathname) {
|
|
64
|
-
|
|
13
|
+
props.routerStore.adapters.batch(() => props.routerStore.routesHistory.pop());
|
|
65
14
|
}
|
|
66
|
-
void
|
|
15
|
+
void props.routerStore.redirectTo({
|
|
67
16
|
noHistoryPush: true,
|
|
68
17
|
...getInitialRoute({
|
|
69
|
-
routes:
|
|
18
|
+
routes: props.routes,
|
|
70
19
|
pathname: history.location.pathname,
|
|
71
20
|
fallback: "error404"
|
|
72
21
|
})
|
|
73
22
|
});
|
|
74
23
|
});
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
24
|
+
}, []);
|
|
25
|
+
const [config] = useState(
|
|
26
|
+
() => props.routerStore.adapters.makeObservable({
|
|
27
|
+
loadedComponentName: void 0,
|
|
28
|
+
loadedComponentPage: void 0,
|
|
29
|
+
currentProps: {}
|
|
30
|
+
})
|
|
31
|
+
);
|
|
32
|
+
const setLoadedComponent = useCallback(() => {
|
|
33
|
+
const { loadedComponentName, loadedComponentPage } = config;
|
|
34
|
+
const { currentRoute, isRedirecting } = props.routerStore;
|
|
35
|
+
const componentConfig = props.routes[currentRoute.name];
|
|
81
36
|
let preventRedirect = false;
|
|
82
37
|
if (isRedirecting) preventRedirect = true;
|
|
83
|
-
else if (loadedComponentName ===
|
|
84
|
-
else if (loadedComponentPage != null &&
|
|
85
|
-
if (loadedComponentPage ===
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
38
|
+
else if (loadedComponentName === currentRoute.name) preventRedirect = true;
|
|
39
|
+
else if (loadedComponentPage != null && currentRoute.name != null) {
|
|
40
|
+
if (loadedComponentPage === currentRoute.pageName) {
|
|
41
|
+
props.routerStore.adapters.batch(() => {
|
|
42
|
+
config.currentProps = "props" in componentConfig ? componentConfig.props || {} : {};
|
|
43
|
+
config[Symbol.for("$adm")]?.batch();
|
|
89
44
|
});
|
|
90
45
|
preventRedirect = true;
|
|
91
46
|
}
|
|
92
47
|
}
|
|
93
48
|
if (preventRedirect) return;
|
|
94
|
-
|
|
95
|
-
if (
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
49
|
+
props.routerStore.adapters.batch(() => {
|
|
50
|
+
if (loadedComponentName) props.beforeUpdatePageComponent?.();
|
|
51
|
+
props.beforeSetPageComponent?.(componentConfig);
|
|
52
|
+
config.currentProps = "props" in componentConfig ? componentConfig.props || {} : {};
|
|
53
|
+
config.loadedComponentName = currentRoute.name;
|
|
54
|
+
config.loadedComponentPage = componentConfig.pageName;
|
|
55
|
+
config[Symbol.for("$adm")]?.batch();
|
|
101
56
|
});
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
this.loadedComponentName = currentRouteName;
|
|
110
|
-
this.loadedComponentPage = componentConfig.pageName;
|
|
111
|
-
this.loadedComponent = RouteComponent;
|
|
57
|
+
}, []);
|
|
58
|
+
useState(() => {
|
|
59
|
+
props.routerStore.adapters.batch(() => {
|
|
60
|
+
props.beforeMount?.();
|
|
61
|
+
redirectOnHistoryPop();
|
|
62
|
+
setLoadedComponent();
|
|
63
|
+
disposerRef.current = props.routerStore.adapters.autorun(setLoadedComponent);
|
|
112
64
|
});
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
|
|
65
|
+
});
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
return () => {
|
|
68
|
+
disposerRef.current?.();
|
|
69
|
+
};
|
|
70
|
+
}, []);
|
|
71
|
+
if (!config.loadedComponentName) return null;
|
|
72
|
+
const LoadedComponent = props.routes[config.loadedComponentName]?.component || null;
|
|
73
|
+
if (LoadedComponent) return /* @__PURE__ */ jsx(LoadedComponent, { ...config.currentProps });
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
function RouterWrapper(props) {
|
|
77
|
+
const Component = props.routerStore.adapters.observer ? props.routerStore.adapters.observer(RouterInner) : RouterInner;
|
|
78
|
+
return /* @__PURE__ */ jsx(Component, { ...props });
|
|
79
|
+
}
|
|
80
|
+
var Router = memo(RouterWrapper);
|
|
123
81
|
export {
|
|
124
82
|
Router
|
|
125
83
|
};
|