@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
package/dist/src/index.js CHANGED
@@ -24,21 +24,27 @@ import {
24
24
  slideOutToTop,
25
25
  zoomIn,
26
26
  zoomOut
27
- } from "../shared/chunk-pdqr78k9.js";
27
+ } from "../shared/chunk-18frwfc4.js";
28
28
  import {
29
+ ErrorBoundary,
29
30
  Link,
30
31
  Outlet,
31
32
  OutletContext,
32
33
  RouterView,
33
34
  createLink,
35
+ getCurrentErrorHandler,
34
36
  parseSearchParams,
35
37
  useSearchParams
36
- } from "../shared/chunk-67z8b0q8.js";
37
- import"../shared/chunk-kjwp5q5s.js";
38
- import"../shared/chunk-4xkw6h1s.js";
38
+ } from "../shared/chunk-2wag9c7v.js";
39
+ import {
40
+ beginDeferringMounts,
41
+ discardDeferredMounts,
42
+ flushDeferredMounts,
43
+ onMount
44
+ } from "../shared/chunk-ge2e6y2s.js";
39
45
  import {
40
46
  createRouter
41
- } from "../shared/chunk-7g722pdh.js";
47
+ } from "../shared/chunk-jtma4sh4.js";
42
48
  import {
43
49
  defineRoutes
44
50
  } from "../shared/chunk-am9zaw4h.js";
@@ -47,7 +53,7 @@ import {
47
53
  form,
48
54
  formDataToObject,
49
55
  validate
50
- } from "../shared/chunk-yb4a0smw.js";
56
+ } from "../shared/chunk-4gmtsf6v.js";
51
57
  import {
52
58
  EntityStore,
53
59
  FieldSelectionTracker,
@@ -56,12 +62,11 @@ import {
56
62
  getMutationEventBus,
57
63
  getQueryEnvelopeStore,
58
64
  getRelationSchema,
59
- invalidate,
60
65
  query,
61
66
  queryMatch,
62
67
  registerRelationSchema,
63
68
  resetRelationSchemas_TEST_ONLY
64
- } from "../shared/chunk-szk0hyjg.js";
69
+ } from "../shared/chunk-4gen306a.js";
65
70
  import"../shared/chunk-jrtrk5z4.js";
66
71
  import {
67
72
  ThemeProvider,
@@ -78,30 +83,35 @@ import {
78
83
  resolveChildren,
79
84
  s,
80
85
  variants
81
- } from "../shared/chunk-pq8khh47.js";
86
+ } from "../shared/chunk-t3rnfxc0.js";
82
87
  import {
83
88
  __append,
84
89
  __element,
85
90
  __enterChildren,
86
91
  __exitChildren,
92
+ __insert,
87
93
  __staticText
88
- } from "../shared/chunk-vwz86vg9.js";
89
- import"../shared/chunk-prj7nm08.js";
94
+ } from "../shared/chunk-mbnda3pv.js";
95
+ import"../shared/chunk-h1fsr8kv.js";
90
96
  import {
91
97
  RENDER_NODE_BRAND,
92
98
  createDOMAdapter,
93
99
  getAdapter,
94
100
  isRenderNode,
95
101
  setAdapter
96
- } from "../shared/chunk-c61572xp.js";
102
+ } from "../shared/chunk-2y9f9j62.js";
97
103
  import {
98
104
  RouterContext,
99
105
  useParams,
100
106
  useRouter
101
- } from "../shared/chunk-4cmt1ve8.js";
107
+ } from "../shared/chunk-f4d5nphq.js";
108
+ import {
109
+ invalidate,
110
+ invalidateTenantQueries
111
+ } from "../shared/chunk-2eh4p2n7.js";
102
112
  import {
103
113
  isBrowser
104
- } from "../shared/chunk-bybgyjye.js";
114
+ } from "../shared/chunk-da2w7j7w.js";
105
115
  import {
106
116
  DisposalScopeError,
107
117
  _tryOnCleanup,
@@ -117,6 +127,7 @@ import {
117
127
  getContextScope,
118
128
  getIsHydrating,
119
129
  getSSRContext,
130
+ onCleanup,
120
131
  popScope,
121
132
  pushScope,
122
133
  runCleanups,
@@ -125,80 +136,76 @@ import {
125
136
  startHydration,
126
137
  untrack,
127
138
  useContext
128
- } from "../shared/chunk-2qe6aqhb.js";
129
- // src/component/error-boundary-context.ts
130
- var handlerStack = [];
131
- function pushErrorHandler(handler) {
132
- handlerStack.push(handler);
133
- }
134
- function popErrorHandler() {
135
- handlerStack.pop();
136
- }
137
- function getCurrentErrorHandler() {
138
- if (handlerStack.length === 0) {
139
- return;
140
- }
141
- return handlerStack[handlerStack.length - 1];
142
- }
143
-
144
- // src/component/error-boundary.ts
145
- function toError(value) {
146
- if (value instanceof Error) {
147
- return value;
148
- }
149
- return new Error(String(value));
139
+ } from "../shared/chunk-656n0x6y.js";
140
+ // src/component/default-error-fallback.ts
141
+ function DefaultErrorFallback({ error, retry }) {
142
+ const container = document.createElement("div");
143
+ container.setAttribute("data-testid", "error-fallback");
144
+ Object.assign(container.style, {
145
+ display: "flex",
146
+ flexDirection: "column",
147
+ alignItems: "center",
148
+ justifyContent: "center",
149
+ padding: "2rem",
150
+ textAlign: "center"
151
+ });
152
+ const heading = document.createElement("h2");
153
+ heading.textContent = "Something went wrong";
154
+ Object.assign(heading.style, {
155
+ fontSize: "1.25rem",
156
+ fontWeight: "600",
157
+ marginBottom: "0.5rem",
158
+ color: "inherit"
159
+ });
160
+ const message = document.createElement("p");
161
+ message.textContent = error.message;
162
+ Object.assign(message.style, {
163
+ fontSize: "0.875rem",
164
+ opacity: "0.7",
165
+ marginBottom: "1rem",
166
+ maxWidth: "24rem"
167
+ });
168
+ const button = document.createElement("button");
169
+ button.type = "button";
170
+ button.setAttribute("data-testid", "error-retry");
171
+ button.textContent = "Try again";
172
+ Object.assign(button.style, {
173
+ padding: "0.5rem 1rem",
174
+ borderRadius: "0.375rem",
175
+ border: "1px solid currentColor",
176
+ background: "transparent",
177
+ cursor: "pointer",
178
+ fontSize: "0.875rem"
179
+ });
180
+ button.addEventListener("click", retry);
181
+ container.appendChild(heading);
182
+ container.appendChild(message);
183
+ container.appendChild(button);
184
+ return container;
150
185
  }
151
- function ErrorBoundary(props) {
152
- function handleAsyncError(error, placeholder) {
153
- const fallbackNode = props.fallback(error, retry);
154
- function retry() {
155
- try {
156
- const retryResult = props.children();
157
- if (fallbackNode.parentNode) {
158
- fallbackNode.parentNode.replaceChild(retryResult, fallbackNode);
159
- }
160
- } catch (_retryThrown) {}
161
- }
162
- if (placeholder.parentNode) {
163
- placeholder.parentNode.replaceChild(fallbackNode, placeholder);
164
- }
186
+ // src/component/foreign.ts
187
+ function Foreign({
188
+ tag = "div",
189
+ onReady,
190
+ html,
191
+ id,
192
+ className,
193
+ style
194
+ }) {
195
+ const el = __element(tag);
196
+ if (id)
197
+ el.id = id;
198
+ if (className)
199
+ el.setAttribute("class", className);
200
+ if (style)
201
+ Object.assign(el.style, style);
202
+ if (html && getSSRContext()) {
203
+ el.innerHTML = html;
165
204
  }
166
- try {
167
- pushErrorHandler(handleAsyncError);
168
- const result = props.children();
169
- popErrorHandler();
170
- return result;
171
- } catch (thrown) {
172
- let retry = function() {
173
- try {
174
- const retryResult = props.children();
175
- if (fallbackNode.parentNode) {
176
- fallbackNode.parentNode.replaceChild(retryResult, fallbackNode);
177
- }
178
- } catch (_retryThrown) {}
179
- };
180
- popErrorHandler();
181
- const error = toError(thrown);
182
- const fallbackNode = props.fallback(error, retry);
183
- return fallbackNode;
184
- }
185
- }
186
- // src/component/lifecycle.ts
187
- function onMount(callback) {
188
- if (getSSRContext())
189
- return;
190
- const scope = pushScope();
191
- try {
192
- const cleanup = untrack(callback);
193
- if (typeof cleanup === "function") {
194
- _tryOnCleanup(cleanup);
195
- }
196
- } finally {
197
- popScope();
198
- if (scope.length > 0) {
199
- _tryOnCleanup(() => runCleanups(scope));
200
- }
205
+ if (onReady && !getSSRContext()) {
206
+ onMount(() => onReady(el));
201
207
  }
208
+ return el;
202
209
  }
203
210
  // src/dom/list-transition.ts
204
211
  function createItemProxy(itemSignal) {
@@ -459,7 +466,7 @@ function ref() {
459
466
  function isPromise(value) {
460
467
  return value != null && typeof value === "object" && typeof value.then === "function";
461
468
  }
462
- function toError2(value) {
469
+ function toError(value) {
463
470
  if (value instanceof Error) {
464
471
  return value;
465
472
  }
@@ -491,17 +498,26 @@ function Suspense(props) {
491
498
  }
492
499
  } catch (retryError) {
493
500
  if (!isPromise(retryError)) {
494
- propagateError(toError2(retryError), placeholder, errorHandler);
501
+ propagateError(toError(retryError), placeholder, errorHandler);
495
502
  }
496
503
  }
497
504
  }).catch((error) => {
498
- propagateError(toError2(error), placeholder, errorHandler);
505
+ propagateError(toError(error), placeholder, errorHandler);
499
506
  });
500
507
  return placeholder;
501
508
  }
502
509
  }
503
510
  // src/dialog/dialog-stack.ts
504
511
  var DialogStackContext = createContext(undefined, "@vertz/ui::DialogStackContext");
512
+ var DialogHandleContext = createContext(undefined, "@vertz/ui::DialogHandleContext");
513
+ var DialogIdContext = createContext(undefined, "@vertz/ui::DialogIdContext");
514
+ function useDialog() {
515
+ const handle = useContext(DialogHandleContext);
516
+ if (!handle) {
517
+ throw new Error("useDialog() must be called within a dialog opened via DialogStack");
518
+ }
519
+ return handle;
520
+ }
505
521
  function useDialogStack() {
506
522
  const stack = useContext(DialogStackContext);
507
523
  if (!stack) {
@@ -509,10 +525,13 @@ function useDialogStack() {
509
525
  }
510
526
  const capturedScope = getContextScope();
511
527
  return {
512
- open(component, props) {
513
- return stack.openWithScope(component, props, capturedScope);
528
+ open(component, props, options) {
529
+ return stack.openWithScope(component, props, capturedScope, options);
514
530
  },
515
531
  openWithScope: stack.openWithScope,
532
+ confirm(opts) {
533
+ return stack.confirm(opts);
534
+ },
516
535
  get size() {
517
536
  return stack.size;
518
537
  },
@@ -521,25 +540,84 @@ function useDialogStack() {
521
540
  }
522
541
  };
523
542
  }
543
+ function DialogStackProvider({ children: children2 }) {
544
+ const container = __element("div", { "data-dialog-container": "" });
545
+ const stack = createDialogStack(container);
546
+ return DialogStackContext.Provider({
547
+ value: stack,
548
+ children: () => {
549
+ const frag = document.createDocumentFragment();
550
+ __insert(frag, children2);
551
+ frag.appendChild(container);
552
+ return frag;
553
+ }
554
+ });
555
+ }
556
+ function ConfirmDialogComponent({
557
+ title,
558
+ description,
559
+ confirm: confirmLabel = "Confirm",
560
+ cancel: cancelLabel = "Cancel",
561
+ intent = "primary",
562
+ dialog
563
+ }) {
564
+ const frag = document.createDocumentFragment();
565
+ const titleEl = document.createElement("h2");
566
+ titleEl.setAttribute("data-part", "title");
567
+ titleEl.textContent = title;
568
+ frag.appendChild(titleEl);
569
+ if (description) {
570
+ const descEl = document.createElement("p");
571
+ descEl.setAttribute("data-part", "description");
572
+ descEl.textContent = description;
573
+ frag.appendChild(descEl);
574
+ }
575
+ const footer = document.createElement("div");
576
+ footer.setAttribute("data-part", "footer");
577
+ const cancelBtn = document.createElement("button");
578
+ cancelBtn.setAttribute("type", "button");
579
+ cancelBtn.setAttribute("data-part", "confirm-cancel");
580
+ cancelBtn.textContent = cancelLabel;
581
+ cancelBtn.addEventListener("click", () => dialog.close(false));
582
+ const confirmBtn = document.createElement("button");
583
+ confirmBtn.setAttribute("type", "button");
584
+ confirmBtn.setAttribute("data-part", "confirm-action");
585
+ confirmBtn.setAttribute("data-intent", intent);
586
+ confirmBtn.textContent = confirmLabel;
587
+ confirmBtn.addEventListener("click", () => dialog.close(true));
588
+ footer.appendChild(cancelBtn);
589
+ footer.appendChild(confirmBtn);
590
+ frag.appendChild(footer);
591
+ return frag;
592
+ }
524
593
  function createDialogStack(container) {
525
594
  const entries = [];
526
595
  let nextId = 0;
527
- function open(component, props, capturedScope) {
596
+ function open(component, props, capturedScope, options) {
528
597
  return new Promise((resolve) => {
529
598
  if (entries.length > 0) {
530
- entries[entries.length - 1].wrapper.setAttribute("data-state", "background");
599
+ entries[entries.length - 1].dialogEl.setAttribute("data-state", "background");
531
600
  }
532
- const wrapper = document.createElement("div");
533
- wrapper.setAttribute("data-dialog-wrapper", "");
534
- wrapper.setAttribute("data-state", "open");
535
- wrapper.setAttribute("data-dialog-depth", "0");
601
+ const dialogId = `dlg-${nextId}`;
602
+ const dialogEl = document.createElement("dialog");
603
+ dialogEl.setAttribute("data-dialog-wrapper", "");
604
+ dialogEl.setAttribute("data-state", "open");
605
+ dialogEl.setAttribute("data-dialog-depth", "0");
606
+ const panel = document.createElement("div");
607
+ panel.setAttribute("data-part", "panel");
608
+ panel.setAttribute("role", "dialog");
609
+ panel.setAttribute("aria-modal", "true");
610
+ panel.setAttribute("aria-labelledby", `${dialogId}-title`);
611
+ panel.setAttribute("aria-describedby", `${dialogId}-desc`);
612
+ dialogEl.appendChild(panel);
536
613
  const entry = {
537
614
  id: nextId++,
538
- wrapper,
615
+ dialogEl,
616
+ panel,
539
617
  node: null,
540
618
  resolve,
541
619
  cleanups: [],
542
- dismissible: true,
620
+ dismissible: options?.dismissible !== false,
543
621
  settled: false
544
622
  };
545
623
  const prevScope = setContextScope(capturedScope ?? null);
@@ -549,60 +627,93 @@ function createDialogStack(container) {
549
627
  closeEntry(entry, args[0]);
550
628
  }
551
629
  };
552
- entry.node = component({ ...props, dialog: handle });
630
+ DialogHandleContext.Provider(handle, () => {
631
+ DialogIdContext.Provider(dialogId, () => {
632
+ entry.node = component({ ...props, dialog: handle });
633
+ });
634
+ });
553
635
  entry.cleanups = [...scope];
554
636
  popScope();
555
637
  setContextScope(prevScope);
556
- if (entry.dismissible) {
557
- wrapper.addEventListener("keydown", (e) => {
558
- if (e.key === "Escape" && entries[entries.length - 1] === entry) {
559
- e.preventDefault();
560
- e.stopPropagation();
561
- dismissEntry(entry);
562
- }
563
- });
564
- }
565
- wrapper.appendChild(entry.node);
566
- container.appendChild(wrapper);
638
+ dialogEl.addEventListener("cancel", (e) => {
639
+ e.preventDefault();
640
+ if (entry.dismissible && entries[entries.length - 1] === entry) {
641
+ dismissEntry(entry);
642
+ }
643
+ });
644
+ dialogEl.addEventListener("click", (e) => {
645
+ if (!entry.dismissible)
646
+ return;
647
+ const rect = panel.getBoundingClientRect();
648
+ const isOutside = e.clientX < rect.left || e.clientX > rect.right || e.clientY < rect.top || e.clientY > rect.bottom;
649
+ if (isOutside) {
650
+ dismissEntry(entry);
651
+ }
652
+ });
653
+ panel.appendChild(entry.node);
654
+ const titleTarget = panel.querySelector('[data-part="title"]');
655
+ if (titleTarget && !titleTarget.id)
656
+ titleTarget.id = `${dialogId}-title`;
657
+ const descTarget = panel.querySelector('[data-part="description"]');
658
+ if (descTarget && !descTarget.id)
659
+ descTarget.id = `${dialogId}-desc`;
660
+ container.appendChild(dialogEl);
567
661
  entries.push(entry);
568
662
  updateDepthAttributes();
663
+ dialogEl.showModal();
569
664
  });
570
665
  }
571
- function closeEntry(entry, result) {
666
+ function removeEntry(entry, resolution) {
572
667
  if (entry.settled)
573
668
  return;
574
669
  const idx = entries.indexOf(entry);
575
670
  if (idx === -1)
576
671
  return;
577
672
  entry.settled = true;
578
- entry.wrapper.setAttribute("data-state", "closed");
579
- onAnimationsComplete(entry.wrapper, () => {
673
+ entry.dialogEl.setAttribute("data-state", "closed");
674
+ entry.dialogEl.setAttribute("inert", "");
675
+ onAnimationsComplete(entry.dialogEl, () => {
580
676
  runCleanups(entry.cleanups);
581
- if (entry.wrapper.parentNode === container) {
582
- container.removeChild(entry.wrapper);
677
+ if (entry.dialogEl.open) {
678
+ entry.dialogEl.close();
679
+ }
680
+ if (entry.dialogEl.parentNode === container) {
681
+ container.removeChild(entry.dialogEl);
583
682
  }
584
683
  const entryIdx = entries.indexOf(entry);
585
684
  if (entryIdx !== -1) {
586
685
  entries.splice(entryIdx, 1);
587
686
  }
588
687
  if (entries.length > 0) {
589
- entries[entries.length - 1].wrapper.setAttribute("data-state", "open");
688
+ entries[entries.length - 1].dialogEl.setAttribute("data-state", "open");
590
689
  }
591
690
  updateDepthAttributes();
592
- entry.resolve({ ok: true, data: result });
691
+ entry.resolve(resolution);
593
692
  });
594
693
  }
694
+ function closeEntry(entry, result) {
695
+ removeEntry(entry, { ok: true, data: result });
696
+ }
697
+ function dismissEntry(entry) {
698
+ removeEntry(entry, { ok: false });
699
+ }
595
700
  function updateDepthAttributes() {
596
701
  for (let i = 0;i < entries.length; i++) {
597
- entries[i].wrapper.setAttribute("data-dialog-depth", String(entries.length - 1 - i));
702
+ entries[i].dialogEl.setAttribute("data-dialog-depth", String(entries.length - 1 - i));
598
703
  }
599
704
  }
600
705
  return {
601
- open(component, props) {
602
- return open(component, props);
706
+ open(component, props, options) {
707
+ return open(component, props, undefined, options);
708
+ },
709
+ openWithScope(component, props, scope, options) {
710
+ return open(component, props, scope, options);
603
711
  },
604
- openWithScope(component, props, scope) {
605
- return open(component, props, scope);
712
+ async confirm(opts) {
713
+ const result = await open(ConfirmDialogComponent, opts, undefined, {
714
+ dismissible: opts.dismissible ?? false
715
+ });
716
+ return result.ok ? result.data : false;
606
717
  },
607
718
  get size() {
608
719
  return entries.length;
@@ -613,30 +724,118 @@ function createDialogStack(container) {
613
724
  }
614
725
  }
615
726
  };
616
- function dismissEntry(entry) {
617
- if (entry.settled)
618
- return;
619
- const idx = entries.indexOf(entry);
620
- if (idx === -1)
621
- return;
622
- entry.settled = true;
623
- entry.wrapper.setAttribute("data-state", "closed");
624
- onAnimationsComplete(entry.wrapper, () => {
625
- runCleanups(entry.cleanups);
626
- if (entry.wrapper.parentNode === container) {
627
- container.removeChild(entry.wrapper);
628
- }
629
- const entryIdx = entries.indexOf(entry);
630
- if (entryIdx !== -1) {
631
- entries.splice(entryIdx, 1);
632
- }
633
- if (entries.length > 0) {
634
- entries[entries.length - 1].wrapper.setAttribute("data-state", "open");
635
- }
636
- updateDepthAttributes();
637
- entry.resolve({ ok: false });
638
- });
727
+ }
728
+ // src/format/relative-time.ts
729
+ function toDate(date) {
730
+ if (date instanceof Date)
731
+ return date;
732
+ if (typeof date === "number")
733
+ return new Date(date);
734
+ return new Date(date);
735
+ }
736
+ var rtfCache = new Map;
737
+ function getFormatter(locale, numeric = "auto") {
738
+ const key = `${locale ?? ""}:${numeric}`;
739
+ let rtf = rtfCache.get(key);
740
+ if (!rtf) {
741
+ rtf = new Intl.RelativeTimeFormat(locale, { numeric, style: "long" });
742
+ rtfCache.set(key, rtf);
743
+ }
744
+ return rtf;
745
+ }
746
+ function formatRelativeTime(date, options) {
747
+ const now = options?.now ?? new Date;
748
+ const d = toDate(date);
749
+ if (Number.isNaN(d.getTime())) {
750
+ throw new Error(`formatRelativeTime: invalid date input: ${String(date)}`);
751
+ }
752
+ const diffMs = now.getTime() - d.getTime();
753
+ const diffSec = Math.floor(Math.abs(diffMs) / 1000);
754
+ const locale = options?.locale;
755
+ const numeric = options?.numeric ?? "auto";
756
+ const rtf = getFormatter(locale, numeric);
757
+ const sign = diffMs >= 0 ? -1 : 1;
758
+ if (diffSec < 10) {
759
+ return rtf.format(0, "second");
760
+ }
761
+ if (diffSec < 60) {
762
+ return rtf.format(sign * diffSec, "second");
763
+ }
764
+ const diffMin = Math.floor(diffSec / 60);
765
+ if (diffMin < 60) {
766
+ return rtf.format(sign * diffMin, "minute");
767
+ }
768
+ const diffHours = Math.floor(diffMin / 60);
769
+ if (diffHours < 24) {
770
+ return rtf.format(sign * diffHours, "hour");
771
+ }
772
+ const diffDays = Math.floor(diffHours / 24);
773
+ if (diffDays < 7) {
774
+ return rtf.format(sign * diffDays, "day");
775
+ }
776
+ if (diffDays < 30) {
777
+ const diffWeeks = Math.floor(diffDays / 7);
778
+ return rtf.format(sign * diffWeeks, "week");
779
+ }
780
+ if (diffDays < 365) {
781
+ const diffMonths = Math.floor(diffDays / 30);
782
+ return rtf.format(sign * diffMonths, "month");
639
783
  }
784
+ const diffYears = Math.floor(diffDays / 365);
785
+ return rtf.format(sign * diffYears, "year");
786
+ }
787
+ // src/format/relative-time-component.ts
788
+ function getAdaptiveInterval(date) {
789
+ const d = toDate(date);
790
+ const elapsedMs = Math.abs(Date.now() - d.getTime());
791
+ const elapsedSec = elapsedMs / 1000;
792
+ if (elapsedSec < 60)
793
+ return 1e4;
794
+ if (elapsedSec < 3600)
795
+ return 60000;
796
+ if (elapsedSec < 86400)
797
+ return 3600000;
798
+ return null;
799
+ }
800
+ function RelativeTime({
801
+ date,
802
+ locale,
803
+ numeric,
804
+ updateInterval,
805
+ className,
806
+ title
807
+ }) {
808
+ const d = toDate(date);
809
+ const isoString = d.toISOString();
810
+ const opts = { locale, numeric };
811
+ const el = document.createElement("time");
812
+ el.setAttribute("datetime", isoString);
813
+ el.textContent = formatRelativeTime(date, opts);
814
+ if (title !== false) {
815
+ el.title = typeof title === "string" ? title : new Intl.DateTimeFormat(locale, {
816
+ dateStyle: "long",
817
+ timeStyle: "medium"
818
+ }).format(d);
819
+ }
820
+ if (className) {
821
+ el.className = className;
822
+ }
823
+ onMount(() => {
824
+ let timerId;
825
+ function tick() {
826
+ el.textContent = formatRelativeTime(date, opts);
827
+ const interval = updateInterval ?? getAdaptiveInterval(date);
828
+ if (interval !== null) {
829
+ timerId = setTimeout(tick, interval);
830
+ }
831
+ }
832
+ const initialInterval = updateInterval ?? getAdaptiveInterval(date);
833
+ if (initialInterval !== null) {
834
+ timerId = setTimeout(tick, initialInterval);
835
+ }
836
+ return () => clearTimeout(timerId);
837
+ });
838
+ return el;
640
839
  }
641
840
  // src/image/config.ts
642
841
  var optimizerBaseUrl = null;
@@ -788,11 +987,29 @@ function mount(app, options) {
788
987
  }
789
988
  if (root.firstChild) {
790
989
  const scope2 = pushScope();
990
+ let hydrationOk = false;
791
991
  try {
992
+ beginDeferringMounts();
792
993
  startHydration(root);
793
994
  app();
794
995
  endHydration();
996
+ hydrationOk = true;
997
+ } catch (e) {
998
+ discardDeferredMounts();
999
+ discardDeferredEffects();
1000
+ endHydration();
795
1001
  popScope();
1002
+ runCleanups(scope2);
1003
+ if (typeof process !== "undefined" && true) {
1004
+ console.warn("[mount] Hydration failed — re-rendering from scratch (no data loss):", e);
1005
+ }
1006
+ }
1007
+ if (hydrationOk) {
1008
+ try {
1009
+ flushDeferredMounts();
1010
+ } finally {
1011
+ popScope();
1012
+ }
796
1013
  options?.onMount?.(root);
797
1014
  const handle2 = {
798
1015
  unmount: () => {
@@ -804,14 +1021,6 @@ function mount(app, options) {
804
1021
  };
805
1022
  mountedRoots.set(root, handle2);
806
1023
  return handle2;
807
- } catch (e) {
808
- discardDeferredEffects();
809
- endHydration();
810
- popScope();
811
- runCleanups(scope2);
812
- if (typeof process !== "undefined" && true) {
813
- console.warn("[mount] Hydration failed — re-rendering from scratch (no data loss):", e);
814
- }
815
1024
  }
816
1025
  }
817
1026
  const scope = pushScope();
@@ -883,6 +1092,7 @@ export {
883
1092
  useRouter,
884
1093
  useParams,
885
1094
  useDialogStack,
1095
+ useDialog,
886
1096
  useContext,
887
1097
  untrack,
888
1098
  slideOutToTop,
@@ -907,12 +1117,14 @@ export {
907
1117
  parseSearchParams,
908
1118
  palettes,
909
1119
  onMount,
1120
+ onCleanup,
910
1121
  onAnimationsComplete,
911
1122
  mount,
912
1123
  keyframes,
913
1124
  isRenderNode,
914
1125
  isQueryDescriptor,
915
1126
  isBrowser,
1127
+ invalidateTenantQueries,
916
1128
  invalidate,
917
1129
  injectCSS,
918
1130
  hydrateIslands,
@@ -923,6 +1135,7 @@ export {
923
1135
  getInjectedCSS,
924
1136
  getEntityStore,
925
1137
  getAdapter,
1138
+ formatRelativeTime,
926
1139
  formDataToObject,
927
1140
  form,
928
1141
  font,
@@ -957,6 +1170,7 @@ export {
957
1170
  Suspense,
958
1171
  RouterView,
959
1172
  RouterContext,
1173
+ RelativeTime,
960
1174
  RENDER_NODE_BRAND,
961
1175
  QueryEnvelopeStore,
962
1176
  Presence,
@@ -966,11 +1180,16 @@ export {
966
1180
  Link,
967
1181
  Island,
968
1182
  Image,
1183
+ Foreign,
969
1184
  FieldSelectionTracker,
970
1185
  ErrorBoundary,
971
1186
  EntityStore,
972
1187
  DisposalScopeError,
1188
+ DialogStackProvider,
973
1189
  DialogStackContext,
1190
+ DialogIdContext,
1191
+ DialogHandleContext,
1192
+ DefaultErrorFallback,
974
1193
  ANIMATION_EASING,
975
1194
  ANIMATION_DURATION
976
1195
  };