mobx-route 1.3.4 → 2.1.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  <img src="docs/public/logo.png" align="right" width="156" alt="logo" />
2
2
 
3
- # mobx-route
3
+ # mobx-route
4
4
 
5
5
  [![NPM version][npm-image]][npm-url] [![build status][github-build-actions-image]][github-actions-url] [![npm download][download-image]][download-url] [![bundle size][bundlephobia-image]][bundlephobia-url]
6
6
 
@@ -14,23 +14,189 @@
14
14
  [bundlephobia-url]: https://bundlephobia.com/result?p=mobx-route
15
15
  [bundlephobia-image]: https://badgen.net/bundlephobia/minzip/mobx-route
16
16
 
17
+ 🚀 Simple and lightweight **typed** MobX router 🚀
18
+ _Uses [`path-to-regexp`](https://www.npmjs.com/package/path-to-regexp) power for path matching_
17
19
 
18
- 🚀 Simple and lightweight typed MobX router 🚀
19
- _Uses [`path-to-regexp` power](https://www.npmjs.com/package/path-to-regexp)_
20
+ ### [📖 Read the docs →](https://js2me.github.io/mobx-route/)
20
21
 
21
- ### [Read the docs →](https://js2me.github.io/mobx-route/)
22
+ ---
22
23
 
24
+ ## Quick Start
23
25
 
24
26
  ```ts
25
27
  import { createRoute } from "mobx-route";
26
28
 
27
29
  const userDetails = createRoute("/users/:id");
28
30
 
29
- await userDetails.open({ id: 1 }); // path params are required
31
+ // Path params are required TypeScript enforces it
32
+ await userDetails.open({ id: 1 });
30
33
 
31
- userDetails.isOpened; // true;
34
+ userDetails.isOpened; // true
35
+ userDetails.params; // { id: "1" } — fully typed
32
36
  ```
33
37
 
34
- ## Contribution Guide
38
+ ---
35
39
 
36
- Want to contribute ? [Follow this guide](https://github.com/js2me/mobx-route/blob/master/CONTRIBUTING.md)
40
+ ## Features
41
+
42
+ ### 🔗 Nested Routes with `.extend()`
43
+
44
+ Build route trees naturally — no config arrays, no `<Routes>` wrappers:
45
+
46
+ ```ts
47
+ const users = createRoute("/users");
48
+ const userDetails = users.extend("/:userId");
49
+ const userPhotos = userDetails.extend("/photos");
50
+
51
+ // Path is auto-concatenated: /users/:userId/photos
52
+ await userPhotos.open({ userId: 42 });
53
+ // → /users/42/photos
54
+
55
+ users.isOpened; // true (parent is open too)
56
+ users.hasOpenedChildren; // true
57
+ ```
58
+
59
+ ### 🛡️ Route Guards & Redirects
60
+
61
+ Protect routes with `beforeOpen` — cancel navigation or redirect:
62
+
63
+ ```ts
64
+ const dashboard = createRoute("/dashboard", {
65
+ beforeOpen: async () => {
66
+ if (!await isAuthenticated()) {
67
+ return { url: "/login", replace: true }; // redirect
68
+ }
69
+ // return undefined → proceed
70
+ },
71
+ checkOpened: () => currentUser.isAuthorized, // reactive predicate
72
+ });
73
+ ```
74
+
75
+ ### 🔮 Virtual Routes for Modals & Drawers
76
+
77
+ Same `.open()` / `.close()` / `.isOpened` API — but no URL involved:
78
+
79
+ ```ts
80
+ const authModal = createVirtualRoute({
81
+ checkOpened: (route) => route.query.data.modal === "auth",
82
+ open: (_, route) => route.query.update({ modal: "auth" }),
83
+ close: (route) => route.query.update({ modal: undefined }),
84
+ beforeClose: () => !hasUnsavedChanges, // prevent closing
85
+ });
86
+
87
+ authModal.isOpened; // reactive — auto-updates from query
88
+ authModal.isClosing; // for exit animations
89
+ ```
90
+
91
+ ### 🎯 Typed Query Params
92
+
93
+ ```ts
94
+ const search = createRoute<
95
+ "/search",
96
+ {},
97
+ {},
98
+ { q: string; page?: number; sort?: "asc" | "desc" }
99
+ >("/search");
100
+
101
+ // TQueryParams types the INPUT — what you pass to open()
102
+ await search.open({}, { query: { q: "mobx", page: 1 } });
103
+
104
+ // query.data is always Record<string, string> at runtime (values come from URL)
105
+ search.query.data.q; // string
106
+ search.query.data.page; // string | undefined — use Number() or QueryParam for typed access
107
+ ```
108
+
109
+ ### 🔄 `update()` for In-Place Changes
110
+
111
+ Replace params without polluting browser history:
112
+
113
+ ```ts
114
+ await userRoute.open({ userId: 1 }, { query: { tab: "profile" } });
115
+ await userRoute.update({ userId: 2 });
116
+ // → /users/2?tab=profile (replace: true, mergeQuery: true by default)
117
+ ```
118
+
119
+ ### 🧩 React Integration
120
+
121
+ ```tsx
122
+ import { RouteView, RouteViewGroup, Link } from "mobx-route/react";
123
+
124
+ // Declarative route rendering
125
+ <RouteView route={userRoute} view={UserPage} fallback={<Loading />} />
126
+
127
+ // Route switching with fallback
128
+ <RouteViewGroup otherwise={notFoundRoute}>
129
+ <RouteView route={homeRoute} view={HomePage} />
130
+ <RouteView route={userRoute} view={UserPage} />
131
+ <div>Not found</div>
132
+ </RouteViewGroup>
133
+
134
+ // Type-safe links
135
+ <Link to={userRoute} params={{ userId: 42 }}>Profile</Link>
136
+ ```
137
+
138
+ ### 🧠 View Model Integration
139
+
140
+ ```ts
141
+ import { RouteViewModel } from "mobx-route/view-model";
142
+
143
+ class UserPageVM extends RouteViewModel<typeof userRoute> {
144
+ route = userRoute;
145
+ // payload, pathParams, query, isMounted — all built-in
146
+ }
147
+ ```
148
+
149
+ ### 🌍 Optional Path Segments & Wildcards
150
+
151
+ ```ts
152
+ // Optional segment
153
+ const route = createRoute("/users{/:tab}");
154
+ route.open(); // → /users
155
+ route.open({ tab: 1 }); // → /users/1
156
+
157
+ // Wildcard/rest params
158
+ const docs = createRoute("/docs/*rest");
159
+ docs.open({ rest: ["api", "v2", "auth"] }); // → /docs/api/v2/auth
160
+ ```
161
+
162
+ ### 📦 Tree-Shakeable Subpath Exports
163
+
164
+ Only pay for what you use:
165
+
166
+ ```ts
167
+ import { createRoute } from "mobx-route"; // core only
168
+ import { RouteView, Link } from "mobx-route/react"; // + React
169
+ import { RouteViewModel } from "mobx-route/view-model"; // + VM
170
+ ```
171
+
172
+ ---
173
+
174
+ ## Installation
175
+
176
+ ```bash
177
+ npm install mobx-route
178
+ # or
179
+ pnpm add mobx-route
180
+ # or
181
+ yarn add mobx-route
182
+ ```
183
+
184
+ Peer dependencies (React integration is optional):
185
+
186
+ ```bash
187
+ npm install mobx
188
+ # For React:
189
+ npm install mobx-react-lite react react-dom
190
+ ```
191
+
192
+ ---
193
+
194
+ ## Contribution Guide
195
+
196
+ Want to contribute? [Follow this guide](https://github.com/js2me/mobx-route/blob/master/CONTRIBUTING.md)
197
+
198
+ ---
199
+
200
+ ## License
201
+
202
+ [MIT](https://github.com/js2me/mobx-route/blob/master/LICENSE)
package/index.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const mobxLocationHistory = require("mobx-location-history");
4
- const virtualRoute = require("./virtual-route-B_X_wClE.cjs");
4
+ const virtualRoute = require("./virtual-route-EXYD3rMt.cjs");
5
5
  const isRouteEntity = (route) => route && "isOpened" in route;
6
6
  exports.Route = virtualRoute.Route;
7
7
  exports.RouteGroup = virtualRoute.RouteGroup;
package/index.d.ts CHANGED
@@ -19,12 +19,12 @@ interface AbstractVirtualRoute<TParams extends AnyObject | EmptyObject = EmptyOb
19
19
  extraParams?: VirtualOpenExtraParams<TQueryParams>
20
20
  ] : [params: TParams, extraParams?: VirtualOpenExtraParams<TQueryParams>]): Promise<void>;
21
21
  }
22
- interface VirtualRouteConfiguration<TParams extends AnyObject | EmptyObject = EmptyObject, TQueryParams extends Record<string, any> = AnyObject> {
22
+ interface VirtualRouteConfiguration<TParams extends AnyObject | EmptyObject = EmptyObject> {
23
23
  /**
24
24
  * [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html#abortsignal)
25
25
  */
26
26
  abortSignal?: AbortSignal;
27
- queryParams?: IQueryParams<TQueryParams>;
27
+ queryParams?: IQueryParams;
28
28
  /**
29
29
  * [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html#initialparams)
30
30
  */
@@ -88,10 +88,10 @@ interface VirtualRouteTrx<TQueryParams extends Record<string, any> = AnyObject>
88
88
  * [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html)
89
89
  */
90
90
  declare class VirtualRoute<TParams extends AnyObject | EmptyObject = EmptyObject, TQueryParams extends Record<string, any> = AnyObject> implements AbstractVirtualRoute<TParams, TQueryParams> {
91
- protected config: VirtualRouteConfiguration<TParams, TQueryParams>;
91
+ protected config: VirtualRouteConfiguration<TParams>;
92
92
  private isDestroyed?;
93
93
  private disposer?;
94
- query: IQueryParams<TQueryParams>;
94
+ query: IQueryParams;
95
95
  params: TParams | null;
96
96
  protected status: 'opening' | 'open-rejected' | 'opened' | 'closing' | 'closed' | 'unknown';
97
97
  private openChecker;
@@ -103,7 +103,7 @@ declare class VirtualRoute<TParams extends AnyObject | EmptyObject = EmptyObject
103
103
  * [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html#isouteropened)
104
104
  */
105
105
  isOuterOpened: boolean | undefined;
106
- constructor(config?: VirtualRouteConfiguration<TParams, TQueryParams>);
106
+ constructor(config?: VirtualRouteConfiguration<TParams>);
107
107
  /**
108
108
  * [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html#isopened)
109
109
  */
@@ -135,7 +135,7 @@ declare class VirtualRoute<TParams extends AnyObject | EmptyObject = EmptyObject
135
135
  private confirmClosing;
136
136
  destroy(): void;
137
137
  }
138
- declare const createVirtualRoute: <TParams extends AnyObject | EmptyObject = EmptyObject, TQueryParams extends Record<string, any> = AnyObject>(config?: VirtualRouteConfiguration<TParams, TQueryParams>) => VirtualRoute<TParams, TQueryParams>;
138
+ declare const createVirtualRoute: <TParams extends AnyObject | EmptyObject = EmptyObject, TQueryParams extends Record<string, any> = AnyObject>(config?: VirtualRouteConfiguration<TParams>) => VirtualRoute<TParams, TQueryParams>;
139
139
 
140
140
  /**
141
141
  * Class for grouping related routes and managing their state.
@@ -224,7 +224,7 @@ interface CreatedUrlOutputParams {
224
224
  /** @see [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#createurl) */
225
225
  omitQuery?: boolean;
226
226
  }
227
- interface RouteConfiguration<TPath extends string, TInputParams extends InputPathParams<TPath> = InputPathParams<TPath>, TOutputParams extends AnyObject = ParsedPathParams<TPath>, TParentRoute extends Route<string, any, any, any, any> | null = null, TQueryParams extends Record<string, any> = AnyObject> extends Omit<Partial<RouteGlobalConfig>, 'createUrl'> {
227
+ interface RouteConfiguration<TPath extends string, TInputParams extends InputPathParams<TPath> = InputPathParams<TPath>, TOutputParams extends AnyObject = ParsedPathParams<TPath>, TQueryParams extends Record<string, any> = AnyObject> extends Omit<Partial<RouteGlobalConfig>, 'createUrl'> {
228
228
  /**
229
229
  * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#abortsignal)
230
230
  */
@@ -242,7 +242,7 @@ interface RouteConfiguration<TPath extends string, TInputParams extends InputPat
242
242
  meta?: AnyObject;
243
243
  parseOptions?: ParseOptions;
244
244
  matchOptions?: MatchOptions & ParseOptions;
245
- parent?: TParentRoute;
245
+ parent?: AnyRoute | null;
246
246
  children?: AnyRoute[];
247
247
  /**
248
248
  * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#params)
@@ -263,17 +263,17 @@ interface RouteConfiguration<TPath extends string, TInputParams extends InputPat
263
263
  /**
264
264
  * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#afteropen)
265
265
  */
266
- afterOpen?: (data: ParsedPathData<NoInfer<TPath>>, route: Route<NoInfer<TPath>, NoInfer<TInputParams>, NoInfer<TOutputParams>, NoInfer<TParentRoute>, NoInfer<TQueryParams>>) => void;
266
+ afterOpen?: (data: ParsedPathData<NoInfer<TPath>>, route: Route<NoInfer<TPath>, NoInfer<TInputParams>, NoInfer<TOutputParams>, NoInfer<TQueryParams>>) => void;
267
267
  /**
268
268
  * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#afterupdate)
269
269
  */
270
- afterUpdate?: (data: ParsedPathData<NoInfer<TPath>>, route: Route<NoInfer<TPath>, NoInfer<TInputParams>, NoInfer<TOutputParams>, NoInfer<TParentRoute>, NoInfer<TQueryParams>>) => void;
270
+ afterUpdate?: (data: ParsedPathData<NoInfer<TPath>>, route: Route<NoInfer<TPath>, NoInfer<TInputParams>, NoInfer<TOutputParams>, NoInfer<TQueryParams>>) => void;
271
271
  /**
272
272
  * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#createurl)
273
273
  */
274
274
  createUrl?: UrlCreateParamsFn<TInputParams, TQueryParams>;
275
275
  }
276
- type AnyRoute = Route<any, any, any, any, any>;
276
+ type AnyRoute = Route<any, any, any, any>;
277
277
  type InputPathParam = string | number | boolean | null;
278
278
  type ParsedPathParam = string;
279
279
  type Simplify<T> = T extends infer U ? {
@@ -303,18 +303,24 @@ interface ParsedPathData<TPath extends string> {
303
303
  path: string;
304
304
  params: ParsedPathParams<TPath>;
305
305
  }
306
- type InferPath<T extends AnyRoute> = T extends Route<infer TPath, any, any, any, any> ? TPath : never;
307
- type InferInputParams<T extends AnyRoute> = T extends VirtualRoute<infer TParams> ? TParams : T extends Route<any, infer TInputParams, any, any, any> ? TInputParams : never;
308
- type InferParams<T extends AnyRoute> = T extends VirtualRoute<infer TParams> ? TParams : T extends Route<any, any, infer TParams, any, any> ? TParams : never;
309
- type InferQueryParams<T extends AnyRoute> = T extends Route<any, any, any, any, infer TQueryParams> ? TQueryParams : never;
306
+ type InferPath<T extends AnyRoute> = T extends Route<infer TPath, any, any, any> ? TPath : never;
307
+ type InferInputParams<T extends AnyRoute> = T extends VirtualRoute<infer TParams> ? TParams : T extends Route<any, infer TInputParams, any, any> ? TInputParams : never;
308
+ type InferParams<T extends AnyRoute> = T extends VirtualRoute<infer TParams> ? TParams : T extends Route<any, any, infer TParams, any> ? TParams : never;
309
+ /**
310
+ * Extracts the query params input type from a route.
311
+ *
312
+ * Note: this represents the INPUT shape used in `open()`, `createUrl()`, etc.
313
+ * The actual `route.query.data` values are always `Record<string, string>` at runtime.
314
+ */
315
+ type InferQueryParams<T extends AnyRoute> = T extends Route<any, any, any, infer TQueryParams> ? TQueryParams : never;
310
316
 
311
317
  /**
312
318
  * Class for creating path based route.
313
319
  *
314
320
  * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html)
315
321
  */
316
- declare class Route<TPath extends string, TInputParams extends InputPathParams<TPath> = InputPathParams<TPath>, TOutputParams extends AnyObject = ParsedPathParams<TPath>, TParentRoute extends Route<any, any, any, any, any> | null = null, TQueryParams extends Record<string, any> = AnyObject> {
317
- protected config: RouteConfiguration<TPath, TInputParams, TOutputParams, TParentRoute, TQueryParams>;
322
+ declare class Route<TPath extends string, TInputParams extends InputPathParams<TPath> = InputPathParams<TPath>, TOutputParams extends AnyObject = ParsedPathParams<TPath>, TQueryParams extends Record<string, any> = AnyObject> {
323
+ protected config: RouteConfiguration<TPath, TInputParams, TOutputParams, TQueryParams>;
318
324
  private isDestroyed?;
319
325
  private disposer?;
320
326
  protected history: History;
@@ -323,8 +329,8 @@ declare class Route<TPath extends string, TInputParams extends InputPathParams<T
323
329
  *
324
330
  * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#parent)
325
331
  */
326
- parent: TParentRoute;
327
- query: IQueryParams<TQueryParams>;
332
+ parent: AnyRoute | null;
333
+ query: IQueryParams;
328
334
  private _tokenData;
329
335
  private _matcher?;
330
336
  private _compiler?;
@@ -357,7 +363,7 @@ declare class Route<TPath extends string, TInputParams extends InputPathParams<T
357
363
  * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#children)
358
364
  */
359
365
  children: AnyRoute[];
360
- constructor(pathDeclaration: TPath, config?: RouteConfiguration<TPath, TInputParams, TOutputParams, TParentRoute, TQueryParams>);
366
+ constructor(pathDeclaration: TPath, config?: RouteConfiguration<TPath, TInputParams, TOutputParams, TQueryParams>);
361
367
  protected get baseUrl(): string | undefined;
362
368
  /**
363
369
  * Checks whether current route matches provided path.
@@ -392,7 +398,15 @@ declare class Route<TPath extends string, TInputParams extends InputPathParams<T
392
398
  * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#params)
393
399
  */
394
400
  get params(): TOutputParams | null;
395
- protected get isPathMatched(): boolean;
401
+ protected get isConfigPathMatched(): boolean;
402
+ /**
403
+ * Whether the current URL path includes this route's path pattern.
404
+ * Uses prefix matching (`end: false`), so `/users` matches `/users/123`.
405
+ * Useful for navigation menu highlighting.
406
+ *
407
+ * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#ispathmatched)
408
+ */
409
+ get isPathMatched(): boolean;
396
410
  /**
397
411
  * Defines the "open" state for this route.
398
412
  *
@@ -404,7 +418,7 @@ declare class Route<TPath extends string, TInputParams extends InputPathParams<T
404
418
  *
405
419
  * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#extend)
406
420
  */
407
- extend<TExtendedPath extends string, TExtendedInputParams extends InputPathParams<`${TPath}${TExtendedPath}`> = InputPathParams<`${TPath}${TExtendedPath}`>, TExtendedOutputParams extends AnyObject = TInputParams & ParsedPathParams<`${TPath}${TExtendedPath}`>, TExtendedQueryParams extends Record<string, any> = TQueryParams>(pathDeclaration: TExtendedPath, config?: Omit<RouteConfiguration<`${TPath}${TExtendedPath}`, TInputParams & TExtendedInputParams, TExtendedOutputParams, any, TExtendedQueryParams>, 'parent'>): Route<`${TPath}${TExtendedPath}`, TInputParams & TExtendedInputParams, TExtendedOutputParams, this, TExtendedQueryParams>;
421
+ extend<TExtendedPath extends string, TExtendedInputParams extends InputPathParams<`${TPath}${TExtendedPath}`> = InputPathParams<`${TPath}${TExtendedPath}`>, TExtendedOutputParams extends AnyObject = TInputParams & ParsedPathParams<`${TPath}${TExtendedPath}`>, TExtendedQueryParams extends Record<string, any> = TQueryParams>(pathDeclaration: TExtendedPath, config?: Omit<RouteConfiguration<`${TPath}${TExtendedPath}`, TInputParams & TExtendedInputParams, TExtendedOutputParams, TExtendedQueryParams>, 'parent'>): Route<`${TPath}${TExtendedPath}`, TInputParams & TExtendedInputParams, TExtendedOutputParams, TExtendedQueryParams>;
408
422
  /**
409
423
  * Manually add child routes.
410
424
  *
@@ -484,7 +498,7 @@ declare class Route<TPath extends string, TInputParams extends InputPathParams<T
484
498
  */
485
499
  destroy(): void;
486
500
  }
487
- declare const createRoute: <TPath extends string, TInputParams extends InputPathParams<TPath> = InputPathParams<TPath>, TOutputParams extends AnyObject = ParsedPathParams<TPath>, TParentRoute extends Route<any, any, any, any, any> | null = null, TQueryParams extends Record<string, any> = AnyObject>(path: TPath, config?: RouteConfiguration<TPath, TInputParams, TOutputParams, TParentRoute, TQueryParams>) => Route<TPath, TInputParams, TOutputParams, TParentRoute, TQueryParams>;
501
+ declare const createRoute: <TPath extends string, TInputParams extends InputPathParams<TPath> = InputPathParams<TPath>, TOutputParams extends AnyObject = ParsedPathParams<TPath>, TQueryParams extends Record<string, any> = AnyObject>(path: TPath, config?: RouteConfiguration<TPath, TInputParams, TOutputParams, TQueryParams>) => Route<TPath, TInputParams, TOutputParams, TQueryParams>;
488
502
 
489
503
  /**
490
504
  * Global configuration for routes and router.
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export * from "mobx-location-history";
2
- import { R, a, b, V, c, d, e, g, r } from "./virtual-route-C7NPJx5y.js";
2
+ import { R, a, b, V, c, d, e, g, r } from "./virtual-route-DgVGEWRJ.js";
3
3
  const isRouteEntity = (route) => route && "isOpened" in route;
4
4
  export {
5
5
  R as Route,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mobx-route",
3
- "version": "1.3.4",
3
+ "version": "2.1.0",
4
4
  "keywords": [
5
5
  "mobx",
6
6
  "react",
@@ -67,13 +67,13 @@
67
67
  "require": "./view-model.cjs",
68
68
  "default": "./view-model.js"
69
69
  },
70
- "./virtual-route-B_X_wClE": {
71
- "require": "./virtual-route-B_X_wClE.cjs",
72
- "default": "./virtual-route-B_X_wClE.cjs"
70
+ "./virtual-route-DgVGEWRJ": {
71
+ "import": "./virtual-route-DgVGEWRJ.js",
72
+ "default": "./virtual-route-DgVGEWRJ.js"
73
73
  },
74
- "./virtual-route-C7NPJx5y": {
75
- "import": "./virtual-route-C7NPJx5y.js",
76
- "default": "./virtual-route-C7NPJx5y.js"
74
+ "./virtual-route-EXYD3rMt": {
75
+ "require": "./virtual-route-EXYD3rMt.cjs",
76
+ "default": "./virtual-route-EXYD3rMt.cjs"
77
77
  }
78
78
  },
79
79
  "files": [
package/view-model.cjs CHANGED
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const mobx = require("mobx");
4
4
  const mobxViewModel = require("mobx-view-model");
5
- const virtualRoute = require("./virtual-route-B_X_wClE.cjs");
5
+ const virtualRoute = require("./virtual-route-EXYD3rMt.cjs");
6
6
  const annotations = [
7
7
  [mobx.computed.struct, "pathParams"],
8
8
  [mobx.computed, "query"]
package/view-model.d.ts CHANGED
@@ -63,7 +63,7 @@ interface CreatedUrlOutputParams {
63
63
  /** @see [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#createurl) */
64
64
  omitQuery?: boolean;
65
65
  }
66
- interface RouteConfiguration<TPath extends string, TInputParams extends InputPathParams<TPath> = InputPathParams<TPath>, TOutputParams extends AnyObject = ParsedPathParams<TPath>, TParentRoute extends Route<string, any, any, any, any> | null = null, TQueryParams extends Record<string, any> = AnyObject> extends Omit<Partial<RouteGlobalConfig>, 'createUrl'> {
66
+ interface RouteConfiguration<TPath extends string, TInputParams extends InputPathParams<TPath> = InputPathParams<TPath>, TOutputParams extends AnyObject = ParsedPathParams<TPath>, TQueryParams extends Record<string, any> = AnyObject> extends Omit<Partial<RouteGlobalConfig>, 'createUrl'> {
67
67
  /**
68
68
  * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#abortsignal)
69
69
  */
@@ -81,7 +81,7 @@ interface RouteConfiguration<TPath extends string, TInputParams extends InputPat
81
81
  meta?: AnyObject;
82
82
  parseOptions?: ParseOptions;
83
83
  matchOptions?: MatchOptions & ParseOptions;
84
- parent?: TParentRoute;
84
+ parent?: AnyRoute | null;
85
85
  children?: AnyRoute[];
86
86
  /**
87
87
  * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#params)
@@ -102,17 +102,17 @@ interface RouteConfiguration<TPath extends string, TInputParams extends InputPat
102
102
  /**
103
103
  * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#afteropen)
104
104
  */
105
- afterOpen?: (data: ParsedPathData<NoInfer<TPath>>, route: Route<NoInfer<TPath>, NoInfer<TInputParams>, NoInfer<TOutputParams>, NoInfer<TParentRoute>, NoInfer<TQueryParams>>) => void;
105
+ afterOpen?: (data: ParsedPathData<NoInfer<TPath>>, route: Route<NoInfer<TPath>, NoInfer<TInputParams>, NoInfer<TOutputParams>, NoInfer<TQueryParams>>) => void;
106
106
  /**
107
107
  * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#afterupdate)
108
108
  */
109
- afterUpdate?: (data: ParsedPathData<NoInfer<TPath>>, route: Route<NoInfer<TPath>, NoInfer<TInputParams>, NoInfer<TOutputParams>, NoInfer<TParentRoute>, NoInfer<TQueryParams>>) => void;
109
+ afterUpdate?: (data: ParsedPathData<NoInfer<TPath>>, route: Route<NoInfer<TPath>, NoInfer<TInputParams>, NoInfer<TOutputParams>, NoInfer<TQueryParams>>) => void;
110
110
  /**
111
111
  * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#createurl)
112
112
  */
113
113
  createUrl?: UrlCreateParamsFn<TInputParams, TQueryParams>;
114
114
  }
115
- type AnyRoute = Route<any, any, any, any, any>;
115
+ type AnyRoute = Route<any, any, any, any>;
116
116
  type InputPathParam = string | number | boolean | null;
117
117
  type ParsedPathParam = string;
118
118
  type Simplify<T> = T extends infer U ? {
@@ -148,8 +148,8 @@ interface ParsedPathData<TPath extends string> {
148
148
  *
149
149
  * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html)
150
150
  */
151
- declare class Route<TPath extends string, TInputParams extends InputPathParams<TPath> = InputPathParams<TPath>, TOutputParams extends AnyObject = ParsedPathParams<TPath>, TParentRoute extends Route<any, any, any, any, any> | null = null, TQueryParams extends Record<string, any> = AnyObject> {
152
- protected config: RouteConfiguration<TPath, TInputParams, TOutputParams, TParentRoute, TQueryParams>;
151
+ declare class Route<TPath extends string, TInputParams extends InputPathParams<TPath> = InputPathParams<TPath>, TOutputParams extends AnyObject = ParsedPathParams<TPath>, TQueryParams extends Record<string, any> = AnyObject> {
152
+ protected config: RouteConfiguration<TPath, TInputParams, TOutputParams, TQueryParams>;
153
153
  private isDestroyed?;
154
154
  private disposer?;
155
155
  protected history: History;
@@ -158,8 +158,8 @@ declare class Route<TPath extends string, TInputParams extends InputPathParams<T
158
158
  *
159
159
  * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#parent)
160
160
  */
161
- parent: TParentRoute;
162
- query: IQueryParams<TQueryParams>;
161
+ parent: AnyRoute | null;
162
+ query: IQueryParams;
163
163
  private _tokenData;
164
164
  private _matcher?;
165
165
  private _compiler?;
@@ -192,7 +192,7 @@ declare class Route<TPath extends string, TInputParams extends InputPathParams<T
192
192
  * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#children)
193
193
  */
194
194
  children: AnyRoute[];
195
- constructor(pathDeclaration: TPath, config?: RouteConfiguration<TPath, TInputParams, TOutputParams, TParentRoute, TQueryParams>);
195
+ constructor(pathDeclaration: TPath, config?: RouteConfiguration<TPath, TInputParams, TOutputParams, TQueryParams>);
196
196
  protected get baseUrl(): string | undefined;
197
197
  /**
198
198
  * Checks whether current route matches provided path.
@@ -227,7 +227,15 @@ declare class Route<TPath extends string, TInputParams extends InputPathParams<T
227
227
  * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#params)
228
228
  */
229
229
  get params(): TOutputParams | null;
230
- protected get isPathMatched(): boolean;
230
+ protected get isConfigPathMatched(): boolean;
231
+ /**
232
+ * Whether the current URL path includes this route's path pattern.
233
+ * Uses prefix matching (`end: false`), so `/users` matches `/users/123`.
234
+ * Useful for navigation menu highlighting.
235
+ *
236
+ * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#ispathmatched)
237
+ */
238
+ get isPathMatched(): boolean;
231
239
  /**
232
240
  * Defines the "open" state for this route.
233
241
  *
@@ -239,7 +247,7 @@ declare class Route<TPath extends string, TInputParams extends InputPathParams<T
239
247
  *
240
248
  * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#extend)
241
249
  */
242
- extend<TExtendedPath extends string, TExtendedInputParams extends InputPathParams<`${TPath}${TExtendedPath}`> = InputPathParams<`${TPath}${TExtendedPath}`>, TExtendedOutputParams extends AnyObject = TInputParams & ParsedPathParams<`${TPath}${TExtendedPath}`>, TExtendedQueryParams extends Record<string, any> = TQueryParams>(pathDeclaration: TExtendedPath, config?: Omit<RouteConfiguration<`${TPath}${TExtendedPath}`, TInputParams & TExtendedInputParams, TExtendedOutputParams, any, TExtendedQueryParams>, 'parent'>): Route<`${TPath}${TExtendedPath}`, TInputParams & TExtendedInputParams, TExtendedOutputParams, this, TExtendedQueryParams>;
250
+ extend<TExtendedPath extends string, TExtendedInputParams extends InputPathParams<`${TPath}${TExtendedPath}`> = InputPathParams<`${TPath}${TExtendedPath}`>, TExtendedOutputParams extends AnyObject = TInputParams & ParsedPathParams<`${TPath}${TExtendedPath}`>, TExtendedQueryParams extends Record<string, any> = TQueryParams>(pathDeclaration: TExtendedPath, config?: Omit<RouteConfiguration<`${TPath}${TExtendedPath}`, TInputParams & TExtendedInputParams, TExtendedOutputParams, TExtendedQueryParams>, 'parent'>): Route<`${TPath}${TExtendedPath}`, TInputParams & TExtendedInputParams, TExtendedOutputParams, TExtendedQueryParams>;
243
251
  /**
244
252
  * Manually add child routes.
245
253
  *
package/view-model.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { computed } from "mobx";
2
2
  import { ViewModelBase, applyObservable } from "mobx-view-model";
3
- import { r as routeConfig } from "./virtual-route-C7NPJx5y.js";
3
+ import { r as routeConfig } from "./virtual-route-DgVGEWRJ.js";
4
4
  const annotations = [
5
5
  [computed.struct, "pathParams"],
6
6
  [computed, "query"]
@@ -32,6 +32,7 @@ const routeConfig = createGlobalDynamicConfig(
32
32
  const annotations$3 = [
33
33
  [
34
34
  computed,
35
+ "isConfigPathMatched",
35
36
  "isPathMatched",
36
37
  "isOpened",
37
38
  "isOpening",
@@ -60,9 +61,13 @@ class Route {
60
61
  if (this.config.abortSignal?.aborted) {
61
62
  this.isDestroyed = true;
62
63
  } else {
63
- this.disposer = reaction(() => this.isPathMatched, this.checkPathMatch, {
64
- fireImmediately: true
65
- });
64
+ this.disposer = reaction(
65
+ () => this.isConfigPathMatched,
66
+ this.checkPathMatch,
67
+ {
68
+ fireImmediately: true
69
+ }
70
+ );
66
71
  this.updateDisposer = reaction(
67
72
  () => {
68
73
  if (this.status !== "open-confirmed") return void 0;
@@ -179,7 +184,7 @@ class Route {
179
184
  if (this.status === "opening") {
180
185
  return true;
181
186
  }
182
- if (this.isDestroyed || !this.isPathMatched || this.params === null || this.status === "open-confirmed" || this.status === "open-rejected") {
187
+ if (this.isDestroyed || !this.isConfigPathMatched || this.params === null || this.status === "open-confirmed" || this.status === "open-rejected") {
183
188
  return false;
184
189
  }
185
190
  return this.status === "closed" || this.status === "unknown";
@@ -222,16 +227,38 @@ class Route {
222
227
  }
223
228
  return this.parsedPathData?.params ?? null;
224
229
  }
225
- get isPathMatched() {
230
+ get isConfigPathMatched() {
226
231
  return this.parsedPathData !== null;
227
232
  }
233
+ /**
234
+ * Whether the current URL path includes this route's path pattern.
235
+ * Uses prefix matching (`end: false`), so `/users` matches `/users/123`.
236
+ * Useful for navigation menu highlighting.
237
+ *
238
+ * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#ispathmatched)
239
+ */
240
+ get isPathMatched() {
241
+ let pathname = this.isHash ? this.history.location.hash.slice(1) : this.history.location.pathname;
242
+ if (this.baseUrl) {
243
+ if (!pathname.startsWith(this.baseUrl)) return false;
244
+ pathname = pathname.replace(this.baseUrl, "");
245
+ }
246
+ if (this.pathDeclaration === "" || this.pathDeclaration === "/") {
247
+ return pathname === "/" || pathname === "" || pathname.startsWith("/");
248
+ }
249
+ const matcher = match(this.tokenData, {
250
+ end: false,
251
+ ...this.config.matchOptions
252
+ });
253
+ return matcher(pathname) !== false;
254
+ }
228
255
  /**
229
256
  * Defines the "open" state for this route.
230
257
  *
231
258
  * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#isopened)
232
259
  */
233
260
  get isOpened() {
234
- if (this.isDestroyed || !this.isPathMatched || this.params === null || this.status !== "open-confirmed") {
261
+ if (this.isDestroyed || !this.isConfigPathMatched || this.params === null || this.status !== "open-confirmed") {
235
262
  return false;
236
263
  }
237
264
  return (
@@ -427,7 +454,7 @@ class Route {
427
454
  this.history.push(trx.url, trx.state);
428
455
  }
429
456
  }
430
- if (this.isPathMatched) {
457
+ if (this.isConfigPathMatched) {
431
458
  const wasAlreadyConfirmed = this.status === "open-confirmed";
432
459
  runInAction(() => {
433
460
  this.status = "open-confirmed";
@@ -510,10 +537,7 @@ class Route {
510
537
  this.updateDisposer = void 0;
511
538
  }
512
539
  }
513
- const createRoute = (path, config) => new Route(
514
- path,
515
- config
516
- );
540
+ const createRoute = (path, config) => new Route(path, config);
517
541
  const annotations$2 = [
518
542
  [computed, "isOpened", "indexRoute", "canNavigate"],
519
543
  [observable.shallow, "routes"]
@@ -824,4 +848,4 @@ export {
824
848
  groupRoutes as g,
825
849
  routeConfig as r
826
850
  };
827
- //# sourceMappingURL=virtual-route-C7NPJx5y.js.map
851
+ //# sourceMappingURL=virtual-route-DgVGEWRJ.js.map