@vertz/ui 0.2.34 → 0.2.36

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.
@@ -864,6 +864,13 @@ function query(source, options = {}) {
864
864
  function getCacheKey() {
865
865
  return cacheKeyComputed.value;
866
866
  }
867
+ function resolveCurrentCacheKey() {
868
+ if (currentEffectKey) {
869
+ const depHash = depHashSignal.peek();
870
+ return depHash ? `${currentEffectKey}:${depHash}` : currentEffectKey;
871
+ }
872
+ return getCacheKey();
873
+ }
867
874
  let currentRetainedKey = null;
868
875
  const retainable = "retain" in cache && "release" in cache;
869
876
  function retainKey(key) {
@@ -904,6 +911,7 @@ function query(source, options = {}) {
904
911
  const error = signal(undefined);
905
912
  const idle = signal(initialData === undefined);
906
913
  const entityBacked = signal(false);
914
+ let currentEffectKey;
907
915
  function normalizeToEntityStore(result) {
908
916
  if (!entityMeta)
909
917
  return;
@@ -1018,12 +1026,33 @@ function query(source, options = {}) {
1018
1026
  let ssrHydrated = false;
1019
1027
  let navPrefetchDeferred = false;
1020
1028
  if (!isSSR() && initialData === undefined) {
1021
- const hydrationKey = customKey ?? baseKey;
1029
+ let hydrationKey;
1030
+ const hasSSRData = !!globalThis.__VERTZ_SSR_DATA__;
1031
+ if (customKey) {
1032
+ hydrationKey = customKey;
1033
+ } else if (hasSSRData) {
1034
+ try {
1035
+ const raw = callThunkWithCapture();
1036
+ if (raw !== null) {
1037
+ if (isQueryDescriptor(raw)) {
1038
+ if (raw._entity && !entityMeta) {
1039
+ entityMeta = raw._entity;
1040
+ }
1041
+ } else {
1042
+ raw.catch(() => {});
1043
+ }
1044
+ }
1045
+ } catch {}
1046
+ hydrationKey = getCacheKey();
1047
+ } else {
1048
+ hydrationKey = baseKey;
1049
+ }
1022
1050
  const isNavigation = isNavPrefetchActive();
1023
1051
  ssrHydrationCleanup = hydrateQueryFromSSR(hydrationKey, (result) => {
1024
1052
  normalizeToEntityStore(result);
1025
1053
  rawData.value = result;
1026
1054
  loading.value = false;
1055
+ idle.value = false;
1027
1056
  cache.set(hydrationKey, result);
1028
1057
  ssrHydrated = true;
1029
1058
  }, { persistent: isNavigation });
@@ -1140,7 +1169,7 @@ function query(source, options = {}) {
1140
1169
  handleFetchPromise(fetchPromise, id, key);
1141
1170
  }
1142
1171
  function refetch() {
1143
- const key = getCacheKey();
1172
+ const key = resolveCurrentCacheKey();
1144
1173
  currentRetainedKey = null;
1145
1174
  cache.delete(key);
1146
1175
  getInflight().delete(key);
@@ -1184,10 +1213,12 @@ function query(source, options = {}) {
1184
1213
  isFirst = false;
1185
1214
  return;
1186
1215
  }
1187
- if (!isQueryDescriptor(trackRaw)) {
1216
+ const descriptorKey = isQueryDescriptor(trackRaw) ? trackRaw._key : undefined;
1217
+ if (!descriptorKey) {
1188
1218
  trackRaw.catch(() => {});
1189
1219
  }
1190
- const derivedKey = untrack(() => getCacheKey());
1220
+ const depHash2 = untrack(() => depHashSignal.value);
1221
+ const derivedKey = descriptorKey ? depHash2 ? `${descriptorKey}:${depHash2}` : descriptorKey : untrack(() => getCacheKey());
1191
1222
  const cached = untrack(() => cache.get(derivedKey));
1192
1223
  if (cached !== undefined) {
1193
1224
  retainKey(derivedKey);
@@ -1253,7 +1284,9 @@ function query(source, options = {}) {
1253
1284
  untrack(() => {
1254
1285
  idle.value = false;
1255
1286
  });
1256
- const key = effectKey ?? untrack(() => getCacheKey());
1287
+ const depHash = untrack(() => depHashSignal.value);
1288
+ currentEffectKey = effectKey;
1289
+ const key = effectKey ? depHash ? `${effectKey}:${depHash}` : effectKey : untrack(() => getCacheKey());
1257
1290
  if (!customKey && !effectKey) {
1258
1291
  const existing = untrack(() => getInflight().get(key));
1259
1292
  if (existing) {
@@ -1339,7 +1372,7 @@ function query(source, options = {}) {
1339
1372
  rawData.value = undefined;
1340
1373
  loading.value = true;
1341
1374
  });
1342
- const cacheKey = untrack(() => getCacheKey());
1375
+ const cacheKey = untrack(() => resolveCurrentCacheKey());
1343
1376
  cache.delete(cacheKey);
1344
1377
  const queryKey = customKey ?? meta.entityType;
1345
1378
  getEntityStore().queryIndices.clear(queryKey);
@@ -458,7 +458,7 @@ function createRouter(routes, initialUrlOrOptions, maybeOptions) {
458
458
  }
459
459
  }
460
460
  }
461
- async function applyNavigation(url2, preMatch, transitionConfig) {
461
+ async function applyNavigation(url2, preMatch, transitionConfig, skipLoaders) {
462
462
  if (currentAbort) {
463
463
  currentAbort.abort();
464
464
  }
@@ -476,7 +476,9 @@ function createRouter(routes, initialUrlOrOptions, maybeOptions) {
476
476
  if (match) {
477
477
  visitedUrls.add(normalizeUrl(url2));
478
478
  searchParams.value = match.search;
479
- await runLoaders(match, gen, abort.signal);
479
+ if (!skipLoaders) {
480
+ await runLoaders(match, gen, abort.signal);
481
+ }
480
482
  } else {
481
483
  searchParams.value = {};
482
484
  if (gen === navigationGen) {
@@ -487,8 +489,11 @@ function createRouter(routes, initialUrlOrOptions, maybeOptions) {
487
489
  }
488
490
  async function navigate(input) {
489
491
  const navUrl = buildNavigationUrl(input.to, input);
492
+ const navMatch = matchRoute(routes, navUrl);
493
+ const navPathname = navUrl.split("?")[0]?.split("#")[0] || "/";
494
+ const isSearchParamOnly = window.location.pathname === navPathname;
490
495
  const gen = ++navigateGen;
491
- const handle = startPrefetch(navUrl);
496
+ const handle = isSearchParamOnly ? null : startPrefetch(navUrl);
492
497
  if (input.replace) {
493
498
  window.history.replaceState(null, "", navUrl);
494
499
  } else {
@@ -500,9 +505,8 @@ function createRouter(routes, initialUrlOrOptions, maybeOptions) {
500
505
  }
501
506
  if (gen !== navigateGen)
502
507
  return;
503
- const match = matchRoute(routes, navUrl);
504
- const transitionConfig = input.viewTransition ?? match?.route.viewTransition ?? options?.viewTransition;
505
- await applyNavigation(navUrl, match, transitionConfig);
508
+ const transitionConfig = isSearchParamOnly ? undefined : input.viewTransition ?? navMatch?.route.viewTransition ?? options?.viewTransition;
509
+ await applyNavigation(navUrl, navMatch, transitionConfig, isSearchParamOnly);
506
510
  }
507
511
  async function revalidate() {
508
512
  const match = current.value;
@@ -1296,8 +1296,27 @@ type ExtractParams<T extends string> = [ExtractParamsFromSegments<WithoutWildcar
1296
1296
  * - Fallback: `string` → `string` (backward compat)
1297
1297
  */
1298
1298
  type PathWithParams<T extends string> = T extends `${infer Before}*` ? `${PathWithParams<Before>}${string}` : T extends `${infer Before}:${string}/${infer After}` ? `${Before}${string}/${PathWithParams<`${After}`>}` : T extends `${infer Before}:${string}` ? `${Before}${string}` : T;
1299
- /** Union of route pattern keys from a route map. */
1300
- type RoutePattern<TRouteMap extends Record<string, unknown>> = keyof TRouteMap & string;
1299
+ /**
1300
+ * Join parent and child route path segments.
1301
+ * - `JoinPaths<'/', '/brands'>` → `'/brands'`
1302
+ * - `JoinPaths<'/admin', '/settings'>` → `'/admin/settings'`
1303
+ * - `JoinPaths<'', '/brands'>` → `'/brands'`
1304
+ */
1305
+ type JoinPaths<
1306
+ Parent extends string,
1307
+ Child extends string
1308
+ > = Parent extends "" | "/" ? Child : Child extends "/" ? Parent : `${Parent}${Child}`;
1309
+ /**
1310
+ * Union of all route pattern keys from a route map, including nested children.
1311
+ * Recursively walks `children` and concatenates parent + child paths.
1312
+ * Short-circuits to `string` for index signatures (backward compat).
1313
+ */
1314
+ type RoutePattern<
1315
+ TRouteMap extends Record<string, unknown>,
1316
+ _Prefix extends string = ""
1317
+ > = string extends keyof TRouteMap ? string : { [K in keyof TRouteMap & string] : JoinPaths<_Prefix, K> | (TRouteMap[K] extends {
1318
+ children: infer C extends Record<string, unknown>;
1319
+ } ? RoutePattern<C, JoinPaths<_Prefix, K>> : never) }[keyof TRouteMap & string];
1301
1320
  /**
1302
1321
  * Union of all valid URL shapes for a route map.
1303
1322
  * Maps each route pattern key through `PathWithParams` to produce the accepted URL shapes.
@@ -1424,8 +1443,22 @@ type TypedRoutes<T extends Record<string, RouteConfigLike> = RouteDefinitionMap>
1424
1443
  */
1425
1444
  type InferRouteMap<T> = T extends TypedRoutes<infer R> ? R : T;
1426
1445
  /**
1446
+ * Search nested children for a route's search params schema.
1447
+ * Returns the schema output type if found, `never` if not found.
1448
+ */
1449
+ type FindSearchParamsInChildren<
1450
+ TPath extends string,
1451
+ TMap extends Record<string, RouteConfigLike>,
1452
+ _Prefix extends string = ""
1453
+ > = string extends keyof TMap ? never : { [K in keyof TMap & string] : JoinPaths<_Prefix, K> extends TPath ? TMap[K] extends {
1454
+ searchParams: SearchParamSchema<infer S>;
1455
+ } ? S : never : TMap[K] extends {
1456
+ children: infer C extends Record<string, RouteConfigLike>;
1457
+ } ? FindSearchParamsInChildren<TPath, C, JoinPaths<_Prefix, K>> : never }[keyof TMap & string];
1458
+ /**
1427
1459
  * Extract the search params type from a route definition map for a given path.
1428
1460
  *
1461
+ * Recursively searches nested `children` when the path is not a top-level key.
1429
1462
  * If the route at `TPath` has a `searchParams` schema, resolves to the schema's
1430
1463
  * output type `T`. Otherwise resolves to `Record<string, string>` (raw URL params).
1431
1464
  *
@@ -1436,7 +1469,7 @@ type ExtractSearchParams<
1436
1469
  TMap extends Record<string, RouteConfigLike> = RouteDefinitionMap
1437
1470
  > = TPath extends keyof TMap ? TMap[TPath] extends {
1438
1471
  searchParams: SearchParamSchema<infer T>;
1439
- } ? T : Record<string, string> : Record<string, string>;
1472
+ } ? T : Record<string, string> : [FindSearchParamsInChildren<TPath, TMap>] extends [never] ? Record<string, string> : FindSearchParamsInChildren<TPath, TMap>;
1440
1473
  /** Internal compiled route. */
1441
1474
  interface CompiledRoute {
1442
1475
  /** The original path pattern. */
package/dist/src/index.js CHANGED
@@ -45,7 +45,7 @@ import {
45
45
  } from "../shared/chunk-mntc8w0g.js";
46
46
  import {
47
47
  createRouter
48
- } from "../shared/chunk-mm9ms792.js";
48
+ } from "../shared/chunk-pkhyqntn.js";
49
49
  import {
50
50
  defineRoutes
51
51
  } from "../shared/chunk-ah86rm07.js";
@@ -66,7 +66,7 @@ import {
66
66
  query,
67
67
  registerRelationSchema,
68
68
  resetRelationSchemas_TEST_ONLY
69
- } from "../shared/chunk-rdz5k67m.js";
69
+ } from "../shared/chunk-7dngshyk.js";
70
70
  import"../shared/chunk-jrtrk5z4.js";
71
71
  import {
72
72
  ThemeProvider,
@@ -20,7 +20,7 @@ import {
20
20
  MemoryCache,
21
21
  QueryEnvelopeStore,
22
22
  deriveKey
23
- } from "../shared/chunk-rdz5k67m.js";
23
+ } from "../shared/chunk-7dngshyk.js";
24
24
  import"../shared/chunk-jrtrk5z4.js";
25
25
  import {
26
26
  ALIGNMENT_MAP,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  query
3
- } from "../../shared/chunk-rdz5k67m.js";
3
+ } from "../../shared/chunk-7dngshyk.js";
4
4
  import"../../shared/chunk-jrtrk5z4.js";
5
5
  import"../../shared/chunk-pv0apt9z.js";
6
6
  import"../../shared/chunk-sjypbv24.js";
@@ -34,8 +34,27 @@ type ExtractParams<T extends string> = [ExtractParamsFromSegments<WithoutWildcar
34
34
  * - Fallback: `string` → `string` (backward compat)
35
35
  */
36
36
  type PathWithParams<T extends string> = T extends `${infer Before}*` ? `${PathWithParams<Before>}${string}` : T extends `${infer Before}:${string}/${infer After}` ? `${Before}${string}/${PathWithParams<`${After}`>}` : T extends `${infer Before}:${string}` ? `${Before}${string}` : T;
37
- /** Union of route pattern keys from a route map. */
38
- type RoutePattern<TRouteMap extends Record<string, unknown>> = keyof TRouteMap & string;
37
+ /**
38
+ * Join parent and child route path segments.
39
+ * - `JoinPaths<'/', '/brands'>` → `'/brands'`
40
+ * - `JoinPaths<'/admin', '/settings'>` → `'/admin/settings'`
41
+ * - `JoinPaths<'', '/brands'>` → `'/brands'`
42
+ */
43
+ type JoinPaths<
44
+ Parent extends string,
45
+ Child extends string
46
+ > = Parent extends "" | "/" ? Child : Child extends "/" ? Parent : `${Parent}${Child}`;
47
+ /**
48
+ * Union of all route pattern keys from a route map, including nested children.
49
+ * Recursively walks `children` and concatenates parent + child paths.
50
+ * Short-circuits to `string` for index signatures (backward compat).
51
+ */
52
+ type RoutePattern<
53
+ TRouteMap extends Record<string, unknown>,
54
+ _Prefix extends string = ""
55
+ > = string extends keyof TRouteMap ? string : { [K in keyof TRouteMap & string] : JoinPaths<_Prefix, K> | (TRouteMap[K] extends {
56
+ children: infer C extends Record<string, unknown>;
57
+ } ? RoutePattern<C, JoinPaths<_Prefix, K>> : never) }[keyof TRouteMap & string];
39
58
  /**
40
59
  * Union of all valid URL shapes for a route map.
41
60
  * Maps each route pattern key through `PathWithParams` to produce the accepted URL shapes.
@@ -162,8 +181,22 @@ type TypedRoutes<T extends Record<string, RouteConfigLike> = RouteDefinitionMap>
162
181
  */
163
182
  type InferRouteMap<T> = T extends TypedRoutes<infer R> ? R : T;
164
183
  /**
184
+ * Search nested children for a route's search params schema.
185
+ * Returns the schema output type if found, `never` if not found.
186
+ */
187
+ type FindSearchParamsInChildren<
188
+ TPath extends string,
189
+ TMap extends Record<string, RouteConfigLike>,
190
+ _Prefix extends string = ""
191
+ > = string extends keyof TMap ? never : { [K in keyof TMap & string] : JoinPaths<_Prefix, K> extends TPath ? TMap[K] extends {
192
+ searchParams: SearchParamSchema<infer S>;
193
+ } ? S : never : TMap[K] extends {
194
+ children: infer C extends Record<string, RouteConfigLike>;
195
+ } ? FindSearchParamsInChildren<TPath, C, JoinPaths<_Prefix, K>> : never }[keyof TMap & string];
196
+ /**
165
197
  * Extract the search params type from a route definition map for a given path.
166
198
  *
199
+ * Recursively searches nested `children` when the path is not a top-level key.
167
200
  * If the route at `TPath` has a `searchParams` schema, resolves to the schema's
168
201
  * output type `T`. Otherwise resolves to `Record<string, string>` (raw URL params).
169
202
  *
@@ -174,7 +207,7 @@ type ExtractSearchParams<
174
207
  TMap extends Record<string, RouteConfigLike> = RouteDefinitionMap
175
208
  > = TPath extends keyof TMap ? TMap[TPath] extends {
176
209
  searchParams: SearchParamSchema<infer T>;
177
- } ? T : Record<string, string> : Record<string, string>;
210
+ } ? T : Record<string, string> : [FindSearchParamsInChildren<TPath, TMap>] extends [never] ? Record<string, string> : FindSearchParamsInChildren<TPath, TMap>;
178
211
  /** Internal compiled route. */
179
212
  interface CompiledRoute {
180
213
  /** The original path pattern. */
@@ -10,7 +10,7 @@ import {
10
10
  import"../../shared/chunk-mntc8w0g.js";
11
11
  import {
12
12
  createRouter
13
- } from "../../shared/chunk-mm9ms792.js";
13
+ } from "../../shared/chunk-pkhyqntn.js";
14
14
  import {
15
15
  defineRoutes
16
16
  } from "../../shared/chunk-ah86rm07.js";
@@ -138,8 +138,27 @@ type ExtractParams<T extends string> = [ExtractParamsFromSegments<WithoutWildcar
138
138
  } : Record<string, never> : HasWildcard<T> extends true ? { [K in ExtractParamsFromSegments<WithoutWildcard<T>>] : string } & {
139
139
  "*": string;
140
140
  } : { [K in ExtractParamsFromSegments<WithoutWildcard<T>>] : string };
141
- /** Union of route pattern keys from a route map. */
142
- type RoutePattern<TRouteMap extends Record<string, unknown>> = keyof TRouteMap & string;
141
+ /**
142
+ * Join parent and child route path segments.
143
+ * - `JoinPaths<'/', '/brands'>` → `'/brands'`
144
+ * - `JoinPaths<'/admin', '/settings'>` → `'/admin/settings'`
145
+ * - `JoinPaths<'', '/brands'>` → `'/brands'`
146
+ */
147
+ type JoinPaths<
148
+ Parent extends string,
149
+ Child extends string
150
+ > = Parent extends "" | "/" ? Child : Child extends "/" ? Parent : `${Parent}${Child}`;
151
+ /**
152
+ * Union of all route pattern keys from a route map, including nested children.
153
+ * Recursively walks `children` and concatenates parent + child paths.
154
+ * Short-circuits to `string` for index signatures (backward compat).
155
+ */
156
+ type RoutePattern<
157
+ TRouteMap extends Record<string, unknown>,
158
+ _Prefix extends string = ""
159
+ > = string extends keyof TRouteMap ? string : { [K in keyof TRouteMap & string] : JoinPaths<_Prefix, K> | (TRouteMap[K] extends {
160
+ children: infer C extends Record<string, unknown>;
161
+ } ? RoutePattern<C, JoinPaths<_Prefix, K>> : never) }[keyof TRouteMap & string];
143
162
  /**
144
163
  * View Transitions API integration.
145
164
  *
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createRouter
3
- } from "../../shared/chunk-mm9ms792.js";
3
+ } from "../../shared/chunk-pkhyqntn.js";
4
4
  import {
5
5
  defineRoutes
6
6
  } from "../../shared/chunk-ah86rm07.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vertz/ui",
3
- "version": "0.2.34",
3
+ "version": "0.2.36",
4
4
  "description": "Vertz UI framework — signals, components, JSX runtime",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -77,11 +77,11 @@
77
77
  "typecheck": "tsc --noEmit"
78
78
  },
79
79
  "dependencies": {
80
- "@vertz/fetch": "^0.2.31"
80
+ "@vertz/fetch": "^0.2.35"
81
81
  },
82
82
  "devDependencies": {
83
83
  "@happy-dom/global-registrator": "^20.7.0",
84
- "@vertz/schema": "^0.2.31",
84
+ "@vertz/schema": "^0.2.35",
85
85
  "bunup": "^0.16.31",
86
86
  "happy-dom": "^20.7.0",
87
87
  "typescript": "^5.7.0"