@vertz/ui 0.2.22 → 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.
Files changed (36) hide show
  1. package/dist/shared/{chunk-pdqr78k9.js → chunk-18frwfc4.js} +1 -1
  2. package/dist/shared/chunk-2eh4p2n7.js +39 -0
  3. package/dist/shared/{chunk-67z8b0q8.js → chunk-2wag9c7v.js} +182 -53
  4. package/dist/shared/{chunk-c61572xp.js → chunk-2y9f9j62.js} +1 -1
  5. package/dist/shared/{chunk-szk0hyjg.js → chunk-4gen306a.js} +212 -155
  6. package/dist/shared/{chunk-yb4a0smw.js → chunk-4gmtsf6v.js} +1 -1
  7. package/dist/shared/{chunk-2qe6aqhb.js → chunk-656n0x6y.js} +48 -48
  8. package/dist/shared/{chunk-bybgyjye.js → chunk-da2w7j7w.js} +1 -1
  9. package/dist/shared/{chunk-4cmt1ve8.js → chunk-f4d5nphq.js} +1 -1
  10. package/dist/shared/chunk-ge2e6y2s.js +102 -0
  11. package/dist/shared/{chunk-4xkw6h1s.js → chunk-h1fsr8kv.js} +67 -1
  12. package/dist/shared/{chunk-7g722pdh.js → chunk-jtma4sh4.js} +2 -2
  13. package/dist/shared/{chunk-vwz86vg9.js → chunk-mbnda3pv.js} +96 -18
  14. package/dist/shared/{chunk-pq8khh47.js → chunk-t3rnfxc0.js} +64 -23
  15. package/dist/src/auth/public.d.ts +35 -1
  16. package/dist/src/auth/public.js +72 -3
  17. package/dist/src/components/index.d.ts +2 -2
  18. package/dist/src/components/index.js +51 -46
  19. package/dist/src/css/public.d.ts +7 -3
  20. package/dist/src/css/public.js +5 -5
  21. package/dist/src/form/public.js +2 -2
  22. package/dist/src/index.d.ts +211 -39
  23. package/dist/src/index.js +372 -153
  24. package/dist/src/internals.d.ts +70 -6
  25. package/dist/src/internals.js +161 -34
  26. package/dist/src/jsx-runtime/index.js +3 -5
  27. package/dist/src/query/public.d.ts +7 -3
  28. package/dist/src/query/public.js +5 -4
  29. package/dist/src/router/public.d.ts +27 -4
  30. package/dist/src/router/public.js +9 -10
  31. package/dist/src/test/index.d.ts +12 -3
  32. package/dist/src/test/index.js +3 -3
  33. package/package.json +4 -3
  34. package/reactivity.json +1 -1
  35. package/dist/shared/chunk-kjwp5q5s.js +0 -53
  36. package/dist/shared/chunk-prj7nm08.js +0 -67
@@ -81,6 +81,31 @@ declare function getContextScope(): ContextScope | null;
81
81
  */
82
82
  declare function setContextScope(scope: ContextScope | null): ContextScope | null;
83
83
  /**
84
+ * Compiler-injected: push a new mount frame at component body start.
85
+ * Returns the stack depth AFTER pushing — used by __discardMountFrame
86
+ * to avoid popping a parent frame if __flushMountFrame already popped ours.
87
+ */
88
+ declare function __pushMountFrame(): number;
89
+ /**
90
+ * Compiler-injected: flush the current mount frame after JSX evaluation.
91
+ * Pops the frame first (so the stack is clean even if a callback throws),
92
+ * then executes all deferred callbacks. All callbacks run even if one throws —
93
+ * the first error is rethrown after all have executed.
94
+ *
95
+ * During hydration (postHydrationQueue is non-null), callbacks are pushed
96
+ * to the queue instead of executing — they run after endHydration() via
97
+ * flushDeferredMounts(). This prevents onMount DOM manipulation from
98
+ * corrupting the hydration cursor.
99
+ */
100
+ declare function __flushMountFrame(): void;
101
+ /**
102
+ * Compiler-injected: discard the current mount frame in error paths.
103
+ * Only pops if the stack depth still matches `expectedDepth` (the value
104
+ * returned by __pushMountFrame). This prevents popping a parent frame
105
+ * when __flushMountFrame already popped ours (e.g., a callback threw).
106
+ */
107
+ declare function __discardMountFrame(expectedDepth: number): void;
108
+ /**
84
109
  * Shared CSS token lookup tables.
85
110
  *
86
111
  * This is the single source of truth for all CSS token resolution data.
@@ -117,7 +142,12 @@ declare const KEYWORD_MAP: Record<string, CSSDeclarationEntry[]>;
117
142
  declare const DISPLAY_MAP: Record<string, string>;
118
143
  /** Spacing scale: number -> rem. 1=0.25rem, 2=0.5rem, 4=1rem, 8=2rem, etc. */
119
144
  declare const SPACING_SCALE: Record<string, string>;
120
- /** 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
+ */
121
151
  declare const RADIUS_SCALE: Record<string, string>;
122
152
  /** Shadow scale. */
123
153
  declare const SHADOW_SCALE: Record<string, string>;
@@ -295,6 +325,16 @@ declare function onAnimationsComplete(el: Element, callback: () => void): void;
295
325
  */
296
326
  declare function __attr(el: HTMLElement, name: string, fn: () => string | boolean | Record<string, string | number> | null | undefined): DisposeFn;
297
327
  /**
328
+ * Create a reactive DOM property binding.
329
+ * Unlike __attr (which uses setAttribute), this directly assigns to the
330
+ * element's IDL property (e.g., el.value, el.checked). This is required
331
+ * for form-related properties where setAttribute doesn't control the
332
+ * displayed state (e.g., <select>.value, <input>.checked).
333
+ *
334
+ * Uses deferredDomEffect so the first run is skipped during hydration.
335
+ */
336
+ declare function __prop(el: HTMLElement, name: string, fn: () => unknown): DisposeFn;
337
+ /**
298
338
  * Reactive display toggle.
299
339
  * When fn() returns false, the element is hidden (display: none).
300
340
  * When fn() returns true, the element is shown (display restored).
@@ -408,6 +448,11 @@ declare function __exitChildren(): void;
408
448
  * Bind an event handler to an element.
409
449
  * Returns a cleanup function to remove the listener.
410
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
+ *
411
456
  * Compiler output target for event bindings (onClick, onInput, etc.).
412
457
  */
413
458
  declare function __on(el: HTMLElement, event: string, handler: EventListener): () => void;
@@ -440,11 +485,23 @@ declare function clearChildren(container: Node): void;
440
485
  * @param items - A signal or getter function containing the array of items.
441
486
  * The compiler generates `() => signal.value` as a getter; the runtime
442
487
  * also accepts a raw Signal for direct use in tests.
443
- * @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).
444
490
  * @param renderFn - Creates a DOM node for an item (called once per key)
445
491
  * @returns A dispose function to stop the reactive list reconciliation
446
492
  */
447
- 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;
448
505
  declare function styleObjectToString(style: Record<string, string | number | null | undefined>): string;
449
506
  /**
450
507
  * Returns true when running in a real browser environment.
@@ -590,7 +647,10 @@ interface RouteConfig<
590
647
  signal: AbortSignal;
591
648
  }) => Promise<TLoaderData> | TLoaderData;
592
649
  /** Optional error component rendered when loader throws. */
593
- errorComponent?: (error: Error) => Node;
650
+ errorComponent?: (props: {
651
+ error: Error;
652
+ retry: () => void;
653
+ }) => Node;
594
654
  /** Optional path params schema for validation/parsing. */
595
655
  params?: ParamSchema<TParams>;
596
656
  /** Optional search params schema for validation/coercion. */
@@ -618,7 +678,10 @@ interface CompiledRoute {
618
678
  params: Record<string, string>;
619
679
  signal: AbortSignal;
620
680
  }) => Promise<unknown> | unknown;
621
- errorComponent?: RouteConfig["errorComponent"];
681
+ errorComponent?: (props: {
682
+ error: Error;
683
+ retry: () => void;
684
+ }) => Node;
622
685
  /** Optional path params schema for validation/parsing. */
623
686
  params?: ParamSchema<unknown>;
624
687
  searchParams?: RouteConfig["searchParams"];
@@ -958,6 +1021,7 @@ declare class QueryEnvelopeStore {
958
1021
  private _envelopes;
959
1022
  get(queryKey: string): QueryEnvelope | undefined;
960
1023
  set(queryKey: string, envelope: QueryEnvelope): void;
1024
+ delete(queryKey: string): void;
961
1025
  clear(): void;
962
1026
  }
963
1027
  /** Entry registered by query() during SSR for renderToHTML() to await. */
@@ -1058,4 +1122,4 @@ declare function getSSRContext(): SSRRenderContext | undefined;
1058
1122
  * clears during HMR module re-evaluation.
1059
1123
  */
1060
1124
  declare function hasSSRResolver(): boolean;
1061
- 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, __on, __list, __insert, __exitChildren, __enterChildren, __element, __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,16 +2,13 @@ import {
2
2
  deserializeProps,
3
3
  onAnimationsComplete,
4
4
  resolveComponent
5
- } from "../shared/chunk-pdqr78k9.js";
5
+ } from "../shared/chunk-18frwfc4.js";
6
6
  import {
7
- __attr,
8
- __classList,
7
+ __discardMountFrame,
8
+ __flushMountFrame,
9
9
  __on,
10
- __show
11
- } from "../shared/chunk-kjwp5q5s.js";
12
- import {
13
- styleObjectToString
14
- } from "../shared/chunk-4xkw6h1s.js";
10
+ __pushMountFrame
11
+ } from "../shared/chunk-ge2e6y2s.js";
15
12
  import {
16
13
  executeLoaders,
17
14
  matchPath,
@@ -22,7 +19,7 @@ import {
22
19
  MemoryCache,
23
20
  QueryEnvelopeStore,
24
21
  deriveKey
25
- } from "../shared/chunk-szk0hyjg.js";
22
+ } from "../shared/chunk-4gen306a.js";
26
23
  import"../shared/chunk-jrtrk5z4.js";
27
24
  import {
28
25
  ALIGNMENT_MAP,
@@ -43,28 +40,37 @@ import {
43
40
  SIZE_KEYWORDS,
44
41
  SPACING_SCALE,
45
42
  compileTheme
46
- } from "../shared/chunk-pq8khh47.js";
43
+ } from "../shared/chunk-t3rnfxc0.js";
47
44
  import {
48
45
  __append,
46
+ __attr,
49
47
  __child,
48
+ __classList,
50
49
  __element,
51
50
  __enterChildren,
52
51
  __exitChildren,
53
52
  __insert,
53
+ __prop,
54
+ __show,
54
55
  __staticText,
55
56
  __text
56
- } from "../shared/chunk-vwz86vg9.js";
57
- 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";
58
63
  import {
59
64
  RENDER_NODE_BRAND,
60
65
  createDOMAdapter,
61
66
  getAdapter,
62
67
  isRenderNode,
63
68
  setAdapter
64
- } from "../shared/chunk-c61572xp.js";
69
+ } from "../shared/chunk-2y9f9j62.js";
70
+ import"../shared/chunk-2eh4p2n7.js";
65
71
  import {
66
72
  isBrowser
67
- } from "../shared/chunk-bybgyjye.js";
73
+ } from "../shared/chunk-da2w7j7w.js";
68
74
  import {
69
75
  _tryOnCleanup,
70
76
  claimComment,
@@ -84,7 +90,7 @@ import {
84
90
  signal,
85
91
  startSignalCollection,
86
92
  stopSignalCollection
87
- } from "../shared/chunk-2qe6aqhb.js";
93
+ } from "../shared/chunk-656n0x6y.js";
88
94
  // src/dom/conditional.ts
89
95
  function normalizeNode(branchResult) {
90
96
  if (branchResult == null || typeof branchResult === "boolean") {
@@ -108,9 +114,14 @@ function __conditional(condFn, trueFn, falseFn) {
108
114
  return csrConditional(condFn, trueFn, falseFn);
109
115
  }
110
116
  function hydrateConditional(condFn, trueFn, falseFn) {
111
- const anchor = claimComment() ?? getAdapter().createComment("conditional");
117
+ const claimed = claimComment();
118
+ if (!claimed) {
119
+ return csrConditional(condFn, trueFn, falseFn);
120
+ }
121
+ const anchor = claimed;
112
122
  let currentNode = null;
113
123
  let branchCleanups = [];
124
+ let resultNode = anchor;
114
125
  const outerScope = pushScope();
115
126
  let isFirstRun = true;
116
127
  domEffect(() => {
@@ -121,13 +132,29 @@ function hydrateConditional(condFn, trueFn, falseFn) {
121
132
  const branchResult2 = show ? trueFn() : falseFn();
122
133
  popScope();
123
134
  branchCleanups = scope2;
135
+ let contentNode = null;
124
136
  if (branchResult2 == null || typeof branchResult2 === "boolean") {
125
- currentNode = getAdapter().createComment("empty");
137
+ contentNode = null;
126
138
  } else if (isRenderNode(branchResult2)) {
127
- currentNode = branchResult2;
139
+ contentNode = branchResult2;
128
140
  } else {
129
- const claimed = claimText();
130
- currentNode = claimed ?? getAdapter().createTextNode(String(branchResult2));
141
+ const claimed2 = claimText();
142
+ contentNode = claimed2 ?? getAdapter().createTextNode(String(branchResult2));
143
+ }
144
+ const anchorParent = anchor.parentNode;
145
+ if (anchorParent) {
146
+ const wrap = getAdapter().createElement("span");
147
+ wrap.style.display = "contents";
148
+ anchorParent.insertBefore(wrap, anchor);
149
+ wrap.appendChild(anchor);
150
+ if (contentNode?.parentNode && contentNode.parentNode !== wrap) {
151
+ wrap.appendChild(contentNode);
152
+ }
153
+ currentNode = wrap;
154
+ resultNode = wrap;
155
+ } else {
156
+ currentNode = contentNode ?? getAdapter().createComment("empty");
157
+ resultNode = currentNode;
131
158
  }
132
159
  return;
133
160
  }
@@ -145,13 +172,13 @@ function hydrateConditional(condFn, trueFn, falseFn) {
145
172
  currentNode = newNode;
146
173
  });
147
174
  popScope();
148
- const wrapper = () => {
175
+ const disposeFn = () => {
149
176
  runCleanups(branchCleanups);
150
177
  runCleanups(outerScope);
151
178
  };
152
- _tryOnCleanup(wrapper);
153
- const result = Object.assign(anchor, {
154
- dispose: wrapper
179
+ _tryOnCleanup(disposeFn);
180
+ const result = Object.assign(resultNode, {
181
+ dispose: disposeFn
155
182
  });
156
183
  return result;
157
184
  }
@@ -202,11 +229,13 @@ function clearChildren(container) {
202
229
  }
203
230
  }
204
231
  // src/dom/list.ts
232
+ var unkeyedListWarned = false;
205
233
  function createItemProxy(itemSignal) {
206
- if (typeof itemSignal.peek() !== "object" || itemSignal.peek() == null) {
207
- return itemSignal.peek();
234
+ const initial = itemSignal.peek();
235
+ if (typeof initial !== "object" || initial == null) {
236
+ return initial;
208
237
  }
209
- return new Proxy({}, {
238
+ return new Proxy(initial, {
210
239
  get(_target, prop, receiver) {
211
240
  const current = itemSignal.value;
212
241
  if (current == null)
@@ -217,6 +246,9 @@ function createItemProxy(itemSignal) {
217
246
  }
218
247
  return value;
219
248
  },
249
+ set() {
250
+ return false;
251
+ },
220
252
  has(_target, prop) {
221
253
  const current = itemSignal.value;
222
254
  if (current == null)
@@ -234,6 +266,12 @@ function createItemProxy(itemSignal) {
234
266
  if (current == null)
235
267
  return;
236
268
  return Reflect.getOwnPropertyDescriptor(current, prop);
269
+ },
270
+ getPrototypeOf() {
271
+ const current = itemSignal.value;
272
+ if (current == null)
273
+ return null;
274
+ return Object.getPrototypeOf(current);
237
275
  }
238
276
  });
239
277
  }
@@ -242,7 +280,12 @@ function __list(container, items, keyFn, renderFn) {
242
280
  const nodeMap = new Map;
243
281
  const scopeMap = new Map;
244
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
+ }
245
287
  const isHydrationRun = getIsHydrating();
288
+ let startOffset = isHydrationRun ? -1 : container.childNodes.length;
246
289
  const outerScope = pushScope();
247
290
  let isFirstRun = true;
248
291
  domEffect(() => {
@@ -250,19 +293,47 @@ function __list(container, items, keyFn, renderFn) {
250
293
  if (isFirstRun && isHydrationRun) {
251
294
  isFirstRun = false;
252
295
  for (const [i, item] of newItems.entries()) {
253
- const key = keyFn(item, i);
254
- const itemSig = signal(item);
255
- const proxy = createItemProxy(itemSig);
296
+ const key = keyFn ? keyFn(item, i) : i;
256
297
  const scope = pushScope();
257
- 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
+ }
258
308
  popScope();
259
- nodeMap.set(key, node);
260
309
  scopeMap.set(key, scope);
261
- itemSignalMap.set(key, itemSig);
262
310
  }
311
+ startOffset = container.childNodes.length - nodeMap.size;
263
312
  return;
264
313
  }
265
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
+ }
266
337
  const newKeySet = new Set(newItems.map((item, i) => keyFn(item, i)));
267
338
  for (const [key, node] of nodeMap) {
268
339
  if (!newKeySet.has(key)) {
@@ -298,11 +369,12 @@ function __list(container, items, keyFn, renderFn) {
298
369
  desiredNodes.push(node);
299
370
  }
300
371
  for (const [i, desiredNode] of desiredNodes.entries()) {
301
- const currentChild = container.childNodes[i];
372
+ const currentChild = container.childNodes[startOffset + i];
302
373
  if (currentChild !== desiredNode) {
303
374
  container.insertBefore(desiredNode, currentChild ?? null);
304
375
  }
305
376
  }
377
+ fixUpSelectValue(container);
306
378
  });
307
379
  popScope();
308
380
  const wrapper = () => {
@@ -315,6 +387,56 @@ function __list(container, items, keyFn, renderFn) {
315
387
  _tryOnCleanup(wrapper);
316
388
  return wrapper;
317
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
+ }
318
440
  export {
319
441
  stopSignalCollection,
320
442
  startSignalCollection,
@@ -349,13 +471,18 @@ export {
349
471
  __text,
350
472
  styleObjectToString as __styleStr,
351
473
  __staticText,
474
+ __spread,
352
475
  __show,
476
+ __pushMountFrame,
477
+ __prop,
353
478
  __on,
354
479
  __list,
355
480
  __insert,
481
+ __flushMountFrame,
356
482
  __exitChildren,
357
483
  __enterChildren,
358
484
  __element,
485
+ __discardMountFrame,
359
486
  __conditional,
360
487
  __classList,
361
488
  __child,
@@ -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,11 +1,12 @@
1
1
  import {
2
2
  query,
3
3
  queryMatch
4
- } from "../../shared/chunk-szk0hyjg.js";
4
+ } from "../../shared/chunk-4gen306a.js";
5
5
  import"../../shared/chunk-jrtrk5z4.js";
6
- import"../../shared/chunk-c61572xp.js";
7
- import"../../shared/chunk-bybgyjye.js";
8
- import"../../shared/chunk-2qe6aqhb.js";
6
+ import"../../shared/chunk-2y9f9j62.js";
7
+ import"../../shared/chunk-2eh4p2n7.js";
8
+ import"../../shared/chunk-da2w7j7w.js";
9
+ import"../../shared/chunk-656n0x6y.js";
9
10
 
10
11
  // src/query/public.ts
11
12
  import { isQueryDescriptor } from "@vertz/fetch";
@@ -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,26 +6,25 @@ import {
6
6
  createLink,
7
7
  parseSearchParams,
8
8
  useSearchParams
9
- } from "../../shared/chunk-67z8b0q8.js";
10
- import"../../shared/chunk-kjwp5q5s.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
- } from "../../shared/chunk-7g722pdh.js";
13
+ } from "../../shared/chunk-jtma4sh4.js";
15
14
  import {
16
15
  defineRoutes
17
16
  } from "../../shared/chunk-am9zaw4h.js";
18
17
  import"../../shared/chunk-jrtrk5z4.js";
19
- import"../../shared/chunk-vwz86vg9.js";
20
- import"../../shared/chunk-prj7nm08.js";
21
- import"../../shared/chunk-c61572xp.js";
18
+ import"../../shared/chunk-mbnda3pv.js";
19
+ import"../../shared/chunk-h1fsr8kv.js";
20
+ import"../../shared/chunk-2y9f9j62.js";
22
21
  import {
23
22
  RouterContext,
24
23
  useParams,
25
24
  useRouter
26
- } from "../../shared/chunk-4cmt1ve8.js";
27
- import"../../shared/chunk-bybgyjye.js";
28
- import"../../shared/chunk-2qe6aqhb.js";
25
+ } from "../../shared/chunk-f4d5nphq.js";
26
+ import"../../shared/chunk-da2w7j7w.js";
27
+ import"../../shared/chunk-656n0x6y.js";
29
28
  export {
30
29
  useSearchParams,
31
30
  useRouter,