@vertz/ui 0.2.23 → 0.2.24

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.
@@ -142,7 +142,12 @@ declare const KEYWORD_MAP: Record<string, CSSDeclarationEntry[]>;
142
142
  declare const DISPLAY_MAP: Record<string, string>;
143
143
  /** Spacing scale: number -> rem. 1=0.25rem, 2=0.5rem, 4=1rem, 8=2rem, etc. */
144
144
  declare const SPACING_SCALE: Record<string, string>;
145
- /** Border radius scale — matches Tailwind v4 / shadcn. */
145
+ /**
146
+ * Border radius scale — derived from the `--radius` CSS custom property.
147
+ *
148
+ * All levels (except none/full) are proportional to `--radius` (default 0.375rem).
149
+ * Changing `--radius` on a theme element scales every component's border-radius.
150
+ */
146
151
  declare const RADIUS_SCALE: Record<string, string>;
147
152
  /** Shadow scale. */
148
153
  declare const SHADOW_SCALE: Record<string, string>;
@@ -443,6 +448,11 @@ declare function __exitChildren(): void;
443
448
  * Bind an event handler to an element.
444
449
  * Returns a cleanup function to remove the listener.
445
450
  *
451
+ * Registers the cleanup with the current disposal scope (if any) so that
452
+ * event listeners are automatically removed when the owning component or
453
+ * dialog is unmounted. Without this, listeners on dynamically-mounted
454
+ * elements (e.g., forms inside useDialogStack dialogs) would leak.
455
+ *
446
456
  * Compiler output target for event bindings (onClick, onInput, etc.).
447
457
  */
448
458
  declare function __on(el: HTMLElement, event: string, handler: EventListener): () => void;
@@ -475,11 +485,23 @@ declare function clearChildren(container: Node): void;
475
485
  * @param items - A signal or getter function containing the array of items.
476
486
  * The compiler generates `() => signal.value` as a getter; the runtime
477
487
  * also accepts a raw Signal for direct use in tests.
478
- * @param keyFn - Extracts a unique key from each item (receives item and index)
488
+ * @param keyFn - Extracts a unique key from each item (receives item and index).
489
+ * Pass `null` for unkeyed lists — triggers full-replacement mode (safe but slower).
479
490
  * @param renderFn - Creates a DOM node for an item (called once per key)
480
491
  * @returns A dispose function to stop the reactive list reconciliation
481
492
  */
482
- declare function __list<T>(container: HTMLElement, items: Signal<T[]> | (() => T[]), keyFn: (item: T, index: number) => string | number, renderFn: (item: T) => Node): DisposeFn;
493
+ declare function __list<T>(container: HTMLElement, items: Signal<T[]> | (() => T[]), keyFn: ((item: T, index: number) => string | number) | null, renderFn: (item: T) => Node): DisposeFn;
494
+ /**
495
+ * Apply a spread props object to a DOM element.
496
+ *
497
+ * Compiler output target for JSX spread attributes on intrinsic elements:
498
+ * <button {...rest} /> → __spread(el, rest)
499
+ *
500
+ * Handles event handlers (on*), ref, style, class/className, htmlFor,
501
+ * SVG attribute normalization, and standard HTML attributes.
502
+ * Uses replace (not merge) semantics — last-wins, matching source order.
503
+ */
504
+ declare function __spread(el: Element, props: Record<string, unknown>): void;
483
505
  declare function styleObjectToString(style: Record<string, string | number | null | undefined>): string;
484
506
  /**
485
507
  * Returns true when running in a real browser environment.
@@ -625,7 +647,10 @@ interface RouteConfig<
625
647
  signal: AbortSignal;
626
648
  }) => Promise<TLoaderData> | TLoaderData;
627
649
  /** Optional error component rendered when loader throws. */
628
- errorComponent?: (error: Error) => Node;
650
+ errorComponent?: (props: {
651
+ error: Error;
652
+ retry: () => void;
653
+ }) => Node;
629
654
  /** Optional path params schema for validation/parsing. */
630
655
  params?: ParamSchema<TParams>;
631
656
  /** Optional search params schema for validation/coercion. */
@@ -653,7 +678,10 @@ interface CompiledRoute {
653
678
  params: Record<string, string>;
654
679
  signal: AbortSignal;
655
680
  }) => Promise<unknown> | unknown;
656
- errorComponent?: RouteConfig["errorComponent"];
681
+ errorComponent?: (props: {
682
+ error: Error;
683
+ retry: () => void;
684
+ }) => Node;
657
685
  /** Optional path params schema for validation/parsing. */
658
686
  params?: ParamSchema<unknown>;
659
687
  searchParams?: RouteConfig["searchParams"];
@@ -993,6 +1021,7 @@ declare class QueryEnvelopeStore {
993
1021
  private _envelopes;
994
1022
  get(queryKey: string): QueryEnvelope | undefined;
995
1023
  set(queryKey: string, envelope: QueryEnvelope): void;
1024
+ delete(queryKey: string): void;
996
1025
  clear(): void;
997
1026
  }
998
1027
  /** Entry registered by query() during SSR for renderToHTML() to await. */
@@ -1093,4 +1122,4 @@ declare function getSSRContext(): SSRRenderContext | undefined;
1093
1122
  * clears during HMR module re-evaluation.
1094
1123
  */
1095
1124
  declare function hasSSRResolver(): boolean;
1096
- export { stopSignalCollection, startSignalCollection, setContextScope, setAdapter, runCleanups, resolveComponent, removeNode, registerSSRResolver, pushScope, popScope, onCleanup, onAnimationsComplete, matchRoute, matchPath, lifecycleEffect, isRenderNode, isBrowser, insertBefore, hasSSRResolver, getSSRContext, getContextScope, getAdapter, executeLoaders, domEffect, deserializeProps, deriveKey, createDOMAdapter, compileTheme, clearChildren, _tryOnCleanup, __text, styleObjectToString as __styleStr, __staticText, __show, __pushMountFrame, __prop, __on, __list, __insert, __flushMountFrame, __exitChildren, __enterChildren, __element, __discardMountFrame, __conditional, __classList, __child, __attr, __append, SSRRenderContext, SSRQueryEntry, SSRAuth, SPACING_SCALE, SIZE_KEYWORDS, SHADOW_SCALE, RenderText, RenderNode, RenderElement, RenderAdapter, RENDER_NODE_BRAND, RADIUS_SCALE, QueryEnvelopeStore, PropertyMapping, PSEUDO_PREFIXES, PSEUDO_MAP, PROPERTY_MAP, MemoryCache, MatchResult, LINE_HEIGHT_SCALE, KEYWORD_MAP, HEIGHT_AXIS_PROPERTIES, FONT_WEIGHT_SCALE, FONT_SIZE_SCALE, EntityStore, DISPLAY_MAP, CSS_COLOR_KEYWORDS, CSSDeclarationEntry, CONTENT_MAP, COLOR_NAMESPACES, ALIGNMENT_MAP };
1125
+ export { stopSignalCollection, startSignalCollection, setContextScope, setAdapter, runCleanups, resolveComponent, removeNode, registerSSRResolver, pushScope, popScope, onCleanup, onAnimationsComplete, matchRoute, matchPath, lifecycleEffect, isRenderNode, isBrowser, insertBefore, hasSSRResolver, getSSRContext, getContextScope, getAdapter, executeLoaders, domEffect, deserializeProps, deriveKey, createDOMAdapter, compileTheme, clearChildren, _tryOnCleanup, __text, styleObjectToString as __styleStr, __staticText, __spread, __show, __pushMountFrame, __prop, __on, __list, __insert, __flushMountFrame, __exitChildren, __enterChildren, __element, __discardMountFrame, __conditional, __classList, __child, __attr, __append, SSRRenderContext, SSRQueryEntry, SSRAuth, SPACING_SCALE, SIZE_KEYWORDS, SHADOW_SCALE, RenderText, RenderNode, RenderElement, RenderAdapter, RENDER_NODE_BRAND, RADIUS_SCALE, QueryEnvelopeStore, PropertyMapping, PSEUDO_PREFIXES, PSEUDO_MAP, PROPERTY_MAP, MemoryCache, MatchResult, LINE_HEIGHT_SCALE, KEYWORD_MAP, HEIGHT_AXIS_PROPERTIES, FONT_WEIGHT_SCALE, FONT_SIZE_SCALE, EntityStore, DISPLAY_MAP, CSS_COLOR_KEYWORDS, CSSDeclarationEntry, CONTENT_MAP, COLOR_NAMESPACES, ALIGNMENT_MAP };
@@ -2,20 +2,13 @@ import {
2
2
  deserializeProps,
3
3
  onAnimationsComplete,
4
4
  resolveComponent
5
- } from "../shared/chunk-p3fz6qqp.js";
5
+ } from "../shared/chunk-18frwfc4.js";
6
6
  import {
7
- __attr,
8
- __classList,
9
7
  __discardMountFrame,
10
8
  __flushMountFrame,
11
9
  __on,
12
- __prop,
13
- __pushMountFrame,
14
- __show
15
- } from "../shared/chunk-2kyhn86t.js";
16
- import {
17
- styleObjectToString
18
- } from "../shared/chunk-4xkw6h1s.js";
10
+ __pushMountFrame
11
+ } from "../shared/chunk-ge2e6y2s.js";
19
12
  import {
20
13
  executeLoaders,
21
14
  matchPath,
@@ -26,7 +19,7 @@ import {
26
19
  MemoryCache,
27
20
  QueryEnvelopeStore,
28
21
  deriveKey
29
- } from "../shared/chunk-g6fb5yc2.js";
22
+ } from "../shared/chunk-4gen306a.js";
30
23
  import"../shared/chunk-jrtrk5z4.js";
31
24
  import {
32
25
  ALIGNMENT_MAP,
@@ -47,18 +40,26 @@ import {
47
40
  SIZE_KEYWORDS,
48
41
  SPACING_SCALE,
49
42
  compileTheme
50
- } from "../shared/chunk-xhc7arn9.js";
43
+ } from "../shared/chunk-t3rnfxc0.js";
51
44
  import {
52
45
  __append,
46
+ __attr,
53
47
  __child,
48
+ __classList,
54
49
  __element,
55
50
  __enterChildren,
56
51
  __exitChildren,
57
52
  __insert,
53
+ __prop,
54
+ __show,
58
55
  __staticText,
59
56
  __text
60
- } from "../shared/chunk-13tvh4wq.js";
61
- import"../shared/chunk-prj7nm08.js";
57
+ } from "../shared/chunk-mbnda3pv.js";
58
+ import {
59
+ SVG_NS,
60
+ normalizeSVGAttr,
61
+ styleObjectToString
62
+ } from "../shared/chunk-h1fsr8kv.js";
62
63
  import {
63
64
  RENDER_NODE_BRAND,
64
65
  createDOMAdapter,
@@ -66,6 +67,7 @@ import {
66
67
  isRenderNode,
67
68
  setAdapter
68
69
  } from "../shared/chunk-2y9f9j62.js";
70
+ import"../shared/chunk-2eh4p2n7.js";
69
71
  import {
70
72
  isBrowser
71
73
  } from "../shared/chunk-da2w7j7w.js";
@@ -227,6 +229,7 @@ function clearChildren(container) {
227
229
  }
228
230
  }
229
231
  // src/dom/list.ts
232
+ var unkeyedListWarned = false;
230
233
  function createItemProxy(itemSignal) {
231
234
  const initial = itemSignal.peek();
232
235
  if (typeof initial !== "object" || initial == null) {
@@ -277,6 +280,10 @@ function __list(container, items, keyFn, renderFn) {
277
280
  const nodeMap = new Map;
278
281
  const scopeMap = new Map;
279
282
  const itemSignalMap = new Map;
283
+ if (!keyFn && !unkeyedListWarned) {
284
+ unkeyedListWarned = true;
285
+ console.warn("[vertz] .map() without a key prop uses full-replacement mode (slower). " + "Add a key prop to list items for efficient updates: " + "{items.map(item => <Item key={item.id} />)}");
286
+ }
280
287
  const isHydrationRun = getIsHydrating();
281
288
  let startOffset = isHydrationRun ? -1 : container.childNodes.length;
282
289
  const outerScope = pushScope();
@@ -286,20 +293,47 @@ function __list(container, items, keyFn, renderFn) {
286
293
  if (isFirstRun && isHydrationRun) {
287
294
  isFirstRun = false;
288
295
  for (const [i, item] of newItems.entries()) {
289
- const key = keyFn(item, i);
290
- const itemSig = signal(item);
291
- const proxy = createItemProxy(itemSig);
296
+ const key = keyFn ? keyFn(item, i) : i;
292
297
  const scope = pushScope();
293
- const node = renderFn(proxy);
298
+ if (keyFn) {
299
+ const itemSig = signal(item);
300
+ const proxy = createItemProxy(itemSig);
301
+ const node = renderFn(proxy);
302
+ itemSignalMap.set(key, itemSig);
303
+ nodeMap.set(key, node);
304
+ } else {
305
+ const node = renderFn(item);
306
+ nodeMap.set(key, node);
307
+ }
294
308
  popScope();
295
- nodeMap.set(key, node);
296
309
  scopeMap.set(key, scope);
297
- itemSignalMap.set(key, itemSig);
298
310
  }
299
311
  startOffset = container.childNodes.length - nodeMap.size;
300
312
  return;
301
313
  }
302
314
  isFirstRun = false;
315
+ if (!keyFn) {
316
+ for (const scope of scopeMap.values()) {
317
+ runCleanups(scope);
318
+ }
319
+ scopeMap.clear();
320
+ for (const node of nodeMap.values()) {
321
+ node.parentNode?.removeChild(node);
322
+ }
323
+ nodeMap.clear();
324
+ itemSignalMap.clear();
325
+ for (const item of newItems) {
326
+ const scope = pushScope();
327
+ const node = renderFn(item);
328
+ popScope();
329
+ container.appendChild(node);
330
+ const internalKey = nodeMap.size;
331
+ nodeMap.set(internalKey, node);
332
+ scopeMap.set(internalKey, scope);
333
+ }
334
+ fixUpSelectValue(container);
335
+ return;
336
+ }
303
337
  const newKeySet = new Set(newItems.map((item, i) => keyFn(item, i)));
304
338
  for (const [key, node] of nodeMap) {
305
339
  if (!newKeySet.has(key)) {
@@ -340,12 +374,7 @@ function __list(container, items, keyFn, renderFn) {
340
374
  container.insertBefore(desiredNode, currentChild ?? null);
341
375
  }
342
376
  }
343
- if (container.tagName === "SELECT") {
344
- const selected = container.querySelector("option[selected]");
345
- if (selected) {
346
- Reflect.set(container, "value", selected.value);
347
- }
348
- }
377
+ fixUpSelectValue(container);
349
378
  });
350
379
  popScope();
351
380
  const wrapper = () => {
@@ -358,6 +387,56 @@ function __list(container, items, keyFn, renderFn) {
358
387
  _tryOnCleanup(wrapper);
359
388
  return wrapper;
360
389
  }
390
+ function fixUpSelectValue(container) {
391
+ if (container.tagName === "SELECT") {
392
+ const selected = container.querySelector("option[selected]");
393
+ if (selected) {
394
+ Reflect.set(container, "value", selected.value);
395
+ }
396
+ }
397
+ }
398
+ // src/dom/spread.ts
399
+ var SKIP_KEYS = new Set(["children", "key"]);
400
+ var PROP_ALIASES = {
401
+ className: "class",
402
+ htmlFor: "for"
403
+ };
404
+ function __spread(el, props) {
405
+ const isSvg = el.namespaceURI === SVG_NS;
406
+ for (const key of Object.keys(props)) {
407
+ if (SKIP_KEYS.has(key))
408
+ continue;
409
+ const value = props[key];
410
+ if (key === "ref") {
411
+ if (value && typeof value === "object" && "current" in value) {
412
+ value.current = el;
413
+ }
414
+ continue;
415
+ }
416
+ if (key.length > 2 && key.startsWith("on") && typeof value === "function") {
417
+ const eventName = key.slice(2).toLowerCase();
418
+ el.addEventListener(eventName, value);
419
+ continue;
420
+ }
421
+ if (value == null || value === false)
422
+ continue;
423
+ const attrName = PROP_ALIASES[key] ?? key;
424
+ if (attrName === "style") {
425
+ if (typeof value === "object") {
426
+ el.setAttribute("style", styleObjectToString(value));
427
+ } else {
428
+ el.setAttribute("style", String(value));
429
+ }
430
+ continue;
431
+ }
432
+ if (value === true) {
433
+ el.setAttribute(attrName, "");
434
+ continue;
435
+ }
436
+ const finalName = isSvg ? normalizeSVGAttr(attrName) : attrName;
437
+ el.setAttribute(finalName, String(value));
438
+ }
439
+ }
361
440
  export {
362
441
  stopSignalCollection,
363
442
  startSignalCollection,
@@ -392,6 +471,7 @@ export {
392
471
  __text,
393
472
  styleObjectToString as __styleStr,
394
473
  __staticText,
474
+ __spread,
395
475
  __show,
396
476
  __pushMountFrame,
397
477
  __prop,
@@ -1,11 +1,9 @@
1
- import {
2
- styleObjectToString
3
- } from "../../shared/chunk-4xkw6h1s.js";
4
1
  import {
5
2
  SVG_NS,
6
3
  isSVGTag,
7
- normalizeSVGAttr
8
- } from "../../shared/chunk-prj7nm08.js";
4
+ normalizeSVGAttr,
5
+ styleObjectToString
6
+ } from "../../shared/chunk-h1fsr8kv.js";
9
7
 
10
8
  // src/jsx-runtime/index.ts
11
9
  function applyChildren(parent, children) {
@@ -37,8 +37,6 @@ interface QueryOptions<T> {
37
37
  initialData?: T;
38
38
  /** Debounce re-fetches triggered by reactive dependency changes (ms). */
39
39
  debounce?: number;
40
- /** When false, the query will not fetch. Defaults to true. */
41
- enabled?: boolean;
42
40
  /** Explicit cache key. When omitted, derived from the thunk. */
43
41
  key?: string;
44
42
  /** Custom cache store. Defaults to a shared in-memory Map. */
@@ -72,6 +70,8 @@ interface QueryResult<
72
70
  readonly revalidating: Unwrapped<ReadonlySignal<boolean>>;
73
71
  /** The error from the latest failed fetch, or undefined. */
74
72
  readonly error: Unwrapped<ReadonlySignal<E | undefined>>;
73
+ /** True when the query has never fetched (thunk returned null or not yet run). */
74
+ readonly idle: Unwrapped<ReadonlySignal<boolean>>;
75
75
  /** Manually trigger a refetch (clears cache for this key). */
76
76
  refetch: () => void;
77
77
  /** Alias for refetch — revalidate the cached data. */
@@ -93,7 +93,11 @@ declare function query<
93
93
  T,
94
94
  E
95
95
  >(descriptor: QueryDescriptor<T, E>, options?: Omit<QueryOptions<T>, "key">): QueryResult<T, E>;
96
- declare function query<T>(thunk: () => Promise<T>, options?: QueryOptions<T>): QueryResult<T>;
96
+ declare function query<
97
+ T,
98
+ E
99
+ >(thunk: () => QueryDescriptor<T, E> | null, options?: Omit<QueryOptions<T>, "key">): QueryResult<T, E>;
100
+ declare function query<T>(thunk: () => Promise<T> | null, options?: QueryOptions<T>): QueryResult<T>;
97
101
  interface QueryMatchHandlers<
98
102
  T,
99
103
  E
@@ -1,9 +1,10 @@
1
1
  import {
2
2
  query,
3
3
  queryMatch
4
- } from "../../shared/chunk-g6fb5yc2.js";
4
+ } from "../../shared/chunk-4gen306a.js";
5
5
  import"../../shared/chunk-jrtrk5z4.js";
6
6
  import"../../shared/chunk-2y9f9j62.js";
7
+ import"../../shared/chunk-2eh4p2n7.js";
7
8
  import"../../shared/chunk-da2w7j7w.js";
8
9
  import"../../shared/chunk-656n0x6y.js";
9
10
 
@@ -93,7 +93,10 @@ interface RouteConfig<
93
93
  signal: AbortSignal;
94
94
  }) => Promise<TLoaderData> | TLoaderData;
95
95
  /** Optional error component rendered when loader throws. */
96
- errorComponent?: (error: Error) => Node;
96
+ errorComponent?: (props: {
97
+ error: Error;
98
+ retry: () => void;
99
+ }) => Node;
97
100
  /** Optional path params schema for validation/parsing. */
98
101
  params?: ParamSchema<TParams>;
99
102
  /** Optional search params schema for validation/coercion. */
@@ -131,7 +134,10 @@ interface RouteConfigLike {
131
134
  params: Record<string, string>;
132
135
  signal: AbortSignal;
133
136
  }): unknown;
134
- errorComponent?: (error: Error) => Node;
137
+ errorComponent?: (props: {
138
+ error: Error;
139
+ retry: () => void;
140
+ }) => Node;
135
141
  params?: ParamSchema<unknown>;
136
142
  searchParams?: SearchParamSchema<unknown>;
137
143
  children?: Record<string, RouteConfigLike>;
@@ -165,7 +171,10 @@ interface CompiledRoute {
165
171
  params: Record<string, string>;
166
172
  signal: AbortSignal;
167
173
  }) => Promise<unknown> | unknown;
168
- errorComponent?: RouteConfig["errorComponent"];
174
+ errorComponent?: (props: {
175
+ error: Error;
176
+ retry: () => void;
177
+ }) => Node;
169
178
  /** Optional path params schema for validation/parsing. */
170
179
  params?: ParamSchema<unknown>;
171
180
  searchParams?: RouteConfig["searchParams"];
@@ -449,9 +458,23 @@ declare function useRouter<T extends Record<string, RouteConfigLike> = RouteDefi
449
458
  */
450
459
  declare function useParams<TPath extends string = string>(): ExtractParams<TPath>;
451
460
  declare function useParams<T extends Record<string, unknown>>(): T;
461
+ /** Props for error fallback components (shared by DefaultErrorFallback and route errorComponent). */
462
+ interface ErrorFallbackProps {
463
+ error: Error;
464
+ retry: () => void;
465
+ }
466
+ /** Error fallback component signature, reuses ErrorFallbackProps from DefaultErrorFallback. */
467
+ type ErrorFallbackFn = (props: ErrorFallbackProps) => Node;
452
468
  interface RouterViewProps {
453
469
  router: Router;
470
+ /** Rendered when no route matches (404). */
454
471
  fallback?: () => Node;
472
+ /**
473
+ * Global error fallback for all routes. When set, every route component is
474
+ * automatically wrapped in an ErrorBoundary using this fallback.
475
+ * Per-route `errorComponent` takes precedence over this.
476
+ */
477
+ errorFallback?: ErrorFallbackFn;
455
478
  }
456
479
  /**
457
480
  * Renders the matched route's component inside a container div.
@@ -464,7 +487,7 @@ interface RouterViewProps {
464
487
  * domEffect runs the component factory (to attach reactivity/event handlers)
465
488
  * but skips clearing the container.
466
489
  */
467
- declare function RouterView({ router, fallback }: RouterViewProps): HTMLElement;
490
+ declare function RouterView({ router, fallback, errorFallback }: RouterViewProps): HTMLElement;
468
491
  /**
469
492
  * Parse URLSearchParams into a typed object, optionally through a schema.
470
493
  *
@@ -6,9 +6,8 @@ import {
6
6
  createLink,
7
7
  parseSearchParams,
8
8
  useSearchParams
9
- } from "../../shared/chunk-016m1fq0.js";
10
- import"../../shared/chunk-2kyhn86t.js";
11
- import"../../shared/chunk-4xkw6h1s.js";
9
+ } from "../../shared/chunk-2wag9c7v.js";
10
+ import"../../shared/chunk-ge2e6y2s.js";
12
11
  import {
13
12
  createRouter
14
13
  } from "../../shared/chunk-jtma4sh4.js";
@@ -16,8 +15,8 @@ import {
16
15
  defineRoutes
17
16
  } from "../../shared/chunk-am9zaw4h.js";
18
17
  import"../../shared/chunk-jrtrk5z4.js";
19
- import"../../shared/chunk-13tvh4wq.js";
20
- import"../../shared/chunk-prj7nm08.js";
18
+ import"../../shared/chunk-mbnda3pv.js";
19
+ import"../../shared/chunk-h1fsr8kv.js";
21
20
  import"../../shared/chunk-2y9f9j62.js";
22
21
  import {
23
22
  RouterContext,
@@ -187,7 +187,10 @@ interface RouteConfig<
187
187
  signal: AbortSignal;
188
188
  }) => Promise<TLoaderData> | TLoaderData;
189
189
  /** Optional error component rendered when loader throws. */
190
- errorComponent?: (error: Error) => Node;
190
+ errorComponent?: (props: {
191
+ error: Error;
192
+ retry: () => void;
193
+ }) => Node;
191
194
  /** Optional path params schema for validation/parsing. */
192
195
  params?: ParamSchema<TParams>;
193
196
  /** Optional search params schema for validation/coercion. */
@@ -225,7 +228,10 @@ interface RouteConfigLike {
225
228
  params: Record<string, string>;
226
229
  signal: AbortSignal;
227
230
  }): unknown;
228
- errorComponent?: (error: Error) => Node;
231
+ errorComponent?: (props: {
232
+ error: Error;
233
+ retry: () => void;
234
+ }) => Node;
229
235
  params?: ParamSchema<unknown>;
230
236
  searchParams?: SearchParamSchema<unknown>;
231
237
  children?: Record<string, RouteConfigLike>;
@@ -243,7 +249,10 @@ interface CompiledRoute {
243
249
  params: Record<string, string>;
244
250
  signal: AbortSignal;
245
251
  }) => Promise<unknown> | unknown;
246
- errorComponent?: RouteConfig["errorComponent"];
252
+ errorComponent?: (props: {
253
+ error: Error;
254
+ retry: () => void;
255
+ }) => Node;
247
256
  /** Optional path params schema for validation/parsing. */
248
257
  params?: ParamSchema<unknown>;
249
258
  searchParams?: RouteConfig["searchParams"];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vertz/ui",
3
- "version": "0.2.23",
3
+ "version": "0.2.24",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Vertz UI framework — signals, components, JSX runtime",
@@ -69,15 +69,16 @@
69
69
  "scripts": {
70
70
  "build": "bunup",
71
71
  "test": "bun test",
72
+ "test:benchmark": "bun test src/dom/__tests__/hydration-deferred-effects-bench.local.ts",
72
73
  "test:watch": "bun test --watch",
73
74
  "typecheck": "tsc --noEmit"
74
75
  },
75
76
  "dependencies": {
76
- "@vertz/fetch": "^0.2.22"
77
+ "@vertz/fetch": "^0.2.23"
77
78
  },
78
79
  "devDependencies": {
79
80
  "@happy-dom/global-registrator": "^20.7.0",
80
- "@vertz/schema": "^0.2.22",
81
+ "@vertz/schema": "^0.2.23",
81
82
  "bunup": "^0.16.31",
82
83
  "happy-dom": "^20.7.0",
83
84
  "typescript": "^5.7.0"
package/reactivity.json CHANGED
@@ -29,7 +29,7 @@
29
29
  "kind": "function",
30
30
  "reactivity": {
31
31
  "plainProperties": ["refetch", "revalidate", "dispose"],
32
- "signalProperties": ["data", "loading", "error", "revalidating"],
32
+ "signalProperties": ["data", "loading", "error", "revalidating", "idle"],
33
33
  "type": "signal-api"
34
34
  }
35
35
  },
@@ -1,67 +0,0 @@
1
- // src/dom/svg-tags.ts
2
- var SVG_TAGS = new Set([
3
- "svg",
4
- "path",
5
- "circle",
6
- "ellipse",
7
- "rect",
8
- "line",
9
- "polyline",
10
- "polygon",
11
- "g",
12
- "defs",
13
- "symbol",
14
- "use",
15
- "text",
16
- "tspan",
17
- "image",
18
- "foreignObject",
19
- "filter",
20
- "feGaussianBlur",
21
- "feOffset",
22
- "feColorMatrix",
23
- "feBlend",
24
- "feMerge",
25
- "feMergeNode",
26
- "feComposite",
27
- "feFlood",
28
- "linearGradient",
29
- "radialGradient",
30
- "stop",
31
- "pattern",
32
- "clipPath",
33
- "mask",
34
- "animate",
35
- "animateTransform",
36
- "set",
37
- "marker",
38
- "desc"
39
- ]);
40
- var SVG_NS = "http://www.w3.org/2000/svg";
41
- function isSVGTag(tag) {
42
- return SVG_TAGS.has(tag);
43
- }
44
- var SVG_ATTR_MAP = {
45
- strokeWidth: "stroke-width",
46
- strokeLinecap: "stroke-linecap",
47
- strokeLinejoin: "stroke-linejoin",
48
- strokeDasharray: "stroke-dasharray",
49
- strokeDashoffset: "stroke-dashoffset",
50
- strokeOpacity: "stroke-opacity",
51
- fillOpacity: "fill-opacity",
52
- fillRule: "fill-rule",
53
- clipRule: "clip-rule",
54
- clipPath: "clip-path",
55
- stopColor: "stop-color",
56
- stopOpacity: "stop-opacity",
57
- floodColor: "flood-color",
58
- floodOpacity: "flood-opacity",
59
- colorInterpolation: "color-interpolation",
60
- colorInterpolationFilters: "color-interpolation-filters",
61
- viewBox: "viewBox"
62
- };
63
- function normalizeSVGAttr(attr) {
64
- return SVG_ATTR_MAP[attr] ?? attr;
65
- }
66
-
67
- export { SVG_NS, isSVGTag, normalizeSVGAttr };