@epoch32/visage 1.1.2 → 1.1.4

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 (52) hide show
  1. package/dist/api/index.js +55 -4085
  2. package/dist/charts/index.js +48 -2806
  3. package/dist/devtools/index.js +18 -4766
  4. package/dist/dom/index.js +32 -1639
  5. package/dist/form/index.js +13 -1498
  6. package/dist/index-061jf06a.js +848 -0
  7. package/dist/index-0madxn60.js +442 -0
  8. package/dist/index-1xtrtz1t.js +256 -0
  9. package/dist/index-2zz0g2n2.js +212 -0
  10. package/dist/index-5s255b3w.js +303 -0
  11. package/dist/index-6kfe1nr4.js +1179 -0
  12. package/dist/index-8czhpea8.js +338 -0
  13. package/dist/index-8x8xz80v.js +727 -0
  14. package/dist/index-921pn75b.js +0 -0
  15. package/dist/index-965ryh36.js +537 -0
  16. package/dist/index-9fvarkrx.js +98 -0
  17. package/dist/index-a4xns6cc.js +219 -0
  18. package/dist/index-b5wc752a.js +1696 -0
  19. package/dist/index-df5e614s.js +334 -0
  20. package/dist/index-dyvgtp43.js +1094 -0
  21. package/dist/index-grhdtcb5.js +234 -0
  22. package/dist/index-h6tjqk6e.js +158 -0
  23. package/dist/index-js199er4.js +101 -0
  24. package/dist/index-x2rs3vab.js +124 -0
  25. package/dist/index-y9bq7h9g.js +1162 -0
  26. package/dist/index-zr6cvset.js +2092 -0
  27. package/dist/index.d.ts +1 -1
  28. package/dist/index.js +458 -11915
  29. package/dist/jsx-runtime/index.js +13 -1719
  30. package/dist/query/index.js +47 -2505
  31. package/dist/router/index.js +25 -1945
  32. package/dist/rpc/index.js +39 -3567
  33. package/dist/server/index.js +11 -1256
  34. package/dist/signals/index.js +52 -1160
  35. package/dist/style/index.js +77 -2429
  36. package/dist/template/index.js +7 -1232
  37. package/dist/ui/index.d.ts +1 -1
  38. package/dist/ui/index.js +150 -4244
  39. package/dist/ui/tabs.d.ts +23 -1
  40. package/dist/virtual/index.js +12 -2044
  41. package/dist/vite/index.js +5 -744
  42. package/package.json +2 -2
  43. package/src/dom/render.ts +20 -7
  44. package/src/index.ts +2 -0
  45. package/src/signals/computed.ts +19 -12
  46. package/src/signals/context.ts +1 -2
  47. package/src/signals/effect.ts +7 -7
  48. package/src/signals/signal.ts +16 -12
  49. package/src/signals/system.ts +50 -21
  50. package/src/ui/index.ts +2 -0
  51. package/src/ui/tabs.tsx +211 -5
  52. package/src/ui/utils.ts +1 -3
package/dist/ui/index.js CHANGED
@@ -1,4246 +1,152 @@
1
- // src/signals/types.ts
2
- var SubscriberState;
3
- ((SubscriberState) => {
4
- SubscriberState[SubscriberState["CLEAN"] = 0] = "CLEAN";
5
- SubscriberState[SubscriberState["CHECK_DIRTY"] = 1] = "CHECK_DIRTY";
6
- SubscriberState[SubscriberState["DIRTY"] = 2] = "DIRTY";
7
- SubscriberState[SubscriberState["DISPOSED"] = 3] = "DISPOSED";
8
- })(SubscriberState ||= {});
9
- var SIGNAL_BRAND = Symbol("visage.signal");
10
- var COMPUTED_BRAND = Symbol("visage.computed");
11
- function isSignal(value) {
12
- return typeof value === "function" && ((SIGNAL_BRAND in value) || (COMPUTED_BRAND in value));
13
- }
14
-
15
- // src/signals/system.ts
16
- var currentSubscriber = null;
17
- var currentScope = null;
18
- var batchDepth = 0;
19
- var pendingEffects = new Set;
20
- var warnedCyclicSubscribers = new WeakSet;
21
- var isFlushing = false;
22
- function setCurrentSubscriber(sub) {
23
- currentSubscriber = sub;
24
- }
25
- function setCurrentScope(scope) {
26
- currentScope = scope;
27
- }
28
- function getCurrentScope() {
29
- return currentScope;
30
- }
31
- function addPendingEffect(eff) {
32
- pendingEffects.add(eff);
33
- }
34
- function removePendingEffect(eff) {
35
- pendingEffects.delete(eff);
36
- }
37
- var MAX_FLUSH_COUNT = 100;
38
- function flushEffects() {
39
- if (isFlushing || batchDepth > 0)
40
- return;
41
- isFlushing = true;
42
- let iterations = 0;
43
- try {
44
- while (pendingEffects.size > 0) {
45
- if (++iterations > MAX_FLUSH_COUNT) {
46
- pendingEffects.clear();
47
- throw new Error(`[Visage Reactivity] Maximum update depth exceeded (${MAX_FLUSH_COUNT} cycles). ` + `An effect continuously triggered state mutations (infinite loop detected). ` + `Ensure effects that modify signals do not unconditionally depend on them, or use untrack() to read state.`);
48
- }
49
- const effectsToRun = Array.from(pendingEffects);
50
- pendingEffects.clear();
51
- for (const eff of effectsToRun) {
52
- if (eff.state === 2 /* DIRTY */ || eff.state === 1 /* CHECK_DIRTY */) {
53
- eff.run();
54
- }
55
- }
56
- }
57
- } finally {
58
- isFlushing = false;
59
- }
60
- }
61
- function batch(fn) {
62
- batchDepth++;
63
- try {
64
- return fn();
65
- } finally {
66
- batchDepth--;
67
- if (batchDepth === 0) {
68
- flushEffects();
69
- }
70
- }
71
- }
72
- function untrack(fn) {
73
- const prev = currentSubscriber;
74
- currentSubscriber = null;
75
- try {
76
- return fn();
77
- } finally {
78
- currentSubscriber = prev;
79
- }
80
- }
81
-
82
- // src/signals/computed.ts
83
- class Computed {
84
- [COMPUTED_BRAND] = true;
85
- _fn;
86
- _value;
87
- _subscribers = new Set;
88
- sources = new Set;
89
- sourceVersions = new Map;
90
- state = 2 /* DIRTY */;
91
- scope;
92
- version = 0;
93
- constructor(fn) {
94
- this._fn = fn;
95
- this.scope = currentScope;
96
- if (currentScope) {
97
- currentScope.addSubscriber(this);
98
- }
99
- }
100
- get() {
101
- if (this.state === 3 /* DISPOSED */) {
102
- return this._fn();
103
- }
104
- if (currentSubscriber !== null && currentSubscriber.state !== 3 /* DISPOSED */) {
105
- this._subscribers.add(currentSubscriber);
106
- currentSubscriber.sources.add(this);
107
- currentSubscriber.sourceVersions.set(this, this.version);
108
- }
109
- if (this.state === 2 /* DIRTY */ || this.state === 1 /* CHECK_DIRTY */) {
110
- this.updateIfNecessary();
111
- }
112
- return this._value;
113
- }
114
- get value() {
115
- return this.get();
116
- }
117
- removeSubscriber(sub) {
118
- this._subscribers.delete(sub);
119
- }
120
- markDirty(targetState = 1 /* CHECK_DIRTY */) {
121
- if (this.state >= targetState || this.state === 3 /* DISPOSED */) {
122
- return;
123
- }
124
- this.state = targetState;
125
- for (const sub of this._subscribers) {
126
- sub.markDirty(1 /* CHECK_DIRTY */);
127
- }
128
- }
129
- updateIfNecessary() {
130
- if (this.state === 2 /* DIRTY */) {
131
- const prev = this._value;
132
- this.recompute();
133
- return !Object.is(prev, this._value);
134
- }
135
- if (this.state === 1 /* CHECK_DIRTY */) {
136
- let anyChanged = false;
137
- for (const source of this.sources) {
138
- if (source instanceof Computed) {
139
- source.updateIfNecessary();
140
- }
141
- const lastVersion = this.sourceVersions.get(source);
142
- if (lastVersion !== undefined && lastVersion !== source.version) {
143
- anyChanged = true;
144
- }
145
- }
146
- if (anyChanged) {
147
- const prev = this._value;
148
- this.recompute();
149
- return !Object.is(prev, this._value);
150
- }
151
- this.state = 0 /* CLEAN */;
152
- return false;
153
- }
154
- return false;
155
- }
156
- recompute() {
157
- this.cleanupSources();
158
- const prevSubscriber = currentSubscriber;
159
- setCurrentSubscriber(this);
160
- const prevScope = currentScope;
161
- setCurrentScope(this.scope);
162
- try {
163
- const next = this._fn();
164
- if (!Object.is(this._value, next)) {
165
- this._value = next;
166
- this.version++;
167
- }
168
- this.state = 0 /* CLEAN */;
169
- } finally {
170
- setCurrentSubscriber(prevSubscriber);
171
- setCurrentScope(prevScope);
172
- }
173
- }
174
- cleanupSources() {
175
- for (const source of this.sources) {
176
- source.removeSubscriber(this);
177
- }
178
- this.sources.clear();
179
- this.sourceVersions.clear();
180
- }
181
- dispose() {
182
- if (this.state === 3 /* DISPOSED */)
183
- return;
184
- this.state = 3 /* DISPOSED */;
185
- this.cleanupSources();
186
- this._subscribers.clear();
187
- }
188
- }
189
- function computed(fn, options) {
190
- const isInternal = options?.internal ?? false;
191
- const customName = options?.name;
192
- const c = new Computed(fn);
193
- const accessor = () => c.get();
194
- Object.defineProperties(accessor, {
195
- [COMPUTED_BRAND]: { value: true },
196
- get: { value: () => c.get() },
197
- value: { get: () => c.get() }
198
- });
199
- if (!isInternal && typeof window !== "undefined" && window.__VISAGE_DEVTOOLS__) {
200
- const devtools = window.__VISAGE_DEVTOOLS__;
201
- const sigId = devtools.registerSignal({
202
- name: customName,
203
- type: "computed",
204
- getValue: () => c.get(),
205
- version: () => c.version,
206
- subscribersCount: () => c._subscribers?.size ?? 0,
207
- dependencies: () => Array.from(c.sources ?? []).map((src) => src._devId).filter(Boolean),
208
- dependents: () => Array.from(c._subscribers ?? []).map((sub) => sub._devId).filter(Boolean)
209
- });
210
- c._devId = sigId;
211
- if (currentScope) {
212
- currentScope.addCleanup(() => {
213
- devtools.unregisterSignal(sigId);
214
- });
215
- }
216
- }
217
- return accessor;
218
- }
219
- var createMemo = computed;
220
- // src/style/cx.ts
221
- function hasReactiveClass(val) {
222
- if (typeof val === "function")
223
- return true;
224
- if (Array.isArray(val)) {
225
- for (let i = 0;i < val.length; i++) {
226
- if (hasReactiveClass(val[i]))
227
- return true;
228
- }
229
- return false;
230
- }
231
- if (typeof val === "object" && val !== null) {
232
- for (const k in val) {
233
- if (typeof val[k] === "function")
234
- return true;
235
- }
236
- }
237
- return false;
238
- }
239
- function normalizeClass(val) {
240
- if (!val)
241
- return "";
242
- if (typeof val === "function")
243
- return normalizeClass(val());
244
- if (typeof val === "string")
245
- return val.trim();
246
- if (typeof val === "number")
247
- return String(val);
248
- if (Array.isArray(val)) {
249
- let res = "";
250
- for (let i = 0;i < val.length; i++) {
251
- const item = typeof val[i] === "function" ? val[i]() : val[i];
252
- const itemStr = normalizeClass(item);
253
- if (itemStr) {
254
- res = res ? `${res} ${itemStr}` : itemStr;
255
- }
256
- }
257
- return res;
258
- }
259
- if (typeof val === "object") {
260
- let res = "";
261
- for (const key in val) {
262
- const condition = typeof val[key] === "function" ? val[key]() : val[key];
263
- if (condition) {
264
- res = res ? `${res} ${key}` : key;
265
- }
266
- }
267
- return res;
268
- }
269
- return "";
270
- }
271
- function cx(...args) {
272
- return normalizeClass(args);
273
- }
274
-
275
- // src/style/scale.ts
276
- var UNITLESS_PROPERTIES = new Set([
277
- "animationIterationCount",
278
- "aspectRatio",
279
- "borderImageSlice",
280
- "columnCount",
281
- "columns",
282
- "flex",
283
- "flexGrow",
284
- "flexShrink",
285
- "flexOrder",
286
- "fontWeight",
287
- "lineHeight",
288
- "opacity",
289
- "order",
290
- "orphans",
291
- "scale",
292
- "tabSize",
293
- "widows",
294
- "zIndex",
295
- "zoom",
296
- "fillOpacity",
297
- "strokeOpacity"
298
- ]);
299
- var DIMENSION_KEYWORDS = {
300
- screen: "100dvh",
301
- "screen-h": "100dvh",
302
- "screen-w": "100dvw",
303
- full: "100%",
304
- half: "50%",
305
- third: "33.333333%",
306
- "two-thirds": "66.666667%",
307
- quarter: "25%",
308
- "three-quarters": "75%",
309
- auto: "auto",
310
- min: "min-content",
311
- max: "max-content",
312
- fit: "fit-content"
313
- };
314
- function space(val) {
315
- if (val === undefined || val === null || val === "")
316
- return "";
317
- if (typeof val === "number") {
318
- if (val === 0)
319
- return "0px";
320
- return `${val * 4}px`;
321
- }
322
- const str = String(val).trim();
323
- if (str in DIMENSION_KEYWORDS) {
324
- return DIMENSION_KEYWORDS[str];
325
- }
326
- return str;
327
- }
328
- function resolveDimension(val) {
329
- if (val === undefined || val === null || val === "")
330
- return "";
331
- if (typeof val === "number") {
332
- if (val === 0)
333
- return "0px";
334
- if (val > 48)
335
- return `${val}px`;
336
- return `${val * 4}px`;
337
- }
338
- const str = String(val).trim();
339
- if (str in DIMENSION_KEYWORDS) {
340
- return DIMENSION_KEYWORDS[str];
341
- }
342
- return str;
343
- }
344
- function px(val) {
345
- return `${val}px`;
346
- }
347
- function rem(val) {
348
- return `${val}rem`;
349
- }
350
- function em(val) {
351
- return `${val}em`;
352
- }
353
- function fluid(minPx, maxPx, options) {
354
- const minVw = options?.minVw ?? 375;
355
- const maxVw = options?.maxVw ?? 1280;
356
- const slope = (maxPx - minPx) / (maxVw - minVw);
357
- const yIntercept = -minVw * slope + minPx;
358
- const slopeVw = slope * 100;
359
- const preferred = `${yIntercept.toFixed(2)}px + ${slopeVw.toFixed(2)}vw`;
360
- const min = Math.min(minPx, maxPx);
361
- const max = Math.max(minPx, maxPx);
362
- return `clamp(${min}px, ${preferred}, ${max}px)`;
363
- }
364
- var SHADOW_PRESETS = {
365
- none: "none",
366
- sm: "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
367
- md: "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)",
368
- lg: "0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1)",
369
- xl: "0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1)",
370
- soft: "0 8px 30px rgba(0, 0, 0, 0.06)",
371
- glow: "0 0 24px rgba(168, 85, 247, 0.35)",
372
- inner: "inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)"
373
- };
374
- function shadow(variant) {
375
- if (variant in SHADOW_PRESETS) {
376
- return SHADOW_PRESETS[variant];
377
- }
378
- return variant;
379
- }
380
- var RADIUS_PRESETS = {
381
- none: "0px",
382
- sm: "4px",
383
- md: "8px",
384
- lg: "12px",
385
- xl: "16px",
386
- "2xl": "20px",
387
- "3xl": "24px",
388
- full: "9999px"
389
- };
390
- function radius(variant) {
391
- if (typeof variant === "number") {
392
- return `${variant}px`;
393
- }
394
- if (variant in RADIUS_PRESETS) {
395
- return RADIUS_PRESETS[variant];
396
- }
397
- return String(variant);
398
- }
399
- function glass(options = {}) {
400
- const blurVal = typeof options.blur === "number" ? `${options.blur}px` : options.blur ?? "20px";
401
- const tintVal = options.tint ?? "rgba(255, 255, 255, 0.65)";
402
- const borderVal = options.border ?? "1px solid rgba(255, 255, 255, 0.75)";
403
- return {
404
- backdropFilter: `blur(${blurVal})`,
405
- WebkitBackdropFilter: `blur(${blurVal})`,
406
- backgroundColor: tintVal,
407
- border: borderVal
408
- };
409
- }
410
- function formatStyleProp(prop, val) {
411
- if (val === null || val === undefined || val === "")
412
- return "";
413
- if (typeof val === "number") {
414
- if (val === 0 || UNITLESS_PROPERTIES.has(prop)) {
415
- return String(val);
416
- }
417
- return `${val}px`;
418
- }
419
- const str = String(val).trim();
420
- if (str in DIMENSION_KEYWORDS) {
421
- const lowerProp = prop.toLowerCase();
422
- if (str === "screen") {
423
- if (lowerProp.includes("width"))
424
- return "100dvw";
425
- return "100dvh";
426
- }
427
- return DIMENSION_KEYWORDS[str];
428
- }
429
- return str;
430
- }
431
-
432
- // src/dom/render.ts
433
- function isReactive(value) {
434
- return isSignal(value) || typeof value === "function";
435
- }
436
- function resolveValue(val) {
437
- if (typeof val === "function") {
438
- return val();
439
- }
440
- return val;
441
- }
442
- function render(fn, container) {
443
- return createRoot((dispose) => {
444
- container.textContent = "";
445
- const node = insertChild(container, fn());
446
- onCleanup(() => {
447
- if (node && node instanceof Node && node.parentNode === container) {
448
- container.removeChild(node);
449
- }
450
- });
451
- return dispose;
452
- });
453
- }
454
- function setAttribute(el, key, value) {
455
- if (key.startsWith("on") && typeof value === "function") {
456
- const eventName = key.startsWith("onCapture") ? key.slice(9).toLowerCase() : key.slice(2).toLowerCase();
457
- const useCapture = key.startsWith("onCapture");
458
- el.addEventListener(eventName, value, useCapture);
459
- onCleanup(() => {
460
- el.removeEventListener(eventName, value, useCapture);
461
- });
462
- return;
463
- }
464
- if (key === "ref" && typeof value === "function") {
465
- value(el);
466
- return;
467
- }
468
- if (key === "class" || key === "className") {
469
- if (hasReactiveClass(value)) {
470
- effect(() => {
471
- const cls = normalizeClass(value);
472
- if (cls)
473
- el.setAttribute("class", cls);
474
- else
475
- el.removeAttribute("class");
476
- });
477
- } else {
478
- const cls = normalizeClass(value);
479
- if (cls)
480
- el.setAttribute("class", cls);
481
- else
482
- el.removeAttribute("class");
483
- }
484
- return;
485
- }
486
- if (isReactive(value)) {
487
- effect(() => {
488
- const resolved = resolveValue(value);
489
- applyProp(el, key, resolved);
490
- });
491
- } else {
492
- applyProp(el, key, value);
493
- }
494
- }
495
- function setStyleProperty(el, prop, val) {
496
- const formatted = formatStyleProp(prop, val);
497
- if (prop.startsWith("--") || prop.includes("-")) {
498
- if (formatted === "") {
499
- el.style.removeProperty(prop);
500
- } else {
501
- el.style.setProperty(prop, formatted);
502
- }
503
- } else {
504
- el.style[prop] = formatted;
505
- }
506
- }
507
- function applyProp(el, key, value) {
508
- if (value === null || value === undefined || value === false && !key.startsWith("aria-") && !key.startsWith("data-")) {
509
- if (key === "className" || key === "class") {
510
- el.removeAttribute("class");
511
- } else if (key === "style" && typeof value === "string") {
512
- el.removeAttribute("style");
513
- } else if (key in el && !(el instanceof SVGElement)) {
514
- try {
515
- el[key] = typeof el[key] === "boolean" ? false : "";
516
- } catch {
517
- el.removeAttribute(key);
518
- }
519
- } else {
520
- el.removeAttribute(key);
521
- }
522
- return;
523
- }
524
- if (key === "className" || key === "class") {
525
- const cls = normalizeClass(value);
526
- if (cls) {
527
- el.setAttribute("class", cls);
528
- } else {
529
- el.removeAttribute("class");
530
- }
531
- } else if (key === "style") {
532
- if (typeof value === "string") {
533
- el.setAttribute("style", value);
534
- } else if (typeof value === "object" && value !== null) {
535
- for (const styleKey in value) {
536
- const styleVal = value[styleKey];
537
- if (isReactive(styleVal)) {
538
- effect(() => {
539
- setStyleProperty(el, styleKey, resolveValue(styleVal));
540
- });
541
- } else {
542
- setStyleProperty(el, styleKey, styleVal);
543
- }
544
- }
545
- }
546
- } else if (key === "dangerouslySetInnerHTML" && value && typeof value.__html === "string") {
547
- el.innerHTML = value.__html;
548
- } else if (key in el && !(el instanceof SVGElement) && key !== "list" && key !== "form") {
549
- try {
550
- el[key] = value;
551
- } catch {
552
- el.setAttribute(key, String(value));
553
- }
554
- } else {
555
- if (key.startsWith("aria-") || key.startsWith("data-")) {
556
- el.setAttribute(key, String(value));
557
- } else if (value === true) {
558
- el.setAttribute(key, "");
559
- } else {
560
- el.setAttribute(key, String(value));
561
- }
562
- }
563
- }
564
- function insertChild(parent, child, before = null) {
565
- if (child === null || child === undefined || child === false || child === true) {
566
- return null;
567
- }
568
- if (child instanceof Node) {
569
- parent.insertBefore(child, before);
570
- return child;
571
- }
572
- if (Array.isArray(child)) {
573
- const fragment = document.createDocumentFragment();
574
- for (const item of child) {
575
- insertChild(fragment, item);
576
- }
577
- parent.insertBefore(fragment, before);
578
- return fragment;
579
- }
580
- if (isReactive(child)) {
581
- const marker = document.createTextNode("");
582
- parent.insertBefore(marker, before);
583
- let childScope = null;
584
- let currentNodes = [];
585
- effect(() => {
586
- const resolved = resolveValue(child);
587
- if ((typeof resolved === "string" || typeof resolved === "number") && currentNodes.length === 1 && currentNodes[0].nodeType === Node.TEXT_NODE) {
588
- currentNodes[0].data = String(resolved);
589
- return;
590
- }
591
- if (childScope) {
592
- childScope.dispose();
593
- }
594
- childScope = new Scope(getActiveScope());
595
- runInScope(childScope, () => {
596
- for (const node of currentNodes) {
597
- if (node.parentNode) {
598
- node.parentNode.removeChild(node);
599
- }
600
- }
601
- currentNodes = [];
602
- if (resolved === null || resolved === undefined || resolved === false) {
603
- return;
604
- }
605
- const frag = document.createDocumentFragment();
606
- if (typeof resolved === "string" || typeof resolved === "number" || typeof resolved === "boolean") {
607
- frag.appendChild(document.createTextNode(String(resolved)));
608
- } else {
609
- insertChild(frag, resolved);
610
- }
611
- currentNodes = Array.from(frag.childNodes);
612
- if (marker.parentNode) {
613
- marker.parentNode.insertBefore(frag, marker);
614
- }
615
- });
616
- });
617
- onCleanup(() => {
618
- if (childScope) {
619
- childScope.dispose();
620
- }
621
- for (const node of currentNodes) {
622
- if (node.parentNode) {
623
- node.parentNode.removeChild(node);
624
- }
625
- }
626
- if (marker.parentNode) {
627
- marker.parentNode.removeChild(marker);
628
- }
629
- });
630
- return marker;
631
- }
632
- const textNode = document.createTextNode(String(child));
633
- parent.insertBefore(textNode, before);
634
- return textNode;
635
- }
636
-
637
- // src/signals/scope.ts
638
- class Scope {
639
- subscribers = new Set;
640
- cleanups = [];
641
- parent = null;
642
- isDisposed = false;
643
- context;
644
- constructor(parent = currentScope) {
645
- this.parent = parent;
646
- if (parent && !parent.isDisposed) {
647
- parent.cleanups.push(() => this.dispose());
648
- if (parent.context) {
649
- this.context = new Map(parent.context);
650
- }
651
- }
652
- }
653
- addSubscriber(sub) {
654
- if (this.isDisposed)
655
- return;
656
- this.subscribers.add(sub);
657
- }
658
- addCleanup(fn) {
659
- if (this.isDisposed) {
660
- fn();
661
- return;
662
- }
663
- this.cleanups.push(fn);
664
- }
665
- dispose() {
666
- if (this.isDisposed)
667
- return;
668
- this.isDisposed = true;
669
- for (const sub of this.subscribers) {
670
- sub.dispose();
671
- }
672
- this.subscribers.clear();
673
- for (let i = this.cleanups.length - 1;i >= 0; i--) {
674
- try {
675
- this.cleanups[i]();
676
- } catch (err) {
677
- console.error("Error during cleanup:", err);
678
- }
679
- }
680
- this.cleanups = [];
681
- }
682
- }
683
- function onCleanup(fn) {
684
- if (currentSubscriber && "addCleanup" in currentSubscriber) {
685
- currentSubscriber.addCleanup(fn);
686
- } else if (currentScope) {
687
- currentScope.addCleanup(fn);
688
- }
689
- }
690
- function createRoot(fn) {
691
- const prevScope = currentScope;
692
- const scope = new Scope(null);
693
- setCurrentScope(scope);
694
- try {
695
- return fn(() => scope.dispose());
696
- } finally {
697
- setCurrentScope(prevScope);
698
- }
699
- }
700
- function runInScope(scope, fn) {
701
- const prevScope = currentScope;
702
- setCurrentScope(scope);
703
- try {
704
- return fn();
705
- } finally {
706
- setCurrentScope(prevScope);
707
- }
708
- }
709
- function getActiveScope() {
710
- return getCurrentScope();
711
- }
712
-
713
- // src/signals/context.ts
714
- function createContext(defaultValue) {
715
- const id = Symbol("visage.context");
716
- const context = {
717
- id,
718
- defaultValue,
719
- Provider: (props) => {
720
- const parentScope = getActiveScope();
721
- const scope = new Scope(parentScope);
722
- if (!scope.context) {
723
- scope.context = new Map(parentScope?.context);
724
- }
725
- scope.context.set(id, props.value);
726
- return runInScope(scope, () => {
727
- const content = typeof props.children === "function" ? untrack(() => props.children()) : props.children;
728
- if (typeof document !== "undefined") {
729
- const frag = document.createDocumentFragment();
730
- insertChild(frag, content);
731
- return frag;
732
- }
733
- return content;
734
- });
735
- }
736
- };
737
- return context;
738
- }
739
- function useContext(context) {
740
- let scope = getActiveScope();
741
- while (scope) {
742
- if (scope.context?.has(context.id)) {
743
- return scope.context.get(context.id);
744
- }
745
- scope = scope.parent;
746
- }
747
- return context.defaultValue;
748
- }
749
- // src/signals/effect.ts
750
- class Effect {
751
- _fn;
752
- sources = new Set;
753
- sourceVersions = new Map;
754
- cleanups = [];
755
- state = 2 /* DIRTY */;
756
- scope;
757
- constructor(fn) {
758
- this._fn = fn;
759
- this.scope = currentScope;
760
- if (currentScope) {
761
- currentScope.addSubscriber(this);
762
- }
763
- this.run();
764
- }
765
- addCleanup(fn) {
766
- this.cleanups.push(fn);
767
- }
768
- runCleanups() {
769
- for (let i = this.cleanups.length - 1;i >= 0; i--) {
770
- try {
771
- this.cleanups[i]();
772
- } catch (e) {
773
- console.error("Error in effect cleanup:", e);
774
- }
775
- }
776
- this.cleanups = [];
777
- }
778
- markDirty(targetState = 2 /* DIRTY */) {
779
- if (this.state >= targetState || this.state === 3 /* DISPOSED */) {
780
- return;
781
- }
782
- this.state = targetState;
783
- addPendingEffect(this);
784
- if (batchDepth === 0) {
785
- flushEffects();
786
- }
787
- }
788
- run() {
789
- if (this.state === 3 /* DISPOSED */)
790
- return;
791
- if (this.state === 1 /* CHECK_DIRTY */) {
792
- let isDirty = false;
793
- for (const source of this.sources) {
794
- if (source instanceof Computed) {
795
- source.updateIfNecessary();
796
- }
797
- const lastVersion = this.sourceVersions.get(source);
798
- if (lastVersion !== undefined && lastVersion !== source.version) {
799
- isDirty = true;
800
- }
801
- }
802
- if (!isDirty) {
803
- this.state = 0 /* CLEAN */;
804
- return;
805
- }
806
- }
807
- this.runCleanups();
808
- this.cleanupSources();
809
- const prevSubscriber = currentSubscriber;
810
- setCurrentSubscriber(this);
811
- const prevScope = currentScope;
812
- setCurrentScope(this.scope);
813
- try {
814
- this.state = 0 /* CLEAN */;
815
- const res = this._fn();
816
- if (typeof res === "function") {
817
- this.cleanups.push(res);
818
- }
819
- } finally {
820
- setCurrentSubscriber(prevSubscriber);
821
- setCurrentScope(prevScope);
822
- }
823
- }
824
- cleanupSources() {
825
- for (const source of this.sources) {
826
- source.removeSubscriber(this);
827
- }
828
- this.sources.clear();
829
- this.sourceVersions.clear();
830
- }
831
- dispose() {
832
- if (this.state === 3 /* DISPOSED */)
833
- return;
834
- this.state = 3 /* DISPOSED */;
835
- this.runCleanups();
836
- this.cleanupSources();
837
- removePendingEffect(this);
838
- }
839
- }
840
- function effect(fn) {
841
- const eff = new Effect(fn);
842
- return () => eff.dispose();
843
- }
844
- var createEffect = effect;
845
- // src/signals/signal.ts
846
- class Signal {
847
- [SIGNAL_BRAND] = true;
848
- _value;
849
- _subscribers = new Set;
850
- _equals;
851
- _onSet;
852
- version = 0;
853
- constructor(initialValue, equals, onSet) {
854
- this._value = initialValue;
855
- this._equals = equals ?? Object.is;
856
- this._onSet = onSet;
857
- }
858
- get() {
859
- if (currentSubscriber !== null && currentSubscriber.state !== 3 /* DISPOSED */) {
860
- this._subscribers.add(currentSubscriber);
861
- currentSubscriber.sources.add(this);
862
- currentSubscriber.sourceVersions.set(this, this.version);
863
- }
864
- return this._value;
865
- }
866
- set(newValue) {
867
- if (this._equals(this._value, newValue)) {
868
- return;
869
- }
870
- if (currentSubscriber !== null && this._subscribers.has(currentSubscriber)) {
871
- if (!warnedCyclicSubscribers.has(currentSubscriber)) {
872
- warnedCyclicSubscribers.add(currentSubscriber);
873
- if (typeof console !== "undefined" && typeof console.warn === "function") {
874
- console.warn(`[Visage Reactivity] Cyclic update detected: An active subscriber modified a signal that it depends on. ` + `To read a signal inside an effect/computed without creating a circular dependency, wrap the read in untrack():
875
- ` + ` untrack(() => signal())`);
876
- }
877
- }
878
- }
879
- this._value = newValue;
880
- this.version++;
881
- if (this._onSet) {
882
- this._onSet(newValue);
883
- }
884
- batch(() => {
885
- this.notify();
886
- });
887
- }
888
- update(fn) {
889
- this.set(fn(this._value));
890
- }
891
- get value() {
892
- return this.get();
893
- }
894
- set value(val) {
895
- this.set(val);
896
- }
897
- removeSubscriber(sub) {
898
- this._subscribers.delete(sub);
899
- }
900
- notify() {
901
- if (this._subscribers.size === 0)
902
- return;
903
- const subs = Array.from(this._subscribers);
904
- for (const sub of subs) {
905
- sub.markDirty(2 /* DIRTY */);
906
- }
907
- }
908
- }
909
- function resolveStorage(storageOption) {
910
- if (storageOption && typeof storageOption === "object") {
911
- return storageOption;
912
- }
913
- if (storageOption === "session") {
914
- try {
915
- if (typeof sessionStorage !== "undefined")
916
- return sessionStorage;
917
- } catch {}
918
- try {
919
- if (typeof window !== "undefined" && window.sessionStorage) {
920
- return window.sessionStorage;
921
- }
922
- } catch {}
923
- try {
924
- if (typeof globalThis !== "undefined" && globalThis.sessionStorage) {
925
- return globalThis.sessionStorage;
926
- }
927
- } catch {}
928
- return null;
929
- }
930
- try {
931
- if (typeof localStorage !== "undefined")
932
- return localStorage;
933
- } catch {}
934
- try {
935
- if (typeof window !== "undefined" && window.localStorage) {
936
- return window.localStorage;
937
- }
938
- } catch {}
939
- try {
940
- if (typeof globalThis !== "undefined" && globalThis.localStorage) {
941
- return globalThis.localStorage;
942
- }
943
- } catch {}
944
- return null;
945
- }
946
- function signal(initialValue, optionsOrEquals) {
947
- const equals = typeof optionsOrEquals === "function" ? optionsOrEquals : optionsOrEquals?.equals;
948
- const isInternal = typeof optionsOrEquals === "object" ? optionsOrEquals?.internal : false;
949
- const customName = typeof optionsOrEquals === "object" ? optionsOrEquals?.name : undefined;
950
- const persistOption = typeof optionsOrEquals === "object" ? optionsOrEquals?.persist : undefined;
951
- const persistConfig = persistOption ? typeof persistOption === "string" ? { key: persistOption } : persistOption : undefined;
952
- let effectiveInitial = initialValue;
953
- const storage = persistConfig ? resolveStorage(persistConfig.storage) : null;
954
- const serialize = persistConfig?.serialize ?? JSON.stringify;
955
- const deserialize = persistConfig?.deserialize ?? JSON.parse;
956
- if (persistConfig && storage) {
957
- try {
958
- const stored = storage.getItem(persistConfig.key);
959
- if (stored !== null) {
960
- effectiveInitial = deserialize(stored);
961
- }
962
- } catch {}
963
- }
964
- let isSyncing = false;
965
- const onSet = persistConfig && storage ? (val) => {
966
- if (isSyncing)
967
- return;
968
- try {
969
- storage.setItem(persistConfig.key, serialize(val));
970
- } catch {}
971
- } : undefined;
972
- const s = new Signal(effectiveInitial, equals, onSet);
973
- if (persistConfig && storage && (persistConfig.syncTabs ?? true) && typeof window !== "undefined" && typeof window.addEventListener === "function") {
974
- const onStorage = (e) => {
975
- if (e.key === persistConfig.key) {
976
- try {
977
- const nextVal = e.newValue !== null ? deserialize(e.newValue) : initialValue;
978
- isSyncing = true;
979
- try {
980
- s.set(nextVal);
981
- } finally {
982
- isSyncing = false;
983
- }
984
- } catch {}
985
- }
986
- };
987
- window.addEventListener("storage", onStorage);
988
- if (currentScope) {
989
- currentScope.addCleanup(() => {
990
- window.removeEventListener("storage", onStorage);
991
- });
992
- }
993
- }
994
- const accessor = (...args) => {
995
- if (args.length === 0) {
996
- return s.get();
997
- }
998
- s.set(args[0]);
999
- return args[0];
1000
- };
1001
- Object.defineProperties(accessor, {
1002
- [SIGNAL_BRAND]: { value: true },
1003
- get: { value: () => s.get() },
1004
- set: { value: (v) => s.set(v) },
1005
- update: { value: (fn) => s.update(fn) },
1006
- value: {
1007
- get: () => s.get(),
1008
- set: (v) => s.set(v)
1009
- }
1010
- });
1011
- if (!isInternal && typeof window !== "undefined" && window.__VISAGE_DEVTOOLS__) {
1012
- const devtools = window.__VISAGE_DEVTOOLS__;
1013
- const sigId = devtools.registerSignal({
1014
- name: customName,
1015
- type: "signal",
1016
- getValue: () => s.get(),
1017
- version: () => s.version,
1018
- subscribersCount: () => s._subscribers?.size ?? 0,
1019
- dependents: () => Array.from(s._subscribers ?? []).map((sub) => sub._devId).filter(Boolean)
1020
- });
1021
- s._devId = sigId;
1022
- if (currentScope) {
1023
- currentScope.addCleanup(() => {
1024
- devtools.unregisterSignal(sigId);
1025
- });
1026
- }
1027
- }
1028
- return accessor;
1029
- }
1030
- function createSignal(initialValue, optionsOrEquals) {
1031
- const s = signal(initialValue, optionsOrEquals);
1032
- const setter = (value) => {
1033
- if (typeof value === "function") {
1034
- s.update(value);
1035
- } else {
1036
- s.set(value);
1037
- }
1038
- };
1039
- return [s, setter];
1040
- }
1041
- // src/signals/store.ts
1042
- var STORE_RAW = Symbol("visage.store.raw");
1043
- var STORE_SIGNALS = Symbol("visage.store.signals");
1044
- var STORE_PROXY = Symbol("visage.store.proxy");
1045
- function isObject(val) {
1046
- return typeof val === "object" && val !== null && (typeof Node === "undefined" || !(val instanceof Node)) && !isSignal(val);
1047
- }
1048
- function getOrCreatePropertySignal(target, prop) {
1049
- let signalsMap = target[STORE_SIGNALS];
1050
- if (!signalsMap) {
1051
- signalsMap = new Map;
1052
- Object.defineProperty(target, STORE_SIGNALS, {
1053
- value: signalsMap,
1054
- enumerable: false,
1055
- writable: true
1056
- });
1057
- }
1058
- let sig = signalsMap.get(prop);
1059
- if (!sig) {
1060
- sig = new Signal(target[prop]);
1061
- signalsMap.set(prop, sig);
1062
- }
1063
- return sig;
1064
- }
1065
- function createStoreProxy(target) {
1066
- if (!isObject(target))
1067
- return target;
1068
- if (target[STORE_PROXY])
1069
- return target[STORE_PROXY];
1070
- const proxy = new Proxy(target, {
1071
- get(target, prop, receiver) {
1072
- if (prop === STORE_RAW)
1073
- return target;
1074
- if (prop === STORE_PROXY)
1075
- return proxy;
1076
- if (typeof prop === "string" || typeof prop === "symbol") {
1077
- const sig = getOrCreatePropertySignal(target, prop);
1078
- sig.get();
1079
- }
1080
- const value = Reflect.get(target, prop, receiver);
1081
- if (isObject(value)) {
1082
- return createStoreProxy(value);
1083
- }
1084
- return value;
1085
- },
1086
- set(target, prop, value, receiver) {
1087
- const prevValue = Reflect.get(target, prop, receiver);
1088
- if (Object.is(prevValue, value)) {
1089
- return true;
1090
- }
1091
- const success = Reflect.set(target, prop, value, receiver);
1092
- if (success) {
1093
- const sig = getOrCreatePropertySignal(target, prop);
1094
- sig.set(value);
1095
- if (Array.isArray(target) && prop !== "length") {
1096
- const lenSig = getOrCreatePropertySignal(target, "length");
1097
- lenSig.set(target.length);
1098
- }
1099
- }
1100
- return success;
1101
- },
1102
- deleteProperty(target, prop) {
1103
- const hadProp = Reflect.has(target, prop);
1104
- const success = Reflect.deleteProperty(target, prop);
1105
- if (hadProp && success) {
1106
- const sig = getOrCreatePropertySignal(target, prop);
1107
- sig.set(undefined);
1108
- }
1109
- return success;
1110
- }
1111
- });
1112
- Object.defineProperty(target, STORE_PROXY, {
1113
- value: proxy,
1114
- enumerable: false,
1115
- writable: true
1116
- });
1117
- return proxy;
1118
- }
1119
- function createStore(initialState) {
1120
- if (!isObject(initialState)) {
1121
- throw new Error("createStore requires an object or array as initial state");
1122
- }
1123
- return createStoreProxy(initialState);
1124
- }
1125
- function mutateStore(store, mutator) {
1126
- batch(() => {
1127
- mutator(store);
1128
- });
1129
- }
1130
- function unwrapStore(store) {
1131
- if (isObject(store) && store[STORE_RAW]) {
1132
- return store[STORE_RAW];
1133
- }
1134
- return store;
1135
- }
1136
- // src/dom/control-flow.ts
1137
- function Show(props) {
1138
- if (typeof document === "undefined") {
1139
- const condition = resolveValue(props.when);
1140
- if (condition) {
1141
- return typeof props.children === "function" && props.children.length > 0 ? props.children(() => resolveValue(props.when)) : typeof props.children === "function" ? props.children() : props.children;
1142
- }
1143
- return props.fallback ?? null;
1144
- }
1145
- const marker = document.createComment("visage-show");
1146
- const initialFrag = document.createDocumentFragment();
1147
- initialFrag.appendChild(marker);
1148
- let currentScope = null;
1149
- let currentContent = [];
1150
- effect(() => {
1151
- const condition = resolveValue(props.when);
1152
- if (currentScope) {
1153
- currentScope.dispose();
1154
- currentScope = null;
1155
- }
1156
- for (const node of currentContent) {
1157
- if (node.parentNode) {
1158
- node.parentNode.removeChild(node);
1159
- }
1160
- }
1161
- currentContent = [];
1162
- const frag = document.createDocumentFragment();
1163
- if (condition) {
1164
- currentScope = new Scope(getActiveScope());
1165
- untrack(() => {
1166
- runInScope(currentScope, () => {
1167
- const childRes = typeof props.children === "function" && props.children.length > 0 ? props.children(() => resolveValue(props.when)) : typeof props.children === "function" ? props.children() : props.children;
1168
- insertChild(frag, childRes);
1169
- });
1170
- });
1171
- } else if (props.fallback !== undefined) {
1172
- currentScope = new Scope(getActiveScope());
1173
- untrack(() => {
1174
- runInScope(currentScope, () => {
1175
- const fallbackRes = typeof props.fallback === "function" ? props.fallback() : props.fallback;
1176
- insertChild(frag, fallbackRes);
1177
- });
1178
- });
1179
- }
1180
- currentContent = Array.from(frag.childNodes);
1181
- const parent = marker.parentNode;
1182
- if (parent) {
1183
- parent.insertBefore(frag, marker);
1184
- }
1185
- });
1186
- onCleanup(() => {
1187
- if (currentScope) {
1188
- currentScope.dispose();
1189
- }
1190
- for (const node of currentContent) {
1191
- if (node.parentNode) {
1192
- node.parentNode.removeChild(node);
1193
- }
1194
- }
1195
- if (marker.parentNode) {
1196
- marker.parentNode.removeChild(marker);
1197
- }
1198
- });
1199
- return initialFrag;
1200
- }
1201
- function For(props) {
1202
- if (typeof document === "undefined") {
1203
- const list = resolveValue(props.each) ?? [];
1204
- if (list.length === 0) {
1205
- return props.fallback ?? null;
1206
- }
1207
- return list.map((item, idx) => props.children(item, () => idx));
1208
- }
1209
- const marker = document.createTextNode("");
1210
- const initialFrag = document.createDocumentFragment();
1211
- let items = [];
1212
- let fallbackScope = null;
1213
- let fallbackNodes = [];
1214
- let isMounted = false;
1215
- effect(() => {
1216
- const list = resolveValue(props.each) ?? [];
1217
- const parent = marker.parentNode ?? (!isMounted ? initialFrag : null);
1218
- if (list.length === 0) {
1219
- for (const rec of items) {
1220
- rec.scope.dispose();
1221
- for (const node of rec.nodes) {
1222
- if (node.parentNode)
1223
- node.parentNode.removeChild(node);
1224
- }
1225
- }
1226
- items = [];
1227
- if (props.fallback !== undefined && fallbackNodes.length === 0 && parent) {
1228
- fallbackScope = new Scope(getActiveScope());
1229
- untrack(() => {
1230
- runInScope(fallbackScope, () => {
1231
- const frag = document.createDocumentFragment();
1232
- insertChild(frag, props.fallback);
1233
- fallbackNodes = Array.from(frag.childNodes);
1234
- if (marker.parentNode) {
1235
- marker.parentNode.insertBefore(frag, marker);
1236
- } else if (!isMounted) {
1237
- initialFrag.appendChild(frag);
1238
- }
1239
- });
1240
- });
1241
- }
1242
- return;
1243
- }
1244
- if (fallbackNodes.length > 0) {
1245
- if (fallbackScope) {
1246
- fallbackScope.dispose();
1247
- fallbackScope = null;
1248
- }
1249
- for (const node of fallbackNodes) {
1250
- if (node.parentNode)
1251
- node.parentNode.removeChild(node);
1252
- }
1253
- fallbackNodes = [];
1254
- }
1255
- if (!parent)
1256
- return;
1257
- const newItems = [];
1258
- const prevMap = new Map;
1259
- for (const rec of items) {
1260
- prevMap.set(rec.item, rec);
1261
- }
1262
- for (let i = 0;i < list.length; i++) {
1263
- const item = list[i];
1264
- const existing = prevMap.get(item);
1265
- if (existing) {
1266
- existing.indexSignal(i);
1267
- newItems.push(existing);
1268
- prevMap.delete(item);
1269
- } else {
1270
- let indexVal = i;
1271
- const indexSubscribers = new Set;
1272
- const indexSignal = (...args) => {
1273
- if (args.length > 0 && args[0] !== undefined && args[0] !== indexVal) {
1274
- indexVal = args[0];
1275
- for (const sub of Array.from(indexSubscribers))
1276
- sub();
1277
- }
1278
- return indexVal;
1279
- };
1280
- const itemScope = new Scope(getActiveScope());
1281
- let itemNodes = [];
1282
- untrack(() => {
1283
- runInScope(itemScope, () => {
1284
- const frag = document.createDocumentFragment();
1285
- const child = props.children(item, indexSignal);
1286
- insertChild(frag, child);
1287
- itemNodes = Array.from(frag.childNodes);
1288
- });
1289
- });
1290
- newItems.push({
1291
- item,
1292
- scope: itemScope,
1293
- nodes: itemNodes,
1294
- indexSignal
1295
- });
1296
- }
1297
- }
1298
- for (const [, removed] of prevMap) {
1299
- removed.scope.dispose();
1300
- for (const node of removed.nodes) {
1301
- if (node.parentNode)
1302
- node.parentNode.removeChild(node);
1303
- }
1304
- }
1305
- if (marker.parentNode) {
1306
- let currentMarker = marker;
1307
- for (let i = newItems.length - 1;i >= 0; i--) {
1308
- const rec = newItems[i];
1309
- for (let j = rec.nodes.length - 1;j >= 0; j--) {
1310
- const node = rec.nodes[j];
1311
- if (node.nextSibling !== currentMarker) {
1312
- marker.parentNode.insertBefore(node, currentMarker);
1313
- }
1314
- currentMarker = node;
1315
- }
1316
- }
1317
- } else if (!isMounted) {
1318
- for (const rec of newItems) {
1319
- for (const node of rec.nodes) {
1320
- initialFrag.appendChild(node);
1321
- }
1322
- }
1323
- }
1324
- items = newItems;
1325
- });
1326
- isMounted = true;
1327
- initialFrag.appendChild(marker);
1328
- onCleanup(() => {
1329
- for (const rec of items) {
1330
- rec.scope.dispose();
1331
- }
1332
- if (fallbackScope) {
1333
- fallbackScope.dispose();
1334
- }
1335
- });
1336
- return initialFrag;
1337
- }
1338
- function Portal(props) {
1339
- if (typeof document === "undefined") {
1340
- return null;
1341
- }
1342
- const marker = document.createTextNode("");
1343
- let currentScope = null;
1344
- let nodes = [];
1345
- effect(() => {
1346
- const target = props.mount ?? (typeof document !== "undefined" ? document.body : null);
1347
- if (!target)
1348
- return;
1349
- if (currentScope) {
1350
- currentScope.dispose();
1351
- currentScope = null;
1352
- }
1353
- for (const node of nodes) {
1354
- if (node.parentNode) {
1355
- node.parentNode.removeChild(node);
1356
- }
1357
- }
1358
- nodes = [];
1359
- currentScope = new Scope(getActiveScope());
1360
- untrack(() => {
1361
- runInScope(currentScope, () => {
1362
- const childRes = typeof props.children === "function" ? props.children() : props.children;
1363
- const frag = document.createDocumentFragment();
1364
- insertChild(frag, childRes);
1365
- nodes = Array.from(frag.childNodes);
1366
- target.appendChild(frag);
1367
- });
1368
- });
1369
- });
1370
- onCleanup(() => {
1371
- if (currentScope) {
1372
- currentScope.dispose();
1373
- currentScope = null;
1374
- }
1375
- for (const node of nodes) {
1376
- if (node.parentNode) {
1377
- node.parentNode.removeChild(node);
1378
- }
1379
- }
1380
- nodes = [];
1381
- });
1382
- return marker;
1383
- }
1384
-
1385
- // src/ui/utils.ts
1386
- var idCounter = 0;
1387
- function createId(prefix = "visage") {
1388
- return `${prefix}-${++idCounter}`;
1389
- }
1390
- function createControllableSignal(options) {
1391
- const isControlled = typeof options.value === "function";
1392
- const internal = signal(options.defaultValue, { internal: true });
1393
- const getter = computed(() => {
1394
- if (isControlled) {
1395
- const externalVal = options.value();
1396
- if (externalVal !== undefined)
1397
- return externalVal;
1398
- }
1399
- return internal();
1400
- }, { internal: true });
1401
- const setter = (next) => {
1402
- const currentVal = getter();
1403
- const nextVal = typeof next === "function" ? next(currentVal) : next;
1404
- if (!isControlled) {
1405
- internal.set(nextVal);
1406
- }
1407
- if (options.onChange && nextVal !== currentVal) {
1408
- options.onChange(nextVal);
1409
- }
1410
- };
1411
- return [getter, setter];
1412
- }
1413
- function trapFocus(container, event) {
1414
- if (event.key !== "Tab")
1415
- return;
1416
- const focusables = container.querySelectorAll('button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])');
1417
- if (focusables.length === 0) {
1418
- event.preventDefault();
1419
- return;
1420
- }
1421
- const first = focusables[0];
1422
- const last = focusables[focusables.length - 1];
1423
- if (event.shiftKey) {
1424
- if (document.activeElement === first) {
1425
- last.focus();
1426
- event.preventDefault();
1427
- }
1428
- } else {
1429
- if (document.activeElement === last) {
1430
- first.focus();
1431
- event.preventDefault();
1432
- }
1433
- }
1434
- }
1435
- function onClickOutside(elements, handler) {
1436
- const listener = (event) => {
1437
- const target = event.target;
1438
- if (!target)
1439
- return;
1440
- const list = Array.isArray(elements) ? elements : [elements];
1441
- const isInside = list.some((el) => el?.contains(target));
1442
- if (!isInside) {
1443
- handler(event);
1444
- }
1445
- };
1446
- if (typeof document !== "undefined") {
1447
- document.addEventListener("mousedown", listener, true);
1448
- document.addEventListener("touchstart", listener, true);
1449
- }
1450
- return () => {
1451
- if (typeof document !== "undefined") {
1452
- document.removeEventListener("mousedown", listener, true);
1453
- document.removeEventListener("touchstart", listener, true);
1454
- }
1455
- };
1456
- }
1457
-
1458
- // src/dom/resource.ts
1459
- var SuspenseContext = createContext(null);
1460
- function createResource(sourceOrFetcher, maybeFetcher) {
1461
- const isDirect = typeof maybeFetcher !== "function";
1462
- const fetcher = isDirect ? sourceOrFetcher : maybeFetcher;
1463
- const source = isDirect ? null : sourceOrFetcher;
1464
- const data = signal(undefined);
1465
- const loading = signal(true);
1466
- const error = signal(null);
1467
- let currentPromise = null;
1468
- let requestId = 0;
1469
- const load = async (arg) => {
1470
- const currentReq = ++requestId;
1471
- loading.set(true);
1472
- error.set(null);
1473
- const promise = isDirect ? fetcher() : fetcher(arg);
1474
- currentPromise = promise;
1475
- const suspense = useContext(SuspenseContext);
1476
- if (suspense) {
1477
- suspense.registerPromise(promise);
1478
- }
1479
- try {
1480
- const res = await promise;
1481
- if (currentReq === requestId) {
1482
- data.set(res);
1483
- loading.set(false);
1484
- currentPromise = null;
1485
- }
1486
- return res;
1487
- } catch (err) {
1488
- if (currentReq === requestId) {
1489
- error.set(err);
1490
- loading.set(false);
1491
- currentPromise = null;
1492
- }
1493
- throw err;
1494
- }
1495
- };
1496
- if (source) {
1497
- effect(() => {
1498
- const sourceVal = resolveValue(source);
1499
- if (sourceVal !== false && sourceVal !== null && sourceVal !== undefined) {
1500
- load(sourceVal).catch(() => {});
1501
- }
1502
- });
1503
- } else {
1504
- load().catch(() => {});
1505
- }
1506
- const accessor = () => {
1507
- if (loading() && currentPromise) {
1508
- const suspense = useContext(SuspenseContext);
1509
- if (suspense) {
1510
- suspense.registerPromise(currentPromise);
1511
- }
1512
- }
1513
- return data();
1514
- };
1515
- Object.defineProperties(accessor, {
1516
- loading: { get: () => loading },
1517
- error: { get: () => error },
1518
- mutate: { value: (val) => data.set(val) },
1519
- refetch: { value: () => source ? load(resolveValue(source)) : load() }
1520
- });
1521
- return accessor;
1522
- }
1523
-
1524
- // src/dom/lazy.ts
1525
- function lazy(importer) {
1526
- let loadedComponent = null;
1527
- let loadingPromise = null;
1528
- const preload = () => {
1529
- if (loadedComponent) {
1530
- return Promise.resolve(loadedComponent);
1531
- }
1532
- if (!loadingPromise) {
1533
- loadingPromise = importer().then((mod) => {
1534
- const comp = mod && typeof mod === "object" && "default" in mod ? mod.default : mod;
1535
- loadedComponent = comp;
1536
- return comp;
1537
- }).catch((err) => {
1538
- loadingPromise = null;
1539
- throw err;
1540
- });
1541
- }
1542
- return loadingPromise;
1543
- };
1544
- const LazyWrapper = (props) => {
1545
- if (loadedComponent) {
1546
- return loadedComponent(props);
1547
- }
1548
- const promise = preload();
1549
- const suspense = useContext(SuspenseContext);
1550
- if (suspense) {
1551
- suspense.registerPromise(promise);
1552
- }
1553
- const res = createResource(() => promise);
1554
- return () => {
1555
- const Comp = res();
1556
- return Comp ? Comp(props) : null;
1557
- };
1558
- };
1559
- LazyWrapper.preload = preload;
1560
- return LazyWrapper;
1561
- }
1562
- // src/dom/async.ts
1563
- function Suspense(props) {
1564
- if (typeof document === "undefined") {
1565
- return typeof props.children === "function" ? props.children() : props.children;
1566
- }
1567
- const marker = document.createTextNode("");
1568
- const initialFrag = document.createDocumentFragment();
1569
- const pendingCount = signal(0);
1570
- let currentScope = null;
1571
- let currentNodes = [];
1572
- let isMounted = false;
1573
- const suspenseValue = {
1574
- registerPromise(p) {
1575
- pendingCount.update((c) => c + 1);
1576
- p.finally(() => {
1577
- pendingCount.update((c) => Math.max(0, c - 1));
1578
- });
1579
- }
1580
- };
1581
- const renderContent = (content) => {
1582
- const parent = marker.parentNode ?? (!isMounted ? initialFrag : null);
1583
- if (!parent)
1584
- return;
1585
- for (const n of currentNodes) {
1586
- if (n.parentNode)
1587
- n.parentNode.removeChild(n);
1588
- }
1589
- currentNodes = [];
1590
- const frag = document.createDocumentFragment();
1591
- insertChild(frag, content);
1592
- currentNodes = Array.from(frag.childNodes);
1593
- if (marker.parentNode) {
1594
- marker.parentNode.insertBefore(frag, marker);
1595
- } else if (!isMounted) {
1596
- initialFrag.appendChild(frag);
1597
- }
1598
- };
1599
- effect(() => {
1600
- if (currentScope) {
1601
- currentScope.dispose();
1602
- currentScope = null;
1603
- }
1604
- currentScope = new Scope(getActiveScope());
1605
- runInScope(currentScope, () => {
1606
- let threwPromise = null;
1607
- let rendered = null;
1608
- try {
1609
- const SuspenseProvider = SuspenseContext.Provider;
1610
- rendered = SuspenseProvider({
1611
- value: suspenseValue,
1612
- children: props.children
1613
- });
1614
- } catch (err) {
1615
- if (err && typeof err.then === "function") {
1616
- threwPromise = err;
1617
- suspenseValue.registerPromise(err);
1618
- } else {
1619
- throw err;
1620
- }
1621
- }
1622
- if (pendingCount() > 0 || threwPromise) {
1623
- renderContent(props.fallback);
1624
- } else {
1625
- renderContent(rendered);
1626
- }
1627
- });
1628
- });
1629
- isMounted = true;
1630
- initialFrag.appendChild(marker);
1631
- onCleanup(() => {
1632
- if (currentScope)
1633
- currentScope.dispose();
1634
- });
1635
- return initialFrag;
1636
- }
1637
- function ErrorBoundary(props) {
1638
- if (typeof document === "undefined") {
1639
- try {
1640
- return typeof props.children === "function" ? props.children() : props.children;
1641
- } catch (err) {
1642
- return typeof props.fallback === "function" ? props.fallback(err, () => {}) : props.fallback;
1643
- }
1644
- }
1645
- const marker = document.createTextNode("");
1646
- const initialFrag = document.createDocumentFragment();
1647
- const currentError = signal(null);
1648
- let currentScope = null;
1649
- let currentNodes = [];
1650
- let isMounted = false;
1651
- const reset = () => {
1652
- currentError.set(null);
1653
- };
1654
- const renderNodes = (child) => {
1655
- const parent = marker.parentNode ?? (!isMounted ? initialFrag : null);
1656
- if (!parent)
1657
- return;
1658
- for (const n of currentNodes) {
1659
- if (n.parentNode)
1660
- n.parentNode.removeChild(n);
1661
- }
1662
- currentNodes = [];
1663
- const frag = document.createDocumentFragment();
1664
- insertChild(frag, child);
1665
- currentNodes = Array.from(frag.childNodes);
1666
- if (marker.parentNode) {
1667
- marker.parentNode.insertBefore(frag, marker);
1668
- } else if (!isMounted) {
1669
- initialFrag.appendChild(frag);
1670
- }
1671
- };
1672
- effect(() => {
1673
- const err = currentError();
1674
- if (currentScope) {
1675
- currentScope.dispose();
1676
- currentScope = null;
1677
- }
1678
- currentScope = new Scope(getActiveScope());
1679
- runInScope(currentScope, () => {
1680
- if (err !== null) {
1681
- const fallbackNode = typeof props.fallback === "function" ? props.fallback(err, reset) : props.fallback;
1682
- renderNodes(fallbackNode);
1683
- } else {
1684
- try {
1685
- const content = typeof props.children === "function" ? props.children() : props.children;
1686
- renderNodes(content);
1687
- } catch (catchedErr) {
1688
- currentError.set(catchedErr);
1689
- }
1690
- }
1691
- });
1692
- });
1693
- isMounted = true;
1694
- initialFrag.appendChild(marker);
1695
- onCleanup(() => {
1696
- if (currentScope)
1697
- currentScope.dispose();
1698
- });
1699
- return initialFrag;
1700
- }
1701
- // src/jsx-runtime/index.ts
1702
- var SVG_NS = "http://www.w3.org/2000/svg";
1703
- var SVG_TAGS = new Set([
1704
- "svg",
1705
- "path",
1706
- "circle",
1707
- "rect",
1708
- "g",
1709
- "line",
1710
- "polyline",
1711
- "polygon",
1712
- "text",
1713
- "defs",
1714
- "clipPath",
1715
- "linearGradient",
1716
- "radialGradient",
1717
- "stop"
1718
- ]);
1719
- function Fragment(props) {
1720
- if (typeof document === "undefined") {
1721
- return props.children !== undefined ? props.children : [];
1722
- }
1723
- const fragment = document.createDocumentFragment();
1724
- if (props.children !== undefined) {
1725
- insertChild(fragment, props.children);
1726
- }
1727
- return fragment;
1728
- }
1729
- function jsx(type, props = {}, key) {
1730
- if (typeof type === "function") {
1731
- return type(props, key);
1732
- }
1733
- if (typeof type === "string") {
1734
- const { children, ...restProps } = props;
1735
- if (typeof document === "undefined") {
1736
- const attributes = new Map;
1737
- for (const propName in restProps) {
1738
- const val = restProps[propName];
1739
- if (propName === "className" || propName === "class") {
1740
- const resolved = typeof val === "function" ? val() : val;
1741
- if (resolved)
1742
- attributes.set("class", resolved);
1743
- } else if (propName === "style") {
1744
- const val = restProps[propName];
1745
- const resolved = resolveValue(val);
1746
- if (typeof resolved === "string") {
1747
- attributes.set("style", resolved);
1748
- } else if (typeof resolved === "object" && resolved !== null) {
1749
- const styleStr = Object.entries(resolved).map(([k, v]) => {
1750
- const finalVal = resolveValue(v);
1751
- const formatted = formatStyleProp(k, finalVal);
1752
- if (!formatted)
1753
- return "";
1754
- const kebab = k.startsWith("--") ? k : k.replace(/([A-Z])/g, "-$1").toLowerCase();
1755
- return `${kebab}: ${formatted}`;
1756
- }).filter(Boolean).join("; ");
1757
- if (styleStr)
1758
- attributes.set("style", styleStr);
1759
- }
1760
- } else if (!propName.startsWith("on")) {
1761
- const resolved = typeof val === "function" ? val() : val;
1762
- if (resolved === true) {
1763
- attributes.set(propName, propName);
1764
- } else if (resolved !== false && resolved !== null && resolved !== undefined) {
1765
- attributes.set(propName, resolved);
1766
- }
1767
- }
1768
- }
1769
- const childNodes = children !== undefined ? Array.isArray(children) ? children : [children] : [];
1770
- return {
1771
- tagName: type,
1772
- attributes,
1773
- childNodes
1774
- };
1775
- }
1776
- const isSvg = SVG_TAGS.has(type);
1777
- const element = isSvg ? document.createElementNS(SVG_NS, type) : document.createElement(type);
1778
- for (const propName in restProps) {
1779
- setAttribute(element, propName, restProps[propName]);
1780
- }
1781
- if (children !== undefined) {
1782
- insertChild(element, children);
1783
- }
1784
- return element;
1785
- }
1786
- return type;
1787
- }
1788
- var jsxs = jsx;
1789
- var jsxDEV = jsx;
1790
-
1791
- // src/ui/accordion.tsx
1792
- var AccordionContext = createContext(null);
1793
- function useAccordionContext() {
1794
- return useContext(AccordionContext);
1795
- }
1796
- function AccordionRoot(props) {
1797
- const isSingle = props.type === "single";
1798
- const collapsible = props.collapsible ?? !isSingle;
1799
- const [singleValue, setSingleValue] = createControllableSignal({
1800
- value: isSingle ? props.value : undefined,
1801
- defaultValue: isSingle ? props.defaultValue ?? "" : "",
1802
- onChange: isSingle ? props.onValueChange : undefined
1803
- });
1804
- const [multiValue, setMultiValue] = createControllableSignal({
1805
- value: !isSingle ? props.value : undefined,
1806
- defaultValue: !isSingle ? props.defaultValue ?? [] : [],
1807
- onChange: !isSingle ? props.onValueChange : undefined
1808
- });
1809
- const isExpanded = (val) => {
1810
- if (isSingle) {
1811
- return singleValue() === val;
1812
- }
1813
- return multiValue().includes(val);
1814
- };
1815
- const toggleItem = (val) => {
1816
- if (isSingle) {
1817
- if (singleValue() === val) {
1818
- if (collapsible) {
1819
- setSingleValue("");
1820
- }
1821
- } else {
1822
- setSingleValue(val);
1823
- }
1824
- } else {
1825
- const current = multiValue();
1826
- if (current.includes(val)) {
1827
- setMultiValue(current.filter((item) => item !== val));
1828
- } else {
1829
- setMultiValue([...current, val]);
1830
- }
1831
- }
1832
- };
1833
- const ctx = {
1834
- isExpanded,
1835
- toggleItem,
1836
- type: props.type,
1837
- collapsible
1838
- };
1839
- const {
1840
- as: Tag = "div",
1841
- items,
1842
- itemClass,
1843
- triggerClass,
1844
- contentClass,
1845
- children,
1846
- class: className,
1847
- style,
1848
- ...rest
1849
- } = props;
1850
- return AccordionContext.Provider({
1851
- value: ctx,
1852
- children: () => /* @__PURE__ */ jsxs(Tag, {
1853
- class: className,
1854
- style,
1855
- ...rest,
1856
- children: [
1857
- items ? items.map((item) => /* @__PURE__ */ jsx(AccordionItem, {
1858
- value: item.value,
1859
- disabled: item.disabled,
1860
- class: itemClass,
1861
- children: () => /* @__PURE__ */ jsxs(Fragment, {
1862
- children: [
1863
- /* @__PURE__ */ jsx(AccordionTrigger, {
1864
- class: triggerClass,
1865
- children: typeof item.trigger === "function" ? item.trigger() : item.trigger
1866
- }),
1867
- /* @__PURE__ */ jsx(AccordionContent, {
1868
- class: contentClass,
1869
- children: typeof item.content === "function" ? item.content() : item.content
1870
- })
1871
- ]
1872
- })
1873
- })) : null,
1874
- typeof children === "function" ? children() : children
1875
- ]
1876
- })
1877
- });
1878
- }
1879
- var AccordionItemContext = createContext(null);
1880
- function useAccordionItemContext() {
1881
- return useContext(AccordionItemContext);
1882
- }
1883
- function AccordionItem(props) {
1884
- const itemId = createId("accordion-item");
1885
- const ctx = {
1886
- value: props.value,
1887
- itemId
1888
- };
1889
- const accordion = useContext(AccordionContext);
1890
- const isOpen = () => accordion ? accordion.isExpanded(props.value) : false;
1891
- const { value, disabled, as: Tag = "div", children, class: className, style, ...rest } = props;
1892
- return AccordionItemContext.Provider({
1893
- value: ctx,
1894
- children: () => /* @__PURE__ */ jsx(Tag, {
1895
- "data-state": () => isOpen() ? "open" : "closed",
1896
- "data-disabled": disabled,
1897
- class: className,
1898
- style,
1899
- ...rest,
1900
- children: typeof children === "function" ? children() : children
1901
- })
1902
- });
1903
- }
1904
- function AccordionTrigger(props) {
1905
- const accordion = useContext(AccordionContext);
1906
- const item = useContext(AccordionItemContext);
1907
- const isOpen = () => accordion && item ? accordion.isExpanded(item.value) : false;
1908
- const handleClick = (e) => {
1909
- if (props.onClick)
1910
- props.onClick(e);
1911
- if (!e.defaultPrevented && accordion && item) {
1912
- accordion.toggleItem(item.value);
1913
- }
1914
- };
1915
- const { as: Tag = "button", children, onClick, class: className, style, ...rest } = props;
1916
- return /* @__PURE__ */ jsx(Tag, {
1917
- id: item ? `${item.itemId}-trigger` : undefined,
1918
- type: Tag === "button" ? "button" : undefined,
1919
- "aria-expanded": isOpen,
1920
- "aria-controls": item ? `${item.itemId}-content` : undefined,
1921
- "data-state": () => isOpen() ? "open" : "closed",
1922
- class: className,
1923
- style,
1924
- onClick: handleClick,
1925
- ...rest,
1926
- children
1927
- });
1928
- }
1929
- function AccordionContent(props) {
1930
- const accordion = useContext(AccordionContext);
1931
- const item = useContext(AccordionItemContext);
1932
- const isOpen = () => accordion && item ? accordion.isExpanded(item.value) : false;
1933
- const { forceMount, as: Tag = "div", children, class: className, style, ...rest } = props;
1934
- if (forceMount) {
1935
- return /* @__PURE__ */ jsx(Tag, {
1936
- id: item ? `${item.itemId}-content` : undefined,
1937
- role: "region",
1938
- "aria-labelledby": item ? `${item.itemId}-trigger` : undefined,
1939
- "data-state": () => isOpen() ? "open" : "closed",
1940
- hidden: () => !isOpen(),
1941
- class: className,
1942
- style,
1943
- ...rest,
1944
- children
1945
- });
1946
- }
1947
- return /* @__PURE__ */ jsx(Show, {
1948
- when: isOpen,
1949
- children: /* @__PURE__ */ jsx(Tag, {
1950
- id: item ? `${item.itemId}-content` : undefined,
1951
- role: "region",
1952
- "aria-labelledby": item ? `${item.itemId}-trigger` : undefined,
1953
- "data-state": "open",
1954
- class: className,
1955
- style,
1956
- ...rest,
1957
- children
1958
- })
1959
- });
1960
- }
1961
- var Accordion = Object.assign(AccordionRoot, {
1962
- Root: AccordionRoot,
1963
- Item: AccordionItem,
1964
- Trigger: AccordionTrigger,
1965
- Content: AccordionContent
1966
- });
1967
- // src/ui/command-dialog.tsx
1968
- function CommandDialog(props) {
1969
- const [open, setOpen] = createControllableSignal({
1970
- value: props.open,
1971
- defaultValue: props.defaultOpen ?? false,
1972
- onChange: props.onOpenChange
1973
- });
1974
- const { overlayClass, contentClass, style, ...rest } = props;
1975
- return /* @__PURE__ */ jsx(Portal, {
1976
- children: /* @__PURE__ */ jsx("div", {
1977
- style: () => ({
1978
- display: open() ? "flex" : "none",
1979
- position: "fixed",
1980
- inset: 0,
1981
- background: "rgba(0, 0, 0, 0.6)",
1982
- backdropFilter: "blur(4px)",
1983
- alignItems: "flex-start",
1984
- justifyContent: "center",
1985
- paddingTop: "15vh",
1986
- zIndex: 9999
1987
- }),
1988
- class: overlayClass,
1989
- onClick: (e) => {
1990
- if (e.target === e.currentTarget)
1991
- setOpen(false);
1992
- },
1993
- children: /* @__PURE__ */ jsx("div", {
1994
- style: { width: "100%", maxWidth: "560px" },
1995
- class: contentClass,
1996
- children: /* @__PURE__ */ jsx(CommandRoot, {
1997
- ...rest
1998
- })
1999
- })
2000
- })
2001
- });
2002
- }
2003
-
2004
- // src/ui/command.tsx
2005
- var CommandContext = createContext(null);
2006
- function useCommandContext() {
2007
- return useContext(CommandContext);
2008
- }
2009
- function CommandRoot(props) {
2010
- const [search, setSearch] = createControllableSignal({
2011
- value: props.search,
2012
- defaultValue: "",
2013
- onChange: props.onSearchChange
2014
- });
2015
- const [activeValue, setActiveValue] = createControllableSignal({
2016
- value: props.value,
2017
- defaultValue: props.defaultValue ?? "",
2018
- onChange: props.onValueChange
2019
- });
2020
- const commandId = createId("command");
2021
- const filterMatches = (text, keywords) => {
2022
- const q = search().toLowerCase().trim();
2023
- if (!q)
2024
- return true;
2025
- if (text.toLowerCase().includes(q))
2026
- return true;
2027
- if (keywords?.some((k) => k.toLowerCase().includes(q)))
2028
- return true;
2029
- return false;
2030
- };
2031
- const ctx = {
2032
- search,
2033
- setSearch,
2034
- activeValue,
2035
- setActiveValue,
2036
- filterMatches,
2037
- commandId
2038
- };
2039
- const {
2040
- as: Tag = "div",
2041
- placeholder = "Type a command or search...",
2042
- groups,
2043
- items,
2044
- emptyText = "No results found.",
2045
- class: className,
2046
- style,
2047
- inputClass,
2048
- listClass,
2049
- itemClass,
2050
- children,
2051
- ...rest
2052
- } = props;
2053
- if (groups || items) {
2054
- return CommandContext.Provider({
2055
- value: ctx,
2056
- children: () => /* @__PURE__ */ jsxs(Tag, {
2057
- class: className,
2058
- style: { display: "flex", flexDirection: "column", overflow: "hidden", ...style },
2059
- ...rest,
2060
- children: [
2061
- /* @__PURE__ */ jsx(CommandInput, {
2062
- placeholder,
2063
- class: inputClass
2064
- }),
2065
- /* @__PURE__ */ jsxs(CommandList, {
2066
- class: listClass,
2067
- children: [
2068
- /* @__PURE__ */ jsx(CommandEmpty, {
2069
- children: emptyText
2070
- }),
2071
- groups?.map((grp) => /* @__PURE__ */ jsx(CommandGroup, {
2072
- heading: grp.heading,
2073
- children: grp.items.map((item) => /* @__PURE__ */ jsxs(CommandItem, {
2074
- value: item.value,
2075
- shortcut: item.shortcut,
2076
- disabled: item.disabled,
2077
- onSelect: item.onSelect,
2078
- keywords: item.keywords,
2079
- class: item.class ?? itemClass,
2080
- children: [
2081
- item.icon ? /* @__PURE__ */ jsx("span", {
2082
- style: { display: "inline-flex", alignItems: "center", marginRight: "8px" },
2083
- children: typeof item.icon === "function" ? item.icon() : item.icon
2084
- }) : null,
2085
- typeof item.label === "function" ? item.label() : item.label
2086
- ]
2087
- }))
2088
- })),
2089
- items?.map((item) => /* @__PURE__ */ jsxs(CommandItem, {
2090
- value: item.value,
2091
- shortcut: item.shortcut,
2092
- disabled: item.disabled,
2093
- onSelect: item.onSelect,
2094
- keywords: item.keywords,
2095
- class: item.class ?? itemClass,
2096
- children: [
2097
- item.icon ? /* @__PURE__ */ jsx("span", {
2098
- style: { display: "inline-flex", alignItems: "center", marginRight: "8px" },
2099
- children: typeof item.icon === "function" ? item.icon() : item.icon
2100
- }) : null,
2101
- typeof item.label === "function" ? item.label() : item.label
2102
- ]
2103
- })),
2104
- typeof children === "function" ? children() : children
2105
- ]
2106
- })
2107
- ]
2108
- })
2109
- });
2110
- }
2111
- return CommandContext.Provider({
2112
- value: ctx,
2113
- children: () => /* @__PURE__ */ jsx(Tag, {
2114
- class: className,
2115
- style,
2116
- ...rest,
2117
- children: typeof children === "function" ? children() : children
2118
- })
2119
- });
2120
- }
2121
- function CommandInput(props) {
2122
- const ctx = useContext(CommandContext);
2123
- const handleKeyDown = (e) => {
2124
- const list = e.currentTarget.closest('[role="combobox"], [data-command-root], div')?.querySelector('[role="listbox"]');
2125
- if (!list)
2126
- return;
2127
- const items = Array.from(list.querySelectorAll('[role="option"]:not([aria-disabled="true"]):not([style*="display: none"])'));
2128
- if (items.length === 0)
2129
- return;
2130
- const currentActive = items.find((el) => el.getAttribute("aria-selected") === "true") ?? items[0];
2131
- const index = currentActive ? items.indexOf(currentActive) : 0;
2132
- if (e.key === "ArrowDown") {
2133
- e.preventDefault();
2134
- const nextIndex = (index + 1) % items.length;
2135
- const nextItem = items[nextIndex];
2136
- if (nextItem && ctx) {
2137
- ctx.setActiveValue(nextItem.getAttribute("data-value") ?? "");
2138
- nextItem.scrollIntoView({ block: "nearest" });
2139
- }
2140
- } else if (e.key === "ArrowUp") {
2141
- e.preventDefault();
2142
- const prevIndex = (index - 1 + items.length) % items.length;
2143
- const prevItem = items[prevIndex];
2144
- if (prevItem && ctx) {
2145
- ctx.setActiveValue(prevItem.getAttribute("data-value") ?? "");
2146
- prevItem.scrollIntoView({ block: "nearest" });
2147
- }
2148
- } else if (e.key === "Enter" && currentActive) {
2149
- e.preventDefault();
2150
- currentActive.click();
2151
- }
2152
- };
2153
- const { placeholder = "Type a command...", class: className, style, ...rest } = props;
2154
- return /* @__PURE__ */ jsx("input", {
2155
- type: "text",
2156
- role: "searchbox",
2157
- placeholder,
2158
- value: () => ctx?.search() ?? "",
2159
- onInput: (e) => ctx?.setSearch(e.target.value),
2160
- onKeyDown: handleKeyDown,
2161
- class: className,
2162
- style,
2163
- ...rest
2164
- });
2165
- }
2166
- function CommandList(props) {
2167
- const { as: Tag = "div", children, class: className, style, ...rest } = props;
2168
- return /* @__PURE__ */ jsx(Tag, {
2169
- role: "listbox",
2170
- class: className,
2171
- style: { overflowY: "auto", ...style },
2172
- ...rest,
2173
- children
2174
- });
2175
- }
2176
- function CommandEmpty(props) {
2177
- const ctx = useContext(CommandContext);
2178
- const { as: Tag = "div", children, class: className, style, ...rest } = props;
2179
- return /* @__PURE__ */ jsx(Tag, {
2180
- class: className,
2181
- style: () => ({
2182
- display: ctx && ctx.search().trim().length > 0 ? undefined : "none",
2183
- textAlign: "center",
2184
- padding: "16px",
2185
- color: "#94a3b8",
2186
- ...style
2187
- }),
2188
- ...rest,
2189
- children
2190
- });
2191
- }
2192
- function CommandGroup(props) {
2193
- const { heading, as: Tag = "div", children, class: className, style, ...rest } = props;
2194
- return /* @__PURE__ */ jsxs(Tag, {
2195
- role: "group",
2196
- class: className,
2197
- style,
2198
- ...rest,
2199
- children: [
2200
- heading ? /* @__PURE__ */ jsx("div", {
2201
- style: {
2202
- fontSize: "11px",
2203
- fontWeight: 700,
2204
- textTransform: "uppercase",
2205
- letterSpacing: "0.05em",
2206
- color: "#64748b",
2207
- padding: "6px 10px"
2208
- },
2209
- children: heading
2210
- }) : null,
2211
- children
2212
- ]
2213
- });
2214
- }
2215
- function CommandItem(props) {
2216
- const ctx = useContext(CommandContext);
2217
- const itemValue = props.value ?? (typeof props.children === "string" ? props.children : createId("item"));
2218
- const isVisible = () => {
2219
- if (!ctx)
2220
- return true;
2221
- const text = typeof props.children === "string" ? props.children : itemValue;
2222
- return ctx.filterMatches(text, props.keywords);
2223
- };
2224
- const isSelected = () => ctx ? ctx.activeValue() === itemValue : false;
2225
- const handleClick = () => {
2226
- if (props.disabled)
2227
- return;
2228
- if (props.onSelect)
2229
- props.onSelect();
2230
- };
2231
- const { as: Tag = "div", shortcut, disabled, children, class: className, style, ...rest } = props;
2232
- return /* @__PURE__ */ jsxs(Tag, {
2233
- role: "option",
2234
- "data-value": itemValue,
2235
- "aria-selected": isSelected,
2236
- "aria-disabled": disabled,
2237
- class: className,
2238
- style: () => ({
2239
- display: isVisible() ? "flex" : "none",
2240
- alignItems: "center",
2241
- justifyContent: "space-between",
2242
- cursor: disabled ? "not-allowed" : "pointer",
2243
- ...style
2244
- }),
2245
- onClick: handleClick,
2246
- ...rest,
2247
- children: [
2248
- /* @__PURE__ */ jsx("div", {
2249
- style: { display: "flex", alignItems: "center" },
2250
- children
2251
- }),
2252
- shortcut ? /* @__PURE__ */ jsx("span", {
2253
- style: {
2254
- fontSize: "11px",
2255
- color: "#64748b",
2256
- background: "#1e293b",
2257
- padding: "2px 6px",
2258
- borderRadius: "4px"
2259
- },
2260
- children: shortcut
2261
- }) : null
2262
- ]
2263
- });
2264
- }
2265
- var Command = Object.assign(CommandRoot, {
2266
- Root: CommandRoot,
2267
- Dialog: CommandDialog,
2268
- Input: CommandInput,
2269
- List: CommandList,
2270
- Empty: CommandEmpty,
2271
- Group: CommandGroup,
2272
- Item: CommandItem
2273
- });
2274
- // src/ui/data-table.tsx
2275
- function DataTable(props) {
2276
- const [sortState, setSortState] = createControllableSignal({
2277
- value: props.sort,
2278
- defaultValue: { column: "", direction: null },
2279
- onChange: props.onSortChange
2280
- });
2281
- const [selectedKeys, setSelectedKeys] = createControllableSignal({
2282
- value: props.selectedKeys,
2283
- defaultValue: [],
2284
- onChange: props.onSelectionChange
2285
- });
2286
- const [currentPage, setCurrentPage] = createSignal(0, { internal: true });
2287
- const pageSize = props.pageSize ?? 10;
2288
- const selectionMode = props.selection ?? "none";
2289
- const getRowId = (row, index) => {
2290
- if (props.getRowId)
2291
- return props.getRowId(row, index);
2292
- if (row && typeof row === "object" && "id" in row)
2293
- return String(row.id);
2294
- return String(index);
2295
- };
2296
- const filteredData = () => {
2297
- const raw = typeof props.data === "function" ? props.data() : props.data;
2298
- if (!raw)
2299
- return [];
2300
- const filterQuery = props.filter ? (typeof props.filter === "function" ? props.filter() : props.filter)?.toLowerCase().trim() : "";
2301
- if (!filterQuery)
2302
- return raw;
2303
- return raw.filter((row) => Object.values(row).some((val) => String(val).toLowerCase().includes(filterQuery)));
2304
- };
2305
- const sortedData = () => {
2306
- const list = [...filteredData()];
2307
- const currentSort = sortState();
2308
- if (!currentSort.column || !currentSort.direction)
2309
- return list;
2310
- return list.sort((a, b) => {
2311
- const aVal = a[currentSort.column];
2312
- const bVal = b[currentSort.column];
2313
- if (aVal === bVal)
2314
- return 0;
2315
- if (aVal === null || aVal === undefined)
2316
- return 1;
2317
- if (bVal === null || bVal === undefined)
2318
- return -1;
2319
- const comp = aVal < bVal ? -1 : 1;
2320
- return currentSort.direction === "asc" ? comp : -comp;
2321
- });
2322
- };
2323
- const totalPages = () => Math.ceil(sortedData().length / pageSize) || 1;
2324
- const paginatedData = () => {
2325
- if (!props.pageSize)
2326
- return sortedData();
2327
- const start = currentPage() * pageSize;
2328
- return sortedData().slice(start, start + pageSize);
2329
- };
2330
- const handleSort = (colId) => {
2331
- const current = sortState();
2332
- if (current.column !== colId) {
2333
- setSortState({ column: colId, direction: "asc" });
2334
- } else if (current.direction === "asc") {
2335
- setSortState({ column: colId, direction: "desc" });
2336
- } else {
2337
- setSortState({ column: "", direction: null });
2338
- }
2339
- };
2340
- const handleSelectRow = (key, e) => {
2341
- e.stopPropagation();
2342
- if (selectionMode === "single") {
2343
- setSelectedKeys(selectedKeys().includes(key) ? [] : [key]);
2344
- } else if (selectionMode === "multi") {
2345
- const current = selectedKeys();
2346
- if (current.includes(key)) {
2347
- setSelectedKeys(current.filter((k) => k !== key));
2348
- } else {
2349
- setSelectedKeys([...current, key]);
2350
- }
2351
- }
2352
- };
2353
- const handleSelectAll = () => {
2354
- if (selectionMode !== "multi")
2355
- return;
2356
- const allCurrentKeys = paginatedData().map((row, i) => getRowId(row, i));
2357
- const allSelected = allCurrentKeys.every((k) => selectedKeys().includes(k));
2358
- if (allSelected) {
2359
- setSelectedKeys(selectedKeys().filter((k) => !allCurrentKeys.includes(k)));
2360
- } else {
2361
- setSelectedKeys(Array.from(new Set([...selectedKeys(), ...allCurrentKeys])));
2362
- }
2363
- };
2364
- const {
2365
- class: className,
2366
- style,
2367
- tableClass,
2368
- headerClass,
2369
- rowClass,
2370
- cellClass,
2371
- paginationClass,
2372
- emptyText = "No data available",
2373
- ...rest
2374
- } = props;
2375
- return /* @__PURE__ */ jsxs("div", {
2376
- class: className,
2377
- style: { display: "flex", flexDirection: "column", width: "100%", ...style },
2378
- ...rest,
2379
- children: [
2380
- /* @__PURE__ */ jsx("div", {
2381
- style: { overflowX: "auto", width: "100%" },
2382
- children: /* @__PURE__ */ jsxs("table", {
2383
- class: tableClass,
2384
- style: { width: "100%", borderCollapse: "collapse" },
2385
- children: [
2386
- /* @__PURE__ */ jsx("thead", {
2387
- class: headerClass,
2388
- children: /* @__PURE__ */ jsxs("tr", {
2389
- children: [
2390
- selectionMode === "multi" ? /* @__PURE__ */ jsx("th", {
2391
- style: { width: "40px", padding: "8px" },
2392
- children: /* @__PURE__ */ jsx("input", {
2393
- type: "checkbox",
2394
- checked: () => {
2395
- const keys = paginatedData().map((row, i) => getRowId(row, i));
2396
- return keys.length > 0 && keys.every((k) => selectedKeys().includes(k));
2397
- },
2398
- onChange: handleSelectAll
2399
- })
2400
- }) : null,
2401
- props.columns.map((col) => {
2402
- const isSorted = () => sortState().column === col.id;
2403
- const sortDir = () => isSorted() ? sortState().direction : null;
2404
- return /* @__PURE__ */ jsx("th", {
2405
- style: {
2406
- width: col.width,
2407
- textAlign: col.align ?? "left",
2408
- cursor: col.sortable ? "pointer" : "default",
2409
- userSelect: col.sortable ? "none" : "auto",
2410
- padding: "10px 12px"
2411
- },
2412
- onClick: () => {
2413
- if (col.sortable)
2414
- handleSort(col.id);
2415
- },
2416
- children: /* @__PURE__ */ jsxs("div", {
2417
- style: { display: "inline-flex", alignItems: "center", gap: "6px" },
2418
- children: [
2419
- /* @__PURE__ */ jsx("span", {
2420
- children: typeof col.header === "function" ? col.header() : col.header
2421
- }),
2422
- col.sortable ? /* @__PURE__ */ jsx("span", {
2423
- style: { fontSize: "10px", color: isSorted() ? "#38bdf8" : "#64748b" },
2424
- children: () => sortDir() === "asc" ? "▲" : sortDir() === "desc" ? "▼" : "⇅"
2425
- }) : null
2426
- ]
2427
- })
2428
- });
2429
- })
2430
- ]
2431
- })
2432
- }),
2433
- /* @__PURE__ */ jsx("tbody", {
2434
- children: /* @__PURE__ */ jsx(For, {
2435
- each: paginatedData,
2436
- fallback: /* @__PURE__ */ jsx("tr", {
2437
- children: /* @__PURE__ */ jsx("td", {
2438
- colSpan: props.columns.length + (selectionMode === "multi" ? 1 : 0),
2439
- style: { textAlign: "center", padding: "24px", color: "#64748b" },
2440
- children: emptyText
2441
- })
2442
- }),
2443
- children: (row, idx) => {
2444
- const key = () => getRowId(row, idx());
2445
- const isSelected = () => selectedKeys().includes(key());
2446
- return /* @__PURE__ */ jsxs("tr", {
2447
- class: rowClass,
2448
- style: { cursor: props.onRowClick ? "pointer" : "default" },
2449
- "data-selected": isSelected,
2450
- onClick: () => {
2451
- if (props.onRowClick)
2452
- props.onRowClick(row, idx());
2453
- },
2454
- children: [
2455
- selectionMode === "multi" ? /* @__PURE__ */ jsx("td", {
2456
- style: { width: "40px", padding: "8px" },
2457
- children: /* @__PURE__ */ jsx("input", {
2458
- type: "checkbox",
2459
- checked: isSelected,
2460
- onClick: (e) => handleSelectRow(key(), e)
2461
- })
2462
- }) : null,
2463
- props.columns.map((col) => {
2464
- const content = col.cell ? col.cell(row, idx()) : col.accessorKey ? row[col.accessorKey] : row[col.id];
2465
- return /* @__PURE__ */ jsx("td", {
2466
- class: cellClass,
2467
- style: {
2468
- textAlign: col.align ?? "left",
2469
- padding: "10px 12px"
2470
- },
2471
- children: typeof content === "function" ? content() : content
2472
- });
2473
- })
2474
- ]
2475
- });
2476
- }
2477
- })
2478
- })
2479
- ]
2480
- })
2481
- }),
2482
- props.pageSize ? /* @__PURE__ */ jsxs("div", {
2483
- class: paginationClass,
2484
- style: {
2485
- display: "flex",
2486
- alignItems: "center",
2487
- justifyContent: "space-between",
2488
- padding: "10px 12px",
2489
- borderTop: "1px solid #1e293b",
2490
- fontSize: "12px",
2491
- color: "#94a3b8"
2492
- },
2493
- children: [
2494
- /* @__PURE__ */ jsxs("div", {
2495
- children: [
2496
- "Showing ",
2497
- /* @__PURE__ */ jsx("strong", {
2498
- children: () => currentPage() * pageSize + 1
2499
- }),
2500
- " to",
2501
- " ",
2502
- /* @__PURE__ */ jsx("strong", {
2503
- children: () => Math.min((currentPage() + 1) * pageSize, sortedData().length)
2504
- }),
2505
- " ",
2506
- "of ",
2507
- /* @__PURE__ */ jsx("strong", {
2508
- children: () => sortedData().length
2509
- }),
2510
- " entries"
2511
- ]
2512
- }),
2513
- /* @__PURE__ */ jsxs("div", {
2514
- style: { display: "flex", gap: "6px", alignItems: "center" },
2515
- children: [
2516
- /* @__PURE__ */ jsx("button", {
2517
- type: "button",
2518
- disabled: () => currentPage() === 0,
2519
- onClick: () => setCurrentPage((p) => Math.max(0, p - 1)),
2520
- style: { padding: "4px 8px", cursor: "pointer" },
2521
- children: "Previous"
2522
- }),
2523
- /* @__PURE__ */ jsxs("span", {
2524
- children: [
2525
- "Page ",
2526
- /* @__PURE__ */ jsx("strong", {
2527
- children: () => currentPage() + 1
2528
- }),
2529
- " of ",
2530
- /* @__PURE__ */ jsx("strong", {
2531
- children: totalPages
2532
- })
2533
- ]
2534
- }),
2535
- /* @__PURE__ */ jsx("button", {
2536
- type: "button",
2537
- disabled: () => currentPage() >= totalPages() - 1,
2538
- onClick: () => setCurrentPage((p) => Math.min(totalPages() - 1, p + 1)),
2539
- style: { padding: "4px 8px", cursor: "pointer" },
2540
- children: "Next"
2541
- })
2542
- ]
2543
- })
2544
- ]
2545
- }) : null
2546
- ]
2547
- });
2548
- }
2549
- // src/ui/dialog.tsx
2550
- var DialogContext = createContext(null);
2551
- function useDialogContext() {
2552
- const ctx = useContext(DialogContext);
2553
- return ctx;
2554
- }
2555
- function DialogRoot(props) {
2556
- const [open, setOpen] = createControllableSignal({
2557
- value: props.open,
2558
- defaultValue: props.defaultOpen ?? false,
2559
- onChange: props.onOpenChange
2560
- });
2561
- const titleId = createId("dialog-title");
2562
- const descriptionId = createId("dialog-desc");
2563
- const contentRef = { current: null };
2564
- const ctx = {
2565
- open,
2566
- setOpen,
2567
- titleId,
2568
- descriptionId,
2569
- contentRef
2570
- };
2571
- if (props.trigger !== undefined || props.title !== undefined || props.description !== undefined) {
2572
- return DialogContext.Provider({
2573
- value: ctx,
2574
- children: () => /* @__PURE__ */ jsxs(Fragment, {
2575
- children: [
2576
- props.trigger ? /* @__PURE__ */ jsx(DialogTrigger, {
2577
- as: "span",
2578
- class: props.triggerClass,
2579
- children: typeof props.trigger === "function" ? props.trigger() : props.trigger
2580
- }) : null,
2581
- /* @__PURE__ */ jsx(DialogOverlay, {
2582
- class: props.overlayClass,
2583
- portalled: props.portalled
2584
- }),
2585
- /* @__PURE__ */ jsxs(DialogContent, {
2586
- portalled: props.portalled,
2587
- class: props.contentClass,
2588
- children: [
2589
- props.title ? /* @__PURE__ */ jsx(DialogTitle, {
2590
- class: props.titleClass,
2591
- children: typeof props.title === "function" ? props.title() : props.title
2592
- }) : null,
2593
- props.description ? /* @__PURE__ */ jsx(DialogDescription, {
2594
- class: props.descriptionClass,
2595
- children: typeof props.description === "function" ? props.description() : props.description
2596
- }) : null,
2597
- typeof props.children === "function" ? props.children() : props.children,
2598
- props.footer ? /* @__PURE__ */ jsx("div", {
2599
- class: props.footerClass,
2600
- children: typeof props.footer === "function" ? props.footer() : props.footer
2601
- }) : null
2602
- ]
2603
- })
2604
- ]
2605
- })
2606
- });
2607
- }
2608
- return DialogContext.Provider({
2609
- value: ctx,
2610
- children: props.children
2611
- });
2612
- }
2613
- function DialogTrigger(props) {
2614
- const ctx = useContext(DialogContext);
2615
- const handleClick = (e) => {
2616
- if (props.onClick)
2617
- props.onClick(e);
2618
- if (!e.defaultPrevented && ctx) {
2619
- ctx.setOpen(true);
2620
- }
2621
- };
2622
- const { as: Tag = "button", children, onClick, class: className, style, ...rest } = props;
2623
- return /* @__PURE__ */ jsx(Tag, {
2624
- type: Tag === "button" ? "button" : undefined,
2625
- "aria-haspopup": "dialog",
2626
- "aria-expanded": () => ctx?.open() ?? false,
2627
- "data-state": () => ctx?.open() ? "open" : "closed",
2628
- class: className,
2629
- style,
2630
- onClick: handleClick,
2631
- ...rest,
2632
- children
2633
- });
2634
- }
2635
- function DialogPortal(props) {
2636
- return /* @__PURE__ */ jsx(Portal, {
2637
- mount: props.mount,
2638
- children: props.children
2639
- });
2640
- }
2641
- function DialogOverlay(props) {
2642
- const ctx = useContext(DialogContext);
2643
- const handleClick = (e) => {
2644
- if (props.onClick)
2645
- props.onClick(e);
2646
- if (!e.defaultPrevented && ctx) {
2647
- ctx.setOpen(false);
2648
- }
2649
- };
2650
- const {
2651
- as: Tag = "div",
2652
- children,
2653
- onClick,
2654
- class: className,
2655
- style,
2656
- portalled = true,
2657
- mount,
2658
- ...rest
2659
- } = props;
2660
- const overlay = /* @__PURE__ */ jsx(Tag, {
2661
- "data-state": () => ctx?.open() ? "open" : "closed",
2662
- style: () => ({
2663
- display: ctx?.open() ? undefined : "none",
2664
- ...style
2665
- }),
2666
- class: className,
2667
- onClick: handleClick,
2668
- "aria-hidden": "true",
2669
- ...rest,
2670
- children
2671
- });
2672
- return portalled ? /* @__PURE__ */ jsx(Portal, {
2673
- mount,
2674
- children: overlay
2675
- }) : overlay;
2676
- }
2677
- function DialogContent(props) {
2678
- const ctx = useContext(DialogContext);
2679
- const handleKeyDown = (e) => {
2680
- if (props.onKeyDown)
2681
- props.onKeyDown(e);
2682
- if (e.defaultPrevented)
2683
- return;
2684
- if (e.key === "Escape") {
2685
- ctx?.setOpen(false);
2686
- e.stopPropagation();
2687
- } else if (e.key === "Tab" && ctx?.contentRef.current) {
2688
- trapFocus(ctx.contentRef.current, e);
2689
- }
2690
- };
2691
- const handleClick = (e) => {
2692
- if (props.onClick)
2693
- props.onClick(e);
2694
- if (e.defaultPrevented)
2695
- return;
2696
- const target = e.target;
2697
- if (target?.closest("[data-dialog-close]")) {
2698
- ctx?.setOpen(false);
2699
- }
2700
- };
2701
- const {
2702
- as: Tag = "div",
2703
- children,
2704
- onKeyDown,
2705
- onClick: _onClick,
2706
- class: className,
2707
- style,
2708
- portalled = true,
2709
- mount,
2710
- ...rest
2711
- } = props;
2712
- const content = /* @__PURE__ */ jsx(Tag, {
2713
- ref: (el) => {
2714
- if (ctx) {
2715
- ctx.contentRef.current = el;
2716
- if (el && ctx.open()) {
2717
- const focusable = el.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
2718
- if (focusable) {
2719
- setTimeout(() => focusable.focus(), 0);
2720
- }
2721
- }
2722
- }
2723
- },
2724
- role: "dialog",
2725
- "aria-modal": "true",
2726
- "aria-labelledby": ctx?.titleId,
2727
- "aria-describedby": ctx?.descriptionId,
2728
- "data-state": () => ctx?.open() ? "open" : "closed",
2729
- style: () => ({
2730
- display: ctx?.open() ? undefined : "none",
2731
- ...style
2732
- }),
2733
- class: className,
2734
- onKeyDown: handleKeyDown,
2735
- onClick: handleClick,
2736
- tabIndex: -1,
2737
- ...rest,
2738
- children
2739
- });
2740
- return portalled ? /* @__PURE__ */ jsx(Portal, {
2741
- mount,
2742
- children: content
2743
- }) : content;
2744
- }
2745
- function DialogTitle(props) {
2746
- const ctx = useContext(DialogContext);
2747
- const { as: Tag = "h2", children, class: className, style, ...rest } = props;
2748
- return /* @__PURE__ */ jsx(Tag, {
2749
- id: ctx?.titleId,
2750
- class: className,
2751
- style,
2752
- ...rest,
2753
- children
2754
- });
2755
- }
2756
- function DialogDescription(props) {
2757
- const ctx = useContext(DialogContext);
2758
- const { as: Tag = "p", children, class: className, style, ...rest } = props;
2759
- return /* @__PURE__ */ jsx(Tag, {
2760
- id: ctx?.descriptionId,
2761
- class: className,
2762
- style,
2763
- ...rest,
2764
- children
2765
- });
2766
- }
2767
- function DialogClose(props) {
2768
- const ctx = useContext(DialogContext);
2769
- const handleClick = (e) => {
2770
- if (props.onClick)
2771
- props.onClick(e);
2772
- if (!e.defaultPrevented && ctx) {
2773
- ctx.setOpen(false);
2774
- }
2775
- };
2776
- const { as: Tag = "button", children, onClick, class: className, style, ...rest } = props;
2777
- return /* @__PURE__ */ jsx(Tag, {
2778
- type: Tag === "button" ? "button" : undefined,
2779
- "data-dialog-close": "",
2780
- class: className,
2781
- style,
2782
- onClick: handleClick,
2783
- ...rest,
2784
- children
2785
- });
2786
- }
2787
- var Dialog = Object.assign(DialogRoot, {
2788
- Root: DialogRoot,
2789
- Trigger: DialogTrigger,
2790
- Portal: DialogPortal,
2791
- Overlay: DialogOverlay,
2792
- Content: DialogContent,
2793
- Title: DialogTitle,
2794
- Description: DialogDescription,
2795
- Close: DialogClose
2796
- });
2797
- // src/ui/dropdown-menu.tsx
2798
- var DropdownMenuContext = createContext(null);
2799
- function useDropdownMenuContext() {
2800
- return useContext(DropdownMenuContext);
2801
- }
2802
- function DropdownMenuRoot(props) {
2803
- const [open, setOpen] = createControllableSignal({
2804
- value: props.open,
2805
- defaultValue: props.defaultOpen ?? false,
2806
- onChange: props.onOpenChange
2807
- });
2808
- const triggerRef = { current: null };
2809
- const contentRef = { current: null };
2810
- const menuId = createId("dropdown-menu");
2811
- const ctx = {
2812
- open,
2813
- setOpen,
2814
- triggerRef,
2815
- contentRef,
2816
- menuId
2817
- };
2818
- if (props.trigger !== undefined || props.items !== undefined) {
2819
- return DropdownMenuContext.Provider({
2820
- value: ctx,
2821
- children: () => /* @__PURE__ */ jsxs("div", {
2822
- class: "visage-dropdown-root",
2823
- style: { position: "relative", display: "inline-block" },
2824
- children: [
2825
- props.trigger ? /* @__PURE__ */ jsx(DropdownMenuTrigger, {
2826
- as: "span",
2827
- class: props.triggerClass,
2828
- children: typeof props.trigger === "function" ? props.trigger() : props.trigger
2829
- }) : null,
2830
- /* @__PURE__ */ jsxs(DropdownMenuContent, {
2831
- portalled: props.portalled ?? false,
2832
- class: props.contentClass,
2833
- children: [
2834
- props.items ? props.items.map((item) => {
2835
- if (item.separator) {
2836
- return /* @__PURE__ */ jsx(DropdownMenuSeparator, {
2837
- class: item.class ?? props.separatorClass
2838
- });
2839
- }
2840
- return /* @__PURE__ */ jsxs(DropdownMenuItem, {
2841
- disabled: item.disabled,
2842
- onSelect: item.onSelect,
2843
- class: [props.itemClass, item.class, item.danger ? "danger" : ""].filter(Boolean).join(" "),
2844
- children: [
2845
- item.icon ? /* @__PURE__ */ jsx("span", {
2846
- class: "dropdown-item-icon",
2847
- style: {
2848
- display: "inline-flex",
2849
- alignItems: "center",
2850
- marginRight: "8px"
2851
- },
2852
- children: typeof item.icon === "function" ? item.icon() : item.icon
2853
- }) : null,
2854
- typeof item.label === "function" ? item.label() : item.label
2855
- ]
2856
- });
2857
- }) : null,
2858
- typeof props.children === "function" ? props.children() : props.children
2859
- ]
2860
- })
2861
- ]
2862
- })
2863
- });
2864
- }
2865
- return DropdownMenuContext.Provider({
2866
- value: ctx,
2867
- children: props.children
2868
- });
2869
- }
2870
- function DropdownMenuTrigger(props) {
2871
- const ctx = useContext(DropdownMenuContext);
2872
- const handleClick = (e) => {
2873
- if (props.onClick)
2874
- props.onClick(e);
2875
- if (!e.defaultPrevented && ctx) {
2876
- ctx.setOpen(!ctx.open());
2877
- }
2878
- };
2879
- const handleKeyDown = (e) => {
2880
- if (props.onKeyDown)
2881
- props.onKeyDown(e);
2882
- if (e.defaultPrevented)
2883
- return;
2884
- if (e.key === "ArrowDown" || e.key === "Enter" || e.key === " ") {
2885
- if (ctx) {
2886
- ctx.setOpen(true);
2887
- e.preventDefault();
2888
- setTimeout(() => {
2889
- const firstItem = ctx.contentRef.current?.querySelector('[role="menuitem"]:not([disabled])');
2890
- firstItem?.focus();
2891
- }, 0);
2892
- }
2893
- }
2894
- };
2895
- const {
2896
- as: Tag = "button",
2897
- children,
2898
- onClick,
2899
- onKeyDown,
2900
- class: className,
2901
- style,
2902
- ...rest
2903
- } = props;
2904
- return /* @__PURE__ */ jsx(Tag, {
2905
- ref: (el) => {
2906
- if (ctx)
2907
- ctx.triggerRef.current = el;
2908
- },
2909
- type: Tag === "button" ? "button" : undefined,
2910
- "aria-haspopup": "menu",
2911
- "aria-expanded": () => ctx?.open() ?? false,
2912
- "aria-controls": ctx?.menuId,
2913
- "data-state": () => ctx?.open() ? "open" : "closed",
2914
- class: className,
2915
- style,
2916
- onClick: handleClick,
2917
- onKeyDown: handleKeyDown,
2918
- ...rest,
2919
- children
2920
- });
2921
- }
2922
- function DropdownMenuPortal(props) {
2923
- return /* @__PURE__ */ jsx(Portal, {
2924
- mount: props.mount,
2925
- children: props.children
2926
- });
2927
- }
2928
- function DropdownMenuContent(props) {
2929
- const ctx = useContext(DropdownMenuContext);
2930
- const handleKeyDown = (e) => {
2931
- if (props.onKeyDown)
2932
- props.onKeyDown(e);
2933
- if (e.defaultPrevented)
2934
- return;
2935
- const el = ctx?.contentRef.current;
2936
- if (!el)
2937
- return;
2938
- const items = Array.from(el.querySelectorAll('[role="menuitem"]:not([disabled])'));
2939
- const active = document.activeElement;
2940
- const index = active ? items.indexOf(active) : -1;
2941
- if (e.key === "ArrowDown") {
2942
- const nextIndex = index === items.length - 1 || index === -1 ? 0 : index + 1;
2943
- items[nextIndex]?.focus();
2944
- e.preventDefault();
2945
- } else if (e.key === "ArrowUp") {
2946
- const nextIndex = index <= 0 ? items.length - 1 : index - 1;
2947
- items[nextIndex]?.focus();
2948
- e.preventDefault();
2949
- } else if (e.key === "Home") {
2950
- items[0]?.focus();
2951
- e.preventDefault();
2952
- } else if (e.key === "End") {
2953
- items[items.length - 1]?.focus();
2954
- e.preventDefault();
2955
- } else if (e.key === "Escape") {
2956
- if (ctx) {
2957
- ctx.setOpen(false);
2958
- ctx.triggerRef.current?.focus();
2959
- }
2960
- e.preventDefault();
2961
- } else if (e.key === "Tab") {
2962
- if (ctx)
2963
- ctx.setOpen(false);
2964
- }
2965
- };
2966
- const {
2967
- as: Tag = "div",
2968
- children,
2969
- onKeyDown,
2970
- class: className,
2971
- style,
2972
- portalled = true,
2973
- mount,
2974
- ...rest
2975
- } = props;
2976
- const content = /* @__PURE__ */ jsx(Tag, {
2977
- ref: (el) => {
2978
- if (ctx) {
2979
- ctx.contentRef.current = el;
2980
- if (el) {
2981
- const cleanup = onClickOutside([ctx.triggerRef.current, el], () => {
2982
- if (ctx.open()) {
2983
- ctx.setOpen(false);
2984
- }
2985
- });
2986
- onCleanup(cleanup);
2987
- }
2988
- }
2989
- },
2990
- id: ctx?.menuId,
2991
- role: "menu",
2992
- "aria-orientation": "vertical",
2993
- "data-state": () => ctx?.open() ? "open" : "closed",
2994
- class: className,
2995
- style: () => ({
2996
- display: ctx?.open() ? undefined : "none",
2997
- ...style
2998
- }),
2999
- onKeyDown: handleKeyDown,
3000
- tabIndex: -1,
3001
- ...rest,
3002
- children
3003
- });
3004
- return portalled ? /* @__PURE__ */ jsx(Portal, {
3005
- mount,
3006
- children: content
3007
- }) : content;
3008
- }
3009
- function DropdownMenuItem(props) {
3010
- const ctx = useContext(DropdownMenuContext);
3011
- const closeOnSelect = props.closeOnSelect ?? true;
3012
- const handleSelect = (e) => {
3013
- if (props.disabled)
3014
- return;
3015
- if (props.onSelect)
3016
- props.onSelect(e);
3017
- if (!e.defaultPrevented && closeOnSelect && ctx) {
3018
- ctx.setOpen(false);
3019
- ctx.triggerRef.current?.focus();
3020
- }
3021
- };
3022
- const handleClick = (e) => {
3023
- if (props.onClick)
3024
- props.onClick(e);
3025
- handleSelect(e);
3026
- };
3027
- const handleKeyDown = (e) => {
3028
- if (props.onKeyDown)
3029
- props.onKeyDown(e);
3030
- if (e.key === "Enter" || e.key === " ") {
3031
- e.preventDefault();
3032
- handleSelect(e);
3033
- }
3034
- };
3035
- const {
3036
- disabled,
3037
- closeOnSelect: _cos,
3038
- as: Tag = "div",
3039
- children,
3040
- onClick,
3041
- onKeyDown,
3042
- onSelect: _os,
3043
- class: className,
3044
- style,
3045
- ...rest
3046
- } = props;
3047
- return /* @__PURE__ */ jsx(Tag, {
3048
- role: "menuitem",
3049
- tabIndex: -1,
3050
- "aria-disabled": disabled,
3051
- class: className,
3052
- style,
3053
- onClick: handleClick,
3054
- onKeyDown: handleKeyDown,
3055
- ...rest,
3056
- children
3057
- });
3058
- }
3059
- function DropdownMenuSeparator(props) {
3060
- const { as: Tag = "div", class: className, style, ...rest } = props;
3061
- return /* @__PURE__ */ jsx(Tag, {
3062
- role: "separator",
3063
- "aria-orientation": "horizontal",
3064
- class: className,
3065
- style,
3066
- ...rest
3067
- });
3068
- }
3069
- var DropdownMenu = Object.assign(DropdownMenuRoot, {
3070
- Root: DropdownMenuRoot,
3071
- Trigger: DropdownMenuTrigger,
3072
- Portal: DropdownMenuPortal,
3073
- Content: DropdownMenuContent,
3074
- Item: DropdownMenuItem,
3075
- Separator: DropdownMenuSeparator
3076
- });
3077
- // src/ui/icon.tsx
3078
- function createIcon(name, iconNode) {
3079
- const IconComponent = function Icon(props = {}) {
3080
- const size = () => typeof props.size === "function" ? props.size() : props.size ?? 24;
3081
- const color = () => typeof props.color === "function" ? props.color() : props.color ?? "currentColor";
3082
- const strokeWidth = () => typeof props.strokeWidth === "function" ? props.strokeWidth() : props.strokeWidth ?? 2;
3083
- const {
3084
- size: _s,
3085
- color: _c,
3086
- strokeWidth: _sw,
3087
- class: className,
3088
- style,
3089
- children,
3090
- ...rest
3091
- } = props;
3092
- return /* @__PURE__ */ jsxs("svg", {
3093
- xmlns: "http://www.w3.org/2000/svg",
3094
- width: size,
3095
- height: size,
3096
- viewBox: "0 0 24 24",
3097
- fill: "none",
3098
- stroke: color,
3099
- "stroke-width": strokeWidth,
3100
- "stroke-linecap": "round",
3101
- "stroke-linejoin": "round",
3102
- class: className,
3103
- style,
3104
- role: "img",
3105
- "aria-label": props["aria-label"] ?? name,
3106
- ...rest,
3107
- children: [
3108
- /* @__PURE__ */ jsx("title", {
3109
- children: props.title ?? name
3110
- }),
3111
- iconNode.map(([Tag, attrs]) => /* @__PURE__ */ jsx(Tag, {
3112
- ...attrs
3113
- })),
3114
- typeof children === "function" ? children() : children
3115
- ]
3116
- });
3117
- };
3118
- IconComponent.displayName = name;
3119
- return IconComponent;
3120
- }
3121
- // src/style/layout.tsx
3122
- var ALIGN_MAP = {
3123
- start: "flex-start",
3124
- center: "center",
3125
- end: "flex-end",
3126
- stretch: "stretch",
3127
- baseline: "baseline"
3128
- };
3129
- var JUSTIFY_MAP = {
3130
- start: "flex-start",
3131
- center: "center",
3132
- end: "flex-end",
3133
- between: "space-between",
3134
- around: "space-around",
3135
- evenly: "space-evenly",
3136
- stretch: "stretch"
3137
- };
3138
- function resolveBaseStyles(props) {
3139
- const s = {
3140
- boxSizing: "border-box"
3141
- };
3142
- if (props.gap !== undefined)
3143
- s.gap = space(props.gap);
3144
- if (props.p !== undefined)
3145
- s.padding = space(props.p);
3146
- if (props.px !== undefined) {
3147
- s.paddingLeft = space(props.px);
3148
- s.paddingRight = space(props.px);
3149
- }
3150
- if (props.py !== undefined) {
3151
- s.paddingTop = space(props.py);
3152
- s.paddingBottom = space(props.py);
3153
- }
3154
- if (props.pt !== undefined)
3155
- s.paddingTop = space(props.pt);
3156
- if (props.pb !== undefined)
3157
- s.paddingBottom = space(props.pb);
3158
- if (props.pl !== undefined)
3159
- s.paddingLeft = space(props.pl);
3160
- if (props.pr !== undefined)
3161
- s.paddingRight = space(props.pr);
3162
- if (props.m !== undefined)
3163
- s.margin = space(props.m);
3164
- if (props.mx !== undefined) {
3165
- s.marginLeft = space(props.mx);
3166
- s.marginRight = space(props.mx);
3167
- }
3168
- if (props.my !== undefined) {
3169
- s.marginTop = space(props.my);
3170
- s.marginBottom = space(props.my);
3171
- }
3172
- if (props.mt !== undefined)
3173
- s.marginTop = space(props.mt);
3174
- if (props.mb !== undefined)
3175
- s.marginBottom = space(props.mb);
3176
- if (props.ml !== undefined)
3177
- s.marginLeft = space(props.ml);
3178
- if (props.mr !== undefined)
3179
- s.marginRight = space(props.mr);
3180
- if (props.w !== undefined)
3181
- s.width = resolveDimension(props.w);
3182
- if (props.h !== undefined)
3183
- s.height = resolveDimension(props.h);
3184
- if (props.minW !== undefined)
3185
- s.minWidth = resolveDimension(props.minW);
3186
- if (props.maxW !== undefined)
3187
- s.maxWidth = resolveDimension(props.maxW);
3188
- if (props.minH !== undefined)
3189
- s.minHeight = resolveDimension(props.minH);
3190
- if (props.maxH !== undefined)
3191
- s.maxHeight = resolveDimension(props.maxH);
3192
- return s;
3193
- }
3194
- function mergeStyles(base, userStyle) {
3195
- if (!userStyle)
3196
- return base;
3197
- if (typeof userStyle === "string") {
3198
- const baseStr = Object.entries(base).map(([k, v]) => `${k.replace(/([A-Z])/g, "-$1").toLowerCase()}: ${v}`).join("; ");
3199
- return `${baseStr}; ${userStyle}`;
3200
- }
3201
- if (typeof userStyle === "object") {
3202
- return { ...base, ...userStyle };
3203
- }
3204
- return base;
3205
- }
3206
- function cleanProps(props, excludeKeys) {
3207
- const result = {};
3208
- for (const k in props) {
3209
- if (!excludeKeys.has(k)) {
3210
- result[k] = props[k];
3211
- }
3212
- }
3213
- return result;
3214
- }
3215
- var COMMON_EXCLUDE = new Set([
3216
- "as",
3217
- "gap",
3218
- "p",
3219
- "px",
3220
- "py",
3221
- "pt",
3222
- "pb",
3223
- "pl",
3224
- "pr",
3225
- "m",
3226
- "mx",
3227
- "my",
3228
- "mt",
3229
- "mb",
3230
- "ml",
3231
- "mr",
3232
- "w",
3233
- "h",
3234
- "minW",
3235
- "maxW",
3236
- "minH",
3237
- "maxH"
3238
- ]);
3239
- var STACK_EXCLUDE = new Set([
3240
- ...COMMON_EXCLUDE,
3241
- "align",
3242
- "justify",
3243
- "direction",
3244
- "reversed",
3245
- "wrap",
3246
- "inline"
3247
- ]);
3248
- function Stack(props) {
3249
- const { as = "div", children, ...rest } = props;
3250
- const layoutStyles = resolveBaseStyles(props);
3251
- layoutStyles.display = props.inline ? "inline-flex" : "flex";
3252
- layoutStyles.flexDirection = props.direction === "horizontal" ? props.reversed ? "row-reverse" : "row" : props.reversed ? "column-reverse" : "column";
3253
- if (props.align && ALIGN_MAP[props.align]) {
3254
- layoutStyles.alignItems = ALIGN_MAP[props.align];
3255
- }
3256
- if (props.justify && JUSTIFY_MAP[props.justify]) {
3257
- layoutStyles.justifyContent = JUSTIFY_MAP[props.justify];
3258
- }
3259
- if (props.wrap) {
3260
- layoutStyles.flexWrap = props.wrap === true ? "wrap" : props.wrap;
3261
- }
3262
- const domProps = cleanProps(rest, STACK_EXCLUDE);
3263
- domProps.style = mergeStyles(layoutStyles, props.style);
3264
- domProps.children = children;
3265
- return jsx(as, domProps);
3266
- }
3267
- var ROW_EXCLUDE = new Set([...COMMON_EXCLUDE, "align", "justify", "reversed", "wrap", "inline"]);
3268
- function Row(props) {
3269
- const { as = "div", children, ...rest } = props;
3270
- const layoutStyles = resolveBaseStyles(props);
3271
- layoutStyles.display = props.inline ? "inline-flex" : "flex";
3272
- layoutStyles.flexDirection = props.reversed ? "row-reverse" : "row";
3273
- layoutStyles.alignItems = props.align ? ALIGN_MAP[props.align] ?? props.align : "center";
3274
- if (props.justify && JUSTIFY_MAP[props.justify]) {
3275
- layoutStyles.justifyContent = JUSTIFY_MAP[props.justify];
3276
- }
3277
- if (props.wrap) {
3278
- layoutStyles.flexWrap = props.wrap === true ? "wrap" : props.wrap;
3279
- }
3280
- const domProps = cleanProps(rest, ROW_EXCLUDE);
3281
- domProps.style = mergeStyles(layoutStyles, props.style);
3282
- domProps.children = children;
3283
- return jsx(as, domProps);
3284
- }
3285
- var CENTER_EXCLUDE = new Set([...COMMON_EXCLUDE, "inline"]);
3286
- function Center(props) {
3287
- const { as = "div", children, ...rest } = props;
3288
- const layoutStyles = resolveBaseStyles(props);
3289
- layoutStyles.display = props.inline ? "inline-flex" : "flex";
3290
- layoutStyles.alignItems = "center";
3291
- layoutStyles.justifyContent = "center";
3292
- const domProps = cleanProps(rest, CENTER_EXCLUDE);
3293
- domProps.style = mergeStyles(layoutStyles, props.style);
3294
- domProps.children = children;
3295
- return jsx(as, domProps);
3296
- }
3297
- var GRID_EXCLUDE = new Set([
3298
- ...COMMON_EXCLUDE,
3299
- "columns",
3300
- "minChildWidth",
3301
- "rows",
3302
- "rowGap",
3303
- "colGap",
3304
- "align",
3305
- "justify",
3306
- "inline"
3307
- ]);
3308
- function Grid(props) {
3309
- const { as = "div", children, ...rest } = props;
3310
- const layoutStyles = resolveBaseStyles(props);
3311
- layoutStyles.display = props.inline ? "inline-grid" : "grid";
3312
- if (props.minChildWidth !== undefined) {
3313
- const minW = resolveDimension(props.minChildWidth);
3314
- layoutStyles.gridTemplateColumns = `repeat(auto-fit, minmax(min(100%, ${minW}), 1fr))`;
3315
- } else if (props.columns !== undefined) {
3316
- if (typeof props.columns === "number") {
3317
- layoutStyles.gridTemplateColumns = `repeat(${props.columns}, minmax(0, 1fr))`;
3318
- } else {
3319
- layoutStyles.gridTemplateColumns = String(props.columns);
3320
- }
3321
- }
3322
- if (props.rows !== undefined) {
3323
- if (typeof props.rows === "number") {
3324
- layoutStyles.gridTemplateRows = `repeat(${props.rows}, minmax(0, 1fr))`;
3325
- } else {
3326
- layoutStyles.gridTemplateRows = String(props.rows);
3327
- }
3328
- }
3329
- if (props.rowGap !== undefined)
3330
- layoutStyles.rowGap = space(props.rowGap);
3331
- if (props.colGap !== undefined)
3332
- layoutStyles.columnGap = space(props.colGap);
3333
- if (props.align) {
3334
- layoutStyles.alignItems = ALIGN_MAP[props.align] ?? props.align;
3335
- }
3336
- if (props.justify) {
3337
- layoutStyles.justifyItems = props.justify;
3338
- }
3339
- const domProps = cleanProps(rest, GRID_EXCLUDE);
3340
- domProps.style = mergeStyles(layoutStyles, props.style);
3341
- domProps.children = children;
3342
- return jsx(as, domProps);
3343
- }
3344
- var SPACER_EXCLUDE = new Set([...COMMON_EXCLUDE, "size", "x", "y", "flex"]);
3345
- function Spacer(props) {
3346
- const { as = "div", ...rest } = props;
3347
- const layoutStyles = resolveBaseStyles(props);
3348
- if (props.size !== undefined) {
3349
- const s = space(props.size);
3350
- layoutStyles.width = s;
3351
- layoutStyles.height = s;
3352
- layoutStyles.flexShrink = "0";
3353
- } else if (props.x !== undefined || props.y !== undefined) {
3354
- if (props.x !== undefined)
3355
- layoutStyles.width = space(props.x);
3356
- if (props.y !== undefined)
3357
- layoutStyles.height = space(props.y);
3358
- layoutStyles.flexShrink = "0";
3359
- } else {
3360
- layoutStyles.flex = typeof props.flex === "number" ? String(props.flex) : "1 1 0%";
3361
- layoutStyles.alignSelf = "stretch";
3362
- }
3363
- const domProps = cleanProps(rest, SPACER_EXCLUDE);
3364
- domProps.style = mergeStyles(layoutStyles, props.style);
3365
- return jsx(as, domProps);
3366
- }
3367
- // src/ui/popover.tsx
3368
- var PopoverContext = createContext(null);
3369
- function usePopoverContext() {
3370
- return useContext(PopoverContext);
3371
- }
3372
- function PopoverRoot(props) {
3373
- const [open, setOpen] = createControllableSignal({
3374
- value: props.open,
3375
- defaultValue: props.defaultOpen ?? false,
3376
- onChange: props.onOpenChange
3377
- });
3378
- const triggerRef = { current: null };
3379
- const contentRef = { current: null };
3380
- const contentId = createId("popover-content");
3381
- const ctx = {
3382
- open,
3383
- setOpen,
3384
- triggerRef,
3385
- contentRef,
3386
- contentId
3387
- };
3388
- if (props.trigger !== undefined || props.content !== undefined) {
3389
- return PopoverContext.Provider({
3390
- value: ctx,
3391
- children: () => /* @__PURE__ */ jsxs(Fragment, {
3392
- children: [
3393
- props.trigger ? /* @__PURE__ */ jsx(PopoverTrigger, {
3394
- as: "span",
3395
- class: props.triggerClass,
3396
- children: typeof props.trigger === "function" ? props.trigger() : props.trigger
3397
- }) : null,
3398
- /* @__PURE__ */ jsxs(PopoverContent, {
3399
- portalled: props.portalled,
3400
- class: props.contentClass,
3401
- children: [
3402
- typeof props.content === "function" ? props.content() : props.content,
3403
- typeof props.children === "function" ? props.children() : props.children
3404
- ]
3405
- })
3406
- ]
3407
- })
3408
- });
3409
- }
3410
- return PopoverContext.Provider({
3411
- value: ctx,
3412
- children: props.children
3413
- });
3414
- }
3415
- function PopoverTrigger(props) {
3416
- const ctx = useContext(PopoverContext);
3417
- const handleClick = (e) => {
3418
- if (props.onClick)
3419
- props.onClick(e);
3420
- if (!e.defaultPrevented && ctx) {
3421
- ctx.setOpen(!ctx.open());
3422
- }
3423
- };
3424
- const { as: Tag = "button", children, onClick, class: className, style, ...rest } = props;
3425
- return /* @__PURE__ */ jsx(Tag, {
3426
- ref: (el) => {
3427
- if (ctx)
3428
- ctx.triggerRef.current = el;
3429
- },
3430
- type: Tag === "button" ? "button" : undefined,
3431
- "aria-haspopup": "dialog",
3432
- "aria-expanded": () => ctx?.open() ?? false,
3433
- "aria-controls": ctx?.contentId,
3434
- "data-state": () => ctx?.open() ? "open" : "closed",
3435
- class: className,
3436
- style,
3437
- onClick: handleClick,
3438
- ...rest,
3439
- children
3440
- });
3441
- }
3442
- function PopoverPortal(props) {
3443
- return /* @__PURE__ */ jsx(Portal, {
3444
- mount: props.mount,
3445
- children: props.children
3446
- });
3447
- }
3448
- function PopoverContent(props) {
3449
- const ctx = useContext(PopoverContext);
3450
- const handleKeyDown = (e) => {
3451
- if (props.onKeyDown)
3452
- props.onKeyDown(e);
3453
- if (e.defaultPrevented)
3454
- return;
3455
- if (e.key === "Escape" && ctx) {
3456
- ctx.setOpen(false);
3457
- ctx.triggerRef.current?.focus();
3458
- e.stopPropagation();
3459
- }
3460
- };
3461
- const handleClick = (e) => {
3462
- if (props.onClick)
3463
- props.onClick(e);
3464
- if (e.defaultPrevented)
3465
- return;
3466
- const target = e.target;
3467
- if (target?.closest("[data-popover-close]")) {
3468
- ctx?.setOpen(false);
3469
- }
3470
- };
3471
- const {
3472
- as: Tag = "div",
3473
- children,
3474
- onKeyDown,
3475
- onClick: _onClick,
3476
- class: className,
3477
- style,
3478
- portalled = true,
3479
- mount,
3480
- ...rest
3481
- } = props;
3482
- const content = /* @__PURE__ */ jsx(Tag, {
3483
- ref: (el) => {
3484
- if (ctx) {
3485
- ctx.contentRef.current = el;
3486
- if (el) {
3487
- const cleanup = onClickOutside([ctx.triggerRef.current, el], () => {
3488
- if (ctx.open()) {
3489
- ctx.setOpen(false);
3490
- }
3491
- });
3492
- onCleanup(cleanup);
3493
- }
3494
- }
3495
- },
3496
- id: ctx?.contentId,
3497
- role: "dialog",
3498
- "data-state": () => ctx?.open() ? "open" : "closed",
3499
- class: className,
3500
- style: () => ({
3501
- display: ctx?.open() ? undefined : "none",
3502
- ...style
3503
- }),
3504
- onKeyDown: handleKeyDown,
3505
- onClick: handleClick,
3506
- tabIndex: -1,
3507
- ...rest,
3508
- children
3509
- });
3510
- return portalled ? /* @__PURE__ */ jsx(Portal, {
3511
- mount,
3512
- children: content
3513
- }) : content;
3514
- }
3515
- function PopoverClose(props) {
3516
- const ctx = useContext(PopoverContext);
3517
- const handleClick = (e) => {
3518
- if (props.onClick)
3519
- props.onClick(e);
3520
- if (!e.defaultPrevented && ctx) {
3521
- ctx.setOpen(false);
3522
- }
3523
- };
3524
- const { as: Tag = "button", children, onClick, class: className, style, ...rest } = props;
3525
- return /* @__PURE__ */ jsx(Tag, {
3526
- type: Tag === "button" ? "button" : undefined,
3527
- "data-popover-close": "",
3528
- class: className,
3529
- style,
3530
- onClick: handleClick,
3531
- ...rest,
3532
- children
3533
- });
3534
- }
3535
- var Popover = Object.assign(PopoverRoot, {
3536
- Root: PopoverRoot,
3537
- Trigger: PopoverTrigger,
3538
- Portal: PopoverPortal,
3539
- Content: PopoverContent,
3540
- Close: PopoverClose
3541
- });
3542
- // src/ui/switch.tsx
3543
- function SwitchRoot(props) {
3544
- const [checked, setChecked] = createControllableSignal({
3545
- value: props.checked,
3546
- defaultValue: props.defaultChecked ?? false,
3547
- onChange: props.onCheckedChange
3548
- });
3549
- const toggle = () => {
3550
- const isDisabled = typeof props.disabled === "function" ? props.disabled() : Boolean(props.disabled);
3551
- if (isDisabled)
3552
- return;
3553
- setChecked(!checked());
3554
- };
3555
- const handleClick = (e) => {
3556
- if (props.onClick)
3557
- props.onClick(e);
3558
- if (!e.defaultPrevented) {
3559
- toggle();
3560
- }
3561
- };
3562
- const handleKeyDown = (e) => {
3563
- if (props.onKeyDown)
3564
- props.onKeyDown(e);
3565
- if (e.key === "Enter" || e.key === " ") {
3566
- e.preventDefault();
3567
- toggle();
3568
- }
3569
- };
3570
- const {
3571
- checked: _c,
3572
- defaultChecked: _dc,
3573
- onCheckedChange: _occ,
3574
- disabled,
3575
- required,
3576
- name,
3577
- value,
3578
- thumbClass,
3579
- thumbStyle,
3580
- as: Tag = "button",
3581
- children,
3582
- onClick,
3583
- onKeyDown,
3584
- class: className,
3585
- style,
3586
- ...rest
3587
- } = props;
3588
- return /* @__PURE__ */ jsx(Tag, {
3589
- type: Tag === "button" ? "button" : undefined,
3590
- role: "switch",
3591
- "aria-checked": checked,
3592
- "data-state": () => checked() ? "checked" : "unchecked",
3593
- disabled,
3594
- class: className,
3595
- style,
3596
- onClick: handleClick,
3597
- onKeyDown: handleKeyDown,
3598
- ...rest,
3599
- children: children !== undefined ? typeof children === "function" ? children() : children : /* @__PURE__ */ jsx(SwitchThumb, {
3600
- class: thumbClass,
3601
- style: thumbStyle
3602
- })
3603
- });
3604
- }
3605
- function SwitchThumb(props) {
3606
- const { as: Tag = "span", class: className, style, ...rest } = props;
3607
- return /* @__PURE__ */ jsx(Tag, {
3608
- class: className,
3609
- style,
3610
- ...rest
3611
- });
3612
- }
3613
- var Switch = Object.assign(SwitchRoot, {
3614
- Root: SwitchRoot,
3615
- Thumb: SwitchThumb
3616
- });
3617
- // src/ui/tabs.tsx
3618
- var TabsContext = createContext(null);
3619
- function useTabsContext() {
3620
- return useContext(TabsContext);
3621
- }
3622
- function TabsRoot(props) {
3623
- const [value, setValue] = createControllableSignal({
3624
- value: props.value,
3625
- defaultValue: props.defaultValue ?? (props.items && props.items.length > 0 ? props.items[0]?.value : ""),
3626
- onChange: props.onValueChange
3627
- });
3628
- const baseId = createId("tabs");
3629
- const orientation = props.orientation ?? "horizontal";
3630
- const activationMode = props.activationMode ?? "automatic";
3631
- const ctx = {
3632
- value,
3633
- setValue,
3634
- orientation,
3635
- activationMode,
3636
- baseId
3637
- };
3638
- const {
3639
- as: Tag = "div",
3640
- value: _v,
3641
- defaultValue: _dv,
3642
- onValueChange: _ovc,
3643
- orientation: _ori,
3644
- activationMode: _am,
3645
- items,
3646
- listClass,
3647
- triggerClass,
3648
- contentClass,
3649
- children,
3650
- class: className,
3651
- style,
3652
- ...rest
3653
- } = props;
3654
- return TabsContext.Provider({
3655
- value: ctx,
3656
- children: () => /* @__PURE__ */ jsxs(Tag, {
3657
- "data-orientation": orientation,
3658
- class: className,
3659
- style,
3660
- ...rest,
3661
- children: [
3662
- items ? /* @__PURE__ */ jsxs(Fragment, {
3663
- children: [
3664
- /* @__PURE__ */ jsx(TabsList, {
3665
- class: listClass,
3666
- children: items.map((item) => /* @__PURE__ */ jsxs(TabsTrigger, {
3667
- value: item.value,
3668
- disabled: item.disabled,
3669
- class: triggerClass,
3670
- children: [
3671
- item.icon ? /* @__PURE__ */ jsx("span", {
3672
- class: "tab-icon",
3673
- style: { display: "inline-flex", alignItems: "center" },
3674
- children: typeof item.icon === "function" ? item.icon() : item.icon
3675
- }) : null,
3676
- typeof item.label === "function" ? item.label() : item.label
3677
- ]
3678
- }))
3679
- }),
3680
- items.map((item) => /* @__PURE__ */ jsx(TabsContent, {
3681
- value: item.value,
3682
- class: contentClass,
3683
- children: typeof item.content === "function" ? item.content() : item.content
3684
- }))
3685
- ]
3686
- }) : null,
3687
- typeof children === "function" ? children() : children
3688
- ]
3689
- })
3690
- });
3691
- }
3692
- function TabsList(props) {
3693
- const ctx = useContext(TabsContext);
3694
- const handleKeyDown = (e) => {
3695
- if (props.onKeyDown)
3696
- props.onKeyDown(e);
3697
- if (e.defaultPrevented)
3698
- return;
3699
- const target = e.target;
3700
- if (target?.getAttribute("role") !== "tab")
3701
- return;
3702
- const list = target.closest('[role="tablist"]');
3703
- if (!list)
3704
- return;
3705
- const tabs = Array.from(list.querySelectorAll('[role="tab"]:not([disabled])'));
3706
- const index = tabs.indexOf(target);
3707
- if (index === -1)
3708
- return;
3709
- let nextIndex = index;
3710
- const isHorizontal = (ctx?.orientation ?? "horizontal") === "horizontal";
3711
- const prevKey = isHorizontal ? "ArrowLeft" : "ArrowUp";
3712
- const nextKey = isHorizontal ? "ArrowRight" : "ArrowDown";
3713
- if (e.key === prevKey) {
3714
- nextIndex = index === 0 ? tabs.length - 1 : index - 1;
3715
- e.preventDefault();
3716
- } else if (e.key === nextKey) {
3717
- nextIndex = index === tabs.length - 1 ? 0 : index + 1;
3718
- e.preventDefault();
3719
- } else if (e.key === "Home") {
3720
- nextIndex = 0;
3721
- e.preventDefault();
3722
- } else if (e.key === "End") {
3723
- nextIndex = tabs.length - 1;
3724
- e.preventDefault();
3725
- }
3726
- if (nextIndex !== index) {
3727
- const nextTab = tabs[nextIndex];
3728
- nextTab.focus();
3729
- if (ctx?.activationMode === "automatic") {
3730
- const val = nextTab.getAttribute("data-value");
3731
- if (val)
3732
- ctx.setValue(val);
3733
- }
3734
- }
3735
- };
3736
- const { as: Tag = "div", children, onKeyDown, class: className, style, ...rest } = props;
3737
- return /* @__PURE__ */ jsx(Tag, {
3738
- role: "tablist",
3739
- "aria-orientation": ctx?.orientation ?? "horizontal",
3740
- class: className,
3741
- style,
3742
- onKeyDown: handleKeyDown,
3743
- ...rest,
3744
- children
3745
- });
3746
- }
3747
- function TabsTrigger(props) {
3748
- const ctx = useContext(TabsContext);
3749
- const isSelected = () => ctx ? ctx.value() === props.value : false;
3750
- const handleClick = (e) => {
3751
- if (props.onClick)
3752
- props.onClick(e);
3753
- if (!e.defaultPrevented && ctx) {
3754
- ctx.setValue(props.value);
3755
- }
3756
- };
3757
- const {
3758
- value,
3759
- disabled,
3760
- as: Tag = "button",
3761
- children,
3762
- onClick,
3763
- class: className,
3764
- style,
3765
- ...rest
3766
- } = props;
3767
- return /* @__PURE__ */ jsx(Tag, {
3768
- id: ctx ? `${ctx.baseId}-trigger-${value}` : undefined,
3769
- type: Tag === "button" ? "button" : undefined,
3770
- role: "tab",
3771
- "aria-selected": isSelected,
3772
- "aria-controls": ctx ? `${ctx.baseId}-panel-${value}` : undefined,
3773
- "data-state": () => isSelected() ? "active" : "inactive",
3774
- "data-value": value,
3775
- tabIndex: () => isSelected() ? 0 : -1,
3776
- disabled,
3777
- class: className,
3778
- style,
3779
- onClick: handleClick,
3780
- ...rest,
3781
- children
3782
- });
3783
- }
3784
- function TabsContent(props) {
3785
- const ctx = useContext(TabsContext);
3786
- const isSelected = () => ctx ? ctx.value() === props.value : false;
3787
- const { value, forceMount, as: Tag = "div", children, class: className, style, ...rest } = props;
3788
- if (forceMount) {
3789
- return /* @__PURE__ */ jsx(Tag, {
3790
- id: ctx ? `${ctx.baseId}-panel-${value}` : undefined,
3791
- role: "tabpanel",
3792
- "aria-labelledby": ctx ? `${ctx.baseId}-trigger-${value}` : undefined,
3793
- "data-state": () => isSelected() ? "active" : "inactive",
3794
- hidden: () => !isSelected(),
3795
- tabIndex: 0,
3796
- class: className,
3797
- style,
3798
- ...rest,
3799
- children
3800
- });
3801
- }
3802
- return /* @__PURE__ */ jsx(Show, {
3803
- when: isSelected,
3804
- children: /* @__PURE__ */ jsx(Tag, {
3805
- id: ctx ? `${ctx.baseId}-panel-${value}` : undefined,
3806
- role: "tabpanel",
3807
- "aria-labelledby": ctx ? `${ctx.baseId}-trigger-${value}` : undefined,
3808
- "data-state": "active",
3809
- tabIndex: 0,
3810
- class: className,
3811
- style,
3812
- ...rest,
3813
- children
3814
- })
3815
- });
3816
- }
3817
- var Tabs = Object.assign(TabsRoot, {
3818
- Root: TabsRoot,
3819
- List: TabsList,
3820
- Trigger: TabsTrigger,
3821
- Content: TabsContent
3822
- });
3823
- // src/ui/toast.tsx
3824
- function createToastManager() {
3825
- const toasts = signal([]);
3826
- const dismiss = (id) => {
3827
- const item = toasts().find((t) => t.id === id);
3828
- if (item?.onDismiss)
3829
- item.onDismiss();
3830
- toasts.update((list) => list.filter((t) => t.id !== id));
3831
- };
3832
- const show = (options) => {
3833
- const id = createId("toast");
3834
- const normalized = typeof options === "string" ? { title: options } : options;
3835
- const data = {
3836
- id,
3837
- title: normalized.title,
3838
- description: normalized.description,
3839
- variant: normalized.variant ?? "default",
3840
- duration: normalized.duration ?? 5000,
3841
- onDismiss: normalized.onDismiss
3842
- };
3843
- toasts.update((list) => [...list, data]);
3844
- if (data.duration && data.duration > 0) {
3845
- setTimeout(() => {
3846
- dismiss(id);
3847
- }, data.duration);
3848
- }
3849
- return id;
3850
- };
3851
- const success = (title, options) => show({ ...options, title, variant: "success" });
3852
- const error = (title, options) => show({ ...options, title, variant: "error" });
3853
- const warning = (title, options) => show({ ...options, title, variant: "warning" });
3854
- const info = (title, options) => show({ ...options, title, variant: "info" });
3855
- const clear = () => {
3856
- toasts.set([]);
3857
- };
3858
- const fn = function toast(options) {
3859
- return show(options);
3860
- };
3861
- fn.toasts = toasts;
3862
- fn.show = show;
3863
- fn.success = success;
3864
- fn.error = error;
3865
- fn.warning = warning;
3866
- fn.info = info;
3867
- fn.dismiss = dismiss;
3868
- fn.clear = clear;
3869
- return fn;
3870
- }
3871
- var defaultToastManager = createToastManager();
3872
- var toast = defaultToastManager;
3873
- var ToastContext = createContext(defaultToastManager);
3874
- function useToast() {
3875
- return useContext(ToastContext) ?? defaultToastManager;
3876
- }
3877
- function ToastProvider(props) {
3878
- const manager = props.manager ?? defaultToastManager;
3879
- return ToastContext.Provider({
3880
- value: manager,
3881
- children: props.children
3882
- });
3883
- }
3884
- function ToastViewport(props) {
3885
- const manager = useToast();
3886
- const { as: Tag = "section", children, class: className, style, ...rest } = props;
3887
- const defaultRender = (t) => /* @__PURE__ */ jsxs(Toast, {
3888
- id: t.id,
3889
- variant: t.variant,
3890
- class: `visage-toast toast toast-${t.variant ?? "default"}`,
3891
- onDismiss: () => manager.dismiss(t.id),
3892
- children: [
3893
- /* @__PURE__ */ jsxs("div", {
3894
- class: "visage-toast-content",
3895
- children: [
3896
- t.title && /* @__PURE__ */ jsx(ToastTitle, {
3897
- class: "visage-toast-title",
3898
- children: t.title
3899
- }),
3900
- t.description && /* @__PURE__ */ jsx(ToastDescription, {
3901
- class: "visage-toast-description",
3902
- children: t.description
3903
- })
3904
- ]
3905
- }),
3906
- /* @__PURE__ */ jsx(ToastClose, {
3907
- class: "visage-toast-close",
3908
- onClick: () => manager.dismiss(t.id)
3909
- })
3910
- ]
3911
- });
3912
- const renderItem = children ?? defaultRender;
3913
- return /* @__PURE__ */ jsx(Tag, {
3914
- role: "region",
3915
- "aria-label": "Notifications",
3916
- class: className,
3917
- style,
3918
- tabIndex: -1,
3919
- ...rest,
3920
- children: /* @__PURE__ */ jsx(For, {
3921
- each: manager.toasts,
3922
- children: (t) => renderItem(t)
3923
- })
3924
- });
3925
- }
3926
- function ToastRoot(props) {
3927
- const {
3928
- id,
3929
- variant = "default",
3930
- onDismiss,
3931
- as: Tag = "div",
3932
- children,
3933
- class: className,
3934
- style,
3935
- ...rest
3936
- } = props;
3937
- const role = variant === "error" ? "alert" : "status";
3938
- const ariaLive = variant === "error" ? "assertive" : "polite";
3939
- return /* @__PURE__ */ jsx(Tag, {
3940
- id,
3941
- role,
3942
- "aria-live": ariaLive,
3943
- "data-variant": variant,
3944
- "data-state": "open",
3945
- class: className,
3946
- style,
3947
- ...rest,
3948
- children
3949
- });
3950
- }
3951
- function ToastTitle(props) {
3952
- const { as: Tag = "div", children, class: className, style, ...rest } = props;
3953
- return /* @__PURE__ */ jsx(Tag, {
3954
- class: className,
3955
- style,
3956
- ...rest,
3957
- children
3958
- });
3959
- }
3960
- function ToastDescription(props) {
3961
- const { as: Tag = "div", children, class: className, style, ...rest } = props;
3962
- return /* @__PURE__ */ jsx(Tag, {
3963
- class: className,
3964
- style,
3965
- ...rest,
3966
- children
3967
- });
3968
- }
3969
- function ToastClose(props) {
3970
- const { as: Tag = "button", children = "✕", onClick, class: className, style, ...rest } = props;
3971
- return /* @__PURE__ */ jsx(Tag, {
3972
- type: Tag === "button" ? "button" : undefined,
3973
- "aria-label": "Close notification",
3974
- class: className,
3975
- style,
3976
- onClick,
3977
- ...rest,
3978
- children
3979
- });
3980
- }
3981
- var Toast = Object.assign(ToastRoot, {
3982
- Root: ToastRoot,
3983
- Provider: ToastProvider,
3984
- Viewport: ToastViewport,
3985
- Title: ToastTitle,
3986
- Description: ToastDescription,
3987
- Close: ToastClose
3988
- });
3989
- // src/ui/tooltip.tsx
3990
- var TooltipContext = createContext(null);
3991
- function useTooltipContext() {
3992
- return useContext(TooltipContext);
3993
- }
3994
- function TooltipRoot(props) {
3995
- const [open, setOpen] = createControllableSignal({
3996
- value: props.open,
3997
- defaultValue: props.defaultOpen ?? false,
3998
- onChange: props.onOpenChange
3999
- });
4000
- const tooltipId = createId("tooltip");
4001
- const triggerRef = { current: null };
4002
- const ctx = {
4003
- open,
4004
- setOpen,
4005
- openDelay: props.openDelay ?? 150,
4006
- closeDelay: props.closeDelay ?? 100,
4007
- tooltipId,
4008
- triggerRef
4009
- };
4010
- if (props.content !== undefined) {
4011
- return TooltipContext.Provider({
4012
- value: ctx,
4013
- children: () => /* @__PURE__ */ jsxs("span", {
4014
- class: "visage-tooltip-root",
4015
- style: { position: "relative", display: "inline-flex", alignItems: "center" },
4016
- children: [
4017
- /* @__PURE__ */ jsx(TooltipTrigger, {
4018
- as: props.triggerAs ?? "button",
4019
- class: props.triggerClass,
4020
- style: {
4021
- background: "transparent",
4022
- border: "none",
4023
- padding: 0,
4024
- display: "inline-flex",
4025
- alignItems: "center",
4026
- cursor: "help"
4027
- },
4028
- children: typeof props.children === "function" ? props.children() : props.children
4029
- }),
4030
- /* @__PURE__ */ jsx(TooltipContent, {
4031
- side: props.side,
4032
- class: props.contentClass,
4033
- style: props.contentStyle,
4034
- portalled: props.portalled ?? false,
4035
- children: typeof props.content === "function" ? props.content() : props.content
4036
- })
4037
- ]
4038
- })
4039
- });
4040
- }
4041
- return TooltipContext.Provider({
4042
- value: ctx,
4043
- children: props.children
4044
- });
4045
- }
4046
- function TooltipTrigger(props) {
4047
- const ctx = useContext(TooltipContext);
4048
- let openTimer = null;
4049
- let closeTimer = null;
4050
- const clearTimers = () => {
4051
- if (openTimer)
4052
- clearTimeout(openTimer);
4053
- if (closeTimer)
4054
- clearTimeout(closeTimer);
4055
- openTimer = null;
4056
- closeTimer = null;
4057
- };
4058
- const handleMouseEnter = (e) => {
4059
- if (props.onMouseEnter)
4060
- props.onMouseEnter(e);
4061
- clearTimers();
4062
- if (!ctx)
4063
- return;
4064
- if (ctx.openDelay > 0) {
4065
- openTimer = setTimeout(() => ctx.setOpen(true), ctx.openDelay);
4066
- } else {
4067
- ctx.setOpen(true);
4068
- }
4069
- };
4070
- const handleMouseLeave = (e) => {
4071
- if (props.onMouseLeave)
4072
- props.onMouseLeave(e);
4073
- clearTimers();
4074
- if (!ctx)
4075
- return;
4076
- if (ctx.closeDelay > 0) {
4077
- closeTimer = setTimeout(() => ctx.setOpen(false), ctx.closeDelay);
4078
- } else {
4079
- ctx.setOpen(false);
4080
- }
4081
- };
4082
- const handleFocus = (e) => {
4083
- if (props.onFocus)
4084
- props.onFocus(e);
4085
- clearTimers();
4086
- ctx?.setOpen(true);
4087
- };
4088
- const handleBlur = (e) => {
4089
- if (props.onBlur)
4090
- props.onBlur(e);
4091
- clearTimers();
4092
- ctx?.setOpen(false);
4093
- };
4094
- onCleanup(clearTimers);
4095
- const {
4096
- as: Tag = "button",
4097
- children,
4098
- onMouseEnter,
4099
- onMouseLeave,
4100
- onFocus,
4101
- onBlur,
4102
- class: className,
4103
- style,
4104
- ...rest
4105
- } = props;
4106
- return /* @__PURE__ */ jsx(Tag, {
4107
- ref: (el) => {
4108
- if (ctx)
4109
- ctx.triggerRef.current = el;
4110
- },
4111
- type: Tag === "button" ? "button" : undefined,
4112
- tabIndex: Tag === "button" ? undefined : 0,
4113
- "aria-describedby": ctx?.tooltipId,
4114
- "data-state": () => ctx?.open() ? "open" : "closed",
4115
- class: className,
4116
- style: { display: "inline-flex", alignItems: "center", ...style },
4117
- onMouseEnter: handleMouseEnter,
4118
- onMouseLeave: handleMouseLeave,
4119
- onFocus: handleFocus,
4120
- onBlur: handleBlur,
4121
- ...rest,
4122
- children
4123
- });
4124
- }
4125
- function TooltipPortal(props) {
4126
- return /* @__PURE__ */ jsx(Portal, {
4127
- mount: props.mount,
4128
- children: props.children
4129
- });
4130
- }
4131
- function TooltipContent(props) {
4132
- const ctx = useContext(TooltipContext);
4133
- const isOpen = () => ctx ? ctx.open() : false;
4134
- const {
4135
- forceMount,
4136
- as: Tag = "div",
4137
- children,
4138
- class: className,
4139
- style,
4140
- portalled = true,
4141
- mount,
4142
- ...rest
4143
- } = props;
4144
- const content = forceMount ? /* @__PURE__ */ jsx(Tag, {
4145
- id: ctx?.tooltipId,
4146
- role: "tooltip",
4147
- "data-state": () => isOpen() ? "open" : "closed",
4148
- hidden: () => !isOpen(),
4149
- class: className,
4150
- style,
4151
- ...rest,
4152
- children
4153
- }) : /* @__PURE__ */ jsx(Show, {
4154
- when: isOpen,
4155
- children: /* @__PURE__ */ jsx(Tag, {
4156
- id: ctx?.tooltipId,
4157
- role: "tooltip",
4158
- "data-state": "open",
4159
- class: className,
4160
- style,
4161
- ...rest,
4162
- children
4163
- })
4164
- });
4165
- return portalled ? /* @__PURE__ */ jsx(Portal, {
4166
- mount,
4167
- children: content
4168
- }) : content;
4169
- }
4170
- var Tooltip = Object.assign(TooltipRoot, {
4171
- Root: TooltipRoot,
4172
- Trigger: TooltipTrigger,
4173
- Portal: TooltipPortal,
4174
- Content: TooltipContent
4175
- });
1
+ import {
2
+ useAccordionContext2,
3
+ useAccordionItemContext2,
4
+ AccordionItem2,
5
+ AccordionTrigger2,
6
+ AccordionContent2,
7
+ Accordion2,
8
+ CommandDialog2,
9
+ useCommandContext2,
10
+ CommandInput2,
11
+ CommandList2,
12
+ CommandEmpty2,
13
+ CommandGroup2,
14
+ CommandItem2,
15
+ Command2,
16
+ DataTable2,
17
+ useDialogContext2,
18
+ DialogTrigger2,
19
+ DialogPortal2,
20
+ DialogOverlay2,
21
+ DialogContent2,
22
+ DialogTitle2,
23
+ DialogDescription2,
24
+ DialogClose2,
25
+ Dialog2,
26
+ useDropdownMenuContext2,
27
+ DropdownMenuTrigger2,
28
+ DropdownMenuPortal2,
29
+ DropdownMenuContent2,
30
+ DropdownMenuItem2,
31
+ DropdownMenuSeparator2,
32
+ DropdownMenu2,
33
+ createIcon2,
34
+ usePopoverContext2,
35
+ PopoverTrigger2,
36
+ PopoverPortal2,
37
+ PopoverContent2,
38
+ PopoverClose2,
39
+ Popover2,
40
+ createToastManager2,
41
+ defaultToastManager2,
42
+ toast2,
43
+ useToast2,
44
+ ToastProvider2,
45
+ ToastViewport2,
46
+ ToastTitle2,
47
+ ToastDescription2,
48
+ ToastClose2,
49
+ Toast2
50
+ } from "../index-b5wc752a.js";
51
+ import {
52
+ createId2,
53
+ createControllableSignal2,
54
+ trapFocus2,
55
+ onClickOutside2,
56
+ useTabsContext2,
57
+ TabsList2,
58
+ TabsTrigger2,
59
+ TabsContent2,
60
+ createTabs2,
61
+ Tabs2,
62
+ useTooltipContext2,
63
+ TooltipTrigger2,
64
+ TooltipPortal2,
65
+ TooltipContent2,
66
+ Tooltip3,
67
+ SwitchThumb2,
68
+ Switch2
69
+ } from "../index-8x8xz80v.js";
70
+ import {
71
+ Stack2,
72
+ Row2,
73
+ Center2,
74
+ Grid2,
75
+ Spacer2
76
+ } from "../index-1xtrtz1t.js";
77
+ import"../index-9fvarkrx.js";
78
+ import"../index-5s255b3w.js";
79
+ import"../index-a4xns6cc.js";
80
+ import"../index-6kfe1nr4.js";
4176
81
  export {
4177
- Accordion,
4178
- AccordionContent,
4179
- AccordionItem,
4180
- AccordionTrigger,
4181
- Center,
4182
- Command,
4183
- CommandDialog,
4184
- CommandEmpty,
4185
- CommandGroup,
4186
- CommandInput,
4187
- CommandItem,
4188
- CommandList,
4189
- DataTable,
4190
- Dialog,
4191
- DialogClose,
4192
- DialogContent,
4193
- DialogDescription,
4194
- DialogOverlay,
4195
- DialogPortal,
4196
- DialogTitle,
4197
- DialogTrigger,
4198
- DropdownMenu,
4199
- DropdownMenuContent,
4200
- DropdownMenuItem,
4201
- DropdownMenuPortal,
4202
- DropdownMenuSeparator,
4203
- DropdownMenuTrigger,
4204
- Grid,
4205
- Popover,
4206
- PopoverClose,
4207
- PopoverContent,
4208
- PopoverPortal,
4209
- PopoverTrigger,
4210
- Row,
4211
- Spacer,
4212
- Stack,
4213
- Switch,
4214
- SwitchThumb,
4215
- Tabs,
4216
- TabsContent,
4217
- TabsList,
4218
- TabsTrigger,
4219
- Toast,
4220
- ToastClose,
4221
- ToastDescription,
4222
- ToastProvider,
4223
- ToastTitle,
4224
- ToastViewport,
4225
- Tooltip,
4226
- TooltipContent,
4227
- TooltipPortal,
4228
- TooltipTrigger,
4229
- createControllableSignal,
4230
- createIcon,
4231
- createId,
4232
- createToastManager,
4233
- defaultToastManager,
4234
- onClickOutside,
4235
- toast,
4236
- trapFocus,
4237
- useAccordionContext,
4238
- useAccordionItemContext,
4239
- useCommandContext,
4240
- useDialogContext,
4241
- useDropdownMenuContext,
4242
- usePopoverContext,
4243
- useTabsContext,
4244
- useToast,
4245
- useTooltipContext
82
+ Accordion2 as Accordion,
83
+ AccordionContent2 as AccordionContent,
84
+ AccordionItem2 as AccordionItem,
85
+ AccordionTrigger2 as AccordionTrigger,
86
+ Center2 as Center,
87
+ Command2 as Command,
88
+ CommandDialog2 as CommandDialog,
89
+ CommandEmpty2 as CommandEmpty,
90
+ CommandGroup2 as CommandGroup,
91
+ CommandInput2 as CommandInput,
92
+ CommandItem2 as CommandItem,
93
+ CommandList2 as CommandList,
94
+ DataTable2 as DataTable,
95
+ Dialog2 as Dialog,
96
+ DialogClose2 as DialogClose,
97
+ DialogContent2 as DialogContent,
98
+ DialogDescription2 as DialogDescription,
99
+ DialogOverlay2 as DialogOverlay,
100
+ DialogPortal2 as DialogPortal,
101
+ DialogTitle2 as DialogTitle,
102
+ DialogTrigger2 as DialogTrigger,
103
+ DropdownMenu2 as DropdownMenu,
104
+ DropdownMenuContent2 as DropdownMenuContent,
105
+ DropdownMenuItem2 as DropdownMenuItem,
106
+ DropdownMenuPortal2 as DropdownMenuPortal,
107
+ DropdownMenuSeparator2 as DropdownMenuSeparator,
108
+ DropdownMenuTrigger2 as DropdownMenuTrigger,
109
+ Grid2 as Grid,
110
+ Popover2 as Popover,
111
+ PopoverClose2 as PopoverClose,
112
+ PopoverContent2 as PopoverContent,
113
+ PopoverPortal2 as PopoverPortal,
114
+ PopoverTrigger2 as PopoverTrigger,
115
+ Row2 as Row,
116
+ Spacer2 as Spacer,
117
+ Stack2 as Stack,
118
+ Switch2 as Switch,
119
+ SwitchThumb2 as SwitchThumb,
120
+ Tabs2 as Tabs,
121
+ TabsContent2 as TabsContent,
122
+ TabsList2 as TabsList,
123
+ TabsTrigger2 as TabsTrigger,
124
+ Toast2 as Toast,
125
+ ToastClose2 as ToastClose,
126
+ ToastDescription2 as ToastDescription,
127
+ ToastProvider2 as ToastProvider,
128
+ ToastTitle2 as ToastTitle,
129
+ ToastViewport2 as ToastViewport,
130
+ Tooltip3 as Tooltip,
131
+ TooltipContent2 as TooltipContent,
132
+ TooltipPortal2 as TooltipPortal,
133
+ TooltipTrigger2 as TooltipTrigger,
134
+ createControllableSignal2 as createControllableSignal,
135
+ createIcon2 as createIcon,
136
+ createId2 as createId,
137
+ createTabs2 as createTabs,
138
+ createToastManager2 as createToastManager,
139
+ defaultToastManager2 as defaultToastManager,
140
+ onClickOutside2 as onClickOutside,
141
+ toast2 as toast,
142
+ trapFocus2 as trapFocus,
143
+ useAccordionContext2 as useAccordionContext,
144
+ useAccordionItemContext2 as useAccordionItemContext,
145
+ useCommandContext2 as useCommandContext,
146
+ useDialogContext2 as useDialogContext,
147
+ useDropdownMenuContext2 as useDropdownMenuContext,
148
+ usePopoverContext2 as usePopoverContext,
149
+ useTabsContext2 as useTabsContext,
150
+ useToast2 as useToast,
151
+ useTooltipContext2 as useTooltipContext
4246
152
  };