@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
@@ -0,0 +1,102 @@
1
+ import {
2
+ _tryOnCleanup,
3
+ getSSRContext,
4
+ popScope,
5
+ pushScope,
6
+ runCleanups,
7
+ untrack
8
+ } from "./chunk-656n0x6y.js";
9
+
10
+ // src/component/lifecycle.ts
11
+ var mountFrames = [];
12
+ var postHydrationQueue = null;
13
+ function __pushMountFrame() {
14
+ mountFrames.push([]);
15
+ return mountFrames.length;
16
+ }
17
+ function __flushMountFrame() {
18
+ const frame = mountFrames.pop();
19
+ if (!frame)
20
+ return;
21
+ if (postHydrationQueue) {
22
+ for (const cb of frame) {
23
+ postHydrationQueue.push(cb);
24
+ }
25
+ return;
26
+ }
27
+ let firstError;
28
+ for (const cb of frame) {
29
+ try {
30
+ cb();
31
+ } catch (e) {
32
+ if (firstError === undefined)
33
+ firstError = e;
34
+ }
35
+ }
36
+ if (firstError !== undefined)
37
+ throw firstError;
38
+ }
39
+ function __discardMountFrame(expectedDepth) {
40
+ if (mountFrames.length === expectedDepth) {
41
+ mountFrames.pop();
42
+ }
43
+ }
44
+ function beginDeferringMounts() {
45
+ if (!postHydrationQueue) {
46
+ postHydrationQueue = [];
47
+ }
48
+ }
49
+ function flushDeferredMounts() {
50
+ const queue = postHydrationQueue;
51
+ postHydrationQueue = null;
52
+ if (!queue)
53
+ return;
54
+ let firstError;
55
+ for (const cb of queue) {
56
+ try {
57
+ cb();
58
+ } catch (e) {
59
+ if (firstError === undefined)
60
+ firstError = e;
61
+ }
62
+ }
63
+ if (firstError !== undefined)
64
+ throw firstError;
65
+ }
66
+ function discardDeferredMounts() {
67
+ postHydrationQueue = null;
68
+ }
69
+ function onMount(callback) {
70
+ if (getSSRContext())
71
+ return;
72
+ const frame = mountFrames[mountFrames.length - 1];
73
+ if (frame) {
74
+ frame.push(() => executeOnMount(callback));
75
+ } else {
76
+ executeOnMount(callback);
77
+ }
78
+ }
79
+ function executeOnMount(callback) {
80
+ const scope = pushScope();
81
+ try {
82
+ const cleanup = untrack(callback);
83
+ if (typeof cleanup === "function") {
84
+ _tryOnCleanup(cleanup);
85
+ }
86
+ } finally {
87
+ popScope();
88
+ if (scope.length > 0) {
89
+ _tryOnCleanup(() => runCleanups(scope));
90
+ }
91
+ }
92
+ }
93
+
94
+ // src/dom/events.ts
95
+ function __on(el, event, handler) {
96
+ el.addEventListener(event, handler);
97
+ const cleanup = () => el.removeEventListener(event, handler);
98
+ _tryOnCleanup(cleanup);
99
+ return cleanup;
100
+ }
101
+
102
+ export { __pushMountFrame, __flushMountFrame, __discardMountFrame, beginDeferringMounts, flushDeferredMounts, discardDeferredMounts, onMount, __on };
@@ -1,3 +1,69 @@
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
+
1
67
  // src/dom/style.ts
2
68
  function camelToKebab(prop) {
3
69
  const third = prop[2];
@@ -70,4 +136,4 @@ function styleObjectToString(style) {
70
136
  return parts.join("; ");
71
137
  }
72
138
 
73
- export { styleObjectToString };
139
+ export { SVG_NS, isSVGTag, normalizeSVGAttr, styleObjectToString };
@@ -7,11 +7,11 @@ import {
7
7
  } from "./chunk-jrtrk5z4.js";
8
8
  import {
9
9
  isBrowser
10
- } from "./chunk-bybgyjye.js";
10
+ } from "./chunk-da2w7j7w.js";
11
11
  import {
12
12
  getSSRContext,
13
13
  signal
14
- } from "./chunk-2qe6aqhb.js";
14
+ } from "./chunk-656n0x6y.js";
15
15
 
16
16
  // src/router/view-transitions.ts
17
17
  var transitionGen = 0;
@@ -1,12 +1,13 @@
1
1
  import {
2
2
  SVG_NS,
3
3
  isSVGTag,
4
- normalizeSVGAttr
5
- } from "./chunk-prj7nm08.js";
4
+ normalizeSVGAttr,
5
+ styleObjectToString
6
+ } from "./chunk-h1fsr8kv.js";
6
7
  import {
7
8
  getAdapter,
8
9
  isRenderNode
9
- } from "./chunk-c61572xp.js";
10
+ } from "./chunk-2y9f9j62.js";
10
11
  import {
11
12
  claimElement,
12
13
  claimText,
@@ -16,8 +17,11 @@ import {
16
17
  exitChildren,
17
18
  getIsHydrating,
18
19
  pauseHydration,
19
- resumeHydration
20
- } from "./chunk-2qe6aqhb.js";
20
+ popScope,
21
+ pushScope,
22
+ resumeHydration,
23
+ runCleanups
24
+ } from "./chunk-656n0x6y.js";
21
25
 
22
26
  // src/dom/element.ts
23
27
  var MAX_THUNK_DEPTH = 100;
@@ -73,20 +77,33 @@ function __child(fn) {
73
77
  }
74
78
  pauseHydration();
75
79
  try {
80
+ let childCleanups2 = [];
76
81
  wrapper.dispose = domEffect(() => {
77
- const value = fn();
78
- if (isRenderNode(value) && wrapper.childNodes.length === 1 && wrapper.firstChild === value) {
79
- return;
80
- }
81
- if (!isRenderNode(value) && value != null && typeof value !== "boolean" && wrapper.childNodes.length === 1 && wrapper.firstChild.nodeType === 3) {
82
- const text = typeof value === "string" ? value : String(value);
83
- wrapper.firstChild.data = text;
84
- return;
85
- }
86
- while (wrapper.firstChild) {
87
- wrapper.removeChild(wrapper.firstChild);
82
+ runCleanups(childCleanups2);
83
+ const needsPause = getIsHydrating();
84
+ if (needsPause)
85
+ pauseHydration();
86
+ try {
87
+ const scope = pushScope();
88
+ const value = fn();
89
+ popScope();
90
+ childCleanups2 = scope;
91
+ if (isRenderNode(value) && wrapper.childNodes.length === 1 && wrapper.firstChild === value) {
92
+ return;
93
+ }
94
+ if (!isRenderNode(value) && value != null && typeof value !== "boolean" && wrapper.childNodes.length === 1 && wrapper.firstChild.nodeType === 3) {
95
+ const text = typeof value === "string" ? value : String(value);
96
+ wrapper.firstChild.data = text;
97
+ return;
98
+ }
99
+ while (wrapper.firstChild) {
100
+ wrapper.removeChild(wrapper.firstChild);
101
+ }
102
+ resolveAndAppend(wrapper, value);
103
+ } finally {
104
+ if (needsPause)
105
+ resumeHydration();
88
106
  }
89
- resolveAndAppend(wrapper, value);
90
107
  });
91
108
  } finally {
92
109
  resumeHydration();
@@ -96,8 +113,13 @@ function __child(fn) {
96
113
  }
97
114
  wrapper = getAdapter().createElement("span");
98
115
  wrapper.style.display = "contents";
116
+ let childCleanups = [];
99
117
  wrapper.dispose = domEffect(() => {
118
+ runCleanups(childCleanups);
119
+ const scope = pushScope();
100
120
  const value = fn();
121
+ popScope();
122
+ childCleanups = scope;
101
123
  if (isRenderNode(value) && wrapper.childNodes.length === 1 && wrapper.firstChild === value) {
102
124
  return;
103
125
  }
@@ -205,4 +227,60 @@ function __exitChildren() {
205
227
  }
206
228
  }
207
229
 
208
- export { __text, __child, __insert, __element, __append, __staticText, __enterChildren, __exitChildren };
230
+ // src/dom/attributes.ts
231
+ function __attr(el, name, fn) {
232
+ return deferredDomEffect(() => {
233
+ const value = fn();
234
+ if (value == null || value === false) {
235
+ el.removeAttribute(name);
236
+ } else if (value === true) {
237
+ el.setAttribute(name, "");
238
+ } else if (name === "style" && typeof value === "object") {
239
+ el.setAttribute(name, styleObjectToString(value));
240
+ } else {
241
+ el.setAttribute(name, value);
242
+ }
243
+ });
244
+ }
245
+ function __prop(el, name, fn) {
246
+ return deferredDomEffect(() => {
247
+ const value = fn();
248
+ if (value == null) {
249
+ Reflect.set(el, name, typeof Reflect.get(el, name) === "boolean" ? false : "");
250
+ } else {
251
+ Reflect.set(el, name, value);
252
+ }
253
+ if (name === "selected") {
254
+ if (value) {
255
+ el.setAttribute(name, "");
256
+ } else {
257
+ el.removeAttribute(name);
258
+ }
259
+ }
260
+ });
261
+ }
262
+ function __show(el, fn) {
263
+ const originalDisplay = el.style.display;
264
+ return deferredDomEffect(() => {
265
+ el.style.display = fn() ? originalDisplay : "none";
266
+ });
267
+ }
268
+ function __classList(el, classMap) {
269
+ const disposers = [];
270
+ for (const [className, fn] of Object.entries(classMap)) {
271
+ disposers.push(deferredDomEffect(() => {
272
+ if (fn()) {
273
+ el.classList.add(className);
274
+ } else {
275
+ el.classList.remove(className);
276
+ }
277
+ }));
278
+ }
279
+ return () => {
280
+ for (const dispose of disposers) {
281
+ dispose();
282
+ }
283
+ };
284
+ }
285
+
286
+ export { __text, __child, __insert, __element, __append, __staticText, __enterChildren, __exitChildren, __attr, __prop, __show, __classList };
@@ -1,12 +1,13 @@
1
1
  import {
2
2
  __append,
3
+ __attr,
3
4
  __element,
4
5
  __enterChildren,
5
6
  __exitChildren
6
- } from "./chunk-vwz86vg9.js";
7
+ } from "./chunk-mbnda3pv.js";
7
8
  import {
8
9
  getSSRContext
9
- } from "./chunk-2qe6aqhb.js";
10
+ } from "./chunk-656n0x6y.js";
10
11
 
11
12
  // src/component/children.ts
12
13
  var MAX_RESOLVE_DEPTH = 100;
@@ -84,6 +85,9 @@ var PROPERTY_MAP = {
84
85
  decoration: { properties: ["text-decoration"], valueType: "raw" },
85
86
  list: { properties: ["list-style"], valueType: "raw" },
86
87
  ring: { properties: ["outline"], valueType: "ring" },
88
+ overflow: { properties: ["overflow"], valueType: "raw" },
89
+ "overflow-x": { properties: ["overflow-x"], valueType: "raw" },
90
+ "overflow-y": { properties: ["overflow-y"], valueType: "raw" },
87
91
  cursor: { properties: ["cursor"], valueType: "raw" },
88
92
  transition: { properties: ["transition"], valueType: "raw" },
89
93
  resize: { properties: ["resize"], valueType: "raw" },
@@ -120,7 +124,16 @@ var KEYWORD_MAP = {
120
124
  "whitespace-nowrap": [{ property: "white-space", value: "nowrap" }],
121
125
  "shrink-0": [{ property: "flex-shrink", value: "0" }],
122
126
  italic: [{ property: "font-style", value: "italic" }],
123
- "not-italic": [{ property: "font-style", value: "normal" }]
127
+ "not-italic": [{ property: "font-style", value: "normal" }],
128
+ "scale-0": [{ property: "transform", value: "scale(0)" }],
129
+ "scale-75": [{ property: "transform", value: "scale(0.75)" }],
130
+ "scale-90": [{ property: "transform", value: "scale(0.9)" }],
131
+ "scale-95": [{ property: "transform", value: "scale(0.95)" }],
132
+ "scale-100": [{ property: "transform", value: "scale(1)" }],
133
+ "scale-105": [{ property: "transform", value: "scale(1.05)" }],
134
+ "scale-110": [{ property: "transform", value: "scale(1.1)" }],
135
+ "scale-125": [{ property: "transform", value: "scale(1.25)" }],
136
+ "scale-150": [{ property: "transform", value: "scale(1.5)" }]
124
137
  };
125
138
  var DISPLAY_MAP = {
126
139
  flex: "flex",
@@ -169,13 +182,13 @@ var SPACING_SCALE = {
169
182
  };
170
183
  var RADIUS_SCALE = {
171
184
  none: "0",
172
- xs: "0.125rem",
173
- sm: "0.25rem",
174
- md: "0.375rem",
175
- lg: "0.5rem",
176
- xl: "0.75rem",
177
- "2xl": "1rem",
178
- "3xl": "1.5rem",
185
+ xs: "calc(var(--radius) * 0.33)",
186
+ sm: "calc(var(--radius) * 0.67)",
187
+ md: "var(--radius)",
188
+ lg: "calc(var(--radius) * 1.33)",
189
+ xl: "calc(var(--radius) * 2)",
190
+ "2xl": "calc(var(--radius) * 2.67)",
191
+ "3xl": "calc(var(--radius) * 4)",
179
192
  full: "9999px"
180
193
  };
181
194
  var SHADOW_SCALE = {
@@ -450,23 +463,38 @@ function resolveSpacing(value, property) {
450
463
  return scaled;
451
464
  throw new TokenResolveError(`Invalid spacing value '${value}' for '${property}'. Use a spacing scale number (0, 1, 2, 4, 8, etc.) or 'auto'.`, `${property}:${value}`);
452
465
  }
466
+ var OPACITY_PATTERN = /^(.+)\/(\d+)$/;
453
467
  function resolveColor(value, property) {
454
- const dotIndex = value.indexOf(".");
468
+ const opacityMatch = OPACITY_PATTERN.exec(value);
469
+ if (opacityMatch && opacityMatch[1] && opacityMatch[2]) {
470
+ const colorPart = opacityMatch[1];
471
+ const opacityStr = opacityMatch[2];
472
+ const opacity = Number(opacityStr);
473
+ if (opacity < 0 || opacity > 100) {
474
+ throw new TokenResolveError(`Invalid opacity '${opacityStr}' in '${value}'. Opacity must be an integer between 0 and 100.`, `${property}:${value}`);
475
+ }
476
+ const resolvedColor = resolveColorToken(colorPart, property, value);
477
+ return `color-mix(in oklch, ${resolvedColor} ${opacity}%, transparent)`;
478
+ }
479
+ return resolveColorToken(value, property, value);
480
+ }
481
+ function resolveColorToken(token, property, fullValue) {
482
+ const dotIndex = token.indexOf(".");
455
483
  if (dotIndex !== -1) {
456
- const namespace = value.substring(0, dotIndex);
457
- const shade = value.substring(dotIndex + 1);
484
+ const namespace = token.substring(0, dotIndex);
485
+ const shade = token.substring(dotIndex + 1);
458
486
  if (COLOR_NAMESPACES.has(namespace)) {
459
487
  return `var(--color-${namespace}-${shade})`;
460
488
  }
461
- throw new TokenResolveError(`Unknown color token '${value}'. Known namespaces: ${[...COLOR_NAMESPACES].join(", ")}`, `${property}:${value}`);
489
+ throw new TokenResolveError(`Unknown color token '${fullValue}'. Known namespaces: ${[...COLOR_NAMESPACES].join(", ")}`, `${property}:${fullValue}`);
462
490
  }
463
- if (COLOR_NAMESPACES.has(value)) {
464
- return `var(--color-${value})`;
491
+ if (COLOR_NAMESPACES.has(token)) {
492
+ return `var(--color-${token})`;
465
493
  }
466
- if (CSS_COLOR_KEYWORDS.has(value)) {
467
- return value;
494
+ if (CSS_COLOR_KEYWORDS.has(token)) {
495
+ return token;
468
496
  }
469
- throw new TokenResolveError(`Unknown color token '${value}'. Use a design token name (e.g. 'primary', 'background') or 'primary.700' for shades.`, `${property}:${value}`);
497
+ throw new TokenResolveError(`Unknown color token '${fullValue}'. Use a design token name (e.g. 'primary', 'background') or 'primary.700' for shades.`, `${property}:${fullValue}`);
470
498
  }
471
499
  function resolveRadius(value, property) {
472
500
  const scaled = RADIUS_SCALE[value];
@@ -480,6 +508,7 @@ function resolveShadow(value, property) {
480
508
  return scaled;
481
509
  throw new TokenResolveError(`Invalid shadow value '${value}' for '${property}'. Use: ${Object.keys(SHADOW_SCALE).join(", ")}`, `${property}:${value}`);
482
510
  }
511
+ var FRACTION_PATTERN = /^(\d+)\/(\d+)$/;
483
512
  function resolveSize(value, property) {
484
513
  const spaced = SPACING_SCALE[value];
485
514
  if (spaced !== undefined)
@@ -490,7 +519,18 @@ function resolveSize(value, property) {
490
519
  const keyword = SIZE_KEYWORDS[value];
491
520
  if (keyword !== undefined)
492
521
  return keyword;
493
- throw new TokenResolveError(`Invalid size value '${value}' for '${property}'. Use a spacing scale number or keyword (full, screen, min, max, fit, auto).`, `${property}:${value}`);
522
+ const fractionMatch = FRACTION_PATTERN.exec(value);
523
+ if (fractionMatch) {
524
+ const numerator = Number(fractionMatch[1]);
525
+ const denominator = Number(fractionMatch[2]);
526
+ if (denominator === 0) {
527
+ throw new TokenResolveError(`Invalid fraction '${value}' for '${property}'. Denominator cannot be zero.`, `${property}:${value}`);
528
+ }
529
+ const percent = numerator / denominator * 100;
530
+ const formatted = percent % 1 === 0 ? `${percent}` : percent.toFixed(6);
531
+ return `${formatted}%`;
532
+ }
533
+ throw new TokenResolveError(`Invalid size value '${value}' for '${property}'. Use a spacing scale number, keyword (full, screen, min, max, fit, auto), or fraction (1/2, 2/3, etc.).`, `${property}:${value}`);
494
534
  }
495
535
  function resolveAlignment(value, property) {
496
536
  const mapped = ALIGNMENT_MAP[value];
@@ -1058,10 +1098,11 @@ ${darkVars.join(`
1058
1098
  }
1059
1099
 
1060
1100
  // src/css/theme-provider.ts
1061
- function ThemeProvider({ theme = "light", children: children2 }) {
1062
- const el = __element("div", { "data-theme": theme });
1101
+ function ThemeProvider(props) {
1102
+ const el = __element("div");
1103
+ __attr(el, "data-theme", () => props.theme ?? "light");
1063
1104
  __enterChildren(el);
1064
- const nodes = resolveChildren(children2);
1105
+ const nodes = resolveChildren(props.children);
1065
1106
  for (const node of nodes) {
1066
1107
  __append(el, node);
1067
1108
  }
@@ -366,6 +366,40 @@ declare function createAccessProvider(): AccessContextValue;
366
366
  * Returns the built-in icon for known providers, or a generic fallback for unknown.
367
367
  */
368
368
  declare function getProviderIcon(providerId: string, size: number): string;
369
+ import { Result as Result3 } from "@vertz/fetch";
370
+ interface TenantInfo {
371
+ id: string;
372
+ name: string;
373
+ [key: string]: unknown;
374
+ }
375
+ interface ListTenantsResponse {
376
+ tenants: TenantInfo[];
377
+ currentTenantId?: string;
378
+ lastTenantId?: string;
379
+ resolvedDefaultId?: string;
380
+ }
381
+ interface TenantContextValue {
382
+ tenants: Signal<TenantInfo[]>;
383
+ currentTenantId: Signal<string | undefined>;
384
+ lastTenantId: Signal<string | undefined>;
385
+ resolvedDefaultId: Signal<string | undefined>;
386
+ isLoading: Signal<boolean>;
387
+ switchTenant: (tenantId: string) => Promise<Result3<void, Error>>;
388
+ }
389
+ declare const TenantContext: Context<TenantContextValue>;
390
+ declare function useTenant(): UnwrapSignals<TenantContextValue>;
391
+ interface TenantProviderProps {
392
+ /** SDK method to list tenants (generated by codegen). */
393
+ listTenants: () => PromiseLike<Result3<ListTenantsResponse, Error>>;
394
+ /** SDK method to switch tenant (generated by codegen). */
395
+ switchTenant: SdkMethodWithMeta<{
396
+ tenantId: string;
397
+ }, unknown>;
398
+ /** Called after a successful tenant switch. */
399
+ onSwitchComplete?: (tenantId: string) => void;
400
+ children: (() => unknown) | unknown;
401
+ }
402
+ declare function TenantProvider({ listTenants, switchTenant: switchTenantSdk, onSwitchComplete, children }: TenantProviderProps): HTMLElement;
369
403
  /**
370
404
  * Get a display name for a user with a fallback chain.
371
405
  * Chain: user.name (if string & non-empty) → user.email → fallback (default: 'Unknown')
@@ -381,4 +415,4 @@ declare function getUserInitials(user: User | null | undefined): string;
381
415
  * Returns an inline SVG string — no external requests, works in SSR.
382
416
  */
383
417
  declare function getUserIcon(size: number): string;
384
- export { useAuth, useAccessContext, getUserInitials, getUserIcon, getUserDisplayName, getProviderIcon, createAccessProvider, createAccessEventClient, canSignals, can, User, SignUpInput, SignOutOptions, SignInInput, ResetInput, RawAccessCheck, OAuthProviderInfo, MfaInput, ForgotInput, EntitlementRegistry, Entitlement, DenialReason, DenialMeta, ClientAccessEvent, AuthStatus, AuthSdkMethod, AuthSdk, AuthResponse, AuthProviderProps, AuthProvider, AuthErrorCode, AuthContextValue, AuthContext, AuthClientError, AccessSet, AccessEventClientOptions, AccessEventClient, AccessContextValue, AccessContext, AccessCheckData, AccessCheck };
418
+ export { useTenant, useAuth, useAccessContext, getUserInitials, getUserIcon, getUserDisplayName, getProviderIcon, createAccessProvider, createAccessEventClient, canSignals, can, User, TenantProviderProps, TenantProvider, TenantInfo, TenantContextValue, TenantContext, SignUpInput, SignOutOptions, SignInInput, ResetInput, RawAccessCheck, OAuthProviderInfo, MfaInput, ListTenantsResponse, ForgotInput, EntitlementRegistry, Entitlement, DenialReason, DenialMeta, ClientAccessEvent, AuthStatus, AuthSdkMethod, AuthSdk, AuthResponse, AuthProviderProps, AuthProvider, AuthErrorCode, AuthContextValue, AuthContext, AuthClientError, AccessSet, AccessEventClientOptions, AccessEventClient, AccessContextValue, AccessContext, AccessCheckData, AccessCheck };
@@ -1,9 +1,12 @@
1
1
  import {
2
2
  RouterContext
3
- } from "../../shared/chunk-4cmt1ve8.js";
3
+ } from "../../shared/chunk-f4d5nphq.js";
4
+ import {
5
+ invalidateTenantQueries
6
+ } from "../../shared/chunk-2eh4p2n7.js";
4
7
  import {
5
8
  isBrowser
6
- } from "../../shared/chunk-bybgyjye.js";
9
+ } from "../../shared/chunk-da2w7j7w.js";
7
10
  import {
8
11
  _tryOnCleanup,
9
12
  computed,
@@ -11,7 +14,7 @@ import {
11
14
  getSSRContext,
12
15
  signal,
13
16
  useContext
14
- } from "../../shared/chunk-2qe6aqhb.js";
17
+ } from "../../shared/chunk-656n0x6y.js";
15
18
 
16
19
  // src/auth/access-context.ts
17
20
  var AccessContext = createContext(undefined, "@vertz/ui::AccessContext");
@@ -778,6 +781,69 @@ function getProviderIcon(providerId, size) {
778
781
  const iconFn = icons[providerId];
779
782
  return iconFn ? iconFn(size) : fallbackIcon(size);
780
783
  }
784
+ // src/auth/tenant-context.ts
785
+ var TenantContext = createContext(undefined, "@vertz/ui::TenantContext");
786
+ function useTenant() {
787
+ const ctx = useContext(TenantContext);
788
+ if (!ctx)
789
+ throw new Error("useTenant must be called within TenantProvider");
790
+ return ctx;
791
+ }
792
+ function TenantProvider({
793
+ listTenants,
794
+ switchTenant: switchTenantSdk,
795
+ onSwitchComplete,
796
+ children
797
+ }) {
798
+ const authCtx = useContext(AuthContext);
799
+ if (!authCtx)
800
+ throw new Error("TenantProvider must be rendered inside AuthProvider");
801
+ const tenantsSignal = signal([]);
802
+ const currentTenantIdSignal = signal(undefined);
803
+ const lastTenantIdSignal = signal(undefined);
804
+ const resolvedDefaultIdSignal = signal(undefined);
805
+ const isLoadingSignal = signal(true);
806
+ setTimeout(() => {
807
+ fetchTenants().catch(() => {});
808
+ }, 0);
809
+ async function fetchTenants() {
810
+ isLoadingSignal.value = true;
811
+ try {
812
+ const result = await listTenants();
813
+ if (result.ok) {
814
+ tenantsSignal.value = result.data.tenants;
815
+ currentTenantIdSignal.value = result.data.currentTenantId;
816
+ lastTenantIdSignal.value = result.data.lastTenantId;
817
+ resolvedDefaultIdSignal.value = result.data.resolvedDefaultId;
818
+ if (!result.data.currentTenantId && result.data.resolvedDefaultId) {
819
+ await doSwitchTenant(result.data.resolvedDefaultId);
820
+ }
821
+ }
822
+ } finally {
823
+ isLoadingSignal.value = false;
824
+ }
825
+ }
826
+ async function doSwitchTenant(tenantId) {
827
+ const result = await switchTenantSdk({ tenantId });
828
+ if (result.ok) {
829
+ currentTenantIdSignal.value = tenantId;
830
+ lastTenantIdSignal.value = tenantId;
831
+ invalidateTenantQueries();
832
+ onSwitchComplete?.(tenantId);
833
+ return { ok: true, data: undefined };
834
+ }
835
+ return { ok: false, error: result.error };
836
+ }
837
+ const contextValue = {
838
+ tenants: tenantsSignal,
839
+ currentTenantId: currentTenantIdSignal,
840
+ lastTenantId: lastTenantIdSignal,
841
+ resolvedDefaultId: resolvedDefaultIdSignal,
842
+ isLoading: isLoadingSignal,
843
+ switchTenant: doSwitchTenant
844
+ };
845
+ return TenantContext.Provider({ value: contextValue, children });
846
+ }
781
847
  // src/auth/user-display.ts
782
848
  function getUserDisplayName(user, fallback = "Unknown") {
783
849
  if (!user)
@@ -810,6 +876,7 @@ function getUserIcon(size) {
810
876
  return `<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>`;
811
877
  }
812
878
  export {
879
+ useTenant,
813
880
  useAuth,
814
881
  useAccessContext,
815
882
  getUserInitials,
@@ -820,6 +887,8 @@ export {
820
887
  createAccessEventClient,
821
888
  canSignals,
822
889
  can,
890
+ TenantProvider,
891
+ TenantContext,
823
892
  AuthProvider,
824
893
  AuthContext,
825
894
  AccessContext
@@ -36,9 +36,9 @@ declare const Alert: ThemeComponentMap["Alert"];
36
36
  declare const Card: ThemeComponentMap["Card"];
37
37
  declare const FormGroup: ThemeComponentMap["FormGroup"];
38
38
  declare const Avatar: ThemeComponentMap["Avatar"];
39
+ declare const EmptyState: ThemeComponentMap["EmptyState"];
39
40
  declare const Skeleton: ThemeComponentMap["Skeleton"];
40
41
  declare const Table: ThemeComponentMap["Table"];
41
- declare const AlertDialog: ThemeComponentMap["AlertDialog"];
42
42
  declare const Dialog: ThemeComponentMap["Dialog"];
43
43
  declare const DropdownMenu: ThemeComponentMap["DropdownMenu"];
44
44
  declare const Select: ThemeComponentMap["Select"];
@@ -67,4 +67,4 @@ declare const NavigationMenu: ThemeComponentMap["NavigationMenu"];
67
67
  declare const ResizablePanel: ThemeComponentMap["ResizablePanel"];
68
68
  declare const ScrollArea: ThemeComponentMap["ScrollArea"];
69
69
  declare const ToggleGroup: ThemeComponentMap["ToggleGroup"];
70
- export { Tooltip, ToggleGroup, Toggle, Toast, ThemeComponentMap, Textarea, Tabs, Table, Switch, Slider, Skeleton, Sheet, Separator, Select, ScrollArea, ResizablePanel, RadioGroup, Progress, Popover, Pagination, NavigationMenu, Menubar, Label, Input, HoverCard, FormGroup, DropdownMenu, Drawer, Dialog, DatePicker, ContextMenu, Command, Collapsible, Checkbox, Carousel, Card, Calendar, Button, Breadcrumb, Badge, Avatar, AlertDialog, Alert, Accordion };
70
+ export { Tooltip, ToggleGroup, Toggle, Toast, ThemeComponentMap, Textarea, Tabs, Table, Switch, Slider, Skeleton, Sheet, Separator, Select, ScrollArea, ResizablePanel, RadioGroup, Progress, Popover, Pagination, NavigationMenu, Menubar, Label, Input, HoverCard, FormGroup, EmptyState, DropdownMenu, Drawer, Dialog, DatePicker, ContextMenu, Command, Collapsible, Checkbox, Carousel, Card, Calendar, Button, Breadcrumb, Badge, Avatar, Alert, Accordion };