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.
Files changed (55) hide show
  1. package/dist/cjs/adapters/kr-observable/index.js +40 -0
  2. package/dist/cjs/adapters/kr-observable/package.json +1 -0
  3. package/dist/cjs/adapters/mobx/index.js +44 -0
  4. package/dist/cjs/adapters/mobx/package.json +1 -0
  5. package/dist/cjs/adapters/solid/index.js +48 -0
  6. package/dist/cjs/adapters/solid/package.json +1 -0
  7. package/dist/cjs/index.js +204 -13
  8. package/dist/cjs/react/index.js +56 -98
  9. package/dist/cjs/solid/index.js +38 -97
  10. package/dist/esm/adapters/kr-observable/index.js +19 -0
  11. package/dist/esm/adapters/kr-observable/package.json +1 -0
  12. package/dist/esm/adapters/mobx/index.js +23 -0
  13. package/dist/esm/adapters/mobx/package.json +1 -0
  14. package/dist/esm/adapters/solid/index.js +27 -0
  15. package/dist/esm/adapters/solid/package.json +1 -0
  16. package/dist/esm/index.js +204 -13
  17. package/dist/esm/react/index.js +56 -98
  18. package/dist/esm/solid/index.js +37 -96
  19. package/dist/types/adapters/kr-observable.d.ts +3 -0
  20. package/dist/types/adapters/kr-observable.d.ts.map +1 -0
  21. package/dist/types/adapters/mobx.d.ts +3 -0
  22. package/dist/types/adapters/mobx.d.ts.map +1 -0
  23. package/dist/types/adapters/solid.d.ts +3 -0
  24. package/dist/types/adapters/solid.d.ts.map +1 -0
  25. package/dist/types/core/createRouterConfig.d.ts +2 -6
  26. package/dist/types/core/createRouterConfig.d.ts.map +1 -1
  27. package/dist/types/core/createRouterStore.d.ts +2 -11
  28. package/dist/types/core/createRouterStore.d.ts.map +1 -1
  29. package/dist/types/core/index.d.ts +3 -1
  30. package/dist/types/core/index.d.ts.map +1 -1
  31. package/dist/types/core/types/InterfaceRouterStore.d.ts +22 -1
  32. package/dist/types/core/types/InterfaceRouterStore.d.ts.map +1 -1
  33. package/dist/types/core/types/TypeLifecycleConfig.d.ts +13 -0
  34. package/dist/types/core/types/TypeLifecycleConfig.d.ts.map +1 -0
  35. package/dist/types/core/types/TypePropsRouter.d.ts +10 -0
  36. package/dist/types/core/types/TypePropsRouter.d.ts.map +1 -0
  37. package/dist/types/core/types/TypeRouteRaw.d.ts +3 -24
  38. package/dist/types/core/types/TypeRouteRaw.d.ts.map +1 -1
  39. package/dist/types/react/Router.d.ts +3 -11
  40. package/dist/types/react/Router.d.ts.map +1 -1
  41. package/dist/types/solid/Router.d.ts +2 -10
  42. package/dist/types/solid/Router.d.ts.map +1 -1
  43. package/dist/types/tsconfig.types.react.tsbuildinfo +1 -0
  44. package/dist/types/tsconfig.types.solid.tsbuildinfo +1 -0
  45. package/package.json +48 -21
  46. package/tsconfig.solid.json +9 -0
  47. package/tsconfig.types.react.json +11 -0
  48. package/tsconfig.types.solid.json +14 -0
  49. package/dist/types/react/useStore.d.ts +0 -8
  50. package/dist/types/react/useStore.d.ts.map +0 -1
  51. package/dist/types/solid/replaceObject.d.ts +0 -2
  52. package/dist/types/solid/replaceObject.d.ts.map +0 -1
  53. package/dist/types/solid/useStore.d.ts +0 -7
  54. package/dist/types/solid/useStore.d.ts.map +0 -1
  55. package/dist/types/tsconfig.types.tsbuildinfo +0 -1
@@ -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 getAllProperties = (object) => {
51
- const properties = /* @__PURE__ */ new Set();
52
- do {
53
- for (const key of Reflect.ownKeys(object)) {
54
- properties.add([object, key]);
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
- return vm;
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 = this.props.routerStore.routesHistory[this.props.routerStore.routesHistory.length - 2];
43
+ const previousRoutePathname = props.routerStore.routesHistory[props.routerStore.routesHistory.length - 2];
98
44
  if (previousRoutePathname === params.location.pathname) {
99
- this.props.routerStore.routesHistory.pop();
45
+ props.routerStore.routesHistory.pop();
100
46
  }
101
- void this.props.routerStore.redirectTo({
47
+ void props.routerStore.redirectTo({
102
48
  noHistoryPush: true,
103
49
  ...(0, import_reactive_route.getInitialRoute)({
104
- routes: this.props.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 = this.props.routerStore.currentRoute.name;
113
- const currentRoutePage = this.props.routerStore.currentRoute.pageName;
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 (this.props.routerStore.isRedirecting) preventRedirect = true;
116
- else if (this.loadedComponentName === currentRouteName) {
62
+ if (props.routerStore.isRedirecting) preventRedirect = true;
63
+ else if (config.loadedComponentName === currentRouteName) {
117
64
  preventRedirect = true;
118
- } else if (this.loadedComponentPage != null && currentRouteName != null) {
119
- if (this.loadedComponentPage === currentRoutePage) {
120
- const componentConfig = this.props.routes[currentRouteName];
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
- (0, import_solid_js2.batch)(() => {
127
- if (!this.loadedComponentName) {
128
- this.setComponent();
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
- setComponent() {
136
- const currentRouteName = this.props.routerStore.currentRoute.name;
137
- const componentConfig = this.props.routes[currentRouteName];
138
- this.props.beforeSetPageComponent?.(componentConfig);
139
- (0, import_solid_js2.batch)(() => {
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 vm.loadedComponentName;
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[vm.loadedComponentName]?.component || void 0;
96
+ return props.routes[config.loadedComponentName]?.component || void 0;
156
97
  }
157
- }, () => vm.currentProps));
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,
@@ -1,125 +1,83 @@
1
1
  // packages/react/Router.tsx
2
- import { autorun, makeAutoObservable, runInAction as runInAction2 } from "mobx";
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
- var VM = class {
39
- constructor(props) {
40
- this.props = props;
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 = this.props.routerStore.routesHistory[this.props.routerStore.routesHistory.length - 2];
11
+ const previousRoutePathname = props.routerStore.routesHistory[props.routerStore.routesHistory.length - 2];
63
12
  if (previousRoutePathname === params.location.pathname) {
64
- runInAction2(() => this.props.routerStore.routesHistory.pop());
13
+ props.routerStore.adapters.batch(() => props.routerStore.routesHistory.pop());
65
14
  }
66
- void this.props.routerStore.redirectTo({
15
+ void props.routerStore.redirectTo({
67
16
  noHistoryPush: true,
68
17
  ...getInitialRoute({
69
- routes: this.props.routes,
18
+ routes: props.routes,
70
19
  pathname: history.location.pathname,
71
20
  fallback: "error404"
72
21
  })
73
22
  });
74
23
  });
75
- }
76
- setLoadedComponent = () => {
77
- const { loadedComponentName, loadedComponentPage } = this;
78
- const { currentRoute, isRedirecting } = this.props.routerStore;
79
- const currentRouteName = currentRoute.name;
80
- const currentRoutePage = currentRoute.pageName;
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 === currentRouteName) preventRedirect = true;
84
- else if (loadedComponentPage != null && currentRouteName != null) {
85
- if (loadedComponentPage === currentRoutePage) {
86
- const componentConfig = this.props.routes[currentRouteName];
87
- runInAction2(() => {
88
- this.currentProps = "props" in componentConfig ? componentConfig.props || {} : {};
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
- runInAction2(() => {
95
- if (!loadedComponentName) {
96
- this.setComponent(currentRouteName);
97
- } else {
98
- this.props.beforeUpdatePageComponent?.();
99
- this.setComponent(currentRouteName);
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
- setComponent(currentRouteName) {
104
- runInAction2(() => {
105
- const componentConfig = this.props.routes[currentRouteName];
106
- const RouteComponent = componentConfig.component;
107
- this.props.beforeSetPageComponent?.(componentConfig);
108
- this.currentProps = "props" in componentConfig ? componentConfig.props || {} : {};
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
- var Router = observer(
116
- (props) => {
117
- const vm = useStore(VM, props);
118
- const LoadedComponent = vm.loadedComponentName ? vm.loadedComponent : null;
119
- if (LoadedComponent) return /* @__PURE__ */ jsx(LoadedComponent, { ...vm.currentProps });
120
- return null;
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
  };