mobx-route 0.18.0 → 0.19.0
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/index.cjs +536 -17
- package/index.cjs.map +1 -0
- package/index.d.ts +420 -2
- package/index.js +532 -2
- package/index.js.map +1 -0
- package/package.json +20 -63
- package/react.cjs +170 -0
- package/react.cjs.map +1 -0
- package/react.d.ts +71 -0
- package/react.js +170 -0
- package/react.js.map +1 -0
- package/view-model.cjs +56 -0
- package/view-model.cjs.map +1 -0
- package/view-model.d.ts +14 -0
- package/view-model.js +56 -0
- package/view-model.js.map +1 -0
- package/core/config/config.cjs +0 -36
- package/core/config/config.d.cts +0 -7
- package/core/config/config.d.cts.map +0 -1
- package/core/config/config.d.ts +0 -7
- package/core/config/config.d.ts.map +0 -1
- package/core/config/config.js +0 -33
- package/core/config/config.types.cjs +0 -2
- package/core/config/config.types.d.cts +0 -11
- package/core/config/config.types.d.cts.map +0 -1
- package/core/config/config.types.d.ts +0 -11
- package/core/config/config.types.d.ts.map +0 -1
- package/core/config/config.types.js +0 -1
- package/core/config/index.cjs +0 -18
- package/core/config/index.d.cts +0 -3
- package/core/config/index.d.cts.map +0 -1
- package/core/config/index.d.ts +0 -3
- package/core/config/index.d.ts.map +0 -1
- package/core/config/index.js +0 -2
- package/core/index.cjs +0 -21
- package/core/index.d.cts +0 -6
- package/core/index.d.cts.map +0 -1
- package/core/index.d.ts +0 -6
- package/core/index.d.ts.map +0 -1
- package/core/index.js +0 -5
- package/core/route/index.cjs +0 -18
- package/core/route/index.d.cts +0 -3
- package/core/route/index.d.cts.map +0 -1
- package/core/route/index.d.ts +0 -3
- package/core/route/index.d.ts.map +0 -1
- package/core/route/index.js +0 -2
- package/core/route/route.cjs +0 -296
- package/core/route/route.d.cts +0 -107
- package/core/route/route.d.cts.map +0 -1
- package/core/route/route.d.ts +0 -107
- package/core/route/route.d.ts.map +0 -1
- package/core/route/route.js +0 -291
- package/core/route/route.types.cjs +0 -2
- package/core/route/route.types.d.cts +0 -142
- package/core/route/route.types.d.cts.map +0 -1
- package/core/route/route.types.d.ts +0 -142
- package/core/route/route.types.d.ts.map +0 -1
- package/core/route/route.types.js +0 -1
- package/core/route-group/index.cjs +0 -18
- package/core/route-group/index.d.cts +0 -3
- package/core/route-group/index.d.cts.map +0 -1
- package/core/route-group/index.d.ts +0 -3
- package/core/route-group/index.d.ts.map +0 -1
- package/core/route-group/index.js +0 -2
- package/core/route-group/route-group.cjs +0 -67
- package/core/route-group/route-group.d.cts +0 -31
- package/core/route-group/route-group.d.cts.map +0 -1
- package/core/route-group/route-group.d.ts +0 -31
- package/core/route-group/route-group.d.ts.map +0 -1
- package/core/route-group/route-group.js +0 -62
- package/core/route-group/route-group.types.cjs +0 -2
- package/core/route-group/route-group.types.d.cts +0 -15
- package/core/route-group/route-group.types.d.cts.map +0 -1
- package/core/route-group/route-group.types.d.ts +0 -15
- package/core/route-group/route-group.types.d.ts.map +0 -1
- package/core/route-group/route-group.types.js +0 -1
- package/core/router/index.cjs +0 -18
- package/core/router/index.d.cts +0 -3
- package/core/router/index.d.cts.map +0 -1
- package/core/router/index.d.ts +0 -3
- package/core/router/index.d.ts.map +0 -1
- package/core/router/index.js +0 -2
- package/core/router/router.cjs +0 -42
- package/core/router/router.d.cts +0 -18
- package/core/router/router.d.cts.map +0 -1
- package/core/router/router.d.ts +0 -18
- package/core/router/router.d.ts.map +0 -1
- package/core/router/router.js +0 -37
- package/core/router/router.types.cjs +0 -2
- package/core/router/router.types.d.cts +0 -13
- package/core/router/router.types.d.cts.map +0 -1
- package/core/router/router.types.d.ts +0 -13
- package/core/router/router.types.d.ts.map +0 -1
- package/core/router/router.types.js +0 -1
- package/core/utils/is-route-entity.cjs +0 -5
- package/core/utils/is-route-entity.d.cts +0 -3
- package/core/utils/is-route-entity.d.cts.map +0 -1
- package/core/utils/is-route-entity.d.ts +0 -3
- package/core/utils/is-route-entity.d.ts.map +0 -1
- package/core/utils/is-route-entity.js +0 -1
- package/core/virtual-route/index.cjs +0 -18
- package/core/virtual-route/index.d.cts +0 -3
- package/core/virtual-route/index.d.cts.map +0 -1
- package/core/virtual-route/index.d.ts +0 -3
- package/core/virtual-route/index.d.ts.map +0 -1
- package/core/virtual-route/index.js +0 -2
- package/core/virtual-route/virtual-route.cjs +0 -133
- package/core/virtual-route/virtual-route.d.cts +0 -39
- package/core/virtual-route/virtual-route.d.cts.map +0 -1
- package/core/virtual-route/virtual-route.d.ts +0 -39
- package/core/virtual-route/virtual-route.d.ts.map +0 -1
- package/core/virtual-route/virtual-route.js +0 -128
- package/core/virtual-route/virtual-route.types.cjs +0 -2
- package/core/virtual-route/virtual-route.types.d.cts +0 -61
- package/core/virtual-route/virtual-route.types.d.cts.map +0 -1
- package/core/virtual-route/virtual-route.types.d.ts +0 -61
- package/core/virtual-route/virtual-route.types.d.ts.map +0 -1
- package/core/virtual-route/virtual-route.types.js +0 -1
- package/index.d.cts +0 -3
- package/index.d.cts.map +0 -1
- package/index.d.ts.map +0 -1
- package/react/components/index.cjs +0 -21
- package/react/components/index.d.cts +0 -4
- package/react/components/index.d.cts.map +0 -1
- package/react/components/index.d.ts +0 -4
- package/react/components/index.d.ts.map +0 -1
- package/react/components/index.js +0 -5
- package/react/components/link.cjs +0 -79
- package/react/components/link.d.cts +0 -23
- package/react/components/link.d.cts.map +0 -1
- package/react/components/link.d.ts +0 -23
- package/react/components/link.d.ts.map +0 -1
- package/react/components/link.js +0 -76
- package/react/components/route-view-group.cjs +0 -57
- package/react/components/route-view-group.d.cts +0 -26
- package/react/components/route-view-group.d.cts.map +0 -1
- package/react/components/route-view-group.d.ts +0 -26
- package/react/components/route-view-group.d.ts.map +0 -1
- package/react/components/route-view-group.js +0 -54
- package/react/components/route-view.cjs +0 -43
- package/react/components/route-view.d.cts +0 -25
- package/react/components/route-view.d.cts.map +0 -1
- package/react/components/route-view.d.ts +0 -25
- package/react/components/route-view.d.ts.map +0 -1
- package/react/components/route-view.js +0 -40
- package/react/index.cjs +0 -17
- package/react/index.d.cts +0 -2
- package/react/index.d.cts.map +0 -1
- package/react/index.d.ts +0 -2
- package/react/index.d.ts.map +0 -1
- package/react/index.js +0 -1
- package/view-model/index.cjs +0 -17
- package/view-model/index.d.cts +0 -2
- package/view-model/index.d.cts.map +0 -1
- package/view-model/index.d.ts +0 -2
- package/view-model/index.d.ts.map +0 -1
- package/view-model/index.js +0 -1
- package/view-model/route-view-model.cjs +0 -37
- package/view-model/route-view-model.d.cts +0 -13
- package/view-model/route-view-model.d.cts.map +0 -1
- package/view-model/route-view-model.d.ts +0 -13
- package/view-model/route-view-model.d.ts.map +0 -1
- package/view-model/route-view-model.js +0 -33
package/index.cjs
CHANGED
|
@@ -1,18 +1,537 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const mobxLocationHistory = require("mobx-location-history");
|
|
4
|
+
const complex = require("yummies/complex");
|
|
5
|
+
const linkedAbortController = require("linked-abort-controller");
|
|
6
|
+
const mobx = require("mobx");
|
|
7
|
+
const pathToRegexp = require("path-to-regexp");
|
|
8
|
+
const common = require("yummies/common");
|
|
9
|
+
let localHistory;
|
|
10
|
+
const routeConfig = complex.createGlobalDynamicConfig(
|
|
11
|
+
(update) => {
|
|
12
|
+
if (localHistory && update?.history && mobxLocationHistory.isObservableHistory(localHistory)) {
|
|
13
|
+
localHistory.destroy();
|
|
14
|
+
}
|
|
15
|
+
let history;
|
|
16
|
+
if (update?.history) {
|
|
17
|
+
history = update.history;
|
|
18
|
+
} else {
|
|
19
|
+
history = localHistory = mobxLocationHistory.createBrowserHistory();
|
|
20
|
+
}
|
|
21
|
+
let queryParams;
|
|
22
|
+
if (update?.history && !update.queryParams) {
|
|
23
|
+
queryParams = new mobxLocationHistory.QueryParams({ history });
|
|
24
|
+
} else {
|
|
25
|
+
if (update?.queryParams) {
|
|
26
|
+
queryParams = update.queryParams;
|
|
27
|
+
} else {
|
|
28
|
+
queryParams = new mobxLocationHistory.QueryParams({ history });
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
...update,
|
|
33
|
+
history,
|
|
34
|
+
location,
|
|
35
|
+
queryParams
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
class Route {
|
|
40
|
+
constructor(path, config = {}) {
|
|
41
|
+
this.path = path;
|
|
42
|
+
this.config = config;
|
|
43
|
+
this.abortController = new linkedAbortController.LinkedAbortController(config.abortSignal);
|
|
44
|
+
this.history = config.history ?? routeConfig.get().history;
|
|
45
|
+
this.query = config.queryParams ?? routeConfig.get().queryParams;
|
|
46
|
+
this.isIndex = !!this.config.index;
|
|
47
|
+
this.isHash = !!this.config.hash;
|
|
48
|
+
this.meta = this.config.meta;
|
|
49
|
+
this.parent = config.parent ?? null;
|
|
50
|
+
mobx.computed.struct(this, "isOpened");
|
|
51
|
+
mobx.computed.struct(this, "data");
|
|
52
|
+
mobx.computed.struct(this, "params");
|
|
53
|
+
mobx.computed.struct(this, "currentPath");
|
|
54
|
+
mobx.computed.struct(this, "hasOpenedChildren");
|
|
55
|
+
mobx.computed.struct(this, "isAbleToMergeQuery");
|
|
56
|
+
mobx.computed(this, "baseUrl");
|
|
57
|
+
mobx.observable(this, "children");
|
|
58
|
+
mobx.observable.ref(this, "parent");
|
|
59
|
+
mobx.action(this, "addChildren");
|
|
60
|
+
mobx.action(this, "removeChildren");
|
|
61
|
+
mobx.makeObservable(this);
|
|
62
|
+
mobx.onBecomeObserved(this, "isOpened", () => {
|
|
63
|
+
if (!config.afterOpen && !config.afterClose) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
this.reactionDisposer = mobx.reaction(
|
|
67
|
+
() => this.isOpened,
|
|
68
|
+
this.processOpenedState,
|
|
69
|
+
{
|
|
70
|
+
signal: this.abortController.signal,
|
|
71
|
+
fireImmediately: true
|
|
72
|
+
}
|
|
73
|
+
);
|
|
74
|
+
});
|
|
75
|
+
mobx.onBecomeUnobserved(this, "isOpened", () => {
|
|
76
|
+
this.reactionDisposer?.();
|
|
77
|
+
this.reactionDisposer = void 0;
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
abortController;
|
|
81
|
+
history;
|
|
82
|
+
parent;
|
|
83
|
+
query;
|
|
84
|
+
_tokenData;
|
|
85
|
+
_matcher;
|
|
86
|
+
_compiler;
|
|
87
|
+
reactionDisposer;
|
|
88
|
+
meta;
|
|
89
|
+
/**
|
|
90
|
+
* Indicates if this route is an index route. Index routes activate when parent route path matches exactly.
|
|
91
|
+
*
|
|
92
|
+
* [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#isindex-boolean)
|
|
93
|
+
*/
|
|
94
|
+
isIndex;
|
|
95
|
+
/**
|
|
96
|
+
* Indicates if this route is an hash route.
|
|
97
|
+
*
|
|
98
|
+
* [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#ishash-boolean)
|
|
99
|
+
*/
|
|
100
|
+
isHash;
|
|
101
|
+
children = [];
|
|
102
|
+
get baseUrl() {
|
|
103
|
+
const baseUrl = this.config.baseUrl ?? routeConfig.get().baseUrl;
|
|
104
|
+
return baseUrl?.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
|
|
105
|
+
}
|
|
106
|
+
get parsedPathData() {
|
|
107
|
+
let pathnameToCheck;
|
|
108
|
+
if (this.isHash) {
|
|
109
|
+
pathnameToCheck = this.history.location.hash.slice(1);
|
|
110
|
+
} else {
|
|
111
|
+
pathnameToCheck = this.history.location.pathname;
|
|
112
|
+
}
|
|
113
|
+
if (this.baseUrl) {
|
|
114
|
+
if (!this.history.location.pathname.startsWith(this.baseUrl)) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
pathnameToCheck = pathnameToCheck.replace(this.baseUrl, "");
|
|
118
|
+
}
|
|
119
|
+
if ((this.path === "" || this.path === "/") && (pathnameToCheck === "/" || pathnameToCheck === "")) {
|
|
120
|
+
return { params: {}, path: pathnameToCheck };
|
|
121
|
+
}
|
|
122
|
+
this._matcher ??= pathToRegexp.match(this.tokenData, {
|
|
123
|
+
end: false,
|
|
124
|
+
...this.config.matchOptions
|
|
125
|
+
});
|
|
126
|
+
const parsed = this._matcher(pathnameToCheck);
|
|
127
|
+
if (parsed === false) {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
return parsed;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Matched path segment for current URL.
|
|
134
|
+
*
|
|
135
|
+
* [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#currentpath-parsedpathname-null)
|
|
136
|
+
*/
|
|
137
|
+
get currentPath() {
|
|
138
|
+
return this.parsedPathData?.path ?? null;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Current parsed path parameters.
|
|
142
|
+
*
|
|
143
|
+
* [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#params-parsedpathparams-null)
|
|
144
|
+
*/
|
|
145
|
+
get params() {
|
|
146
|
+
if (!this.parsedPathData?.params) {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
let params = this.parsedPathData?.params ?? null;
|
|
150
|
+
if (this.config.params) {
|
|
151
|
+
const result = this.config.params(
|
|
152
|
+
this.parsedPathData.params,
|
|
153
|
+
this.config.meta
|
|
154
|
+
);
|
|
155
|
+
if (result) {
|
|
156
|
+
params = result;
|
|
157
|
+
} else {
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return params;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Defines the "open" state for this route.
|
|
165
|
+
*
|
|
166
|
+
* [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#isopened-boolean)
|
|
167
|
+
*/
|
|
168
|
+
get isOpened() {
|
|
169
|
+
if (this.params === null || this.parsedPathData === null) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
return !this.config.checkOpened || this.config.checkOpened(this.parsedPathData);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Allows to create child route based on this route with merging this route path and extending path.
|
|
176
|
+
*
|
|
177
|
+
* [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#extend-path-config-route)
|
|
178
|
+
*/
|
|
179
|
+
extend(path, config) {
|
|
180
|
+
const { index, params, ...configFromCurrentRoute } = this.config;
|
|
181
|
+
const extendedChild = new Route(`${this.path}${path}`, {
|
|
182
|
+
...configFromCurrentRoute,
|
|
183
|
+
...config,
|
|
184
|
+
parent: this
|
|
185
|
+
});
|
|
186
|
+
this.addChildren(extendedChild);
|
|
187
|
+
return extendedChild;
|
|
188
|
+
}
|
|
189
|
+
addChildren(...routes) {
|
|
190
|
+
this.children.push(...routes);
|
|
191
|
+
}
|
|
192
|
+
removeChildren(...routes) {
|
|
193
|
+
this.children = this.children.filter((child) => !routes.includes(child));
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#hasopenedchildren-boolean)
|
|
197
|
+
*/
|
|
198
|
+
get hasOpenedChildren() {
|
|
199
|
+
return this.children.some(
|
|
200
|
+
(child) => child.isOpened || child.hasOpenedChildren
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
processParams(params) {
|
|
204
|
+
if (params == null) return void 0;
|
|
205
|
+
return Object.entries(params).reduce((acc, [key, value]) => {
|
|
206
|
+
if (value != null) {
|
|
207
|
+
acc[key] = Array.isArray(value) ? value.map(String) : String(value);
|
|
208
|
+
}
|
|
209
|
+
return acc;
|
|
210
|
+
}, {});
|
|
211
|
+
}
|
|
212
|
+
createUrl(...args) {
|
|
213
|
+
const params = args[0];
|
|
214
|
+
const rawQuery = args[1];
|
|
215
|
+
const mergeQueryOrOutputParams = args[2] ?? this.isAbleToMergeQuery;
|
|
216
|
+
const outputParams = typeof mergeQueryOrOutputParams === "boolean" ? { mergeQuery: mergeQueryOrOutputParams } : mergeQueryOrOutputParams;
|
|
217
|
+
const query = outputParams?.mergeQuery ? { ...this.query.data, ...rawQuery } : rawQuery ?? {};
|
|
218
|
+
this._compiler ??= pathToRegexp.compile(this.tokenData);
|
|
219
|
+
const defaultUrlCreateParams = {
|
|
220
|
+
baseUrl: this.baseUrl,
|
|
221
|
+
params,
|
|
222
|
+
query
|
|
223
|
+
};
|
|
224
|
+
const urlCreateParams = this.config.createUrl?.(defaultUrlCreateParams, this.query.data) ?? routeConfig.get().createUrl?.(defaultUrlCreateParams, this.query.data) ?? defaultUrlCreateParams;
|
|
225
|
+
const path = this._compiler(this.processParams(urlCreateParams.params));
|
|
226
|
+
const url = [urlCreateParams.baseUrl, this.isHash ? "#" : "", path].join(
|
|
227
|
+
""
|
|
228
|
+
);
|
|
229
|
+
if (outputParams?.omitQuery) {
|
|
230
|
+
return url;
|
|
231
|
+
}
|
|
232
|
+
return `${url}${mobxLocationHistory.buildSearchString(urlCreateParams.query)}`;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Navigates to this route.
|
|
236
|
+
*
|
|
237
|
+
* [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#open-args)
|
|
238
|
+
*/
|
|
239
|
+
async open(...args) {
|
|
240
|
+
const {
|
|
241
|
+
replace,
|
|
242
|
+
state: rawState,
|
|
243
|
+
query: rawQuery,
|
|
244
|
+
mergeQuery: rawMergeQuery
|
|
245
|
+
} = typeof args[1] === "boolean" || args.length > 2 ? { replace: args[1], query: args[2] } : args[1] ?? {};
|
|
246
|
+
let url;
|
|
247
|
+
let params;
|
|
248
|
+
const mergeQuery = rawMergeQuery ?? this.isAbleToMergeQuery;
|
|
249
|
+
const query = mergeQuery ? { ...this.query.data, ...rawQuery } : rawQuery;
|
|
250
|
+
if (typeof args[0] === "string") {
|
|
251
|
+
url = args[0];
|
|
252
|
+
} else {
|
|
253
|
+
params = args[0];
|
|
254
|
+
url = this.createUrl(args[0], query);
|
|
255
|
+
}
|
|
256
|
+
const state = rawState ?? null;
|
|
257
|
+
const navigationData = {
|
|
258
|
+
url,
|
|
259
|
+
params,
|
|
260
|
+
replace,
|
|
261
|
+
state,
|
|
262
|
+
query
|
|
263
|
+
};
|
|
264
|
+
const feedback = await this.beforeOpen(navigationData);
|
|
265
|
+
if (feedback === false) {
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
if (typeof feedback === "object") {
|
|
269
|
+
Object.assign(navigationData, feedback);
|
|
270
|
+
}
|
|
271
|
+
if (replace) {
|
|
272
|
+
this.history.replace(url, state);
|
|
273
|
+
} else {
|
|
274
|
+
this.history.push(url, state);
|
|
275
|
+
}
|
|
276
|
+
if (!this.reactionDisposer && this.isOpened) {
|
|
277
|
+
this.config.afterOpen?.(this.parsedPathData, this);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
beforeOpen(openData) {
|
|
281
|
+
if (this.config.beforeOpen) {
|
|
282
|
+
return this.config.beforeOpen(openData);
|
|
283
|
+
}
|
|
284
|
+
return true;
|
|
285
|
+
}
|
|
286
|
+
afterClose() {
|
|
287
|
+
if (this.config.afterClose) {
|
|
288
|
+
return this.config.afterClose();
|
|
289
|
+
}
|
|
290
|
+
return true;
|
|
291
|
+
}
|
|
292
|
+
get tokenData() {
|
|
293
|
+
if (!this._tokenData) {
|
|
294
|
+
this._tokenData = pathToRegexp.parse(this.path, this.config.parseOptions);
|
|
295
|
+
}
|
|
296
|
+
return this._tokenData;
|
|
297
|
+
}
|
|
298
|
+
firstOpenedStateCheck = true;
|
|
299
|
+
processOpenedState = (isOpened) => {
|
|
300
|
+
if (this.firstOpenedStateCheck) {
|
|
301
|
+
this.firstOpenedStateCheck = false;
|
|
302
|
+
if (!isOpened) {
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
if (isOpened) {
|
|
307
|
+
this.config.afterOpen?.(this.parsedPathData, this);
|
|
308
|
+
} else {
|
|
309
|
+
this.config.afterClose?.();
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
get isAbleToMergeQuery() {
|
|
313
|
+
return this.config.mergeQuery ?? routeConfig.get().mergeQuery;
|
|
314
|
+
}
|
|
315
|
+
destroy() {
|
|
316
|
+
this.abortController.abort();
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
const createRoute = (path, config) => new Route(path, config);
|
|
320
|
+
class RouteGroup {
|
|
321
|
+
constructor(routes, _indexRoute) {
|
|
322
|
+
this._indexRoute = _indexRoute;
|
|
323
|
+
this.routes = routes;
|
|
324
|
+
mobx.computed.struct(this, "isOpened");
|
|
325
|
+
mobx.computed.struct(this, "indexRoute");
|
|
326
|
+
mobx.observable.shallow(this, "routes");
|
|
327
|
+
mobx.makeObservable(this);
|
|
328
|
+
}
|
|
329
|
+
routes;
|
|
330
|
+
/**
|
|
331
|
+
* Returns true if at least one route in the group is open.
|
|
332
|
+
*
|
|
333
|
+
* [**Documentation**](https://js2me.github.io/mobx-route/core/RouteGroup.html#isopened-boolean)
|
|
334
|
+
*/
|
|
335
|
+
get isOpened() {
|
|
336
|
+
const routes = Object.values(this.routes);
|
|
337
|
+
return routes.some(
|
|
338
|
+
(route) => route.isOpened || "hasOpenedChildren" in route && route.hasOpenedChildren
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* First found index route.
|
|
343
|
+
*
|
|
344
|
+
* [**Documentation**](https://js2me.github.io/mobx-route/core/RouteGroup.html#indexroute-route-undefined)
|
|
345
|
+
*/
|
|
346
|
+
get indexRoute() {
|
|
347
|
+
return this._indexRoute ?? Object.values(this.routes).find(
|
|
348
|
+
(route) => "isIndex" in route && route.isIndex
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Main navigation method for the group.
|
|
353
|
+
*
|
|
354
|
+
* [**Documentation**](https://js2me.github.io/mobx-route/core/RouteGroup.html#open-args-any-void)
|
|
355
|
+
*/
|
|
356
|
+
open(...args) {
|
|
357
|
+
let lastGroupRoute;
|
|
358
|
+
if (this.indexRoute && "open" in this.indexRoute) {
|
|
359
|
+
this.indexRoute.open(...args);
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
for (const routeName in this.routes) {
|
|
363
|
+
const route = this.routes[routeName];
|
|
364
|
+
if (route instanceof RouteGroup) {
|
|
365
|
+
lastGroupRoute = route;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
if (lastGroupRoute) {
|
|
369
|
+
lastGroupRoute.open(...args);
|
|
370
|
+
} else if (process.env.NODE_ENV !== "production") {
|
|
371
|
+
console.warn(
|
|
372
|
+
"RouteGroup doesn't have index route. open() method doesn't work."
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
const createRouteGroup = (routes, indexRoute) => new RouteGroup(routes, indexRoute);
|
|
378
|
+
class Router {
|
|
379
|
+
routes;
|
|
380
|
+
history;
|
|
381
|
+
query;
|
|
382
|
+
constructor(config) {
|
|
383
|
+
this.routes = config.routes;
|
|
384
|
+
this.history = config.history ?? routeConfig.get().history;
|
|
385
|
+
this.query = config.queryParams ?? routeConfig.get().queryParams;
|
|
386
|
+
mobx.computed.struct(this, "location");
|
|
387
|
+
mobx.makeObservable(this);
|
|
388
|
+
}
|
|
389
|
+
get location() {
|
|
390
|
+
return this.history.location;
|
|
391
|
+
}
|
|
392
|
+
navigate(url, options) {
|
|
393
|
+
const query = options?.mergeQuery ?? routeConfig.get().mergeQuery ? { ...this.query.data, ...options?.query } : { ...options?.query };
|
|
394
|
+
const searchString = mobxLocationHistory.buildSearchString(query);
|
|
395
|
+
const navigationUrl = `${url}${searchString}`;
|
|
396
|
+
if (options?.replace) {
|
|
397
|
+
this.history.replace(navigationUrl, options?.state);
|
|
398
|
+
} else {
|
|
399
|
+
this.history.push(navigationUrl, options?.state);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
const createRouter = (config) => new Router(config);
|
|
404
|
+
const isRouteEntity = (route) => route && "isOpened" in route;
|
|
405
|
+
class VirtualRoute {
|
|
406
|
+
constructor(config = {}) {
|
|
407
|
+
this.config = config;
|
|
408
|
+
this.abortController = new linkedAbortController.LinkedAbortController(config.abortSignal);
|
|
409
|
+
this.query = config.queryParams ?? routeConfig.get().queryParams;
|
|
410
|
+
this.params = common.callFunction(config.initialParams, this) ?? null;
|
|
411
|
+
this.openChecker = config.checkOpened;
|
|
412
|
+
this.isLocalOpened = this.openChecker?.(this) ?? false;
|
|
413
|
+
mobx.observable(this, "params");
|
|
414
|
+
mobx.observable.ref(this, "isLocalOpened");
|
|
415
|
+
mobx.observable.ref(this, "_isOpened");
|
|
416
|
+
mobx.computed.struct(this, "isOpened");
|
|
417
|
+
mobx.action(this, "setOpenChecker");
|
|
418
|
+
mobx.action(this, "open");
|
|
419
|
+
mobx.action(this, "close");
|
|
420
|
+
mobx.makeObservable(this);
|
|
421
|
+
mobx.onBecomeObserved(this, "isOpened", () => {
|
|
422
|
+
if (!config.afterOpen && !config.afterClose) {
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
this.reactionDisposer = mobx.reaction(
|
|
426
|
+
() => this.isOpened,
|
|
427
|
+
this.processOpenedState,
|
|
428
|
+
{
|
|
429
|
+
signal: this.abortController.signal,
|
|
430
|
+
fireImmediately: true
|
|
431
|
+
}
|
|
432
|
+
);
|
|
433
|
+
});
|
|
434
|
+
mobx.onBecomeUnobserved(this, "isOpened", () => {
|
|
435
|
+
this.reactionDisposer?.();
|
|
436
|
+
this.reactionDisposer = void 0;
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
abortController;
|
|
440
|
+
query;
|
|
441
|
+
params;
|
|
442
|
+
isLocalOpened;
|
|
443
|
+
openChecker;
|
|
444
|
+
reactionDisposer;
|
|
445
|
+
/**
|
|
446
|
+
* [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html#isopened-boolean)
|
|
447
|
+
*/
|
|
448
|
+
get isOpened() {
|
|
449
|
+
const isOuterOpened = this.openChecker == null || this.openChecker(this);
|
|
450
|
+
return this.isLocalOpened && isOuterOpened;
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html#setopenchecker-openchecker-void)
|
|
454
|
+
*/
|
|
455
|
+
setOpenChecker(openChecker) {
|
|
456
|
+
this.openChecker = openChecker;
|
|
457
|
+
}
|
|
458
|
+
async open(...args) {
|
|
459
|
+
const params = args[0] ?? {};
|
|
460
|
+
const extraParams = args[1];
|
|
461
|
+
if (this.config.beforeOpen) {
|
|
462
|
+
const beforeOpenResult = await this.config.beforeOpen(params, this);
|
|
463
|
+
if (beforeOpenResult === false) {
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
if (this.config.open == null) {
|
|
468
|
+
mobx.runInAction(() => {
|
|
469
|
+
this.isLocalOpened = true;
|
|
470
|
+
});
|
|
471
|
+
} else {
|
|
472
|
+
const result = await this.config.open(params, this);
|
|
473
|
+
mobx.runInAction(() => {
|
|
474
|
+
this.isLocalOpened = result !== false;
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
if (!this.isLocalOpened) {
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
480
|
+
if (extraParams?.query) {
|
|
481
|
+
this.query.update(extraParams.query, extraParams.replace);
|
|
482
|
+
}
|
|
483
|
+
mobx.runInAction(() => {
|
|
484
|
+
this.params = params;
|
|
485
|
+
});
|
|
486
|
+
if (!this.reactionDisposer && this.isOpened) {
|
|
487
|
+
this.config.afterOpen?.(this.params, this);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html#close-void)
|
|
492
|
+
*/
|
|
493
|
+
close() {
|
|
494
|
+
if (this.config.close == null) {
|
|
495
|
+
this.isLocalOpened = false;
|
|
496
|
+
} else {
|
|
497
|
+
const result = this.config.close(this);
|
|
498
|
+
this.isLocalOpened = result !== false;
|
|
499
|
+
}
|
|
500
|
+
this.params = null;
|
|
501
|
+
}
|
|
502
|
+
firstOpenedStateCheck = true;
|
|
503
|
+
processOpenedState = (isOpened) => {
|
|
504
|
+
if (this.firstOpenedStateCheck) {
|
|
505
|
+
this.firstOpenedStateCheck = false;
|
|
506
|
+
if (!isOpened) {
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
if (isOpened) {
|
|
511
|
+
this.config.afterOpen?.(this.params, this);
|
|
512
|
+
} else {
|
|
513
|
+
this.config.afterClose?.();
|
|
514
|
+
}
|
|
515
|
+
};
|
|
516
|
+
destroy() {
|
|
517
|
+
this.abortController.abort();
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
const createVirtualRoute = (config) => new VirtualRoute(config);
|
|
521
|
+
exports.Route = Route;
|
|
522
|
+
exports.RouteGroup = RouteGroup;
|
|
523
|
+
exports.Router = Router;
|
|
524
|
+
exports.VirtualRoute = VirtualRoute;
|
|
525
|
+
exports.createRoute = createRoute;
|
|
526
|
+
exports.createRouteGroup = createRouteGroup;
|
|
527
|
+
exports.createRouter = createRouter;
|
|
528
|
+
exports.createVirtualRoute = createVirtualRoute;
|
|
529
|
+
exports.isRouteEntity = isRouteEntity;
|
|
530
|
+
exports.routeConfig = routeConfig;
|
|
531
|
+
Object.keys(mobxLocationHistory).forEach((k) => {
|
|
532
|
+
if (k !== "default" && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
533
|
+
enumerable: true,
|
|
534
|
+
get: () => mobxLocationHistory[k]
|
|
535
|
+
});
|
|
536
|
+
});
|
|
537
|
+
//# sourceMappingURL=index.cjs.map
|
package/index.cjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/core/config/config.ts","../src/core/route/route.ts","../src/core/route-group/route-group.ts","../src/core/router/router.ts","../src/core/utils/is-route-entity.ts","../src/core/virtual-route/virtual-route.ts"],"sourcesContent":["import {\n createBrowserHistory,\n type History,\n type IQueryParams,\n isObservableHistory,\n QueryParams,\n} from 'mobx-location-history';\nimport { createGlobalDynamicConfig } from 'yummies/complex';\n\nimport type { RouteGlobalConfig } from './config.types.js';\n\nlet localHistory: History | undefined;\n\nexport const routeConfig = createGlobalDynamicConfig<RouteGlobalConfig>(\n (update) => {\n if (localHistory && update?.history && isObservableHistory(localHistory)) {\n localHistory.destroy();\n }\n\n let history: History;\n\n if (update?.history) {\n history = update.history;\n } else {\n history = localHistory = createBrowserHistory();\n }\n\n let queryParams: IQueryParams;\n\n if (update?.history && !update.queryParams) {\n queryParams = new QueryParams({ history });\n } else {\n if (update?.queryParams) {\n queryParams = update.queryParams;\n } else {\n queryParams = new QueryParams({ history });\n }\n }\n\n return {\n ...update,\n history,\n location,\n queryParams,\n };\n },\n);\n","import { LinkedAbortController } from 'linked-abort-controller';\nimport {\n action,\n computed,\n makeObservable,\n observable,\n onBecomeObserved,\n onBecomeUnobserved,\n reaction,\n} from 'mobx';\nimport {\n buildSearchString,\n type History,\n type IQueryParams,\n} from 'mobx-location-history';\nimport {\n compile,\n match,\n type ParamData,\n parse,\n type TokenData,\n} from 'path-to-regexp';\nimport type { AnyObject, IsPartial, Maybe, MaybePromise } from 'yummies/types';\n\nimport { routeConfig } from '../config/index.js';\n\nimport type {\n AnyRoute,\n BeforeOpenFeedback,\n CreatedUrlOutputParams,\n InputPathParams,\n IRoute,\n ParsedPathData,\n ParsedPathParams,\n PreparedNavigationData,\n RouteConfiguration,\n RouteNavigateParams,\n UrlCreateParams,\n} from './route.types.js';\n\n/**\n * Class for creating path based route.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html)\n */\nexport class Route<\n TPath extends string,\n TInputParams extends InputPathParams<TPath> = InputPathParams<TPath>,\n TOutputParams extends AnyObject = ParsedPathParams<TPath>,\n TParentRoute extends Route<any, any, any, any> | null = null,\n> implements IRoute<TPath, TInputParams, TOutputParams>\n{\n protected abortController: AbortController;\n protected history: History;\n parent: TParentRoute;\n\n query: IQueryParams;\n\n private _tokenData: TokenData | undefined;\n private _matcher?: ReturnType<typeof match>;\n private _compiler?: ReturnType<typeof compile>;\n private reactionDisposer: Maybe<VoidFunction>;\n\n meta?: AnyObject;\n\n /**\n * Indicates if this route is an index route. Index routes activate when parent route path matches exactly.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#isindex-boolean)\n */\n isIndex: boolean;\n\n /**\n * Indicates if this route is an hash route.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#ishash-boolean)\n */\n isHash: boolean;\n\n children: AnyRoute[] = [];\n\n constructor(\n public path: TPath,\n protected config: RouteConfiguration<\n TPath,\n TInputParams,\n TOutputParams,\n TParentRoute\n > = {},\n ) {\n this.abortController = new LinkedAbortController(config.abortSignal);\n this.history = config.history ?? routeConfig.get().history;\n this.query = config.queryParams ?? routeConfig.get().queryParams;\n this.isIndex = !!this.config.index;\n this.isHash = !!this.config.hash;\n this.meta = this.config.meta;\n this.parent = config.parent ?? (null as unknown as TParentRoute);\n\n computed.struct(this, 'isOpened');\n computed.struct(this, 'data');\n computed.struct(this, 'params');\n computed.struct(this, 'currentPath');\n computed.struct(this, 'hasOpenedChildren');\n computed.struct(this, 'isAbleToMergeQuery');\n computed(this, 'baseUrl');\n\n observable(this, 'children');\n observable.ref(this, 'parent');\n action(this, 'addChildren');\n action(this, 'removeChildren');\n\n makeObservable(this);\n\n onBecomeObserved(this, 'isOpened', () => {\n if (!config.afterOpen && !config.afterClose) {\n return;\n }\n\n this.reactionDisposer = reaction(\n () => this.isOpened,\n this.processOpenedState,\n {\n signal: this.abortController.signal,\n fireImmediately: true,\n },\n );\n });\n onBecomeUnobserved(this, 'isOpened', () => {\n this.reactionDisposer?.();\n this.reactionDisposer = undefined;\n });\n }\n\n protected get baseUrl() {\n const baseUrl = this.config.baseUrl ?? routeConfig.get().baseUrl;\n return baseUrl?.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;\n }\n\n protected get parsedPathData(): ParsedPathData<TPath> | null {\n let pathnameToCheck: string;\n\n if (this.isHash) {\n pathnameToCheck = this.history.location.hash.slice(1);\n } else {\n pathnameToCheck = this.history.location.pathname;\n }\n\n if (this.baseUrl) {\n if (!this.history.location.pathname.startsWith(this.baseUrl)) {\n return null;\n }\n\n pathnameToCheck = pathnameToCheck.replace(this.baseUrl, '');\n }\n\n if (\n (this.path === '' || this.path === '/') &&\n (pathnameToCheck === '/' || pathnameToCheck === '')\n ) {\n return { params: {} as any, path: pathnameToCheck };\n }\n\n this._matcher ??= match(this.tokenData, {\n end: false,\n ...this.config.matchOptions,\n });\n const parsed = this._matcher(pathnameToCheck);\n\n if (parsed === false) {\n return null;\n }\n\n return parsed as ParsedPathData<TPath>;\n }\n\n /**\n * Matched path segment for current URL.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#currentpath-parsedpathname-null)\n */\n get currentPath(): string | null {\n return this.parsedPathData?.path ?? null;\n }\n\n /**\n * Current parsed path parameters.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#params-parsedpathparams-null)\n */\n get params(): TOutputParams | null {\n if (!this.parsedPathData?.params) {\n return null;\n }\n\n let params: TOutputParams | null =\n (this.parsedPathData?.params as unknown as Maybe<TOutputParams>) ?? null;\n\n if (this.config.params) {\n const result = this.config.params(\n this.parsedPathData.params,\n this.config.meta,\n );\n if (result) {\n params = result;\n } else {\n return null;\n }\n }\n\n return params;\n }\n\n /**\n * Defines the \"open\" state for this route.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#isopened-boolean)\n */\n get isOpened() {\n if (this.params === null || this.parsedPathData === null) {\n return false;\n }\n\n return (\n !this.config.checkOpened || this.config.checkOpened(this.parsedPathData)\n );\n }\n\n /**\n * Allows to create child route based on this route with merging this route path and extending path.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#extend-path-config-route)\n */\n extend<\n TExtendedPath extends string,\n TExtendedInputParams extends\n InputPathParams<`${TPath}${TExtendedPath}`> = InputPathParams<`${TPath}${TExtendedPath}`>,\n TExtendedOutputParams extends AnyObject = TInputParams &\n ParsedPathParams<`${TPath}${TExtendedPath}`>,\n >(\n path: TExtendedPath,\n config?: Omit<\n RouteConfiguration<\n `${TPath}${TExtendedPath}`,\n TInputParams & TExtendedInputParams,\n TExtendedOutputParams,\n any\n >,\n 'parent'\n >,\n ) {\n type ExtendedRoutePath = `${TPath}${TExtendedPath}`;\n type ParentRoute = this;\n // biome-ignore lint/correctness/noUnusedVariables: this is need to extract unused fields\n const { index, params, ...configFromCurrentRoute } = this.config;\n\n const extendedChild = new Route<\n ExtendedRoutePath,\n TInputParams & TExtendedInputParams,\n TExtendedOutputParams,\n ParentRoute\n >(`${this.path}${path}`, {\n ...configFromCurrentRoute,\n ...config,\n parent: this,\n } as any);\n\n this.addChildren(extendedChild as any);\n\n return extendedChild;\n }\n\n addChildren(...routes: AnyRoute[]) {\n this.children.push(...routes);\n }\n\n removeChildren(...routes: AnyRoute[]) {\n this.children = this.children.filter((child) => !routes.includes(child));\n }\n\n /**\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#hasopenedchildren-boolean)\n */\n get hasOpenedChildren(): boolean {\n return this.children.some(\n (child) => child.isOpened || child.hasOpenedChildren,\n );\n }\n\n protected processParams(\n params?: TInputParams | null | undefined,\n ): ParamData | undefined {\n if (params == null) return undefined;\n\n return Object.entries(params).reduce((acc, [key, value]) => {\n if (value != null) {\n acc[key] = Array.isArray(value) ? value.map(String) : String(value);\n }\n return acc;\n }, {} as ParamData);\n }\n\n createUrl(\n ...args: IsPartial<TInputParams> extends true\n ? [\n params?: Maybe<TInputParams>,\n query?: Maybe<AnyObject>,\n mergeQueryOrParams?: boolean | CreatedUrlOutputParams,\n ]\n : [\n params: TInputParams,\n query?: Maybe<AnyObject>,\n mergeQueryOrParams?: boolean | CreatedUrlOutputParams,\n ]\n ) {\n const params = args[0];\n const rawQuery = args[1];\n const mergeQueryOrOutputParams = args[2] ?? this.isAbleToMergeQuery;\n const outputParams: Maybe<CreatedUrlOutputParams> =\n typeof mergeQueryOrOutputParams === 'boolean'\n ? { mergeQuery: mergeQueryOrOutputParams }\n : mergeQueryOrOutputParams;\n\n const query = outputParams?.mergeQuery\n ? { ...this.query.data, ...rawQuery }\n : (rawQuery ?? {});\n\n this._compiler ??= compile(this.tokenData);\n\n const defaultUrlCreateParams: UrlCreateParams<TInputParams> = {\n baseUrl: this.baseUrl,\n params: params as TInputParams,\n query,\n };\n const urlCreateParams: UrlCreateParams<TInputParams> =\n this.config.createUrl?.(defaultUrlCreateParams, this.query.data) ??\n routeConfig.get().createUrl?.(defaultUrlCreateParams, this.query.data) ??\n defaultUrlCreateParams;\n\n const path = this._compiler(this.processParams(urlCreateParams.params));\n\n const url = [urlCreateParams.baseUrl, this.isHash ? '#' : '', path].join(\n '',\n );\n\n if (outputParams?.omitQuery) {\n return url;\n }\n\n return `${url}${buildSearchString(urlCreateParams.query)}`;\n }\n\n /**\n * Navigates to this route.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#open-args)\n */\n open(\n ...args: IsPartial<TInputParams> extends true\n ? [\n params?: TInputParams | null | undefined,\n navigateParams?: RouteNavigateParams,\n ]\n : [params: TInputParams, navigateParams?: RouteNavigateParams]\n ): Promise<void>;\n open(\n ...args: IsPartial<TInputParams> extends true\n ? [\n params?: TInputParams | null | undefined,\n replace?: RouteNavigateParams['replace'],\n query?: RouteNavigateParams['query'],\n ]\n : [\n params: TInputParams,\n replace?: RouteNavigateParams['replace'],\n query?: RouteNavigateParams['query'],\n ]\n ): Promise<void>;\n open(url: string, navigateParams?: RouteNavigateParams): Promise<void>;\n open(\n url: string,\n replace?: RouteNavigateParams['replace'],\n query?: RouteNavigateParams['query'],\n ): Promise<void>;\n\n /**\n * Navigates to this route.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#open-args)\n */\n async open(...args: any[]) {\n const {\n replace,\n state: rawState,\n query: rawQuery,\n mergeQuery: rawMergeQuery,\n } = typeof args[1] === 'boolean' || args.length > 2\n ? ({ replace: args[1], query: args[2] } as RouteNavigateParams)\n : ((args[1] ?? {}) as RouteNavigateParams);\n let url: string;\n let params: Maybe<InputPathParams<TPath>>;\n\n const mergeQuery = rawMergeQuery ?? this.isAbleToMergeQuery;\n const query = mergeQuery ? { ...this.query.data, ...rawQuery } : rawQuery;\n\n if (typeof args[0] === 'string') {\n url = args[0];\n } else {\n params = args[0] as InputPathParams<TPath>;\n url = this.createUrl(args[0], query);\n }\n\n const state = rawState ?? null;\n\n const navigationData: PreparedNavigationData<TInputParams> = {\n url,\n params: params as TInputParams,\n replace,\n state,\n query,\n };\n\n const feedback = await this.beforeOpen(navigationData);\n\n if (feedback === false) {\n return;\n }\n\n if (typeof feedback === 'object') {\n Object.assign(navigationData, feedback);\n }\n\n if (replace) {\n this.history.replace(url, state);\n } else {\n this.history.push(url, state);\n }\n\n if (!this.reactionDisposer && this.isOpened) {\n this.config.afterOpen?.(this.parsedPathData!, this);\n }\n }\n\n protected beforeOpen(\n openData: PreparedNavigationData<TInputParams>,\n ): MaybePromise<BeforeOpenFeedback> {\n if (this.config.beforeOpen) {\n return this.config.beforeOpen(openData);\n }\n\n return true;\n }\n\n protected afterClose() {\n if (this.config.afterClose) {\n return this.config.afterClose();\n }\n\n return true;\n }\n\n protected get tokenData() {\n if (!this._tokenData) {\n this._tokenData = parse(this.path, this.config.parseOptions);\n }\n return this._tokenData;\n }\n\n private firstOpenedStateCheck = true;\n private processOpenedState = (isOpened: boolean) => {\n if (this.firstOpenedStateCheck) {\n this.firstOpenedStateCheck = false;\n // ignore first 'afterClose' callback call\n if (!isOpened) {\n return;\n }\n }\n\n if (isOpened) {\n this.config.afterOpen?.(this.parsedPathData!, this);\n } else {\n this.config.afterClose?.();\n }\n };\n\n private get isAbleToMergeQuery() {\n return this.config.mergeQuery ?? routeConfig.get().mergeQuery;\n }\n\n destroy() {\n this.abortController.abort();\n }\n}\n\nexport const createRoute = <\n TPath extends string,\n TInputParams extends InputPathParams<TPath> = InputPathParams<TPath>,\n TOutputParams extends AnyObject = ParsedPathParams<TPath>,\n TParentRoute extends Route<any, any, any, any> | null = null,\n>(\n path: TPath,\n config?: RouteConfiguration<TPath, TInputParams, TOutputParams, TParentRoute>,\n) => new Route<TPath, TInputParams, TOutputParams, TParentRoute>(path, config);\n","import { computed, makeObservable, observable } from 'mobx';\n\nimport type {\n AbstractRouteGroup,\n AnyRouteEntity,\n RoutesCollection,\n} from './route-group.types.js';\n\ndeclare const process: { env: { NODE_ENV?: string } };\n\n/**\n * Class for grouping related routes and managing their state.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/RouteGroup.html)\n */\nexport class RouteGroup<TRoutesCollection extends RoutesCollection>\n implements AbstractRouteGroup<TRoutesCollection>\n{\n routes: TRoutesCollection;\n\n constructor(\n routes: TRoutesCollection,\n private _indexRoute?: AnyRouteEntity,\n ) {\n this.routes = routes;\n\n computed.struct(this, 'isOpened');\n computed.struct(this, 'indexRoute');\n observable.shallow(this, 'routes');\n makeObservable(this);\n }\n\n /**\n * Returns true if at least one route in the group is open.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/RouteGroup.html#isopened-boolean)\n */\n get isOpened(): boolean {\n const routes = Object.values(this.routes);\n return routes.some(\n (route) =>\n route.isOpened ||\n ('hasOpenedChildren' in route && route.hasOpenedChildren),\n );\n }\n\n /**\n * First found index route.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/RouteGroup.html#indexroute-route-undefined)\n */\n get indexRoute(): AnyRouteEntity | undefined {\n return (this._indexRoute ??\n Object.values(this.routes).find(\n (route) => 'isIndex' in route && route.isIndex,\n )) as unknown as AnyRouteEntity;\n }\n\n /**\n * Main navigation method for the group.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/RouteGroup.html#open-args-any-void)\n */\n open(...args: any[]) {\n let lastGroupRoute: RouteGroup<any> | undefined;\n\n if (this.indexRoute && 'open' in this.indexRoute) {\n this.indexRoute.open(...args);\n return;\n }\n\n for (const routeName in this.routes) {\n const route = this.routes[routeName];\n if (route instanceof RouteGroup) {\n lastGroupRoute = route;\n }\n }\n\n if (lastGroupRoute) {\n lastGroupRoute.open(...args);\n } else if (process.env.NODE_ENV !== 'production') {\n console.warn(\n \"RouteGroup doesn't have index route. open() method doesn't work.\",\n );\n }\n }\n}\n\nexport const createRouteGroup = <TRoutesCollection extends RoutesCollection>(\n routes: TRoutesCollection,\n indexRoute?: AnyRouteEntity,\n) => new RouteGroup<TRoutesCollection>(routes, indexRoute);\n","import { computed, makeObservable } from 'mobx';\nimport {\n buildSearchString,\n type History,\n type IQueryParams,\n} from 'mobx-location-history';\n\nimport { routeConfig } from '../config/index.js';\nimport type { RoutesCollection } from '../route-group/index.js';\n\nimport type {\n RouterConfiguration,\n RouterNavigateOptions,\n} from './router.types.js';\n\n/**\n * Class for centralized routing management.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Router.html)\n */\nexport class Router<TRoutesCollection extends RoutesCollection> {\n routes: TRoutesCollection;\n history: History;\n query: IQueryParams;\n\n constructor(config: RouterConfiguration<TRoutesCollection>) {\n this.routes = config.routes;\n this.history = config.history ?? routeConfig.get().history;\n this.query = config.queryParams ?? routeConfig.get().queryParams;\n\n computed.struct(this, 'location');\n\n makeObservable(this);\n }\n\n get location() {\n return this.history.location;\n }\n\n navigate(url: string, options?: RouterNavigateOptions) {\n const query =\n (options?.mergeQuery ?? routeConfig.get().mergeQuery)\n ? { ...this.query.data, ...options?.query }\n : { ...options?.query };\n\n const searchString = buildSearchString(query);\n const navigationUrl = `${url}${searchString}`;\n\n if (options?.replace) {\n this.history.replace(navigationUrl, options?.state);\n } else {\n this.history.push(navigationUrl, options?.state);\n }\n }\n}\n\nexport const createRouter = <TRoutesCollection extends RoutesCollection>(\n config: RouterConfiguration<TRoutesCollection>,\n) => new Router(config);\n","import type { AnyRouteEntity } from '../route-group/index.js';\n\nexport const isRouteEntity = (route: any): route is AnyRouteEntity =>\n route && 'isOpened' in route;\n","import { LinkedAbortController } from 'linked-abort-controller';\nimport {\n action,\n computed,\n makeObservable,\n observable,\n onBecomeObserved,\n onBecomeUnobserved,\n reaction,\n runInAction,\n} from 'mobx';\nimport type { IQueryParams } from 'mobx-location-history';\nimport { callFunction } from 'yummies/common';\nimport type { AnyObject, EmptyObject, IsPartial, Maybe } from 'yummies/types';\n\nimport { routeConfig } from '../config/index.js';\n\nimport type {\n AbstractVirtualRoute,\n VirtualOpenExtraParams,\n VirtualRouteConfiguration,\n} from './virtual-route.types.js';\n\n/**\n * Class for creating routes with custom activation logic\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html)\n */\nexport class VirtualRoute<TParams extends AnyObject | EmptyObject = EmptyObject>\n implements AbstractVirtualRoute<TParams>\n{\n protected abortController: AbortController;\n query: IQueryParams;\n params: TParams | null;\n\n private isLocalOpened: boolean;\n\n private openChecker: Maybe<VirtualRouteConfiguration<TParams>['checkOpened']>;\n private reactionDisposer: Maybe<VoidFunction>;\n\n constructor(protected config: VirtualRouteConfiguration<TParams> = {}) {\n this.abortController = new LinkedAbortController(config.abortSignal);\n this.query = config.queryParams ?? routeConfig.get().queryParams;\n this.params = callFunction(config.initialParams, this) ?? null;\n this.openChecker = config.checkOpened;\n this.isLocalOpened = this.openChecker?.(this) ?? false;\n\n observable(this, 'params');\n observable.ref(this, 'isLocalOpened');\n observable.ref(this, '_isOpened');\n computed.struct(this, 'isOpened');\n action(this, 'setOpenChecker');\n action(this, 'open');\n action(this, 'close');\n makeObservable(this);\n\n onBecomeObserved(this, 'isOpened', () => {\n if (!config.afterOpen && !config.afterClose) {\n return;\n }\n\n this.reactionDisposer = reaction(\n () => this.isOpened,\n this.processOpenedState,\n {\n signal: this.abortController.signal,\n fireImmediately: true,\n },\n );\n });\n onBecomeUnobserved(this, 'isOpened', () => {\n this.reactionDisposer?.();\n this.reactionDisposer = undefined;\n });\n }\n\n /**\n * [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html#isopened-boolean)\n */\n get isOpened() {\n const isOuterOpened = this.openChecker == null || this.openChecker(this);\n return this.isLocalOpened && isOuterOpened;\n }\n\n /**\n * [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html#setopenchecker-openchecker-void)\n */\n setOpenChecker(\n openChecker: Maybe<VirtualRouteConfiguration<TParams>['checkOpened']>,\n ) {\n this.openChecker = openChecker;\n }\n\n /**\n * [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html#open-params-extraparams-query-replace-promise-void)\n */\n open(\n ...args: IsPartial<TParams> extends true\n ? [params?: Maybe<TParams>, extraParams?: VirtualOpenExtraParams]\n : [params: TParams, extraParams?: VirtualOpenExtraParams]\n ): Promise<void>;\n async open(...args: any[]) {\n const params = (args[0] ?? {}) as unknown as TParams;\n const extraParams: Maybe<VirtualOpenExtraParams> = args[1];\n\n if (this.config.beforeOpen) {\n const beforeOpenResult = await this.config.beforeOpen(params, this);\n if (beforeOpenResult === false) {\n return;\n }\n }\n\n if (this.config.open == null) {\n runInAction(() => {\n this.isLocalOpened = true;\n });\n } else {\n const result = await this.config.open(params, this);\n // because result can return void so this is truthy for opening state\n runInAction(() => {\n this.isLocalOpened = result !== false;\n });\n }\n\n if (!this.isLocalOpened) {\n return;\n }\n\n if (extraParams?.query) {\n this.query.update(extraParams.query, extraParams.replace);\n }\n\n runInAction(() => {\n this.params = params;\n });\n\n if (!this.reactionDisposer && this.isOpened) {\n this.config.afterOpen?.(this.params!, this);\n }\n }\n\n /**\n * [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html#close-void)\n */\n close() {\n if (this.config.close == null) {\n this.isLocalOpened = false;\n } else {\n const result = this.config.close(this);\n // because result can return void so this is truthy for opening state\n this.isLocalOpened = result !== false;\n }\n\n this.params = null;\n }\n\n private firstOpenedStateCheck = true;\n private processOpenedState = (isOpened: boolean) => {\n if (this.firstOpenedStateCheck) {\n this.firstOpenedStateCheck = false;\n // ignore first 'afterClose' callback call\n if (!isOpened) {\n return;\n }\n }\n\n if (isOpened) {\n this.config.afterOpen?.(this.params!, this);\n } else {\n this.config.afterClose?.();\n }\n };\n\n destroy() {\n this.abortController.abort();\n }\n}\n\nexport const createVirtualRoute = <\n TParams extends AnyObject | EmptyObject = EmptyObject,\n>(\n config?: VirtualRouteConfiguration<TParams>,\n) => new VirtualRoute<TParams>(config);\n"],"names":["createGlobalDynamicConfig","isObservableHistory","createBrowserHistory","QueryParams","LinkedAbortController","computed","observable","action","makeObservable","onBecomeObserved","reaction","onBecomeUnobserved","match","compile","buildSearchString","parse","callFunction","runInAction"],"mappings":"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"}
|