@vertz/ui 0.2.14 → 0.2.16

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.
Files changed (32) hide show
  1. package/README.md +49 -0
  2. package/dist/shared/chunk-14eqne2a.js +10 -0
  3. package/dist/shared/{chunk-dksg08fq.js → chunk-1rxa2fz4.js} +2 -8
  4. package/dist/shared/{chunk-8hsz5y4a.js → chunk-4fwcwxn6.js} +14 -4
  5. package/dist/shared/{chunk-hw67ckr3.js → chunk-4mtn7af6.js} +230 -19
  6. package/dist/shared/{chunk-2sth83bd.js → chunk-6jyt4ycw.js} +67 -2
  7. package/dist/shared/{chunk-83g4h38e.js → chunk-6wd36w21.js} +1 -0
  8. package/dist/shared/{chunk-h89w580h.js → chunk-afawz764.js} +1 -1
  9. package/dist/shared/{chunk-nn9v1zmk.js → chunk-b0qqqk03.js} +86 -21
  10. package/dist/shared/{chunk-c9xxsrat.js → chunk-dhehvmj0.js} +179 -10
  11. package/dist/shared/{chunk-mj7b4t40.js → chunk-fkbgbf3n.js} +98 -11
  12. package/dist/shared/{chunk-c30eg6wn.js → chunk-j09yyh34.js} +79 -6
  13. package/dist/shared/chunk-mtsvrj9e.js +23 -0
  14. package/dist/shared/chunk-pnv25zep.js +7 -0
  15. package/dist/shared/{chunk-j6qyxfdc.js → chunk-vndfjfdy.js} +3 -3
  16. package/dist/src/auth/public.d.ts +69 -9
  17. package/dist/src/auth/public.js +217 -13
  18. package/dist/src/css/public.d.ts +110 -2
  19. package/dist/src/css/public.js +8 -4
  20. package/dist/src/form/public.d.ts +33 -7
  21. package/dist/src/form/public.js +2 -2
  22. package/dist/src/index.d.ts +311 -20
  23. package/dist/src/index.js +161 -14
  24. package/dist/src/internals.d.ts +141 -5
  25. package/dist/src/internals.js +17 -9
  26. package/dist/src/query/public.js +4 -3
  27. package/dist/src/router/public.d.ts +39 -9
  28. package/dist/src/router/public.js +17 -11
  29. package/dist/src/test/index.d.ts +26 -23
  30. package/dist/src/test/index.js +5 -4
  31. package/package.json +3 -3
  32. package/reactivity.json +1 -11
@@ -34,6 +34,8 @@ 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
39
  /**
38
40
  * Union of all valid URL shapes for a route map.
39
41
  * Maps each route pattern key through `PathWithParams` to produce the accepted URL shapes.
@@ -43,7 +45,7 @@ type PathWithParams<T extends string> = T extends `${infer Before}*` ? `${PathWi
43
45
  * RoutePaths<{ '/': ..., '/tasks/:id': ... }> = '/' | `/tasks/${string}`
44
46
  * ```
45
47
  */
46
- type RoutePaths<TRouteMap extends Record<string, unknown>> = { [K in keyof TRouteMap & string] : PathWithParams<K> }[keyof TRouteMap & string];
48
+ type RoutePaths<TRouteMap extends Record<string, unknown>> = { [K in RoutePattern<TRouteMap>] : PathWithParams<K> }[RoutePattern<TRouteMap>];
47
49
  /** Schema interface for parsing and validating values (search params, path params). */
48
50
  interface SearchParamSchema<T> {
49
51
  parse(data: unknown): {
@@ -80,6 +82,8 @@ interface RouteConfig<
80
82
  searchParams?: SearchParamSchema<TSearch>;
81
83
  /** Nested child routes. */
82
84
  children?: RouteDefinitionMap;
85
+ /** Whether to pre-render this route at build time (default: true for static routes). */
86
+ prerender?: boolean;
83
87
  }
84
88
  /** A map of path patterns to route configs (user input format). */
85
89
  interface RouteDefinitionMap {
@@ -109,6 +113,7 @@ interface RouteConfigLike {
109
113
  params?: ParamSchema<unknown>;
110
114
  searchParams?: SearchParamSchema<unknown>;
111
115
  children?: Record<string, RouteConfigLike>;
116
+ prerender?: boolean;
112
117
  }
113
118
  /**
114
119
  * Phantom branded array that carries the route map type `T`.
@@ -142,6 +147,8 @@ interface CompiledRoute {
142
147
  searchParams?: RouteConfig["searchParams"];
143
148
  /** Compiled children. */
144
149
  children?: CompiledRoute[];
150
+ /** Whether to pre-render this route at build time (default: true for static routes). */
151
+ prerender?: boolean;
145
152
  }
146
153
  /** A single matched route entry in the matched chain. */
147
154
  interface MatchedRoute {
@@ -229,8 +236,8 @@ type UnwrapSignals<T> = T extends object ? { [K in keyof T] : Unwrapped<T[K]> }
229
236
  interface LinkProps<T extends Record<string, RouteConfigLike> = RouteDefinitionMap> {
230
237
  /** The target URL path. */
231
238
  href: RoutePaths<T>;
232
- /** Text or content for the link. Thunk may return string or Text node. */
233
- children: string | (() => string | Node);
239
+ /** Text or content for the link. Accepts string, Node, or a thunk returning either. */
240
+ children: string | Node | (() => string | Node);
234
241
  /** Class applied when the link's href matches the current path. */
235
242
  activeClass?: string;
236
243
  /** Static class name for the anchor element. */
@@ -251,11 +258,32 @@ interface LinkFactoryOptions {
251
258
  * @returns A Link component function
252
259
  */
253
260
  declare function createLink(currentPath: ReadonlySignal<string>, navigate: (url: string) => void, factoryOptions?: LinkFactoryOptions): (props: LinkProps) => HTMLAnchorElement;
261
+ /**
262
+ * Context-based Link component for client-side navigation.
263
+ *
264
+ * Reads the router from `RouterContext` automatically — no manual wiring needed.
265
+ * Just use `<Link href="/about">About</Link>` inside a router-provided tree.
266
+ */
267
+ declare function Link({ href, children, activeClass, className }: LinkProps): HTMLAnchorElement;
268
+ type NavigateSearchValue = string | number | boolean | null | undefined;
269
+ type NavigateSearch = string | URLSearchParams | Record<string, NavigateSearchValue | readonly NavigateSearchValue[]>;
254
270
  /** Options for router.navigate(). */
255
271
  interface NavigateOptions {
256
272
  /** Use history.replaceState instead of pushState. */
257
273
  replace?: boolean;
274
+ /** Route params used to interpolate dynamic segments in the route pattern. */
275
+ params?: Record<string, string>;
276
+ /** Search params appended to the final URL. */
277
+ search?: NavigateSearch;
258
278
  }
279
+ type NavigateOptionsFor<TPath extends string> = string extends TPath ? NavigateOptions : TPath extends `${string}:${string}` | `${string}*` ? Omit<NavigateOptions, "params"> & {
280
+ params: ExtractParams<TPath>;
281
+ } : Omit<NavigateOptions, "params"> & {
282
+ params?: never;
283
+ };
284
+ type NavigateInput<TPath extends string = string> = {
285
+ to: TPath;
286
+ } & NavigateOptionsFor<TPath>;
259
287
  /** Handle returned by prefetchNavData for cancellation. */
260
288
  interface PrefetchHandle {
261
289
  abort: () => void;
@@ -280,13 +308,14 @@ interface RouterOptions {
280
308
  *
281
309
  * Generic over the route map `T`. Defaults to `RouteDefinitionMap` (string
282
310
  * index signature) for backward compatibility — unparameterized `Router`
283
- * accepts any string in `navigate()`.
311
+ * accepts any string in `navigate().to`.
284
312
  *
285
313
  * Method syntax on `navigate`, `revalidate`, and `dispose` enables bivariant
286
314
  * parameter checking under `strictFunctionTypes`. This means `Router<T>` is
287
315
  * assignable to `Router` (the unparameterized default), which is required for
288
316
  * storing typed routers in the `RouterContext` without contravariance errors.
289
- * At call sites, TypeScript still enforces the `RoutePaths<T>` constraint.
317
+ * At call sites, TypeScript still enforces the `RoutePattern<T>` constraint and
318
+ * the params required for each route pattern.
290
319
  */
291
320
  interface Router<T extends Record<string, RouteConfigLike> = RouteDefinitionMap> {
292
321
  /** Current matched route (reactive signal). */
@@ -297,8 +326,8 @@ interface Router<T extends Record<string, RouteConfigLike> = RouteDefinitionMap>
297
326
  loaderError: Signal<Error | null>;
298
327
  /** Parsed search params from the current route (reactive signal). */
299
328
  searchParams: Signal<Record<string, unknown>>;
300
- /** Navigate to a new URL path. */
301
- navigate(url: RoutePaths<T>, options?: NavigateOptions): Promise<void>;
329
+ /** Navigate to a route pattern, interpolating params and search into the final URL. */
330
+ navigate<TPath extends RoutePattern<T>>(input: NavigateInput<TPath>): Promise<void>;
302
331
  /** Re-run all loaders for the current route. */
303
332
  revalidate(): Promise<void>;
304
333
  /** Remove popstate listener and clean up the router. */
@@ -317,7 +346,8 @@ type TypedRouter<T extends Record<string, RouteConfigLike> = RouteDefinitionMap>
317
346
  * @param initialUrl - The initial URL to match (optional; auto-detects from window.location or SSR context)
318
347
  * @returns Router instance with reactive state and navigation methods
319
348
  */
320
- declare function createRouter<T extends Record<string, RouteConfigLike> = RouteDefinitionMap>(routes: TypedRoutes<T>, initialUrl?: string, options?: RouterOptions): Router<T>;
349
+ declare function createRouter<T extends Record<string, RouteConfigLike> = RouteDefinitionMap>(routes: TypedRoutes<T>, initialUrl: string, options?: RouterOptions): Router<T>;
350
+ declare function createRouter<T extends Record<string, RouteConfigLike> = RouteDefinitionMap>(routes: TypedRoutes<T>, options?: RouterOptions): Router<T>;
321
351
  /**
322
352
  * Props for the JSX pattern of Context.Provider.
323
353
  *
@@ -405,4 +435,4 @@ declare function parseSearchParams<T = Record<string, string>>(urlParams: URLSea
405
435
  * @returns The current search params value
406
436
  */
407
437
  declare function useSearchParams<T>(searchSignal: ReadonlySignal<T>): T;
408
- export { useSearchParams, useRouter, useParams, parseSearchParams, defineRoutes, createRouter, createLink, TypedRoutes, TypedRouter, SearchParamSchema, RouterViewProps, RouterView, RouterContext, Router, RoutePaths, RouteMatch, RouteDefinitionMap, RouteConfig, PathWithParams, ParamSchema, OutletContextValue, OutletContext, Outlet, NavigateOptions, MatchedRoute, LoaderData, LinkProps, InferRouteMap, ExtractParams, CompiledRoute };
438
+ export { useSearchParams, useRouter, useParams, parseSearchParams, defineRoutes, createRouter, createLink, TypedRoutes, TypedRouter, SearchParamSchema, RouterViewProps, RouterView, RouterContext, Router, RoutePattern, RoutePaths, RouteMatch, RouteDefinitionMap, RouteConfig, PathWithParams, ParamSchema, OutletContextValue, OutletContext, Outlet, NavigateOptions, NavigateInput, MatchedRoute, LoaderData, LinkProps, Link, InferRouteMap, ExtractParams, CompiledRoute };
@@ -1,26 +1,31 @@
1
1
  import {
2
+ Link,
2
3
  Outlet,
3
4
  OutletContext,
4
- RouterContext,
5
5
  RouterView,
6
6
  createLink,
7
7
  parseSearchParams,
8
- useParams,
9
- useRouter,
10
8
  useSearchParams
11
- } from "../../shared/chunk-nn9v1zmk.js";
12
- import"../../shared/chunk-dksg08fq.js";
9
+ } from "../../shared/chunk-b0qqqk03.js";
10
+ import"../../shared/chunk-1rxa2fz4.js";
13
11
  import {
14
12
  createRouter
15
- } from "../../shared/chunk-mj7b4t40.js";
13
+ } from "../../shared/chunk-fkbgbf3n.js";
16
14
  import {
17
15
  defineRoutes
18
- } from "../../shared/chunk-83g4h38e.js";
16
+ } from "../../shared/chunk-6wd36w21.js";
19
17
  import"../../shared/chunk-jrtrk5z4.js";
20
- import"../../shared/chunk-j6qyxfdc.js";
18
+ import {
19
+ RouterContext,
20
+ useParams,
21
+ useRouter
22
+ } from "../../shared/chunk-mtsvrj9e.js";
23
+ import"../../shared/chunk-pnv25zep.js";
24
+ import"../../shared/chunk-14eqne2a.js";
25
+ import"../../shared/chunk-vndfjfdy.js";
21
26
  import"../../shared/chunk-prj7nm08.js";
22
- import"../../shared/chunk-h89w580h.js";
23
- import"../../shared/chunk-8hsz5y4a.js";
27
+ import"../../shared/chunk-afawz764.js";
28
+ import"../../shared/chunk-4fwcwxn6.js";
24
29
  export {
25
30
  useSearchParams,
26
31
  useRouter,
@@ -32,5 +37,6 @@ export {
32
37
  RouterView,
33
38
  RouterContext,
34
39
  OutletContext,
35
- Outlet
40
+ Outlet,
41
+ Link
36
42
  };
@@ -138,25 +138,8 @@ 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
- /**
142
- * Convert a route pattern to the union of URL shapes it accepts.
143
- * - Static: `'/'` → `'/'`
144
- * - Param: `'/tasks/:id'` → `` `/tasks/${string}` ``
145
- * - Wildcard: `'/files/*'` → `` `/files/${string}` ``
146
- * - Multi: `'/users/:id/posts/:postId'` → `` `/users/${string}/posts/${string}` ``
147
- * - Fallback: `string` → `string` (backward compat)
148
- */
149
- 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;
150
- /**
151
- * Union of all valid URL shapes for a route map.
152
- * Maps each route pattern key through `PathWithParams` to produce the accepted URL shapes.
153
- *
154
- * Example:
155
- * ```
156
- * RoutePaths<{ '/': ..., '/tasks/:id': ... }> = '/' | `/tasks/${string}`
157
- * ```
158
- */
159
- type RoutePaths<TRouteMap extends Record<string, unknown>> = { [K in keyof TRouteMap & string] : PathWithParams<K> }[keyof TRouteMap & string];
141
+ /** Union of route pattern keys from a route map. */
142
+ type RoutePattern<TRouteMap extends Record<string, unknown>> = keyof TRouteMap & string;
160
143
  /** Schema interface for parsing and validating values (search params, path params). */
161
144
  interface SearchParamSchema<T> {
162
145
  parse(data: unknown): {
@@ -193,6 +176,8 @@ interface RouteConfig<
193
176
  searchParams?: SearchParamSchema<TSearch>;
194
177
  /** Nested child routes. */
195
178
  children?: RouteDefinitionMap;
179
+ /** Whether to pre-render this route at build time (default: true for static routes). */
180
+ prerender?: boolean;
196
181
  }
197
182
  /** A map of path patterns to route configs (user input format). */
198
183
  interface RouteDefinitionMap {
@@ -222,6 +207,7 @@ interface RouteConfigLike {
222
207
  params?: ParamSchema<unknown>;
223
208
  searchParams?: SearchParamSchema<unknown>;
224
209
  children?: Record<string, RouteConfigLike>;
210
+ prerender?: boolean;
225
211
  }
226
212
  /** Internal compiled route. */
227
213
  interface CompiledRoute {
@@ -239,6 +225,8 @@ interface CompiledRoute {
239
225
  searchParams?: RouteConfig["searchParams"];
240
226
  /** Compiled children. */
241
227
  children?: CompiledRoute[];
228
+ /** Whether to pre-render this route at build time (default: true for static routes). */
229
+ prerender?: boolean;
242
230
  }
243
231
  /** A single matched route entry in the matched chain. */
244
232
  interface MatchedRoute {
@@ -273,23 +261,38 @@ interface Signal<T> {
273
261
  /** Manually notify all subscribers (useful after mutating the value in place). */
274
262
  notify(): void;
275
263
  }
264
+ type NavigateSearchValue = string | number | boolean | null | undefined;
265
+ type NavigateSearch = string | URLSearchParams | Record<string, NavigateSearchValue | readonly NavigateSearchValue[]>;
276
266
  /** Options for router.navigate(). */
277
267
  interface NavigateOptions {
278
268
  /** Use history.replaceState instead of pushState. */
279
269
  replace?: boolean;
270
+ /** Route params used to interpolate dynamic segments in the route pattern. */
271
+ params?: Record<string, string>;
272
+ /** Search params appended to the final URL. */
273
+ search?: NavigateSearch;
280
274
  }
275
+ type NavigateOptionsFor<TPath extends string> = string extends TPath ? NavigateOptions : TPath extends `${string}:${string}` | `${string}*` ? Omit<NavigateOptions, "params"> & {
276
+ params: ExtractParams<TPath>;
277
+ } : Omit<NavigateOptions, "params"> & {
278
+ params?: never;
279
+ };
280
+ type NavigateInput<TPath extends string = string> = {
281
+ to: TPath;
282
+ } & NavigateOptionsFor<TPath>;
281
283
  /**
282
284
  * The router instance returned by createRouter.
283
285
  *
284
286
  * Generic over the route map `T`. Defaults to `RouteDefinitionMap` (string
285
287
  * index signature) for backward compatibility — unparameterized `Router`
286
- * accepts any string in `navigate()`.
288
+ * accepts any string in `navigate().to`.
287
289
  *
288
290
  * Method syntax on `navigate`, `revalidate`, and `dispose` enables bivariant
289
291
  * parameter checking under `strictFunctionTypes`. This means `Router<T>` is
290
292
  * assignable to `Router` (the unparameterized default), which is required for
291
293
  * storing typed routers in the `RouterContext` without contravariance errors.
292
- * At call sites, TypeScript still enforces the `RoutePaths<T>` constraint.
294
+ * At call sites, TypeScript still enforces the `RoutePattern<T>` constraint and
295
+ * the params required for each route pattern.
293
296
  */
294
297
  interface Router<T extends Record<string, RouteConfigLike> = RouteDefinitionMap> {
295
298
  /** Current matched route (reactive signal). */
@@ -300,8 +303,8 @@ interface Router<T extends Record<string, RouteConfigLike> = RouteDefinitionMap>
300
303
  loaderError: Signal<Error | null>;
301
304
  /** Parsed search params from the current route (reactive signal). */
302
305
  searchParams: Signal<Record<string, unknown>>;
303
- /** Navigate to a new URL path. */
304
- navigate(url: RoutePaths<T>, options?: NavigateOptions): Promise<void>;
306
+ /** Navigate to a route pattern, interpolating params and search into the final URL. */
307
+ navigate<TPath extends RoutePattern<T>>(input: NavigateInput<TPath>): Promise<void>;
305
308
  /** Re-run all loaders for the current route. */
306
309
  revalidate(): Promise<void>;
307
310
  /** Remove popstate listener and clean up the router. */
@@ -1,11 +1,12 @@
1
1
  import {
2
2
  createRouter
3
- } from "../../shared/chunk-mj7b4t40.js";
3
+ } from "../../shared/chunk-fkbgbf3n.js";
4
4
  import {
5
5
  defineRoutes
6
- } from "../../shared/chunk-83g4h38e.js";
6
+ } from "../../shared/chunk-6wd36w21.js";
7
7
  import"../../shared/chunk-jrtrk5z4.js";
8
- import"../../shared/chunk-8hsz5y4a.js";
8
+ import"../../shared/chunk-14eqne2a.js";
9
+ import"../../shared/chunk-4fwcwxn6.js";
9
10
 
10
11
  // src/test/interactions.ts
11
12
  async function click(el) {
@@ -199,7 +200,7 @@ async function createTestRouter(routes, opts) {
199
200
  container.setAttribute("data-testid", "test-router-container");
200
201
  await renderCurrentRoute(router, container);
201
202
  async function navigate(path) {
202
- await router.navigate(path);
203
+ await router.navigate({ to: path });
203
204
  await renderCurrentRoute(router, container);
204
205
  }
205
206
  return { component: container, navigate, router };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vertz/ui",
3
- "version": "0.2.14",
3
+ "version": "0.2.16",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Vertz UI framework — signals, components, JSX runtime",
@@ -69,11 +69,11 @@
69
69
  "typecheck": "tsc --noEmit"
70
70
  },
71
71
  "dependencies": {
72
- "@vertz/fetch": "^0.2.13"
72
+ "@vertz/fetch": "^0.2.15"
73
73
  },
74
74
  "devDependencies": {
75
75
  "@happy-dom/global-registrator": "^20.7.0",
76
- "@vertz/schema": "^0.2.13",
76
+ "@vertz/schema": "^0.2.15",
77
77
  "bunup": "^0.16.31",
78
78
  "happy-dom": "^20.7.0",
79
79
  "typescript": "^5.7.0"
package/reactivity.json CHANGED
@@ -42,17 +42,7 @@
42
42
  "useAuth": {
43
43
  "kind": "function",
44
44
  "reactivity": {
45
- "plainProperties": [
46
- "signIn",
47
- "signUp",
48
- "signOut",
49
- "refresh",
50
- "mfaChallenge",
51
- "forgotPassword",
52
- "resetPassword"
53
- ],
54
- "signalProperties": ["user", "status", "isAuthenticated", "isLoading", "error"],
55
- "type": "signal-api"
45
+ "type": "reactive-source"
56
46
  }
57
47
  },
58
48
  "useContext": {