@koordinates/xstate-tree 4.8.0 → 4.9.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.
@@ -96,19 +96,34 @@ function buildCreateRoute(history, basePath) {
96
96
  },
97
97
  // @ts-ignore :cry:
98
98
  matches(suppliedUrl, search) {
99
- var _a, _b, _c, _d;
99
+ var _a, _b, _c, _d, _e;
100
100
  const fullUrl = suppliedUrl.endsWith("/")
101
101
  ? suppliedUrl
102
102
  : suppliedUrl + "/";
103
103
  let url = fullUrl;
104
104
  const parentRoutes = getParentArray();
105
105
  let params = {};
106
+ const parsedQuery = (0, query_string_1.parse)(search);
106
107
  while (parentRoutes.length) {
107
108
  const parentRoute = parentRoutes.shift();
108
109
  const parentMatch = parentRoute.matcher(url, undefined);
109
110
  if (parentMatch === false) {
110
111
  return false;
111
112
  }
113
+ // Evaluate parent's canMatch predicate if provided
114
+ if (parentRoute.canMatch) {
115
+ const accumulatedParams = {
116
+ ...params,
117
+ ...((_a = parentMatch.params) !== null && _a !== void 0 ? _a : {}),
118
+ };
119
+ const canMatchResult = parentRoute.canMatch({
120
+ params: accumulatedParams,
121
+ query: parsedQuery,
122
+ });
123
+ if (!canMatchResult) {
124
+ return false;
125
+ }
126
+ }
112
127
  url = url.slice(parentMatch.matchLength);
113
128
  // All routes assume the url starts with a /
114
129
  // so if the parent route matches the / in the url, which consumes it
@@ -116,7 +131,7 @@ function buildCreateRoute(history, basePath) {
116
131
  if (!url.startsWith("/")) {
117
132
  url = "/" + url;
118
133
  }
119
- params = { ...params, ...((_a = parentMatch.params) !== null && _a !== void 0 ? _a : {}) };
134
+ params = { ...params, ...((_b = parentMatch.params) !== null && _b !== void 0 ? _b : {}) };
120
135
  }
121
136
  const matches = matcher(url, (0, query_string_1.parse)(search));
122
137
  // if there is any URL left after matching this route, the last to match
@@ -126,7 +141,7 @@ function buildCreateRoute(history, basePath) {
126
141
  }
127
142
  const fullParams = {
128
143
  ...params,
129
- ...((_b = matches.params) !== null && _b !== void 0 ? _b : {}),
144
+ ...((_c = matches.params) !== null && _c !== void 0 ? _c : {}),
130
145
  };
131
146
  if (fullParamsSchema) {
132
147
  fullParamsSchema.parse(fullParams);
@@ -138,7 +153,7 @@ function buildCreateRoute(history, basePath) {
138
153
  if (canMatch) {
139
154
  const canMatchResult = canMatch({
140
155
  params: fullParams,
141
- query: (_c = matches.query) !== null && _c !== void 0 ? _c : {},
156
+ query: (_d = matches.query) !== null && _d !== void 0 ? _d : {},
142
157
  });
143
158
  if (!canMatchResult) {
144
159
  return false;
@@ -148,7 +163,7 @@ function buildCreateRoute(history, basePath) {
148
163
  originalUrl: `${fullUrl}${search}`,
149
164
  type: event,
150
165
  params: fullParams,
151
- query: (_d = matches.query) !== null && _d !== void 0 ? _d : {},
166
+ query: (_e = matches.query) !== null && _e !== void 0 ? _e : {},
152
167
  };
153
168
  },
154
169
  // @ts-ignore :cry:
@@ -2,22 +2,29 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useIsRouteActive = void 0;
4
4
  const providers_1 = require("./providers");
5
- /**
6
- * @public
7
- * Accepts Routes and returns true if any route is currently active. False if not.
8
- *
9
- * If used outside of a RoutingContext, an error will be thrown.
10
- * @param routes - the routes to check
11
- * @returns true if any route is active, false if not
12
- * @throws if used outside of an xstate-tree root
13
- */
14
- function useIsRouteActive(...routes) {
5
+ function useIsRouteActive(...args) {
15
6
  const activeRouteEvents = (0, providers_1.useActiveRouteEvents)();
16
7
  if (!activeRouteEvents) {
17
8
  throw new Error("useIsRouteActive must be used within a RoutingContext. Are you using it outside of an xstate-tree Root?");
18
9
  }
10
+ let routes;
11
+ let predicate;
12
+ if (args.length === 2 &&
13
+ Array.isArray(args[0]) &&
14
+ typeof args[1] === "function") {
15
+ routes = args[0];
16
+ predicate = args[1];
17
+ }
18
+ else {
19
+ routes = args;
20
+ }
19
21
  return activeRouteEvents.some((activeRouteEvent) => {
20
- return routes.some((route) => activeRouteEvent.type === route.event);
22
+ const matches = routes.some((route) => activeRouteEvent.type === route.event);
23
+ if (!matches)
24
+ return false;
25
+ return predicate
26
+ ? predicate(activeRouteEvent)
27
+ : true;
21
28
  });
22
29
  }
23
30
  exports.useIsRouteActive = useIsRouteActive;
@@ -352,6 +352,13 @@ declare type IsEmptyObject<Obj, ExcludeOptional extends boolean = false> = undef
352
352
  never
353
353
  ] ? true : false;
354
354
 
355
+ /**
356
+ * @public
357
+ * Predicate invoked with the matching active route event to decide whether the
358
+ * route should be considered active.
359
+ */
360
+ declare type IsRouteActivePredicate<TRoutes extends AnyRoute[]> = (event: RoutingEvent<TRoutes[number]>) => boolean;
361
+
355
362
  /**
356
363
  * @public
357
364
  *
@@ -818,6 +825,20 @@ export declare function useActiveRouteEvents(): {
818
825
  */
819
826
  export declare function useIsRouteActive(...routes: AnyRoute[]): boolean;
820
827
 
828
+ /**
829
+ * @public
830
+ * Accepts an array of Routes and a predicate. Returns true if any of the
831
+ * routes is currently active AND the predicate returns true when called with
832
+ * the matching active route event.
833
+ *
834
+ * If used outside of a RoutingContext, an error will be thrown.
835
+ * @param routes - the routes to check
836
+ * @param predicate - called with the matching active route event; return true to treat the route as active
837
+ * @returns true if any route is active and the predicate returns true, false otherwise
838
+ * @throws if used outside of an xstate-tree root
839
+ */
840
+ export declare function useIsRouteActive<TRoutes extends AnyRoute[]>(routes: [...TRoutes], predicate: IsRouteActivePredicate<TRoutes>): boolean;
841
+
821
842
  /**
822
843
  * @public
823
844
  * Accepts a single Route and returns true if the route is currently active and marked as an index route.
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@koordinates/xstate-tree",
3
3
  "main": "lib/index.js",
4
4
  "types": "lib/xstate-tree.d.ts",
5
- "version": "4.8.0",
5
+ "version": "4.9.0",
6
6
  "license": "MIT",
7
7
  "description": "Build UIs with Actors using xstate and React",
8
8
  "keywords": [