@vertz/ui 0.2.35 → 0.2.37

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.
@@ -86,6 +86,13 @@ class MemoryCache {
86
86
  this._refs.set(key, count);
87
87
  this._orphans.delete(key);
88
88
  }
89
+ findByPrefix(prefix) {
90
+ for (const [k, v] of this._store) {
91
+ if (k.startsWith(prefix))
92
+ return { key: k, value: v };
93
+ }
94
+ return;
95
+ }
89
96
  release(key) {
90
97
  const current = this._refs.get(key);
91
98
  if (current === undefined)
@@ -864,6 +871,13 @@ function query(source, options = {}) {
864
871
  function getCacheKey() {
865
872
  return cacheKeyComputed.value;
866
873
  }
874
+ function resolveCurrentCacheKey() {
875
+ if (currentEffectKey) {
876
+ const depHash = depHashSignal.peek();
877
+ return depHash ? `${currentEffectKey}:${depHash}` : currentEffectKey;
878
+ }
879
+ return getCacheKey();
880
+ }
867
881
  let currentRetainedKey = null;
868
882
  const retainable = "retain" in cache && "release" in cache;
869
883
  function retainKey(key) {
@@ -904,6 +918,7 @@ function query(source, options = {}) {
904
918
  const error = signal(undefined);
905
919
  const idle = signal(initialData === undefined);
906
920
  const entityBacked = signal(false);
921
+ let currentEffectKey;
907
922
  function normalizeToEntityStore(result) {
908
923
  if (!entityMeta)
909
924
  return;
@@ -1020,6 +1035,7 @@ function query(source, options = {}) {
1020
1035
  if (!isSSR() && initialData === undefined) {
1021
1036
  let hydrationKey;
1022
1037
  const hasSSRData = !!globalThis.__VERTZ_SSR_DATA__;
1038
+ let initDescriptorKey;
1023
1039
  if (customKey) {
1024
1040
  hydrationKey = customKey;
1025
1041
  } else if (hasSSRData) {
@@ -1027,6 +1043,7 @@ function query(source, options = {}) {
1027
1043
  const raw = callThunkWithCapture();
1028
1044
  if (raw !== null) {
1029
1045
  if (isQueryDescriptor(raw)) {
1046
+ initDescriptorKey = raw._key;
1030
1047
  if (raw._entity && !entityMeta) {
1031
1048
  entityMeta = raw._entity;
1032
1049
  }
@@ -1058,6 +1075,25 @@ function query(source, options = {}) {
1058
1075
  loading.value = false;
1059
1076
  ssrHydrated = true;
1060
1077
  }
1078
+ } else {
1079
+ const cached = cache.get(hydrationKey);
1080
+ if (cached !== undefined) {
1081
+ retainKey(hydrationKey);
1082
+ normalizeToEntityStore(cached);
1083
+ rawData.value = cached;
1084
+ loading.value = false;
1085
+ ssrHydrated = true;
1086
+ } else if (initDescriptorKey && "findByPrefix" in cache) {
1087
+ const mc = cache;
1088
+ const found = mc.findByPrefix(initDescriptorKey + "&") ?? mc.findByPrefix(initDescriptorKey + ":");
1089
+ if (found) {
1090
+ retainKey(found.key);
1091
+ normalizeToEntityStore(found.value);
1092
+ rawData.value = found.value;
1093
+ loading.value = false;
1094
+ ssrHydrated = true;
1095
+ }
1096
+ }
1061
1097
  }
1062
1098
  }
1063
1099
  if (!ssrHydrated && ssrHydrationCleanup !== null && isNavPrefetchActive()) {
@@ -1161,7 +1197,7 @@ function query(source, options = {}) {
1161
1197
  handleFetchPromise(fetchPromise, id, key);
1162
1198
  }
1163
1199
  function refetch() {
1164
- const key = getCacheKey();
1200
+ const key = resolveCurrentCacheKey();
1165
1201
  currentRetainedKey = null;
1166
1202
  cache.delete(key);
1167
1203
  getInflight().delete(key);
@@ -1205,10 +1241,12 @@ function query(source, options = {}) {
1205
1241
  isFirst = false;
1206
1242
  return;
1207
1243
  }
1208
- if (!isQueryDescriptor(trackRaw)) {
1244
+ const descriptorKey = isQueryDescriptor(trackRaw) ? trackRaw._key : undefined;
1245
+ if (!descriptorKey) {
1209
1246
  trackRaw.catch(() => {});
1210
1247
  }
1211
- const derivedKey = untrack(() => getCacheKey());
1248
+ const depHash2 = untrack(() => depHashSignal.value);
1249
+ const derivedKey = descriptorKey ? depHash2 ? `${descriptorKey}:${depHash2}` : descriptorKey : untrack(() => getCacheKey());
1212
1250
  const cached = untrack(() => cache.get(derivedKey));
1213
1251
  if (cached !== undefined) {
1214
1252
  retainKey(derivedKey);
@@ -1219,6 +1257,20 @@ function query(source, options = {}) {
1219
1257
  isFirst = false;
1220
1258
  return;
1221
1259
  }
1260
+ if (descriptorKey && "findByPrefix" in cache) {
1261
+ const mc = cache;
1262
+ const found = untrack(() => mc.findByPrefix(descriptorKey + "&") ?? mc.findByPrefix(descriptorKey + ":"));
1263
+ if (found) {
1264
+ retainKey(found.key);
1265
+ untrack(() => {
1266
+ normalizeToEntityStore(found.value);
1267
+ rawData.value = found.value;
1268
+ loading.value = false;
1269
+ });
1270
+ isFirst = false;
1271
+ return;
1272
+ }
1273
+ }
1222
1274
  }
1223
1275
  isFirst = false;
1224
1276
  return;
@@ -1274,7 +1326,9 @@ function query(source, options = {}) {
1274
1326
  untrack(() => {
1275
1327
  idle.value = false;
1276
1328
  });
1277
- const key = effectKey ?? untrack(() => getCacheKey());
1329
+ const depHash = untrack(() => depHashSignal.value);
1330
+ currentEffectKey = effectKey;
1331
+ const key = effectKey ? depHash ? `${effectKey}:${depHash}` : effectKey : untrack(() => getCacheKey());
1278
1332
  if (!customKey && !effectKey) {
1279
1333
  const existing = untrack(() => getInflight().get(key));
1280
1334
  if (existing) {
@@ -1360,7 +1414,7 @@ function query(source, options = {}) {
1360
1414
  rawData.value = undefined;
1361
1415
  loading.value = true;
1362
1416
  });
1363
- const cacheKey = untrack(() => getCacheKey());
1417
+ const cacheKey = untrack(() => resolveCurrentCacheKey());
1364
1418
  cache.delete(cacheKey);
1365
1419
  const queryKey = customKey ?? meta.entityType;
1366
1420
  getEntityStore().queryIndices.clear(queryKey);
@@ -9,6 +9,7 @@ import {
9
9
  isBrowser
10
10
  } from "./chunk-sjypbv24.js";
11
11
  import {
12
+ batch,
12
13
  getSSRContext,
13
14
  signal
14
15
  } from "./chunk-1yd6jfw5.js";
@@ -458,7 +459,7 @@ function createRouter(routes, initialUrlOrOptions, maybeOptions) {
458
459
  }
459
460
  }
460
461
  }
461
- async function applyNavigation(url2, preMatch, transitionConfig) {
462
+ async function applyNavigation(url2, preMatch, transitionConfig, skipLoaders) {
462
463
  if (currentAbort) {
463
464
  currentAbort.abort();
464
465
  }
@@ -466,29 +467,38 @@ function createRouter(routes, initialUrlOrOptions, maybeOptions) {
466
467
  const abort = new AbortController;
467
468
  currentAbort = abort;
468
469
  const match = preMatch !== undefined ? preMatch : matchRoute(routes, url2);
470
+ if (match) {
471
+ visitedUrls.add(normalizeUrl(url2));
472
+ }
469
473
  if (transitionConfig) {
470
474
  await withViewTransition(() => {
471
- current.value = match;
475
+ batch(() => {
476
+ searchParams.value = match?.search ?? {};
477
+ current.value = match;
478
+ });
472
479
  }, transitionConfig);
473
480
  } else {
474
- current.value = match;
481
+ batch(() => {
482
+ searchParams.value = match?.search ?? {};
483
+ current.value = match;
484
+ });
475
485
  }
476
486
  if (match) {
477
- visitedUrls.add(normalizeUrl(url2));
478
- searchParams.value = match.search;
479
- await runLoaders(match, gen, abort.signal);
480
- } else {
481
- searchParams.value = {};
482
- if (gen === navigationGen) {
483
- loaderData.value = [];
484
- loaderError.value = null;
487
+ if (!skipLoaders) {
488
+ await runLoaders(match, gen, abort.signal);
485
489
  }
490
+ } else if (gen === navigationGen) {
491
+ loaderData.value = [];
492
+ loaderError.value = null;
486
493
  }
487
494
  }
488
495
  async function navigate(input) {
489
496
  const navUrl = buildNavigationUrl(input.to, input);
497
+ const navMatch = matchRoute(routes, navUrl);
498
+ const navPathname = navUrl.split("?")[0]?.split("#")[0] || "/";
499
+ const isSearchParamOnly = window.location.pathname === navPathname;
490
500
  const gen = ++navigateGen;
491
- const handle = startPrefetch(navUrl);
501
+ const handle = isSearchParamOnly ? null : startPrefetch(navUrl);
492
502
  if (input.replace) {
493
503
  window.history.replaceState(null, "", navUrl);
494
504
  } else {
@@ -500,9 +510,8 @@ function createRouter(routes, initialUrlOrOptions, maybeOptions) {
500
510
  }
501
511
  if (gen !== navigateGen)
502
512
  return;
503
- const match = matchRoute(routes, navUrl);
504
- const transitionConfig = input.viewTransition ?? match?.route.viewTransition ?? options?.viewTransition;
505
- await applyNavigation(navUrl, match, transitionConfig);
513
+ const transitionConfig = isSearchParamOnly ? undefined : input.viewTransition ?? navMatch?.route.viewTransition ?? options?.viewTransition;
514
+ await applyNavigation(navUrl, navMatch, transitionConfig, isSearchParamOnly);
506
515
  }
507
516
  async function revalidate() {
508
517
  const match = current.value;
@@ -680,12 +680,15 @@ var vertzSheets = new Set;
680
680
  function injectCSS(cssText) {
681
681
  if (!cssText)
682
682
  return;
683
- const isSSR = getSSRContext() !== undefined;
683
+ const ssrCtx = getSSRContext();
684
+ const isSSR = ssrCtx !== undefined;
684
685
  if (!isSSR && injectedCSS.has(cssText))
685
686
  return;
686
687
  injectedCSS.add(cssText);
687
- if (isSSR)
688
+ if (isSSR) {
689
+ ssrCtx.cssTracker?.add(cssText);
688
690
  return;
691
+ }
689
692
  if (typeof document === "undefined")
690
693
  return;
691
694
  if (typeof CSSStyleSheet !== "undefined" && document.adoptedStyleSheets !== undefined) {
@@ -1135,56 +1138,52 @@ function variants(config) {
1135
1138
  const { base, variants: variantDefs, defaultVariants, compoundVariants } = config;
1136
1139
  const filePath = deriveConfigKey(config);
1137
1140
  const baseResult = css({ base }, filePath);
1138
- const variantResults = {};
1141
+ const variantCache = new Map;
1142
+ const variantStyles = {};
1139
1143
  for (const [variantName, options] of Object.entries(variantDefs)) {
1140
- variantResults[variantName] = {};
1144
+ variantStyles[variantName] = {};
1141
1145
  for (const [optionName, styles] of Object.entries(options)) {
1142
1146
  if (styles.length > 0) {
1143
- const blockName = `${variantName}_${optionName}`;
1144
- const result = css({ [blockName]: styles }, filePath);
1145
- const className = result[blockName];
1146
- if (className) {
1147
- variantResults[variantName][optionName] = {
1148
- className,
1149
- css: result.css
1150
- };
1151
- }
1147
+ variantStyles[variantName][optionName] = styles;
1152
1148
  }
1153
1149
  }
1154
1150
  }
1155
- const compoundResults = [];
1156
- if (compoundVariants) {
1157
- for (let i = 0;i < compoundVariants.length; i++) {
1158
- const compound = compoundVariants[i];
1159
- if (!compound)
1160
- continue;
1161
- const { styles, ...conditions } = compound;
1162
- if (styles.length > 0) {
1163
- const blockName = `compound_${i}`;
1164
- const result = css({ [blockName]: styles }, filePath);
1165
- const className = result[blockName];
1166
- if (className) {
1167
- compoundResults.push({
1168
- conditions,
1169
- className,
1170
- css: result.css
1171
- });
1172
- }
1173
- }
1151
+ const compoundCache = new Map;
1152
+ function ensureVariantOption(variantName, optionName) {
1153
+ const cacheKey = `${variantName}::${optionName}`;
1154
+ const cached = variantCache.get(cacheKey);
1155
+ if (cached)
1156
+ return cached.className;
1157
+ const styles = variantStyles[variantName]?.[optionName];
1158
+ if (!styles)
1159
+ return;
1160
+ const blockName = cacheKey;
1161
+ const result = css({ [blockName]: styles }, filePath);
1162
+ const className = result[blockName];
1163
+ if (className) {
1164
+ variantCache.set(cacheKey, { className, css: result.css });
1165
+ return className;
1174
1166
  }
1167
+ return;
1175
1168
  }
1176
- const allCss = [];
1177
- if (baseResult.css)
1178
- allCss.push(baseResult.css);
1179
- for (const options of Object.values(variantResults)) {
1180
- for (const result of Object.values(options)) {
1181
- if (result.css)
1182
- allCss.push(result.css);
1169
+ function ensureCompoundVariant(index, compound, resolved) {
1170
+ const { styles, ...conditions } = compound;
1171
+ const matches = Object.entries(conditions).every(([key, value]) => resolved[key] === String(value));
1172
+ if (!matches)
1173
+ return;
1174
+ const cached = compoundCache.get(index);
1175
+ if (cached)
1176
+ return cached.className;
1177
+ if (styles.length === 0)
1178
+ return;
1179
+ const blockName = `compound_${index}`;
1180
+ const result = css({ [blockName]: styles }, filePath);
1181
+ const className = result[blockName];
1182
+ if (className) {
1183
+ compoundCache.set(index, { className, css: result.css });
1184
+ return className;
1183
1185
  }
1184
- }
1185
- for (const result of compoundResults) {
1186
- if (result.css)
1187
- allCss.push(result.css);
1186
+ return;
1188
1187
  }
1189
1188
  const fn = (props) => {
1190
1189
  const classNames = [];
@@ -1208,26 +1207,43 @@ function variants(config) {
1208
1207
  }
1209
1208
  }
1210
1209
  for (const [variantName, optionName] of Object.entries(resolved)) {
1211
- const variantGroup = variantResults[variantName];
1212
- if (variantGroup) {
1213
- const result = variantGroup[optionName];
1214
- if (result) {
1215
- classNames.push(result.className);
1216
- }
1210
+ const className = ensureVariantOption(variantName, optionName);
1211
+ if (className) {
1212
+ classNames.push(className);
1217
1213
  }
1218
1214
  }
1219
- for (const compound of compoundResults) {
1220
- const matches = Object.entries(compound.conditions).every(([key, value]) => {
1221
- return resolved[key] === String(value);
1222
- });
1223
- if (matches) {
1224
- classNames.push(compound.className);
1215
+ if (compoundVariants) {
1216
+ for (let i = 0;i < compoundVariants.length; i++) {
1217
+ const compound = compoundVariants[i];
1218
+ if (!compound)
1219
+ continue;
1220
+ const className = ensureCompoundVariant(i, compound, resolved);
1221
+ if (className) {
1222
+ classNames.push(className);
1223
+ }
1225
1224
  }
1226
1225
  }
1227
1226
  return classNames.join(" ");
1228
1227
  };
1229
- fn.css = allCss.join(`
1228
+ Object.defineProperty(fn, "css", {
1229
+ get() {
1230
+ const parts = [];
1231
+ if (baseResult.css)
1232
+ parts.push(baseResult.css);
1233
+ for (const entry of variantCache.values()) {
1234
+ if (entry.css)
1235
+ parts.push(entry.css);
1236
+ }
1237
+ for (const entry of compoundCache.values()) {
1238
+ if (entry.css)
1239
+ parts.push(entry.css);
1240
+ }
1241
+ return parts.join(`
1230
1242
  `);
1243
+ },
1244
+ enumerable: false,
1245
+ configurable: false
1246
+ });
1231
1247
  return fn;
1232
1248
  }
1233
1249
 
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  injectCSS
3
- } from "./chunk-zkh9sysw.js";
3
+ } from "./chunk-g60cswzm.js";
4
4
  import {
5
5
  createContext
6
6
  } from "./chunk-1yd6jfw5.js";
@@ -287,12 +287,16 @@ interface VariantsConfig<V extends VariantDefinitions> {
287
287
  /** The function returned by variants(). Takes optional variant props and returns a className string. */
288
288
  interface VariantFunction<V extends VariantDefinitions> {
289
289
  (props?: VariantProps<V>): string;
290
- /** The extracted CSS for all variant combinations. */
290
+ /** @internal The extracted CSS for variant combinations compiled so far. */
291
291
  css: string;
292
292
  }
293
293
  /**
294
294
  * Create a typed variant function from a config object.
295
295
  *
296
+ * Variant option CSS is compiled lazily on first use — only the base styles
297
+ * are compiled eagerly. This ensures unused variant options never produce CSS,
298
+ * reducing SSR response size for pages that use a subset of available variants.
299
+ *
296
300
  * @param config - Variant configuration (base, variants, defaultVariants, compoundVariants).
297
301
  * @returns A function that accepts variant props and returns a className string.
298
302
  */
@@ -8,7 +8,7 @@ import {
8
8
  globalCss,
9
9
  s,
10
10
  variants
11
- } from "../../shared/chunk-zkh9sysw.js";
11
+ } from "../../shared/chunk-g60cswzm.js";
12
12
  import"../../shared/chunk-dh32wkrv.js";
13
13
  import"../../shared/chunk-h1fsr8kv.js";
14
14
  import"../../shared/chunk-1yd6jfw5.js";
@@ -632,12 +632,16 @@ interface VariantsConfig<V extends VariantDefinitions> {
632
632
  /** The function returned by variants(). Takes optional variant props and returns a className string. */
633
633
  interface VariantFunction<V extends VariantDefinitions> {
634
634
  (props?: VariantProps<V>): string;
635
- /** The extracted CSS for all variant combinations. */
635
+ /** @internal The extracted CSS for variant combinations compiled so far. */
636
636
  css: string;
637
637
  }
638
638
  /**
639
639
  * Create a typed variant function from a config object.
640
640
  *
641
+ * Variant option CSS is compiled lazily on first use — only the base styles
642
+ * are compiled eagerly. This ensures unused variant options never produce CSS,
643
+ * reducing SSR response size for pages that use a subset of available variants.
644
+ *
641
645
  * @param config - Variant configuration (base, variants, defaultVariants, compoundVariants).
642
646
  * @returns A function that accepts variant props and returns a className string.
643
647
  */
@@ -1296,8 +1300,27 @@ type ExtractParams<T extends string> = [ExtractParamsFromSegments<WithoutWildcar
1296
1300
  * - Fallback: `string` → `string` (backward compat)
1297
1301
  */
1298
1302
  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;
1303
+ /**
1304
+ * Join parent and child route path segments.
1305
+ * - `JoinPaths<'/', '/brands'>` → `'/brands'`
1306
+ * - `JoinPaths<'/admin', '/settings'>` → `'/admin/settings'`
1307
+ * - `JoinPaths<'', '/brands'>` → `'/brands'`
1308
+ */
1309
+ type JoinPaths<
1310
+ Parent extends string,
1311
+ Child extends string
1312
+ > = Parent extends "" | "/" ? Child : Child extends "/" ? Parent : `${Parent}${Child}`;
1313
+ /**
1314
+ * Union of all route pattern keys from a route map, including nested children.
1315
+ * Recursively walks `children` and concatenates parent + child paths.
1316
+ * Short-circuits to `string` for index signatures (backward compat).
1317
+ */
1318
+ type RoutePattern<
1319
+ TRouteMap extends Record<string, unknown>,
1320
+ _Prefix extends string = ""
1321
+ > = string extends keyof TRouteMap ? string : { [K in keyof TRouteMap & string] : JoinPaths<_Prefix, K> | (TRouteMap[K] extends {
1322
+ children: infer C extends Record<string, unknown>;
1323
+ } ? RoutePattern<C, JoinPaths<_Prefix, K>> : never) }[keyof TRouteMap & string];
1301
1324
  /**
1302
1325
  * Union of all valid URL shapes for a route map.
1303
1326
  * Maps each route pattern key through `PathWithParams` to produce the accepted URL shapes.
@@ -1424,8 +1447,22 @@ type TypedRoutes<T extends Record<string, RouteConfigLike> = RouteDefinitionMap>
1424
1447
  */
1425
1448
  type InferRouteMap<T> = T extends TypedRoutes<infer R> ? R : T;
1426
1449
  /**
1450
+ * Search nested children for a route's search params schema.
1451
+ * Returns the schema output type if found, `never` if not found.
1452
+ */
1453
+ type FindSearchParamsInChildren<
1454
+ TPath extends string,
1455
+ TMap extends Record<string, RouteConfigLike>,
1456
+ _Prefix extends string = ""
1457
+ > = string extends keyof TMap ? never : { [K in keyof TMap & string] : JoinPaths<_Prefix, K> extends TPath ? TMap[K] extends {
1458
+ searchParams: SearchParamSchema<infer S>;
1459
+ } ? S : never : TMap[K] extends {
1460
+ children: infer C extends Record<string, RouteConfigLike>;
1461
+ } ? FindSearchParamsInChildren<TPath, C, JoinPaths<_Prefix, K>> : never }[keyof TMap & string];
1462
+ /**
1427
1463
  * Extract the search params type from a route definition map for a given path.
1428
1464
  *
1465
+ * Recursively searches nested `children` when the path is not a top-level key.
1429
1466
  * If the route at `TPath` has a `searchParams` schema, resolves to the schema's
1430
1467
  * output type `T`. Otherwise resolves to `Record<string, string>` (raw URL params).
1431
1468
  *
@@ -1436,7 +1473,7 @@ type ExtractSearchParams<
1436
1473
  TMap extends Record<string, RouteConfigLike> = RouteDefinitionMap
1437
1474
  > = TPath extends keyof TMap ? TMap[TPath] extends {
1438
1475
  searchParams: SearchParamSchema<infer T>;
1439
- } ? T : Record<string, string> : Record<string, string>;
1476
+ } ? T : Record<string, string> : [FindSearchParamsInChildren<TPath, TMap>] extends [never] ? Record<string, string> : FindSearchParamsInChildren<TPath, TMap>;
1440
1477
  /** Internal compiled route. */
1441
1478
  interface CompiledRoute {
1442
1479
  /** The original path pattern. */
package/dist/src/index.js CHANGED
@@ -25,7 +25,7 @@ import {
25
25
  slideOutToTop,
26
26
  zoomIn,
27
27
  zoomOut
28
- } from "../shared/chunk-xyg724n1.js";
28
+ } from "../shared/chunk-rxx916ae.js";
29
29
  import {
30
30
  ErrorBoundary,
31
31
  Link,
@@ -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-9ybtmy8t.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-25nwt5fm.js";
69
+ } from "../shared/chunk-4eatzp0p.js";
70
70
  import"../shared/chunk-jrtrk5z4.js";
71
71
  import {
72
72
  ThemeProvider,
@@ -83,7 +83,7 @@ import {
83
83
  resolveChildren,
84
84
  s,
85
85
  variants
86
- } from "../shared/chunk-zkh9sysw.js";
86
+ } from "../shared/chunk-g60cswzm.js";
87
87
  import {
88
88
  RENDER_NODE_BRAND,
89
89
  __append,
@@ -609,6 +609,11 @@ declare class MemoryCache<T = unknown> implements CacheStore<T> {
609
609
  clear(): void;
610
610
  /** Mark a cache key as actively used by a query instance. */
611
611
  retain(key: string): void;
612
+ /** Find the first entry whose key starts with `prefix`. */
613
+ findByPrefix(prefix: string): {
614
+ key: string;
615
+ value: T;
616
+ } | undefined;
612
617
  /** Release a cache key when a query instance disposes or changes key. */
613
618
  release(key: string): void;
614
619
  }
@@ -1134,6 +1139,13 @@ interface SSRRenderContext {
1134
1139
  ssrRedirect?: {
1135
1140
  to: string;
1136
1141
  };
1142
+ /**
1143
+ * Per-request CSS tracker for render-scoped collection.
1144
+ * Populated by injectCSS() during SSR render. collectCSS() reads
1145
+ * from this Set instead of the global injectedCSS to ensure each
1146
+ * response only includes CSS for components actually rendered.
1147
+ */
1148
+ cssTracker?: Set<string>;
1137
1149
  }
1138
1150
  /** Auth state injected into SSRRenderContext by the server. */
1139
1151
  type SSRAuth = ({
@@ -3,7 +3,7 @@ import {
3
3
  deserializeProps,
4
4
  onAnimationsComplete,
5
5
  resolveComponent
6
- } from "../shared/chunk-xyg724n1.js";
6
+ } from "../shared/chunk-rxx916ae.js";
7
7
  import {
8
8
  __discardMountFrame,
9
9
  __flushMountFrame,
@@ -20,7 +20,7 @@ import {
20
20
  MemoryCache,
21
21
  QueryEnvelopeStore,
22
22
  deriveKey
23
- } from "../shared/chunk-25nwt5fm.js";
23
+ } from "../shared/chunk-4eatzp0p.js";
24
24
  import"../shared/chunk-jrtrk5z4.js";
25
25
  import {
26
26
  ALIGNMENT_MAP,
@@ -41,7 +41,7 @@ import {
41
41
  SIZE_KEYWORDS,
42
42
  SPACING_SCALE,
43
43
  compileTheme
44
- } from "../shared/chunk-zkh9sysw.js";
44
+ } from "../shared/chunk-g60cswzm.js";
45
45
  import {
46
46
  RENDER_NODE_BRAND,
47
47
  __append,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  query
3
- } from "../../shared/chunk-25nwt5fm.js";
3
+ } from "../../shared/chunk-4eatzp0p.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-9ybtmy8t.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-9ybtmy8t.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.35",
3
+ "version": "0.2.37",
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"