@vertz/ui-primitives 0.2.15 → 0.2.16

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 (108) hide show
  1. package/dist/shared/chunk-0mcr52hc.js +78 -0
  2. package/dist/shared/chunk-2h5qpc00.js +98 -0
  3. package/dist/shared/chunk-31yptvbf.js +151 -0
  4. package/dist/shared/chunk-34yfm2b0.js +182 -0
  5. package/dist/shared/chunk-3pantb0p.js +108 -0
  6. package/dist/shared/chunk-3s6s6f06.js +61 -0
  7. package/dist/shared/chunk-48v8j0vh.js +267 -0
  8. package/dist/shared/chunk-6dmt4513.js +78 -0
  9. package/dist/shared/chunk-6pnjrst7.js +108 -0
  10. package/dist/shared/chunk-6sqwjfg8.js +169 -0
  11. package/dist/shared/chunk-8qfeqrrz.js +179 -0
  12. package/dist/shared/chunk-8y1jf6xr.js +17 -0
  13. package/dist/shared/chunk-9cqe2q6e.js +56 -0
  14. package/dist/shared/chunk-a6wp8c32.js +32 -0
  15. package/dist/shared/chunk-bcfzteh0.js +148 -0
  16. package/dist/shared/chunk-cr9sbwns.js +235 -0
  17. package/dist/shared/chunk-cvbf1js1.js +52 -0
  18. package/dist/shared/chunk-dkhst4wv.js +97 -0
  19. package/dist/shared/chunk-e2v1c9ex.js +62 -0
  20. package/dist/shared/chunk-e3aj5yw4.js +115 -0
  21. package/dist/shared/chunk-fv1y77tn.js +225 -0
  22. package/dist/shared/chunk-h42bk324.js +58 -0
  23. package/dist/shared/chunk-h9m9x5my.js +119 -0
  24. package/dist/shared/chunk-jctqs9m4.js +60 -0
  25. package/dist/shared/chunk-n92bvn5d.js +149 -0
  26. package/dist/shared/chunk-qpfqyrc5.js +19 -0
  27. package/dist/shared/chunk-qq0e0gym.js +73 -0
  28. package/dist/shared/chunk-t1vkvsz2.js +175 -0
  29. package/dist/shared/chunk-tk1k1bet.js +93 -0
  30. package/dist/shared/chunk-tvpgeswh.js +216 -0
  31. package/dist/shared/chunk-vcp10kne.js +175 -0
  32. package/dist/shared/chunk-ve006hmy.js +51 -0
  33. package/dist/shared/chunk-vq9tfzh8.js +30 -0
  34. package/dist/shared/chunk-vvjyx7fe.js +62 -0
  35. package/dist/shared/chunk-vx1ajy2z.js +115 -0
  36. package/dist/shared/chunk-w06tst6x.js +57 -0
  37. package/dist/shared/chunk-wnttq0gv.js +49 -0
  38. package/dist/shared/chunk-x6qzr3g6.js +100 -0
  39. package/dist/src/accordion/accordion.d.ts +23 -0
  40. package/dist/src/accordion/accordion.js +9 -0
  41. package/dist/src/alert-dialog/alert-dialog.d.ts +26 -0
  42. package/dist/src/alert-dialog/alert-dialog.js +9 -0
  43. package/dist/src/badge/badge.d.ts +10 -0
  44. package/dist/src/badge/badge.js +7 -0
  45. package/dist/src/button/button.d.ts +18 -0
  46. package/dist/src/button/button.js +8 -0
  47. package/dist/src/calendar/calendar.d.ts +40 -0
  48. package/dist/src/calendar/calendar.js +6 -0
  49. package/dist/src/carousel/carousel.d.ts +27 -0
  50. package/dist/src/carousel/carousel.js +8 -0
  51. package/dist/src/checkbox/checkbox.d.ts +20 -0
  52. package/dist/src/checkbox/checkbox.js +9 -0
  53. package/dist/src/collapsible/collapsible.d.ts +21 -0
  54. package/dist/src/collapsible/collapsible.js +8 -0
  55. package/dist/src/combobox/combobox.d.ts +23 -0
  56. package/dist/src/combobox/combobox.js +9 -0
  57. package/dist/src/command/command.d.ts +29 -0
  58. package/dist/src/command/command.js +9 -0
  59. package/dist/src/context-menu/context-menu.d.ts +39 -0
  60. package/dist/src/context-menu/context-menu.js +11 -0
  61. package/dist/src/date-picker/date-picker.d.ts +47 -0
  62. package/dist/src/date-picker/date-picker.js +14 -0
  63. package/dist/src/dialog/dialog.d.ts +24 -0
  64. package/dist/src/dialog/dialog.js +10 -0
  65. package/dist/src/dropdown-menu/dropdown-menu.d.ts +42 -0
  66. package/dist/src/dropdown-menu/dropdown-menu.js +12 -0
  67. package/dist/src/hover-card/hover-card.d.ts +33 -0
  68. package/dist/src/hover-card/hover-card.js +10 -0
  69. package/dist/src/index.js +136 -0
  70. package/dist/src/menu/menu.d.ts +39 -0
  71. package/dist/src/menu/menu.js +11 -0
  72. package/dist/src/menubar/menubar.d.ts +40 -0
  73. package/dist/src/menubar/menubar.js +12 -0
  74. package/dist/src/navigation-menu/navigation-menu.d.ts +25 -0
  75. package/dist/src/navigation-menu/navigation-menu.js +10 -0
  76. package/dist/src/popover/popover.d.ts +32 -0
  77. package/dist/src/popover/popover.js +12 -0
  78. package/dist/src/progress/progress.d.ts +20 -0
  79. package/dist/src/progress/progress.js +8 -0
  80. package/dist/src/radio/radio.d.ts +18 -0
  81. package/dist/src/radio/radio.js +10 -0
  82. package/dist/src/resizable-panel/resizable-panel.d.ts +24 -0
  83. package/dist/src/resizable-panel/resizable-panel.js +8 -0
  84. package/dist/src/scroll-area/scroll-area.d.ts +25 -0
  85. package/dist/src/scroll-area/scroll-area.js +6 -0
  86. package/dist/src/select/select.d.ts +41 -0
  87. package/dist/src/select/select.js +11 -0
  88. package/dist/src/sheet/sheet.d.ts +24 -0
  89. package/dist/src/sheet/sheet.js +10 -0
  90. package/dist/src/slider/slider.d.ts +24 -0
  91. package/dist/src/slider/slider.js +9 -0
  92. package/dist/src/switch/switch.d.ts +9 -0
  93. package/dist/src/switch/switch.js +8 -0
  94. package/dist/src/tabs/tabs.d.ts +23 -0
  95. package/dist/src/tabs/tabs.js +10 -0
  96. package/dist/src/toast/toast.d.ts +24 -0
  97. package/dist/src/toast/toast.js +8 -0
  98. package/dist/src/toggle/toggle.d.ts +9 -0
  99. package/dist/src/toggle/toggle.js +8 -0
  100. package/dist/src/toggle-group/toggle-group.d.ts +22 -0
  101. package/dist/src/toggle-group/toggle-group.js +9 -0
  102. package/dist/src/tooltip/tooltip.d.ts +32 -0
  103. package/dist/src/tooltip/tooltip.js +10 -0
  104. package/dist/src/utils.d.ts +176 -0
  105. package/dist/src/utils.js +72 -0
  106. package/package.json +12 -10
  107. package/dist/index.js +0 -3675
  108. /package/dist/{index.d.ts → src/index.d.ts} +0 -0
package/dist/index.js DELETED
@@ -1,3675 +0,0 @@
1
- // src/accordion/accordion.ts
2
- import { signal } from "@vertz/ui";
3
-
4
- // src/utils/aria.ts
5
- import { onAnimationsComplete } from "@vertz/ui/internals";
6
- var hideGeneration = new WeakMap;
7
- function setExpanded(el, expanded) {
8
- el.setAttribute("aria-expanded", String(expanded));
9
- }
10
- function setSelected(el, selected) {
11
- el.setAttribute("aria-selected", String(selected));
12
- }
13
- function setHidden(el, hidden) {
14
- el.setAttribute("aria-hidden", String(hidden));
15
- el.style.display = hidden ? "none" : "";
16
- }
17
- function setHiddenAnimated(el, hidden) {
18
- const gen = (hideGeneration.get(el) ?? 0) + 1;
19
- hideGeneration.set(el, gen);
20
- if (!hidden) {
21
- el.setAttribute("aria-hidden", "false");
22
- el.style.display = "";
23
- return;
24
- }
25
- el.setAttribute("aria-hidden", "true");
26
- onAnimationsComplete(el, () => {
27
- if (hideGeneration.get(el) === gen) {
28
- el.style.display = "none";
29
- }
30
- });
31
- }
32
- function setChecked(el, checked) {
33
- el.setAttribute("aria-checked", String(checked));
34
- }
35
- function setDisabled(el, disabled) {
36
- el.setAttribute("aria-disabled", String(disabled));
37
- }
38
- function setDataState(el, state) {
39
- el.setAttribute("data-state", state);
40
- }
41
- function setLabelledBy(el, labelId) {
42
- el.setAttribute("aria-labelledby", labelId);
43
- }
44
- function setDescribedBy(el, descriptionId) {
45
- el.setAttribute("aria-describedby", descriptionId);
46
- }
47
- function setPressed(el, pressed) {
48
- el.setAttribute("aria-pressed", String(pressed));
49
- }
50
- function setValueRange(el, now, min, max) {
51
- el.setAttribute("aria-valuenow", String(now));
52
- el.setAttribute("aria-valuemin", String(min));
53
- el.setAttribute("aria-valuemax", String(max));
54
- }
55
-
56
- // src/utils/id.ts
57
- var counter = 0;
58
- function uniqueId(prefix = "vz") {
59
- return `${prefix}-${++counter}`;
60
- }
61
- function linkedIds(prefix = "vz") {
62
- const base = uniqueId(prefix);
63
- return {
64
- triggerId: `${base}-trigger`,
65
- contentId: `${base}-content`
66
- };
67
- }
68
-
69
- // src/utils/keyboard.ts
70
- var Keys = {
71
- Enter: "Enter",
72
- Space: " ",
73
- Escape: "Escape",
74
- ArrowUp: "ArrowUp",
75
- ArrowDown: "ArrowDown",
76
- ArrowLeft: "ArrowLeft",
77
- ArrowRight: "ArrowRight",
78
- Home: "Home",
79
- End: "End",
80
- Tab: "Tab"
81
- };
82
- function isKey(event, ...keys) {
83
- return keys.includes(event.key);
84
- }
85
- function handleListNavigation(event, items, options = {}) {
86
- const { orientation = "vertical", loop = true } = options;
87
- if (items.length === 0)
88
- return null;
89
- const prevKey = orientation === "vertical" ? Keys.ArrowUp : Keys.ArrowLeft;
90
- const nextKey = orientation === "vertical" ? Keys.ArrowDown : Keys.ArrowRight;
91
- const currentIndex = items.indexOf(document.activeElement);
92
- let nextIndex = -1;
93
- if (isKey(event, prevKey)) {
94
- event.preventDefault();
95
- if (currentIndex <= 0) {
96
- nextIndex = loop ? items.length - 1 : 0;
97
- } else {
98
- nextIndex = currentIndex - 1;
99
- }
100
- } else if (isKey(event, nextKey)) {
101
- event.preventDefault();
102
- if (currentIndex >= items.length - 1) {
103
- nextIndex = loop ? 0 : items.length - 1;
104
- } else {
105
- nextIndex = currentIndex + 1;
106
- }
107
- } else if (isKey(event, Keys.Home)) {
108
- event.preventDefault();
109
- nextIndex = 0;
110
- } else if (isKey(event, Keys.End)) {
111
- event.preventDefault();
112
- nextIndex = items.length - 1;
113
- }
114
- const target = items[nextIndex];
115
- if (target) {
116
- target.focus();
117
- return target;
118
- }
119
- return null;
120
- }
121
- function handleActivation(event, handler) {
122
- if (isKey(event, Keys.Enter, Keys.Space)) {
123
- event.preventDefault();
124
- handler();
125
- }
126
- }
127
-
128
- // src/accordion/accordion.ts
129
- var Accordion = {
130
- Root(options = {}) {
131
- const { multiple = false, defaultValue = [], onValueChange } = options;
132
- const state = { value: signal([...defaultValue]) };
133
- const triggers = [];
134
- const itemMap = new Map;
135
- const root = document.createElement("div");
136
- root.setAttribute("data-orientation", "vertical");
137
- function updateItemState(val, open) {
138
- const entry = itemMap.get(val);
139
- if (!entry)
140
- return;
141
- const { trigger: t, content: c } = entry;
142
- if (open) {
143
- setHidden(c, false);
144
- }
145
- const height = c.scrollHeight;
146
- c.style.setProperty("--accordion-content-height", `${height}px`);
147
- setExpanded(t, open);
148
- setDataState(t, open ? "open" : "closed");
149
- setDataState(c, open ? "open" : "closed");
150
- if (!open) {
151
- setHiddenAnimated(c, true);
152
- }
153
- }
154
- function toggleItem(value) {
155
- const prev = [...state.value.peek()];
156
- const current = [...prev];
157
- const idx = current.indexOf(value);
158
- if (idx >= 0) {
159
- current.splice(idx, 1);
160
- } else {
161
- if (multiple) {
162
- current.push(value);
163
- } else {
164
- current.length = 0;
165
- current.push(value);
166
- }
167
- }
168
- state.value.value = current;
169
- onValueChange?.(current);
170
- for (const v of prev) {
171
- if (!current.includes(v)) {
172
- updateItemState(v, false);
173
- }
174
- }
175
- for (const v of current) {
176
- if (!prev.includes(v)) {
177
- updateItemState(v, true);
178
- }
179
- }
180
- }
181
- root.addEventListener("keydown", (event) => {
182
- if (isKey(event, Keys.ArrowUp, Keys.ArrowDown, Keys.Home, Keys.End)) {
183
- handleListNavigation(event, triggers, { orientation: "vertical" });
184
- }
185
- });
186
- function Item(value) {
187
- const baseId = uniqueId("accordion");
188
- const triggerId = `${baseId}-trigger`;
189
- const contentId = `${baseId}-content`;
190
- const isOpen = state.value.peek().includes(value);
191
- const item = document.createElement("div");
192
- item.setAttribute("data-value", value);
193
- const trigger = document.createElement("button");
194
- trigger.setAttribute("type", "button");
195
- trigger.id = triggerId;
196
- trigger.setAttribute("aria-controls", contentId);
197
- trigger.setAttribute("data-value", value);
198
- setExpanded(trigger, isOpen);
199
- setDataState(trigger, isOpen ? "open" : "closed");
200
- const content = document.createElement("div");
201
- content.setAttribute("role", "region");
202
- content.id = contentId;
203
- content.setAttribute("aria-labelledby", triggerId);
204
- setHidden(content, !isOpen);
205
- setDataState(content, isOpen ? "open" : "closed");
206
- trigger.addEventListener("click", () => {
207
- toggleItem(value);
208
- });
209
- itemMap.set(value, { trigger, content });
210
- triggers.push(trigger);
211
- item.appendChild(trigger);
212
- item.appendChild(content);
213
- root.appendChild(item);
214
- if (isOpen) {
215
- requestAnimationFrame(() => {
216
- const height = content.scrollHeight;
217
- content.style.setProperty("--accordion-content-height", `${height}px`);
218
- });
219
- }
220
- return { item, trigger, content };
221
- }
222
- return { root, state, Item };
223
- }
224
- };
225
- // src/alert-dialog/alert-dialog.tsx
226
- import { __element, __on } from "@vertz/ui/internals";
227
- import { signal as signal2 } from "@vertz/ui";
228
-
229
- // src/utils/focus.ts
230
- var FOCUSABLE_SELECTOR = [
231
- "a[href]",
232
- "button:not([disabled])",
233
- "input:not([disabled])",
234
- "select:not([disabled])",
235
- "textarea:not([disabled])",
236
- '[tabindex]:not([tabindex="-1"])',
237
- "[contenteditable]"
238
- ].join(", ");
239
- function getFocusableElements(container) {
240
- return Array.from(container.querySelectorAll(FOCUSABLE_SELECTOR));
241
- }
242
- function trapFocus(container) {
243
- function handleKeyDown(event) {
244
- if (event.key !== "Tab")
245
- return;
246
- const focusable = getFocusableElements(container);
247
- if (focusable.length === 0)
248
- return;
249
- const first = focusable[0];
250
- const last = focusable[focusable.length - 1];
251
- if (!first || !last)
252
- return;
253
- if (event.shiftKey) {
254
- if (document.activeElement === first) {
255
- event.preventDefault();
256
- last.focus();
257
- }
258
- } else {
259
- if (document.activeElement === last) {
260
- event.preventDefault();
261
- first.focus();
262
- }
263
- }
264
- }
265
- container.addEventListener("keydown", handleKeyDown);
266
- return () => {
267
- container.removeEventListener("keydown", handleKeyDown);
268
- };
269
- }
270
- function focusFirst(container) {
271
- const focusable = getFocusableElements(container);
272
- if (focusable.length > 0) {
273
- focusable[0]?.focus();
274
- }
275
- }
276
- function saveFocus() {
277
- const previously = document.activeElement;
278
- return () => {
279
- if (previously && typeof previously.focus === "function") {
280
- previously.focus();
281
- }
282
- };
283
- }
284
- function setRovingTabindex(items, activeIndex) {
285
- for (let i = 0;i < items.length; i++) {
286
- items[i]?.setAttribute("tabindex", i === activeIndex ? "0" : "-1");
287
- }
288
- }
289
-
290
- // src/alert-dialog/alert-dialog.tsx
291
- function AlertDialogRoot(options = {}) {
292
- const { defaultOpen = false, onOpenChange, onAction } = options;
293
- const ids = linkedIds("alertdialog");
294
- const titleId = `${ids.contentId}-title`;
295
- const descriptionId = `${ids.contentId}-description`;
296
- const state = { open: signal2(defaultOpen) };
297
- let restoreFocus = null;
298
- let removeTrap = null;
299
- function show() {
300
- state.open.value = true;
301
- setExpanded(trigger, true);
302
- setHidden(overlay, false);
303
- setHidden(content, false);
304
- setDataState(trigger, "open");
305
- setDataState(overlay, "open");
306
- setDataState(content, "open");
307
- restoreFocus = saveFocus();
308
- removeTrap = trapFocus(content);
309
- queueMicrotask(() => cancel.focus());
310
- onOpenChange?.(true);
311
- }
312
- function hide() {
313
- state.open.value = false;
314
- setExpanded(trigger, false);
315
- setDataState(trigger, "closed");
316
- setDataState(overlay, "closed");
317
- setDataState(content, "closed");
318
- setHiddenAnimated(overlay, true);
319
- setHiddenAnimated(content, true);
320
- removeTrap?.();
321
- removeTrap = null;
322
- restoreFocus?.();
323
- restoreFocus = null;
324
- onOpenChange?.(false);
325
- }
326
- const trigger = (() => {
327
- const __el0 = __element("button");
328
- __el0.setAttribute("type", "button");
329
- {
330
- const __v = ids.triggerId;
331
- if (__v != null && __v !== false)
332
- __el0.setAttribute("id", __v === true ? "" : __v);
333
- }
334
- {
335
- const __v = ids.contentId;
336
- if (__v != null && __v !== false)
337
- __el0.setAttribute("aria-controls", __v === true ? "" : __v);
338
- }
339
- {
340
- const __v = defaultOpen ? "true" : "false";
341
- if (__v != null && __v !== false)
342
- __el0.setAttribute("aria-expanded", __v === true ? "" : __v);
343
- }
344
- {
345
- const __v = defaultOpen ? "open" : "closed";
346
- if (__v != null && __v !== false)
347
- __el0.setAttribute("data-state", __v === true ? "" : __v);
348
- }
349
- __on(__el0, "click", () => {
350
- if (!state.open.peek())
351
- show();
352
- });
353
- return __el0;
354
- })();
355
- const overlay = (() => {
356
- const __el1 = __element("div");
357
- __el1.setAttribute("data-alertdialog-overlay", "");
358
- {
359
- const __v = defaultOpen ? "false" : "true";
360
- if (__v != null && __v !== false)
361
- __el1.setAttribute("aria-hidden", __v === true ? "" : __v);
362
- }
363
- {
364
- const __v = defaultOpen ? "open" : "closed";
365
- if (__v != null && __v !== false)
366
- __el1.setAttribute("data-state", __v === true ? "" : __v);
367
- }
368
- {
369
- const __v = defaultOpen ? "" : "display: none";
370
- if (__v != null && __v !== false)
371
- __el1.setAttribute("style", __v === true ? "" : __v);
372
- }
373
- return __el1;
374
- })();
375
- const content = (() => {
376
- const __el2 = __element("div");
377
- __el2.setAttribute("role", "alertdialog");
378
- {
379
- const __v = ids.contentId;
380
- if (__v != null && __v !== false)
381
- __el2.setAttribute("id", __v === true ? "" : __v);
382
- }
383
- __el2.setAttribute("aria-modal", "true");
384
- {
385
- const __v = titleId;
386
- if (__v != null && __v !== false)
387
- __el2.setAttribute("aria-labelledby", __v === true ? "" : __v);
388
- }
389
- {
390
- const __v = descriptionId;
391
- if (__v != null && __v !== false)
392
- __el2.setAttribute("aria-describedby", __v === true ? "" : __v);
393
- }
394
- {
395
- const __v = defaultOpen ? "false" : "true";
396
- if (__v != null && __v !== false)
397
- __el2.setAttribute("aria-hidden", __v === true ? "" : __v);
398
- }
399
- {
400
- const __v = defaultOpen ? "open" : "closed";
401
- if (__v != null && __v !== false)
402
- __el2.setAttribute("data-state", __v === true ? "" : __v);
403
- }
404
- {
405
- const __v = defaultOpen ? "" : "display: none";
406
- if (__v != null && __v !== false)
407
- __el2.setAttribute("style", __v === true ? "" : __v);
408
- }
409
- return __el2;
410
- })();
411
- const title = (() => {
412
- const __el3 = __element("h2");
413
- {
414
- const __v = titleId;
415
- if (__v != null && __v !== false)
416
- __el3.setAttribute("id", __v === true ? "" : __v);
417
- }
418
- return __el3;
419
- })();
420
- const description = (() => {
421
- const __el4 = __element("p");
422
- {
423
- const __v = descriptionId;
424
- if (__v != null && __v !== false)
425
- __el4.setAttribute("id", __v === true ? "" : __v);
426
- }
427
- return __el4;
428
- })();
429
- const cancel = (() => {
430
- const __el5 = __element("button");
431
- __el5.setAttribute("type", "button");
432
- __on(__el5, "click", () => hide());
433
- return __el5;
434
- })();
435
- const action = (() => {
436
- const __el6 = __element("button");
437
- __el6.setAttribute("type", "button");
438
- __on(__el6, "click", () => {
439
- onAction?.();
440
- hide();
441
- });
442
- return __el6;
443
- })();
444
- if (defaultOpen) {
445
- restoreFocus = saveFocus();
446
- removeTrap = trapFocus(content);
447
- queueMicrotask(() => cancel.focus());
448
- }
449
- return { trigger, overlay, content, title, description, cancel, action, state, show, hide };
450
- }
451
- var AlertDialog = {
452
- Root: AlertDialogRoot
453
- };
454
- // src/badge/badge.tsx
455
- import { __element as __element2 } from "@vertz/ui/internals";
456
- function BadgeRoot(options = {}) {
457
- const { variant = "default" } = options;
458
- const badge = (() => {
459
- const __el0 = __element2("span");
460
- {
461
- const __v = uniqueId("badge");
462
- if (__v != null && __v !== false)
463
- __el0.setAttribute("id", __v === true ? "" : __v);
464
- }
465
- __el0.setAttribute("data-slot", "badge");
466
- {
467
- const __v = variant;
468
- if (__v != null && __v !== false)
469
- __el0.setAttribute("data-variant", __v === true ? "" : __v);
470
- }
471
- return __el0;
472
- })();
473
- return { badge };
474
- }
475
- var Badge = {
476
- Root: BadgeRoot
477
- };
478
- // src/button/button.ts
479
- import { signal as signal3 } from "@vertz/ui";
480
- function createButtonRoot(state, options) {
481
- const el = document.createElement("button");
482
- el.setAttribute("type", "button");
483
- el.setAttribute("role", "button");
484
- setDataState(el, "idle");
485
- if (options.disabled) {
486
- el.disabled = true;
487
- setDisabled(el, true);
488
- }
489
- el.addEventListener("click", () => {
490
- if (state.disabled.peek())
491
- return;
492
- state.pressed.value = true;
493
- setDataState(el, "pressed");
494
- options.onPress?.();
495
- queueMicrotask(() => {
496
- state.pressed.value = false;
497
- setDataState(el, "idle");
498
- });
499
- });
500
- el.addEventListener("keydown", (event) => {
501
- if (state.disabled.peek())
502
- return;
503
- handleActivation(event, () => {
504
- el.click();
505
- });
506
- });
507
- return el;
508
- }
509
- var Button = {
510
- Root(options = {}) {
511
- const state = {
512
- disabled: signal3(options.disabled ?? false),
513
- pressed: signal3(false)
514
- };
515
- const root = createButtonRoot(state, options);
516
- return { root, state };
517
- }
518
- };
519
- // src/calendar/calendar.ts
520
- import { signal as signal4 } from "@vertz/ui";
521
- var MONTH_NAMES = [
522
- "January",
523
- "February",
524
- "March",
525
- "April",
526
- "May",
527
- "June",
528
- "July",
529
- "August",
530
- "September",
531
- "October",
532
- "November",
533
- "December"
534
- ];
535
- var DAY_NAMES = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
536
- function getDaysInMonth(year, month) {
537
- return new Date(year, month + 1, 0).getDate();
538
- }
539
- function isSameDay(a, b) {
540
- return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
541
- }
542
- function addDays(date, days) {
543
- const result = new Date(date);
544
- result.setDate(result.getDate() + days);
545
- return result;
546
- }
547
- function addMonths(date, months) {
548
- const result = new Date(date);
549
- result.setMonth(result.getMonth() + months);
550
- return result;
551
- }
552
- var Calendar = {
553
- Root(options = {}) {
554
- const now = new Date;
555
- const defaultMonth = options.defaultMonth ?? now;
556
- const weekStartsOn = options.weekStartsOn ?? 0;
557
- const mode = options.mode ?? "single";
558
- const state = {
559
- value: signal4(options.defaultValue ?? null),
560
- focusedDate: signal4(defaultMonth),
561
- displayMonth: signal4(defaultMonth)
562
- };
563
- const root = document.createElement("div");
564
- const header = document.createElement("div");
565
- const title = document.createElement("div");
566
- const prevButton = document.createElement("button");
567
- prevButton.setAttribute("type", "button");
568
- const nextButton = document.createElement("button");
569
- nextButton.setAttribute("type", "button");
570
- const grid = document.createElement("table");
571
- grid.setAttribute("role", "grid");
572
- function updateTitle() {
573
- const month = state.displayMonth.peek();
574
- title.textContent = `${MONTH_NAMES[month.getMonth()]} ${month.getFullYear()}`;
575
- }
576
- function isDateDisabled(date) {
577
- if (options.disabled?.(date))
578
- return true;
579
- if (options.minDate && date < options.minDate && !isSameDay(date, options.minDate)) {
580
- return true;
581
- }
582
- if (options.maxDate && date > options.maxDate && !isSameDay(date, options.maxDate)) {
583
- return true;
584
- }
585
- return false;
586
- }
587
- function isSelected(date) {
588
- const val = state.value.peek();
589
- if (val === null)
590
- return false;
591
- if (val instanceof Date)
592
- return isSameDay(val, date);
593
- if (Array.isArray(val))
594
- return val.some((d) => isSameDay(d, date));
595
- if ("from" in val && "to" in val) {
596
- return isSameDay(val.from, date) || isSameDay(val.to, date);
597
- }
598
- return false;
599
- }
600
- function isInRange(date) {
601
- const val = state.value.peek();
602
- if (val === null || !("from" in val))
603
- return false;
604
- const range = val;
605
- return date > range.from && date < range.to;
606
- }
607
- function selectDate(date) {
608
- if (isDateDisabled(date))
609
- return;
610
- if (mode === "single") {
611
- state.value.value = date;
612
- } else if (mode === "multiple") {
613
- const current = state.value.peek() ?? [];
614
- const existing = current.findIndex((d) => isSameDay(d, date));
615
- if (existing >= 0) {
616
- const next = [...current];
617
- next.splice(existing, 1);
618
- state.value.value = next;
619
- } else {
620
- state.value.value = [...current, date];
621
- }
622
- } else if (mode === "range") {
623
- const current = state.value.peek();
624
- if (!current || "to" in current && current.to) {
625
- state.value.value = { from: date, to: date };
626
- } else {
627
- if (date < current.from) {
628
- state.value.value = { from: date, to: current.from };
629
- } else {
630
- state.value.value = { from: current.from, to: date };
631
- }
632
- }
633
- }
634
- options.onValueChange?.(state.value.peek());
635
- }
636
- function buildGrid() {
637
- grid.innerHTML = "";
638
- const display = state.displayMonth.peek();
639
- const year = display.getFullYear();
640
- const month = display.getMonth();
641
- const daysInMonth = getDaysInMonth(year, month);
642
- const thead = document.createElement("thead");
643
- const headerRow = document.createElement("tr");
644
- for (let i = 0;i < 7; i++) {
645
- const dayIndex = (weekStartsOn + i) % 7;
646
- const th = document.createElement("th");
647
- th.setAttribute("scope", "col");
648
- th.textContent = DAY_NAMES[dayIndex] ?? "";
649
- headerRow.appendChild(th);
650
- }
651
- thead.appendChild(headerRow);
652
- grid.appendChild(thead);
653
- const tbody = document.createElement("tbody");
654
- const firstDay = new Date(year, month, 1);
655
- const firstDayOfWeek = firstDay.getDay();
656
- const offset = (firstDayOfWeek - weekStartsOn + 7) % 7;
657
- const startDate = addDays(firstDay, -offset);
658
- let currentDate = startDate;
659
- const totalCells = offset + daysInMonth;
660
- const totalRows = Math.ceil(totalCells / 7);
661
- for (let row = 0;row < totalRows; row++) {
662
- const tr = document.createElement("tr");
663
- for (let col = 0;col < 7; col++) {
664
- const td = document.createElement("td");
665
- td.setAttribute("role", "gridcell");
666
- const btn = document.createElement("button");
667
- btn.setAttribute("type", "button");
668
- const cellDate = new Date(currentDate);
669
- btn.textContent = String(cellDate.getDate());
670
- btn.setAttribute("data-date", cellDate.toISOString().split("T")[0] ?? "");
671
- const isOutside = cellDate.getMonth() !== month;
672
- if (isOutside) {
673
- btn.setAttribute("data-outside-month", "true");
674
- }
675
- if (isSameDay(cellDate, now)) {
676
- btn.setAttribute("data-today", "true");
677
- }
678
- if (isDateDisabled(cellDate)) {
679
- btn.setAttribute("aria-disabled", "true");
680
- }
681
- if (isSelected(cellDate)) {
682
- btn.setAttribute("aria-selected", "true");
683
- }
684
- if (mode === "range") {
685
- const val = state.value.peek();
686
- if (val && "from" in val) {
687
- if (isSameDay(cellDate, val.from)) {
688
- btn.setAttribute("data-range-start", "true");
689
- }
690
- if (isSameDay(cellDate, val.to)) {
691
- btn.setAttribute("data-range-end", "true");
692
- }
693
- if (isInRange(cellDate)) {
694
- btn.setAttribute("data-in-range", "true");
695
- }
696
- }
697
- }
698
- btn.addEventListener("click", () => {
699
- selectDate(cellDate);
700
- rebuildGrid();
701
- });
702
- td.appendChild(btn);
703
- tr.appendChild(td);
704
- currentDate = addDays(currentDate, 1);
705
- }
706
- tbody.appendChild(tr);
707
- }
708
- grid.appendChild(tbody);
709
- }
710
- function rebuildGrid() {
711
- updateTitle();
712
- buildGrid();
713
- }
714
- function navigateMonth(delta) {
715
- state.displayMonth.value = addMonths(state.displayMonth.peek(), delta);
716
- options.onMonthChange?.(state.displayMonth.peek());
717
- rebuildGrid();
718
- }
719
- prevButton.addEventListener("click", () => navigateMonth(-1));
720
- nextButton.addEventListener("click", () => navigateMonth(1));
721
- grid.addEventListener("keydown", (event) => {
722
- const active = document.activeElement;
723
- if (!active || active.tagName !== "BUTTON")
724
- return;
725
- const dateStr = active.getAttribute("data-date");
726
- if (!dateStr)
727
- return;
728
- const focused = new Date(dateStr + "T00:00:00");
729
- let next = null;
730
- if (event.key === "ArrowLeft") {
731
- event.preventDefault();
732
- next = addDays(focused, -1);
733
- } else if (event.key === "ArrowRight") {
734
- event.preventDefault();
735
- next = addDays(focused, 1);
736
- } else if (event.key === "ArrowUp") {
737
- event.preventDefault();
738
- next = addDays(focused, -7);
739
- } else if (event.key === "ArrowDown") {
740
- event.preventDefault();
741
- next = addDays(focused, 7);
742
- } else if (event.key === "Home") {
743
- event.preventDefault();
744
- const dayOfWeek = (focused.getDay() - weekStartsOn + 7) % 7;
745
- next = addDays(focused, -dayOfWeek);
746
- } else if (event.key === "End") {
747
- event.preventDefault();
748
- const dayOfWeek = (focused.getDay() - weekStartsOn + 7) % 7;
749
- next = addDays(focused, 6 - dayOfWeek);
750
- } else if (event.key === "PageUp") {
751
- event.preventDefault();
752
- next = event.shiftKey ? addMonths(focused, -12) : addMonths(focused, -1);
753
- } else if (event.key === "PageDown") {
754
- event.preventDefault();
755
- next = event.shiftKey ? addMonths(focused, 12) : addMonths(focused, 1);
756
- } else if (event.key === "Enter" || event.key === " ") {
757
- event.preventDefault();
758
- selectDate(focused);
759
- rebuildGrid();
760
- return;
761
- }
762
- if (next) {
763
- state.focusedDate.value = next;
764
- if (next.getMonth() !== state.displayMonth.peek().getMonth() || next.getFullYear() !== state.displayMonth.peek().getFullYear()) {
765
- state.displayMonth.value = new Date(next.getFullYear(), next.getMonth(), 1);
766
- options.onMonthChange?.(state.displayMonth.peek());
767
- rebuildGrid();
768
- }
769
- const dateKey = next.toISOString().split("T")[0];
770
- const btn = grid.querySelector(`button[data-date="${dateKey}"]`);
771
- btn?.focus();
772
- }
773
- });
774
- updateTitle();
775
- buildGrid();
776
- root.appendChild(header);
777
- root.appendChild(grid);
778
- header.appendChild(prevButton);
779
- header.appendChild(title);
780
- header.appendChild(nextButton);
781
- return { root, header, title, prevButton, nextButton, grid, state };
782
- }
783
- };
784
- // src/carousel/carousel.ts
785
- import { signal as signal5 } from "@vertz/ui";
786
- var Carousel = {
787
- Root(options = {}) {
788
- const { orientation = "horizontal", loop = false, defaultIndex = 0, onSlideChange } = options;
789
- const state = {
790
- currentIndex: signal5(defaultIndex),
791
- slideCount: signal5(0)
792
- };
793
- const slides = [];
794
- const root = document.createElement("div");
795
- root.setAttribute("role", "region");
796
- root.setAttribute("aria-roledescription", "carousel");
797
- root.setAttribute("data-orientation", orientation);
798
- const viewport = document.createElement("div");
799
- viewport.style.overflow = "hidden";
800
- const prevButton = document.createElement("button");
801
- prevButton.setAttribute("type", "button");
802
- prevButton.setAttribute("aria-label", "Previous slide");
803
- const nextButton = document.createElement("button");
804
- nextButton.setAttribute("type", "button");
805
- nextButton.setAttribute("aria-label", "Next slide");
806
- function updateSlideVisibility() {
807
- const current = state.currentIndex.peek();
808
- for (let i = 0;i < slides.length; i++) {
809
- const slide = slides[i];
810
- if (!slide)
811
- continue;
812
- slide.setAttribute("aria-hidden", String(i !== current));
813
- slide.setAttribute("aria-label", `Slide ${i + 1} of ${slides.length}`);
814
- setDataState(slide, i === current ? "active" : "inactive");
815
- }
816
- if (!loop) {
817
- prevButton.disabled = current <= 0;
818
- nextButton.disabled = current >= slides.length - 1;
819
- }
820
- const translateProp = orientation === "horizontal" ? "translateX" : "translateY";
821
- viewport.style.transform = `${translateProp}(-${current * 100}%)`;
822
- }
823
- function goTo(index) {
824
- const total = slides.length;
825
- if (total === 0)
826
- return;
827
- let next = index;
828
- if (loop) {
829
- next = (index % total + total) % total;
830
- } else {
831
- next = Math.max(0, Math.min(total - 1, index));
832
- }
833
- if (next === state.currentIndex.peek())
834
- return;
835
- state.currentIndex.value = next;
836
- updateSlideVisibility();
837
- onSlideChange?.(next);
838
- }
839
- function goNext() {
840
- goTo(state.currentIndex.peek() + 1);
841
- }
842
- function goPrev() {
843
- goTo(state.currentIndex.peek() - 1);
844
- }
845
- prevButton.addEventListener("click", goPrev);
846
- nextButton.addEventListener("click", goNext);
847
- root.addEventListener("keydown", (event) => {
848
- const prevKey = orientation === "horizontal" ? Keys.ArrowLeft : Keys.ArrowUp;
849
- const nextKey = orientation === "horizontal" ? Keys.ArrowRight : Keys.ArrowDown;
850
- if (isKey(event, prevKey)) {
851
- event.preventDefault();
852
- goPrev();
853
- }
854
- if (isKey(event, nextKey)) {
855
- event.preventDefault();
856
- goNext();
857
- }
858
- });
859
- function Slide() {
860
- const slide = document.createElement("div");
861
- slide.setAttribute("role", "group");
862
- slide.setAttribute("aria-roledescription", "slide");
863
- slides.push(slide);
864
- state.slideCount.value = slides.length;
865
- viewport.appendChild(slide);
866
- updateSlideVisibility();
867
- return slide;
868
- }
869
- root.appendChild(viewport);
870
- updateSlideVisibility();
871
- return { root, viewport, prevButton, nextButton, state, Slide, goTo, goNext, goPrev };
872
- }
873
- };
874
- // src/checkbox/checkbox.ts
875
- import { signal as signal6 } from "@vertz/ui";
876
- function dataStateFor(checked) {
877
- if (checked === "mixed")
878
- return "indeterminate";
879
- return checked ? "checked" : "unchecked";
880
- }
881
- var Checkbox = {
882
- Root(options = {}) {
883
- const { defaultChecked = false, disabled = false, onCheckedChange } = options;
884
- const state = {
885
- checked: signal6(defaultChecked),
886
- disabled: signal6(disabled)
887
- };
888
- const root = document.createElement("button");
889
- root.setAttribute("type", "button");
890
- root.setAttribute("role", "checkbox");
891
- root.id = uniqueId("checkbox");
892
- setChecked(root, defaultChecked);
893
- setDataState(root, dataStateFor(defaultChecked));
894
- if (disabled) {
895
- root.disabled = true;
896
- root.setAttribute("aria-disabled", "true");
897
- }
898
- function toggle() {
899
- if (state.disabled.peek())
900
- return;
901
- const current = state.checked.peek();
902
- const next = current === "mixed" ? true : !current;
903
- state.checked.value = next;
904
- setChecked(root, next);
905
- setDataState(root, dataStateFor(next));
906
- onCheckedChange?.(next);
907
- }
908
- root.addEventListener("click", toggle);
909
- root.addEventListener("keydown", (event) => {
910
- if (isKey(event, Keys.Space)) {
911
- event.preventDefault();
912
- toggle();
913
- }
914
- });
915
- return { root, state };
916
- }
917
- };
918
- // src/collapsible/collapsible.ts
919
- import { signal as signal7 } from "@vertz/ui";
920
- var Collapsible = {
921
- Root(options = {}) {
922
- const { defaultOpen = false, disabled = false, onOpenChange } = options;
923
- const ids = linkedIds("collapsible");
924
- const state = {
925
- open: signal7(defaultOpen),
926
- disabled: signal7(disabled)
927
- };
928
- const root = document.createElement("div");
929
- const trigger = document.createElement("button");
930
- trigger.setAttribute("type", "button");
931
- trigger.id = ids.triggerId;
932
- trigger.setAttribute("aria-controls", ids.contentId);
933
- setExpanded(trigger, defaultOpen);
934
- setDataState(trigger, defaultOpen ? "open" : "closed");
935
- if (disabled) {
936
- trigger.disabled = true;
937
- trigger.setAttribute("aria-disabled", "true");
938
- }
939
- const content = document.createElement("div");
940
- content.id = ids.contentId;
941
- setHidden(content, !defaultOpen);
942
- setDataState(content, defaultOpen ? "open" : "closed");
943
- function toggle() {
944
- if (state.disabled.peek())
945
- return;
946
- const next = !state.open.peek();
947
- state.open.value = next;
948
- if (next) {
949
- setHidden(content, false);
950
- }
951
- const height = content.scrollHeight;
952
- content.style.setProperty("--collapsible-content-height", `${height}px`);
953
- setExpanded(trigger, next);
954
- setDataState(trigger, next ? "open" : "closed");
955
- setDataState(content, next ? "open" : "closed");
956
- if (!next) {
957
- setHiddenAnimated(content, true);
958
- }
959
- onOpenChange?.(next);
960
- }
961
- trigger.addEventListener("click", toggle);
962
- root.appendChild(trigger);
963
- root.appendChild(content);
964
- return { root, trigger, content, state };
965
- }
966
- };
967
- // src/combobox/combobox.ts
968
- import { signal as signal8 } from "@vertz/ui";
969
- var Combobox = {
970
- Root(options = {}) {
971
- const { defaultValue = "", onValueChange, onInputChange } = options;
972
- const ids = linkedIds("combobox");
973
- const state = {
974
- open: signal8(false),
975
- value: signal8(defaultValue),
976
- inputValue: signal8(defaultValue),
977
- activeIndex: signal8(-1)
978
- };
979
- const optionElements = [];
980
- const input = document.createElement("input");
981
- input.setAttribute("type", "text");
982
- input.setAttribute("role", "combobox");
983
- input.setAttribute("aria-autocomplete", "list");
984
- input.setAttribute("aria-controls", ids.contentId);
985
- input.setAttribute("aria-haspopup", "listbox");
986
- input.id = ids.triggerId;
987
- input.value = defaultValue;
988
- setExpanded(input, false);
989
- const listbox = document.createElement("div");
990
- listbox.setAttribute("role", "listbox");
991
- listbox.id = ids.contentId;
992
- setHidden(listbox, true);
993
- setDataState(listbox, "closed");
994
- function open() {
995
- state.open.value = true;
996
- setExpanded(input, true);
997
- setHidden(listbox, false);
998
- setDataState(listbox, "open");
999
- }
1000
- function close() {
1001
- state.open.value = false;
1002
- state.activeIndex.value = -1;
1003
- setExpanded(input, false);
1004
- setDataState(listbox, "closed");
1005
- setHiddenAnimated(listbox, true);
1006
- updateActiveDescendant(-1);
1007
- }
1008
- function selectOption(value) {
1009
- state.value.value = value;
1010
- state.inputValue.value = value;
1011
- input.value = value;
1012
- for (const opt of optionElements) {
1013
- const isActive = opt.getAttribute("data-value") === value;
1014
- setSelected(opt, isActive);
1015
- setDataState(opt, isActive ? "active" : "inactive");
1016
- }
1017
- onValueChange?.(value);
1018
- close();
1019
- input.focus();
1020
- }
1021
- function updateActiveDescendant(index) {
1022
- const opt = optionElements[index];
1023
- if (index >= 0 && opt) {
1024
- input.setAttribute("aria-activedescendant", opt.id);
1025
- for (let i = 0;i < optionElements.length; i++) {
1026
- const el = optionElements[i];
1027
- if (el)
1028
- setDataState(el, i === index ? "active" : "inactive");
1029
- }
1030
- } else {
1031
- input.removeAttribute("aria-activedescendant");
1032
- }
1033
- }
1034
- input.addEventListener("input", () => {
1035
- state.inputValue.value = input.value;
1036
- onInputChange?.(input.value);
1037
- if (!state.open.peek())
1038
- open();
1039
- });
1040
- input.addEventListener("focus", () => {
1041
- if (!state.open.peek() && input.value.length > 0)
1042
- open();
1043
- });
1044
- input.addEventListener("keydown", (event) => {
1045
- if (isKey(event, Keys.Escape)) {
1046
- event.preventDefault();
1047
- close();
1048
- return;
1049
- }
1050
- if (isKey(event, Keys.ArrowDown)) {
1051
- event.preventDefault();
1052
- if (!state.open.peek()) {
1053
- open();
1054
- }
1055
- const next = Math.min(state.activeIndex.peek() + 1, optionElements.length - 1);
1056
- state.activeIndex.value = next;
1057
- updateActiveDescendant(next);
1058
- return;
1059
- }
1060
- if (isKey(event, Keys.ArrowUp)) {
1061
- event.preventDefault();
1062
- const prev = Math.max(state.activeIndex.peek() - 1, 0);
1063
- state.activeIndex.value = prev;
1064
- updateActiveDescendant(prev);
1065
- return;
1066
- }
1067
- if (isKey(event, Keys.Enter)) {
1068
- event.preventDefault();
1069
- const idx = state.activeIndex.peek();
1070
- if (idx >= 0 && idx < optionElements.length) {
1071
- const val = optionElements[idx]?.getAttribute("data-value");
1072
- if (val != null)
1073
- selectOption(val);
1074
- }
1075
- return;
1076
- }
1077
- });
1078
- function Option(value, label) {
1079
- const opt = document.createElement("div");
1080
- const optId = `${ids.contentId}-opt-${optionElements.length}`;
1081
- opt.setAttribute("role", "option");
1082
- opt.id = optId;
1083
- opt.setAttribute("data-value", value);
1084
- opt.textContent = label ?? value;
1085
- const isSelected = value === defaultValue;
1086
- setSelected(opt, isSelected);
1087
- setDataState(opt, isSelected ? "active" : "inactive");
1088
- opt.addEventListener("click", () => {
1089
- selectOption(value);
1090
- });
1091
- optionElements.push(opt);
1092
- listbox.appendChild(opt);
1093
- return opt;
1094
- }
1095
- return { input, listbox, state, Option };
1096
- }
1097
- };
1098
- // src/command/command.ts
1099
- import { signal as signal9 } from "@vertz/ui";
1100
- var Command = {
1101
- Root(options = {}) {
1102
- const { filter: customFilter, onSelect, onInputChange, placeholder } = options;
1103
- const listId = uniqueId("command-list");
1104
- const state = {
1105
- inputValue: signal9(""),
1106
- activeIndex: signal9(0)
1107
- };
1108
- const allItems = [];
1109
- const groups = new Map;
1110
- const root = document.createElement("div");
1111
- const input = document.createElement("input");
1112
- input.setAttribute("type", "text");
1113
- input.setAttribute("role", "combobox");
1114
- input.setAttribute("aria-autocomplete", "list");
1115
- input.setAttribute("aria-expanded", "true");
1116
- input.setAttribute("aria-controls", listId);
1117
- if (placeholder)
1118
- input.placeholder = placeholder;
1119
- const list = document.createElement("div");
1120
- list.setAttribute("role", "listbox");
1121
- list.id = listId;
1122
- const empty = document.createElement("div");
1123
- setHidden(empty, true);
1124
- const defaultFilter = (value, search) => {
1125
- return value.toLowerCase().includes(search.toLowerCase());
1126
- };
1127
- const filterFn = customFilter ?? defaultFilter;
1128
- function getVisibleItems() {
1129
- return allItems.filter((item) => item.getAttribute("aria-hidden") !== "true");
1130
- }
1131
- function updateActiveItem() {
1132
- const visible = getVisibleItems();
1133
- const activeIdx = state.activeIndex.peek();
1134
- for (const item of allItems) {
1135
- item.setAttribute("aria-selected", "false");
1136
- }
1137
- if (visible.length > 0 && activeIdx >= 0 && activeIdx < visible.length) {
1138
- visible[activeIdx]?.setAttribute("aria-selected", "true");
1139
- }
1140
- }
1141
- function runFilter() {
1142
- const search = state.inputValue.peek();
1143
- let visibleCount = 0;
1144
- for (const item of allItems) {
1145
- const value = item.getAttribute("data-value") ?? "";
1146
- const text = item.textContent ?? "";
1147
- const keywords = item.getAttribute("data-keywords") ?? "";
1148
- const searchable = `${value} ${text} ${keywords}`;
1149
- const matches = search === "" || filterFn(searchable, search);
1150
- setHidden(item, !matches);
1151
- if (matches)
1152
- visibleCount++;
1153
- }
1154
- for (const [groupEl, group] of groups) {
1155
- const hasVisible = group.items.some((item) => item.getAttribute("aria-hidden") !== "true");
1156
- setHidden(group.heading, !hasVisible);
1157
- if (!hasVisible) {
1158
- groupEl.style.display = "none";
1159
- } else {
1160
- groupEl.style.display = "";
1161
- }
1162
- }
1163
- setHidden(empty, visibleCount > 0);
1164
- state.activeIndex.value = 0;
1165
- updateActiveItem();
1166
- }
1167
- input.addEventListener("input", () => {
1168
- state.inputValue.value = input.value;
1169
- onInputChange?.(input.value);
1170
- runFilter();
1171
- });
1172
- input.addEventListener("keydown", (event) => {
1173
- const visible = getVisibleItems();
1174
- if (isKey(event, Keys.ArrowDown)) {
1175
- event.preventDefault();
1176
- const next = Math.min(state.activeIndex.peek() + 1, visible.length - 1);
1177
- state.activeIndex.value = next;
1178
- updateActiveItem();
1179
- return;
1180
- }
1181
- if (isKey(event, Keys.ArrowUp)) {
1182
- event.preventDefault();
1183
- const prev = Math.max(state.activeIndex.peek() - 1, 0);
1184
- state.activeIndex.value = prev;
1185
- updateActiveItem();
1186
- return;
1187
- }
1188
- if (isKey(event, Keys.Enter)) {
1189
- event.preventDefault();
1190
- const active = visible[state.activeIndex.peek()];
1191
- if (active) {
1192
- const val = active.getAttribute("data-value");
1193
- if (val !== null) {
1194
- onSelect?.(val);
1195
- }
1196
- }
1197
- return;
1198
- }
1199
- if (isKey(event, Keys.Escape)) {
1200
- event.preventDefault();
1201
- input.value = "";
1202
- state.inputValue.value = "";
1203
- onInputChange?.("");
1204
- runFilter();
1205
- }
1206
- });
1207
- function createItem(value, label, keywords, parent) {
1208
- const item = document.createElement("div");
1209
- item.setAttribute("role", "option");
1210
- item.setAttribute("data-value", value);
1211
- item.setAttribute("aria-selected", "false");
1212
- item.textContent = label ?? value;
1213
- if (keywords && keywords.length > 0) {
1214
- item.setAttribute("data-keywords", keywords.join(" "));
1215
- }
1216
- item.addEventListener("click", () => {
1217
- onSelect?.(value);
1218
- });
1219
- allItems.push(item);
1220
- (parent ?? list).appendChild(item);
1221
- updateActiveItem();
1222
- return item;
1223
- }
1224
- function Item(value, label, keywords) {
1225
- return createItem(value, label, keywords);
1226
- }
1227
- function Group(label) {
1228
- const headingId = uniqueId("command-group");
1229
- const el = document.createElement("div");
1230
- el.setAttribute("role", "group");
1231
- el.setAttribute("aria-labelledby", headingId);
1232
- const heading = document.createElement("div");
1233
- heading.id = headingId;
1234
- heading.textContent = label;
1235
- el.appendChild(heading);
1236
- const groupItems = [];
1237
- groups.set(el, { heading, items: groupItems });
1238
- list.appendChild(el);
1239
- return {
1240
- el,
1241
- Item: (value, itemLabel, keywords) => {
1242
- const item = createItem(value, itemLabel, keywords, el);
1243
- groupItems.push(item);
1244
- return item;
1245
- }
1246
- };
1247
- }
1248
- function Separator() {
1249
- const hr = document.createElement("hr");
1250
- hr.setAttribute("role", "separator");
1251
- list.appendChild(hr);
1252
- return hr;
1253
- }
1254
- root.appendChild(input);
1255
- root.appendChild(list);
1256
- root.appendChild(empty);
1257
- return { root, input, list, empty, state, Item, Group, Separator };
1258
- }
1259
- };
1260
- // src/context-menu/context-menu.ts
1261
- import { signal as signal10 } from "@vertz/ui";
1262
-
1263
- // src/utils/dismiss.ts
1264
- function createDismiss(options) {
1265
- const { onDismiss, insideElements, escapeKey = true, clickOutside = true } = options;
1266
- function handlePointerDown(event) {
1267
- const target = event.target;
1268
- const isInside = insideElements.some((el) => el.contains(target));
1269
- if (!isInside) {
1270
- onDismiss();
1271
- }
1272
- }
1273
- function handleKeyDown(event) {
1274
- if (event.key === "Escape") {
1275
- onDismiss();
1276
- }
1277
- }
1278
- if (clickOutside) {
1279
- document.addEventListener("pointerdown", handlePointerDown, true);
1280
- }
1281
- if (escapeKey) {
1282
- document.addEventListener("keydown", handleKeyDown);
1283
- }
1284
- return function cleanup() {
1285
- if (clickOutside) {
1286
- document.removeEventListener("pointerdown", handlePointerDown, true);
1287
- }
1288
- if (escapeKey) {
1289
- document.removeEventListener("keydown", handleKeyDown);
1290
- }
1291
- };
1292
- }
1293
-
1294
- // src/utils/floating.ts
1295
- import { autoUpdate, computePosition, flip, offset, shift } from "@floating-ui/dom";
1296
- function createFloatingPosition(reference, floating, options = {}) {
1297
- const {
1298
- placement = "bottom-start",
1299
- strategy = "fixed",
1300
- offset: offsetValue = 4,
1301
- flip: enableFlip = true,
1302
- shift: enableShift = true,
1303
- middleware: extraMiddleware = [],
1304
- matchReferenceWidth = false,
1305
- portal = false
1306
- } = options;
1307
- if (portal && floating.parentElement !== document.body) {
1308
- document.body.appendChild(floating);
1309
- }
1310
- const mw = [];
1311
- mw.push(offset(offsetValue));
1312
- if (enableFlip)
1313
- mw.push(flip());
1314
- if (enableShift)
1315
- mw.push(shift());
1316
- if (matchReferenceWidth) {
1317
- mw.push({
1318
- name: "matchReferenceWidth",
1319
- fn({ rects }) {
1320
- floating.style.minWidth = `${rects.reference.width}px`;
1321
- return {};
1322
- }
1323
- });
1324
- }
1325
- mw.push(...extraMiddleware);
1326
- function updatePosition() {
1327
- computePosition(reference, floating, {
1328
- placement,
1329
- strategy,
1330
- middleware: mw
1331
- }).then((result) => {
1332
- floating.style.position = result.strategy;
1333
- floating.style.left = `${result.x}px`;
1334
- floating.style.top = `${result.y}px`;
1335
- const [side = "bottom", align = "center"] = result.placement.split("-");
1336
- floating.setAttribute("data-side", side);
1337
- floating.setAttribute("data-align", align);
1338
- });
1339
- }
1340
- const cleanupAutoUpdate = autoUpdate(reference, floating, updatePosition, {
1341
- animationFrame: true
1342
- });
1343
- return {
1344
- cleanup: cleanupAutoUpdate,
1345
- update() {
1346
- updatePosition();
1347
- return Promise.resolve();
1348
- }
1349
- };
1350
- }
1351
- function virtualElement(x, y) {
1352
- return {
1353
- getBoundingClientRect() {
1354
- return {
1355
- x,
1356
- y,
1357
- top: y,
1358
- left: x,
1359
- bottom: y,
1360
- right: x,
1361
- width: 0,
1362
- height: 0,
1363
- toJSON() {
1364
- return this;
1365
- }
1366
- };
1367
- }
1368
- };
1369
- }
1370
-
1371
- // src/context-menu/context-menu.ts
1372
- var ContextMenu = {
1373
- Root(options = {}) {
1374
- const { onSelect, positioning } = options;
1375
- const state = {
1376
- open: signal10(false),
1377
- activeIndex: signal10(-1)
1378
- };
1379
- const items = [];
1380
- let floatingCleanup = null;
1381
- let dismissCleanup = null;
1382
- const trigger = document.createElement("div");
1383
- const contentId = uniqueId("ctx-menu");
1384
- const content = document.createElement("div");
1385
- content.setAttribute("role", "menu");
1386
- content.id = contentId;
1387
- content.style.position = "fixed";
1388
- setHidden(content, true);
1389
- setDataState(content, "closed");
1390
- function handleClickOutside(event) {
1391
- const target = event.target;
1392
- if (!trigger.contains(target) && !content.contains(target)) {
1393
- close();
1394
- }
1395
- }
1396
- function open(x, y) {
1397
- state.open.value = true;
1398
- setHidden(content, false);
1399
- setDataState(content, "open");
1400
- if (positioning) {
1401
- const result = createFloatingPosition(virtualElement(x, y), content, {
1402
- strategy: "fixed",
1403
- ...positioning
1404
- });
1405
- floatingCleanup = result.cleanup;
1406
- dismissCleanup = createDismiss({
1407
- onDismiss: close,
1408
- insideElements: [trigger, content],
1409
- escapeKey: false
1410
- });
1411
- } else {
1412
- content.style.left = `${x}px`;
1413
- content.style.top = `${y}px`;
1414
- document.addEventListener("mousedown", handleClickOutside);
1415
- }
1416
- state.activeIndex.value = 0;
1417
- updateActiveItem(0);
1418
- items[0]?.focus();
1419
- }
1420
- function close() {
1421
- state.open.value = false;
1422
- setDataState(content, "closed");
1423
- setHiddenAnimated(content, true);
1424
- if (positioning) {
1425
- floatingCleanup?.();
1426
- floatingCleanup = null;
1427
- dismissCleanup?.();
1428
- dismissCleanup = null;
1429
- } else {
1430
- document.removeEventListener("mousedown", handleClickOutside);
1431
- }
1432
- }
1433
- function updateActiveItem(index) {
1434
- for (let i = 0;i < items.length; i++) {
1435
- items[i]?.setAttribute("tabindex", i === index ? "0" : "-1");
1436
- }
1437
- }
1438
- trigger.addEventListener("contextmenu", (event) => {
1439
- event.preventDefault();
1440
- if (state.open.peek()) {
1441
- close();
1442
- }
1443
- open(event.clientX, event.clientY);
1444
- });
1445
- content.addEventListener("keydown", (event) => {
1446
- if (isKey(event, Keys.Escape)) {
1447
- event.preventDefault();
1448
- close();
1449
- return;
1450
- }
1451
- if (isKey(event, Keys.Enter, Keys.Space)) {
1452
- event.preventDefault();
1453
- const active = items[state.activeIndex.peek()];
1454
- if (active) {
1455
- const val = active.getAttribute("data-value");
1456
- if (val !== null) {
1457
- onSelect?.(val);
1458
- close();
1459
- }
1460
- }
1461
- return;
1462
- }
1463
- const result = handleListNavigation(event, items, { orientation: "vertical" });
1464
- if (result) {
1465
- const idx = items.indexOf(result);
1466
- if (idx >= 0) {
1467
- state.activeIndex.value = idx;
1468
- updateActiveItem(idx);
1469
- }
1470
- return;
1471
- }
1472
- if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) {
1473
- const char = event.key.toLowerCase();
1474
- const match = items.find((item) => item.textContent?.toLowerCase().startsWith(char));
1475
- if (match) {
1476
- const idx = items.indexOf(match);
1477
- state.activeIndex.value = idx;
1478
- updateActiveItem(idx);
1479
- match.focus();
1480
- }
1481
- }
1482
- });
1483
- function createItem(value, label, parent) {
1484
- const item = document.createElement("div");
1485
- item.setAttribute("role", "menuitem");
1486
- item.setAttribute("data-value", value);
1487
- item.setAttribute("tabindex", "-1");
1488
- item.textContent = label ?? value;
1489
- item.addEventListener("click", () => {
1490
- onSelect?.(value);
1491
- close();
1492
- });
1493
- items.push(item);
1494
- (parent ?? content).appendChild(item);
1495
- return item;
1496
- }
1497
- function Item(value, label) {
1498
- return createItem(value, label);
1499
- }
1500
- function Group(label) {
1501
- const el = document.createElement("div");
1502
- el.setAttribute("role", "group");
1503
- el.setAttribute("aria-label", label);
1504
- content.appendChild(el);
1505
- return {
1506
- el,
1507
- Item: (value, itemLabel) => createItem(value, itemLabel, el)
1508
- };
1509
- }
1510
- function Separator() {
1511
- const hr = document.createElement("hr");
1512
- hr.setAttribute("role", "separator");
1513
- content.appendChild(hr);
1514
- return hr;
1515
- }
1516
- function Label(text) {
1517
- const el = document.createElement("div");
1518
- el.setAttribute("role", "none");
1519
- el.textContent = text;
1520
- content.appendChild(el);
1521
- return el;
1522
- }
1523
- return { trigger, content, state, Item, Group, Separator, Label };
1524
- }
1525
- };
1526
- // src/date-picker/date-picker.ts
1527
- import { signal as signal12 } from "@vertz/ui";
1528
-
1529
- // src/popover/popover.ts
1530
- import { signal as signal11 } from "@vertz/ui";
1531
- var Popover = {
1532
- Root(options = {}) {
1533
- const { defaultOpen = false, onOpenChange, positioning } = options;
1534
- const ids = linkedIds("popover");
1535
- const state = { open: signal11(defaultOpen) };
1536
- let restoreFocus = null;
1537
- let floatingCleanup = null;
1538
- let dismissCleanup = null;
1539
- const trigger = document.createElement("button");
1540
- trigger.setAttribute("type", "button");
1541
- trigger.id = ids.triggerId;
1542
- trigger.setAttribute("aria-controls", ids.contentId);
1543
- trigger.setAttribute("aria-haspopup", "dialog");
1544
- setExpanded(trigger, defaultOpen);
1545
- setDataState(trigger, defaultOpen ? "open" : "closed");
1546
- const content = document.createElement("div");
1547
- content.setAttribute("role", "dialog");
1548
- content.id = ids.contentId;
1549
- setHidden(content, !defaultOpen);
1550
- setDataState(content, defaultOpen ? "open" : "closed");
1551
- function open() {
1552
- state.open.value = true;
1553
- setExpanded(trigger, true);
1554
- setHidden(content, false);
1555
- setDataState(trigger, "open");
1556
- setDataState(content, "open");
1557
- restoreFocus = saveFocus();
1558
- queueMicrotask(() => focusFirst(content));
1559
- if (positioning) {
1560
- const result = createFloatingPosition(trigger, content, positioning);
1561
- floatingCleanup = result.cleanup;
1562
- dismissCleanup = createDismiss({
1563
- onDismiss: close,
1564
- insideElements: [trigger, content],
1565
- escapeKey: false
1566
- });
1567
- }
1568
- onOpenChange?.(true);
1569
- }
1570
- function close() {
1571
- state.open.value = false;
1572
- setExpanded(trigger, false);
1573
- setDataState(trigger, "closed");
1574
- setDataState(content, "closed");
1575
- setHiddenAnimated(content, true);
1576
- floatingCleanup?.();
1577
- floatingCleanup = null;
1578
- dismissCleanup?.();
1579
- dismissCleanup = null;
1580
- restoreFocus?.();
1581
- restoreFocus = null;
1582
- onOpenChange?.(false);
1583
- }
1584
- trigger.addEventListener("click", () => {
1585
- if (state.open.peek()) {
1586
- close();
1587
- } else {
1588
- open();
1589
- }
1590
- });
1591
- content.addEventListener("keydown", (event) => {
1592
- if (isKey(event, Keys.Escape)) {
1593
- event.preventDefault();
1594
- close();
1595
- }
1596
- });
1597
- return { trigger, content, state };
1598
- }
1599
- };
1600
-
1601
- // src/date-picker/date-picker.ts
1602
- function defaultFormatDate(date) {
1603
- return date.toLocaleDateString();
1604
- }
1605
- function formatRangeDisplay(value, fmt) {
1606
- return `${fmt(value.from)} – ${fmt(value.to)}`;
1607
- }
1608
- var DatePicker = {
1609
- Root(options = {}) {
1610
- const {
1611
- mode = "single",
1612
- defaultValue = null,
1613
- minDate,
1614
- maxDate,
1615
- disabled,
1616
- formatDate = defaultFormatDate,
1617
- placeholder = "Pick a date",
1618
- onValueChange,
1619
- onOpenChange
1620
- } = options;
1621
- const defaultMonth = options.defaultMonth ?? (defaultValue instanceof Date ? defaultValue : defaultValue && ("from" in defaultValue) ? defaultValue.from : new Date);
1622
- const calendarMode = mode === "range" ? "range" : "single";
1623
- const calendarDefaultValue = defaultValue instanceof Date ? defaultValue : defaultValue && ("from" in defaultValue) ? defaultValue : undefined;
1624
- const popover = Popover.Root({
1625
- onOpenChange(open) {
1626
- state.open.value = open;
1627
- onOpenChange?.(open);
1628
- }
1629
- });
1630
- const calendarResult = Calendar.Root({
1631
- mode: calendarMode,
1632
- defaultValue: calendarDefaultValue,
1633
- defaultMonth,
1634
- minDate,
1635
- maxDate,
1636
- disabled,
1637
- onValueChange(value) {
1638
- if (mode === "single" && value instanceof Date) {
1639
- state.value.value = value;
1640
- updateTriggerText();
1641
- onValueChange?.(value);
1642
- hide();
1643
- } else if (mode === "range" && value && "from" in value) {
1644
- const range = value;
1645
- state.value.value = range;
1646
- updateTriggerText();
1647
- onValueChange?.(range);
1648
- if (range.from && range.to && range.from.getTime() !== range.to.getTime()) {
1649
- hide();
1650
- }
1651
- }
1652
- }
1653
- });
1654
- popover.content.appendChild(calendarResult.root);
1655
- const state = {
1656
- open: signal12(false),
1657
- value: signal12(defaultValue),
1658
- displayMonth: calendarResult.state.displayMonth
1659
- };
1660
- function updateTriggerText() {
1661
- const val = state.value.peek();
1662
- if (val === null) {
1663
- popover.trigger.textContent = placeholder;
1664
- popover.trigger.setAttribute("data-placeholder", "true");
1665
- } else if (val instanceof Date) {
1666
- popover.trigger.textContent = formatDate(val);
1667
- popover.trigger.removeAttribute("data-placeholder");
1668
- } else if ("from" in val) {
1669
- popover.trigger.textContent = formatRangeDisplay(val, formatDate);
1670
- popover.trigger.removeAttribute("data-placeholder");
1671
- }
1672
- }
1673
- function show() {
1674
- popover.trigger.click();
1675
- }
1676
- function hide() {
1677
- if (state.open.peek()) {
1678
- popover.trigger.click();
1679
- }
1680
- }
1681
- updateTriggerText();
1682
- return {
1683
- trigger: popover.trigger,
1684
- content: popover.content,
1685
- calendar: {
1686
- root: calendarResult.root,
1687
- header: calendarResult.header,
1688
- title: calendarResult.title,
1689
- prevButton: calendarResult.prevButton,
1690
- nextButton: calendarResult.nextButton,
1691
- grid: calendarResult.grid
1692
- },
1693
- state,
1694
- show,
1695
- hide
1696
- };
1697
- }
1698
- };
1699
- // src/dialog/dialog.ts
1700
- import { signal as signal13 } from "@vertz/ui";
1701
- var Dialog = {
1702
- Root(options = {}) {
1703
- const { modal = true, defaultOpen = false, onOpenChange } = options;
1704
- const ids = linkedIds("dialog");
1705
- const titleId = `${ids.contentId}-title`;
1706
- const state = { open: signal13(defaultOpen) };
1707
- let restoreFocus = null;
1708
- let removeTrap = null;
1709
- const trigger = document.createElement("button");
1710
- trigger.setAttribute("type", "button");
1711
- trigger.id = ids.triggerId;
1712
- trigger.setAttribute("aria-controls", ids.contentId);
1713
- setExpanded(trigger, defaultOpen);
1714
- setDataState(trigger, defaultOpen ? "open" : "closed");
1715
- const overlay = document.createElement("div");
1716
- overlay.setAttribute("data-dialog-overlay", "");
1717
- setHidden(overlay, !defaultOpen);
1718
- setDataState(overlay, defaultOpen ? "open" : "closed");
1719
- const content = document.createElement("div");
1720
- content.setAttribute("role", "dialog");
1721
- content.id = ids.contentId;
1722
- if (modal) {
1723
- content.setAttribute("aria-modal", "true");
1724
- }
1725
- setLabelledBy(content, titleId);
1726
- setHidden(content, !defaultOpen);
1727
- setDataState(content, defaultOpen ? "open" : "closed");
1728
- const title = document.createElement("h2");
1729
- title.id = titleId;
1730
- const close = document.createElement("button");
1731
- close.setAttribute("type", "button");
1732
- close.setAttribute("aria-label", "Close");
1733
- function openDialog() {
1734
- state.open.value = true;
1735
- setExpanded(trigger, true);
1736
- setHidden(overlay, false);
1737
- setHidden(content, false);
1738
- setDataState(trigger, "open");
1739
- setDataState(overlay, "open");
1740
- setDataState(content, "open");
1741
- restoreFocus = saveFocus();
1742
- if (modal) {
1743
- removeTrap = trapFocus(content);
1744
- }
1745
- queueMicrotask(() => focusFirst(content));
1746
- onOpenChange?.(true);
1747
- }
1748
- function closeDialog() {
1749
- state.open.value = false;
1750
- setExpanded(trigger, false);
1751
- setDataState(trigger, "closed");
1752
- setDataState(overlay, "closed");
1753
- setDataState(content, "closed");
1754
- setHiddenAnimated(overlay, true);
1755
- setHiddenAnimated(content, true);
1756
- removeTrap?.();
1757
- removeTrap = null;
1758
- restoreFocus?.();
1759
- restoreFocus = null;
1760
- onOpenChange?.(false);
1761
- }
1762
- trigger.addEventListener("click", () => {
1763
- if (state.open.peek()) {
1764
- closeDialog();
1765
- } else {
1766
- openDialog();
1767
- }
1768
- });
1769
- close.addEventListener("click", () => {
1770
- closeDialog();
1771
- });
1772
- overlay.addEventListener("click", () => {
1773
- closeDialog();
1774
- });
1775
- content.addEventListener("keydown", (event) => {
1776
- if (isKey(event, Keys.Escape)) {
1777
- event.preventDefault();
1778
- event.stopPropagation();
1779
- closeDialog();
1780
- }
1781
- });
1782
- return { trigger, overlay, content, title, close, state, show: openDialog, hide: closeDialog };
1783
- }
1784
- };
1785
- // src/menu/menu.ts
1786
- import { signal as signal14 } from "@vertz/ui";
1787
- var Menu = {
1788
- Root(options = {}) {
1789
- const { onSelect, positioning } = options;
1790
- const ids = linkedIds("menu");
1791
- const state = {
1792
- open: signal14(false),
1793
- activeIndex: signal14(-1)
1794
- };
1795
- const items = [];
1796
- let floatingCleanup = null;
1797
- let dismissCleanup = null;
1798
- const trigger = document.createElement("button");
1799
- trigger.setAttribute("type", "button");
1800
- trigger.id = ids.triggerId;
1801
- trigger.setAttribute("aria-controls", ids.contentId);
1802
- trigger.setAttribute("aria-haspopup", "menu");
1803
- setExpanded(trigger, false);
1804
- setDataState(trigger, "closed");
1805
- const content = document.createElement("div");
1806
- content.setAttribute("role", "menu");
1807
- content.setAttribute("tabindex", "-1");
1808
- content.id = ids.contentId;
1809
- setHidden(content, true);
1810
- setDataState(content, "closed");
1811
- function handleClickOutside(event) {
1812
- const target = event.target;
1813
- if (!trigger.contains(target) && !content.contains(target)) {
1814
- close();
1815
- }
1816
- }
1817
- function open(activateFirst = false) {
1818
- state.open.value = true;
1819
- setExpanded(trigger, true);
1820
- setHidden(content, false);
1821
- setDataState(trigger, "open");
1822
- setDataState(content, "open");
1823
- if (positioning) {
1824
- const ref = positioning.referenceElement ?? trigger;
1825
- const result = createFloatingPosition(ref, content, positioning);
1826
- floatingCleanup = result.cleanup;
1827
- dismissCleanup = createDismiss({
1828
- onDismiss: close,
1829
- insideElements: [ref, trigger, content],
1830
- escapeKey: false
1831
- });
1832
- } else {
1833
- document.addEventListener("mousedown", handleClickOutside);
1834
- }
1835
- if (activateFirst && items.length > 0) {
1836
- state.activeIndex.value = 0;
1837
- updateActiveItem(0);
1838
- items[0]?.focus();
1839
- } else {
1840
- state.activeIndex.value = -1;
1841
- updateActiveItem(-1);
1842
- content.focus();
1843
- }
1844
- }
1845
- function close() {
1846
- state.open.value = false;
1847
- setExpanded(trigger, false);
1848
- setDataState(trigger, "closed");
1849
- setDataState(content, "closed");
1850
- setHiddenAnimated(content, true);
1851
- if (positioning) {
1852
- floatingCleanup?.();
1853
- floatingCleanup = null;
1854
- dismissCleanup?.();
1855
- dismissCleanup = null;
1856
- } else {
1857
- document.removeEventListener("mousedown", handleClickOutside);
1858
- }
1859
- trigger.focus();
1860
- }
1861
- function updateActiveItem(index) {
1862
- for (let i = 0;i < items.length; i++) {
1863
- items[i]?.setAttribute("tabindex", i === index ? "0" : "-1");
1864
- }
1865
- }
1866
- trigger.addEventListener("click", () => {
1867
- if (state.open.peek()) {
1868
- close();
1869
- } else {
1870
- open();
1871
- }
1872
- });
1873
- trigger.addEventListener("keydown", (event) => {
1874
- if (isKey(event, Keys.ArrowDown, Keys.Enter, Keys.Space)) {
1875
- event.preventDefault();
1876
- if (!state.open.peek())
1877
- open(true);
1878
- }
1879
- });
1880
- content.addEventListener("keydown", (event) => {
1881
- if (isKey(event, Keys.Escape)) {
1882
- event.preventDefault();
1883
- close();
1884
- return;
1885
- }
1886
- if (isKey(event, Keys.Enter, Keys.Space)) {
1887
- event.preventDefault();
1888
- const active = items[state.activeIndex.peek()];
1889
- if (active) {
1890
- const val = active.getAttribute("data-value");
1891
- if (val !== null) {
1892
- onSelect?.(val);
1893
- close();
1894
- }
1895
- }
1896
- return;
1897
- }
1898
- if (state.activeIndex.peek() === -1) {
1899
- if (isKey(event, Keys.ArrowDown)) {
1900
- event.preventDefault();
1901
- state.activeIndex.value = 0;
1902
- updateActiveItem(0);
1903
- items[0]?.focus();
1904
- return;
1905
- }
1906
- if (isKey(event, Keys.ArrowUp)) {
1907
- event.preventDefault();
1908
- const last = items.length - 1;
1909
- state.activeIndex.value = last;
1910
- updateActiveItem(last);
1911
- items[last]?.focus();
1912
- return;
1913
- }
1914
- }
1915
- const result = handleListNavigation(event, items, { orientation: "vertical" });
1916
- if (result) {
1917
- const idx = items.indexOf(result);
1918
- if (idx >= 0) {
1919
- state.activeIndex.value = idx;
1920
- updateActiveItem(idx);
1921
- }
1922
- return;
1923
- }
1924
- if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) {
1925
- const char = event.key.toLowerCase();
1926
- const match = items.find((item) => item.textContent?.toLowerCase().startsWith(char));
1927
- if (match) {
1928
- const idx = items.indexOf(match);
1929
- state.activeIndex.value = idx;
1930
- updateActiveItem(idx);
1931
- match.focus();
1932
- }
1933
- }
1934
- });
1935
- function createItem(value, label, parent) {
1936
- const item = document.createElement("div");
1937
- item.setAttribute("role", "menuitem");
1938
- item.setAttribute("data-value", value);
1939
- item.setAttribute("tabindex", "-1");
1940
- item.textContent = label ?? value;
1941
- item.addEventListener("click", () => {
1942
- onSelect?.(value);
1943
- close();
1944
- });
1945
- items.push(item);
1946
- (parent ?? content).appendChild(item);
1947
- return item;
1948
- }
1949
- function Item(value, label) {
1950
- return createItem(value, label);
1951
- }
1952
- function Group(label) {
1953
- const el = document.createElement("div");
1954
- el.setAttribute("role", "group");
1955
- el.setAttribute("aria-label", label);
1956
- content.appendChild(el);
1957
- return {
1958
- el,
1959
- Item: (value, itemLabel) => createItem(value, itemLabel, el)
1960
- };
1961
- }
1962
- function Separator() {
1963
- const hr = document.createElement("hr");
1964
- hr.setAttribute("role", "separator");
1965
- content.appendChild(hr);
1966
- return hr;
1967
- }
1968
- function Label(text) {
1969
- const el = document.createElement("div");
1970
- el.setAttribute("role", "none");
1971
- el.textContent = text;
1972
- content.appendChild(el);
1973
- return el;
1974
- }
1975
- return { trigger, content, state, Item, Group, Separator, Label };
1976
- }
1977
- };
1978
-
1979
- // src/dropdown-menu/dropdown-menu.ts
1980
- var DropdownMenu = {
1981
- Root(options = {}) {
1982
- const { positioning, ...rest } = options;
1983
- return Menu.Root({
1984
- ...rest,
1985
- positioning: {
1986
- placement: "bottom-start",
1987
- ...positioning
1988
- }
1989
- });
1990
- }
1991
- };
1992
- // src/hover-card/hover-card.ts
1993
- import { signal as signal15 } from "@vertz/ui";
1994
- var HoverCard = {
1995
- Root(options = {}) {
1996
- const { openDelay = 700, closeDelay = 300, onOpenChange, positioning } = options;
1997
- const contentId = uniqueId("hovercard");
1998
- const state = { open: signal15(false) };
1999
- let openTimeout = null;
2000
- let closeTimeout = null;
2001
- let floatingCleanup = null;
2002
- const trigger = document.createElement("span");
2003
- trigger.setAttribute("aria-haspopup", "dialog");
2004
- trigger.setAttribute("aria-expanded", "false");
2005
- const content = document.createElement("div");
2006
- content.setAttribute("role", "dialog");
2007
- content.id = contentId;
2008
- setHidden(content, true);
2009
- setDataState(content, "closed");
2010
- function cancelTimers() {
2011
- if (openTimeout) {
2012
- clearTimeout(openTimeout);
2013
- openTimeout = null;
2014
- }
2015
- if (closeTimeout) {
2016
- clearTimeout(closeTimeout);
2017
- closeTimeout = null;
2018
- }
2019
- }
2020
- function show() {
2021
- cancelTimers();
2022
- if (state.open.peek())
2023
- return;
2024
- openTimeout = setTimeout(() => {
2025
- state.open.value = true;
2026
- setExpanded(trigger, true);
2027
- setHidden(content, false);
2028
- setDataState(content, "open");
2029
- if (positioning) {
2030
- const effectivePlacement = positioning.placement ?? "bottom";
2031
- const result = createFloatingPosition(trigger, content, {
2032
- ...positioning,
2033
- placement: effectivePlacement
2034
- });
2035
- floatingCleanup = result.cleanup;
2036
- }
2037
- onOpenChange?.(true);
2038
- openTimeout = null;
2039
- }, openDelay);
2040
- }
2041
- function hide() {
2042
- cancelTimers();
2043
- if (!state.open.peek())
2044
- return;
2045
- closeTimeout = setTimeout(() => {
2046
- state.open.value = false;
2047
- setExpanded(trigger, false);
2048
- setDataState(content, "closed");
2049
- setHiddenAnimated(content, true);
2050
- floatingCleanup?.();
2051
- floatingCleanup = null;
2052
- onOpenChange?.(false);
2053
- closeTimeout = null;
2054
- }, closeDelay);
2055
- }
2056
- trigger.addEventListener("mouseenter", show);
2057
- trigger.addEventListener("mouseleave", hide);
2058
- trigger.addEventListener("focus", () => {
2059
- cancelTimers();
2060
- state.open.value = true;
2061
- setExpanded(trigger, true);
2062
- setHidden(content, false);
2063
- setDataState(content, "open");
2064
- if (positioning) {
2065
- floatingCleanup?.();
2066
- const effectivePlacement = positioning.placement ?? "bottom";
2067
- const result = createFloatingPosition(trigger, content, {
2068
- ...positioning,
2069
- placement: effectivePlacement
2070
- });
2071
- floatingCleanup = result.cleanup;
2072
- }
2073
- onOpenChange?.(true);
2074
- });
2075
- trigger.addEventListener("blur", (event) => {
2076
- const related = event.relatedTarget;
2077
- if (related && (trigger.contains(related) || content.contains(related)))
2078
- return;
2079
- hide();
2080
- });
2081
- content.addEventListener("mouseenter", () => {
2082
- if (closeTimeout) {
2083
- clearTimeout(closeTimeout);
2084
- closeTimeout = null;
2085
- }
2086
- });
2087
- content.addEventListener("mouseleave", hide);
2088
- content.addEventListener("focusin", () => {
2089
- if (closeTimeout) {
2090
- clearTimeout(closeTimeout);
2091
- closeTimeout = null;
2092
- }
2093
- });
2094
- content.addEventListener("focusout", (event) => {
2095
- const related = event.relatedTarget;
2096
- if (related && (trigger.contains(related) || content.contains(related)))
2097
- return;
2098
- hide();
2099
- });
2100
- function hideImmediate() {
2101
- cancelTimers();
2102
- state.open.value = false;
2103
- setExpanded(trigger, false);
2104
- setDataState(content, "closed");
2105
- setHiddenAnimated(content, true);
2106
- floatingCleanup?.();
2107
- floatingCleanup = null;
2108
- onOpenChange?.(false);
2109
- }
2110
- content.addEventListener("keydown", (event) => {
2111
- if (isKey(event, Keys.Escape)) {
2112
- hideImmediate();
2113
- trigger.focus();
2114
- }
2115
- });
2116
- trigger.addEventListener("keydown", (event) => {
2117
- if (isKey(event, Keys.Escape) && state.open.peek()) {
2118
- hideImmediate();
2119
- }
2120
- });
2121
- return { trigger, content, state };
2122
- }
2123
- };
2124
- // src/menubar/menubar.ts
2125
- import { signal as signal16 } from "@vertz/ui";
2126
- var Menubar = {
2127
- Root(options = {}) {
2128
- const { onSelect, positioning } = options;
2129
- const state = { activeMenu: signal16(null) };
2130
- const triggers = [];
2131
- const menus = new Map;
2132
- let floatingCleanup = null;
2133
- let dismissCleanup = null;
2134
- const root = document.createElement("div");
2135
- root.setAttribute("role", "menubar");
2136
- function closeAll() {
2137
- for (const [, menu] of menus) {
2138
- setExpanded(menu.trigger, false);
2139
- setDataState(menu.trigger, "closed");
2140
- setDataState(menu.content, "closed");
2141
- setHiddenAnimated(menu.content, true);
2142
- }
2143
- state.activeMenu.value = null;
2144
- if (positioning) {
2145
- floatingCleanup?.();
2146
- floatingCleanup = null;
2147
- dismissCleanup?.();
2148
- dismissCleanup = null;
2149
- } else {
2150
- document.removeEventListener("mousedown", handleClickOutside);
2151
- }
2152
- }
2153
- function openMenu(value) {
2154
- const current = state.activeMenu.peek();
2155
- if (current && current !== value) {
2156
- const prev = menus.get(current);
2157
- if (prev) {
2158
- setExpanded(prev.trigger, false);
2159
- setDataState(prev.trigger, "closed");
2160
- setDataState(prev.content, "closed");
2161
- setHiddenAnimated(prev.content, true);
2162
- }
2163
- if (positioning) {
2164
- floatingCleanup?.();
2165
- floatingCleanup = null;
2166
- }
2167
- }
2168
- const menu = menus.get(value);
2169
- if (!menu)
2170
- return;
2171
- state.activeMenu.value = value;
2172
- setExpanded(menu.trigger, true);
2173
- setHidden(menu.content, false);
2174
- setDataState(menu.trigger, "open");
2175
- setDataState(menu.content, "open");
2176
- if (positioning) {
2177
- const result = createFloatingPosition(menu.trigger, menu.content, positioning);
2178
- floatingCleanup = result.cleanup;
2179
- if (!dismissCleanup) {
2180
- dismissCleanup = createDismiss({
2181
- onDismiss: closeAll,
2182
- insideElements: [root],
2183
- escapeKey: false
2184
- });
2185
- }
2186
- } else {
2187
- document.addEventListener("mousedown", handleClickOutside);
2188
- }
2189
- const firstItem = menu.items[0];
2190
- if (firstItem) {
2191
- firstItem.setAttribute("tabindex", "0");
2192
- firstItem.focus();
2193
- }
2194
- }
2195
- function handleClickOutside(event) {
2196
- const target = event.target;
2197
- if (!root.contains(target)) {
2198
- closeAll();
2199
- }
2200
- }
2201
- root.addEventListener("keydown", (event) => {
2202
- if (isKey(event, Keys.ArrowLeft, Keys.ArrowRight, Keys.Home, Keys.End)) {
2203
- const focused = document.activeElement;
2204
- const triggerIndex = triggers.indexOf(focused);
2205
- if (triggerIndex >= 0) {
2206
- const result = handleListNavigation(event, triggers, { orientation: "horizontal" });
2207
- if (result && state.activeMenu.peek()) {
2208
- const newTrigger = result;
2209
- const menuValue = newTrigger.getAttribute("data-value");
2210
- if (menuValue)
2211
- openMenu(menuValue);
2212
- }
2213
- }
2214
- }
2215
- });
2216
- function Menu2(value, label) {
2217
- const ids = linkedIds("menubar-menu");
2218
- const items = [];
2219
- const trigger = document.createElement("button");
2220
- trigger.setAttribute("type", "button");
2221
- trigger.setAttribute("role", "menuitem");
2222
- trigger.id = ids.triggerId;
2223
- trigger.setAttribute("aria-controls", ids.contentId);
2224
- trigger.setAttribute("aria-haspopup", "menu");
2225
- trigger.setAttribute("data-value", value);
2226
- trigger.textContent = label ?? value;
2227
- setExpanded(trigger, false);
2228
- setDataState(trigger, "closed");
2229
- setRovingTabindex(triggers.concat(trigger), triggers.length);
2230
- const content = document.createElement("div");
2231
- content.setAttribute("role", "menu");
2232
- content.id = ids.contentId;
2233
- setHidden(content, true);
2234
- setDataState(content, "closed");
2235
- trigger.addEventListener("click", () => {
2236
- if (state.activeMenu.peek() === value) {
2237
- closeAll();
2238
- } else {
2239
- openMenu(value);
2240
- }
2241
- });
2242
- trigger.addEventListener("keydown", (event) => {
2243
- if (isKey(event, Keys.ArrowDown, Keys.Enter, Keys.Space)) {
2244
- event.preventDefault();
2245
- openMenu(value);
2246
- }
2247
- });
2248
- content.addEventListener("keydown", (event) => {
2249
- if (isKey(event, Keys.Escape)) {
2250
- event.preventDefault();
2251
- event.stopPropagation();
2252
- closeAll();
2253
- trigger.focus();
2254
- return;
2255
- }
2256
- if (isKey(event, Keys.Enter, Keys.Space)) {
2257
- event.preventDefault();
2258
- const active = document.activeElement;
2259
- const activeItem = items.find((item) => item === active);
2260
- if (activeItem) {
2261
- const val = activeItem.getAttribute("data-value");
2262
- if (val !== null) {
2263
- onSelect?.(val);
2264
- closeAll();
2265
- trigger.focus();
2266
- }
2267
- }
2268
- return;
2269
- }
2270
- if (isKey(event, Keys.ArrowLeft, Keys.ArrowRight)) {
2271
- event.preventDefault();
2272
- const triggerIdx = triggers.indexOf(trigger);
2273
- let nextIdx;
2274
- if (isKey(event, Keys.ArrowRight)) {
2275
- nextIdx = (triggerIdx + 1) % triggers.length;
2276
- } else {
2277
- nextIdx = (triggerIdx - 1 + triggers.length) % triggers.length;
2278
- }
2279
- const nextTrigger = triggers[nextIdx];
2280
- if (nextTrigger) {
2281
- nextTrigger.focus();
2282
- const nextValue = nextTrigger.getAttribute("data-value");
2283
- if (nextValue)
2284
- openMenu(nextValue);
2285
- }
2286
- return;
2287
- }
2288
- handleListNavigation(event, items, { orientation: "vertical" });
2289
- });
2290
- function createItem(val, itemLabel, parent) {
2291
- const item = document.createElement("div");
2292
- item.setAttribute("role", "menuitem");
2293
- item.setAttribute("data-value", val);
2294
- item.setAttribute("tabindex", "-1");
2295
- item.textContent = itemLabel ?? val;
2296
- item.addEventListener("click", () => {
2297
- onSelect?.(val);
2298
- closeAll();
2299
- trigger.focus();
2300
- });
2301
- items.push(item);
2302
- (parent ?? content).appendChild(item);
2303
- return item;
2304
- }
2305
- function Item(val, itemLabel) {
2306
- return createItem(val, itemLabel);
2307
- }
2308
- function Group(groupLabel) {
2309
- const el = document.createElement("div");
2310
- el.setAttribute("role", "group");
2311
- el.setAttribute("aria-label", groupLabel);
2312
- content.appendChild(el);
2313
- return {
2314
- el,
2315
- Item: (val, l) => createItem(val, l, el)
2316
- };
2317
- }
2318
- function Separator() {
2319
- const hr = document.createElement("hr");
2320
- hr.setAttribute("role", "separator");
2321
- content.appendChild(hr);
2322
- return hr;
2323
- }
2324
- triggers.push(trigger);
2325
- setRovingTabindex(triggers, 0);
2326
- menus.set(value, { trigger, content, items });
2327
- root.appendChild(trigger);
2328
- return { trigger, content, Item, Group, Separator };
2329
- }
2330
- return { root, state, Menu: Menu2 };
2331
- }
2332
- };
2333
- // src/navigation-menu/navigation-menu.ts
2334
- import { signal as signal17 } from "@vertz/ui";
2335
- var NavigationMenu = {
2336
- Root(options = {}) {
2337
- const { orientation = "horizontal", delayOpen = 200, delayClose = 300 } = options;
2338
- const state = { activeItem: signal17(null) };
2339
- const triggers = [];
2340
- const items = new Map;
2341
- let openTimeout = null;
2342
- let closeTimeout = null;
2343
- const root = document.createElement("nav");
2344
- const list = document.createElement("div");
2345
- const viewport = document.createElement("div");
2346
- function cancelTimers() {
2347
- if (openTimeout) {
2348
- clearTimeout(openTimeout);
2349
- openTimeout = null;
2350
- }
2351
- if (closeTimeout) {
2352
- clearTimeout(closeTimeout);
2353
- closeTimeout = null;
2354
- }
2355
- }
2356
- function openItem(value) {
2357
- cancelTimers();
2358
- const current = state.activeItem.peek();
2359
- if (current && current !== value) {
2360
- const prev = items.get(current);
2361
- if (prev) {
2362
- setExpanded(prev.trigger, false);
2363
- setDataState(prev.trigger, "closed");
2364
- setDataState(prev.content, "closed");
2365
- setHiddenAnimated(prev.content, true);
2366
- }
2367
- }
2368
- const item = items.get(value);
2369
- if (!item)
2370
- return;
2371
- state.activeItem.value = value;
2372
- setExpanded(item.trigger, true);
2373
- setHidden(item.content, false);
2374
- setDataState(item.trigger, "open");
2375
- setDataState(item.content, "open");
2376
- }
2377
- function closeAll() {
2378
- cancelTimers();
2379
- const current = state.activeItem.peek();
2380
- if (current) {
2381
- const item = items.get(current);
2382
- if (item) {
2383
- setExpanded(item.trigger, false);
2384
- setDataState(item.trigger, "closed");
2385
- setDataState(item.content, "closed");
2386
- setHiddenAnimated(item.content, true);
2387
- }
2388
- }
2389
- state.activeItem.value = null;
2390
- }
2391
- function Item(value, label) {
2392
- const ids = linkedIds("nav-menu");
2393
- const trigger = document.createElement("button");
2394
- trigger.setAttribute("type", "button");
2395
- trigger.id = ids.triggerId;
2396
- trigger.setAttribute("aria-controls", ids.contentId);
2397
- trigger.setAttribute("data-value", value);
2398
- trigger.textContent = label ?? value;
2399
- setExpanded(trigger, false);
2400
- setDataState(trigger, "closed");
2401
- const content = document.createElement("div");
2402
- content.id = ids.contentId;
2403
- setHidden(content, true);
2404
- setDataState(content, "closed");
2405
- trigger.addEventListener("click", () => {
2406
- if (state.activeItem.peek() === value) {
2407
- closeAll();
2408
- } else {
2409
- openItem(value);
2410
- }
2411
- });
2412
- trigger.addEventListener("mouseenter", () => {
2413
- cancelTimers();
2414
- openTimeout = setTimeout(() => {
2415
- openItem(value);
2416
- openTimeout = null;
2417
- }, delayOpen);
2418
- });
2419
- trigger.addEventListener("mouseleave", () => {
2420
- cancelTimers();
2421
- closeTimeout = setTimeout(() => {
2422
- closeAll();
2423
- closeTimeout = null;
2424
- }, delayClose);
2425
- });
2426
- content.addEventListener("mouseenter", () => {
2427
- cancelTimers();
2428
- });
2429
- content.addEventListener("mouseleave", () => {
2430
- cancelTimers();
2431
- closeTimeout = setTimeout(() => {
2432
- closeAll();
2433
- closeTimeout = null;
2434
- }, delayClose);
2435
- });
2436
- trigger.addEventListener("keydown", (event) => {
2437
- if (isKey(event, Keys.Enter, Keys.Space)) {
2438
- event.preventDefault();
2439
- openItem(value);
2440
- queueMicrotask(() => focusFirst(content));
2441
- }
2442
- if (isKey(event, Keys.Escape)) {
2443
- event.preventDefault();
2444
- closeAll();
2445
- }
2446
- });
2447
- content.addEventListener("keydown", (event) => {
2448
- if (isKey(event, Keys.Escape)) {
2449
- event.preventDefault();
2450
- event.stopPropagation();
2451
- closeAll();
2452
- trigger.focus();
2453
- }
2454
- });
2455
- triggers.push(trigger);
2456
- setRovingTabindex(triggers, 0);
2457
- items.set(value, { trigger, content });
2458
- list.appendChild(trigger);
2459
- viewport.appendChild(content);
2460
- return { trigger, content };
2461
- }
2462
- function Link(href, label) {
2463
- const a = document.createElement("a");
2464
- a.href = href;
2465
- a.textContent = label;
2466
- list.appendChild(a);
2467
- return a;
2468
- }
2469
- list.addEventListener("keydown", (event) => {
2470
- if (isKey(event, Keys.ArrowLeft, Keys.ArrowRight, Keys.Home, Keys.End)) {
2471
- handleListNavigation(event, triggers, {
2472
- orientation: orientation === "horizontal" ? "horizontal" : "vertical"
2473
- });
2474
- }
2475
- });
2476
- root.appendChild(list);
2477
- root.appendChild(viewport);
2478
- return { root, list, viewport, state, Item, Link };
2479
- }
2480
- };
2481
- // src/progress/progress.ts
2482
- import { signal as signal18 } from "@vertz/ui";
2483
- var Progress = {
2484
- Root(options = {}) {
2485
- const { defaultValue = 0, min = 0, max = 100 } = options;
2486
- const state = { value: signal18(defaultValue) };
2487
- const root = document.createElement("div");
2488
- root.setAttribute("role", "progressbar");
2489
- root.id = uniqueId("progress");
2490
- setValueRange(root, defaultValue, min, max);
2491
- const pct = (defaultValue - min) / (max - min) * 100;
2492
- if (pct >= 100) {
2493
- setDataState(root, "complete");
2494
- } else if (pct > 0) {
2495
- setDataState(root, "loading");
2496
- } else {
2497
- setDataState(root, "idle");
2498
- }
2499
- const indicator = document.createElement("div");
2500
- indicator.setAttribute("data-part", "indicator");
2501
- indicator.style.width = `${pct}%`;
2502
- root.appendChild(indicator);
2503
- function setValue(val) {
2504
- const clamped = Math.min(max, Math.max(min, val));
2505
- state.value.value = clamped;
2506
- setValueRange(root, clamped, min, max);
2507
- const p = (clamped - min) / (max - min) * 100;
2508
- indicator.style.width = `${p}%`;
2509
- if (p >= 100) {
2510
- setDataState(root, "complete");
2511
- } else if (p > 0) {
2512
- setDataState(root, "loading");
2513
- } else {
2514
- setDataState(root, "idle");
2515
- }
2516
- }
2517
- return { root, indicator, state, setValue };
2518
- }
2519
- };
2520
- // src/radio/radio.ts
2521
- import { signal as signal19 } from "@vertz/ui";
2522
- var Radio = {
2523
- Root(options = {}) {
2524
- const { defaultValue = "", onValueChange } = options;
2525
- const state = { value: signal19(defaultValue) };
2526
- const items = [];
2527
- const itemValues = [];
2528
- const root = document.createElement("div");
2529
- root.setAttribute("role", "radiogroup");
2530
- root.id = uniqueId("radiogroup");
2531
- function selectItem(value) {
2532
- state.value.value = value;
2533
- for (let i = 0;i < items.length; i++) {
2534
- const item = items[i];
2535
- if (!item)
2536
- continue;
2537
- const isActive = itemValues[i] === value;
2538
- setChecked(item, isActive);
2539
- setDataState(item, isActive ? "checked" : "unchecked");
2540
- }
2541
- setRovingTabindex(items, itemValues.indexOf(value));
2542
- onValueChange?.(value);
2543
- }
2544
- root.addEventListener("keydown", (event) => {
2545
- const result = handleListNavigation(event, items, { orientation: "vertical" });
2546
- if (result) {
2547
- const idx = items.indexOf(result);
2548
- if (idx >= 0) {
2549
- const val = itemValues[idx];
2550
- if (val !== undefined)
2551
- selectItem(val);
2552
- }
2553
- }
2554
- });
2555
- function Item(value, label) {
2556
- const item = document.createElement("div");
2557
- item.setAttribute("role", "radio");
2558
- item.id = uniqueId("radio");
2559
- item.setAttribute("data-value", value);
2560
- item.textContent = label ?? value;
2561
- const isActive = value === state.value.peek();
2562
- setChecked(item, isActive);
2563
- setDataState(item, isActive ? "checked" : "unchecked");
2564
- item.addEventListener("click", () => {
2565
- selectItem(value);
2566
- item.focus();
2567
- });
2568
- items.push(item);
2569
- itemValues.push(value);
2570
- root.appendChild(item);
2571
- setRovingTabindex(items, itemValues.indexOf(state.value.peek()));
2572
- return item;
2573
- }
2574
- return { root, state, Item };
2575
- }
2576
- };
2577
- // src/resizable-panel/resizable-panel.ts
2578
- import { signal as signal20 } from "@vertz/ui";
2579
- var ResizablePanel = {
2580
- Root(options = {}) {
2581
- const { orientation = "horizontal", onResize } = options;
2582
- const state = { sizes: signal20([]) };
2583
- const panels = [];
2584
- const handles = [];
2585
- const root = document.createElement("div");
2586
- root.style.display = "flex";
2587
- root.style.flexDirection = orientation === "horizontal" ? "row" : "column";
2588
- root.setAttribute("data-orientation", orientation);
2589
- function updateSizes(newSizes) {
2590
- state.sizes.value = [...newSizes];
2591
- for (let i = 0;i < panels.length; i++) {
2592
- const panel = panels[i];
2593
- if (!panel)
2594
- continue;
2595
- const size = newSizes[i] ?? 0;
2596
- panel.el.style.flex = `0 0 ${size}%`;
2597
- }
2598
- for (let i = 0;i < handles.length; i++) {
2599
- const handle = handles[i];
2600
- const leftPanel = panels[i];
2601
- if (handle && leftPanel) {
2602
- const size = newSizes[i] ?? 0;
2603
- setValueRange(handle, Math.round(size), Math.round(leftPanel.minSize), Math.round(leftPanel.maxSize));
2604
- }
2605
- }
2606
- onResize?.(newSizes);
2607
- }
2608
- function Panel(panelOptions = {}) {
2609
- const { defaultSize, minSize = 0, maxSize = 100 } = panelOptions;
2610
- const el = document.createElement("div");
2611
- el.setAttribute("data-panel", "");
2612
- panels.push({ el, minSize, maxSize });
2613
- const sizes = state.sizes.peek();
2614
- if (defaultSize != null) {
2615
- sizes.push(defaultSize);
2616
- } else {
2617
- const equalSize = 100 / panels.length;
2618
- sizes.length = 0;
2619
- for (let i = 0;i < panels.length; i++) {
2620
- sizes.push(equalSize);
2621
- }
2622
- }
2623
- updateSizes(sizes);
2624
- root.appendChild(el);
2625
- return el;
2626
- }
2627
- function Handle() {
2628
- const handleIndex = handles.length;
2629
- const handle = document.createElement("div");
2630
- handle.setAttribute("role", "separator");
2631
- handle.setAttribute("tabindex", "0");
2632
- handle.setAttribute("data-orientation", orientation);
2633
- setDataState(handle, "idle");
2634
- handles.push(handle);
2635
- const STEP = 5;
2636
- handle.addEventListener("keydown", (event) => {
2637
- const sizes = [...state.sizes.peek()];
2638
- const leftIdx = handleIndex;
2639
- const rightIdx = handleIndex + 1;
2640
- const leftPanel = panels[leftIdx];
2641
- const rightPanel = panels[rightIdx];
2642
- if (!leftPanel || !rightPanel)
2643
- return;
2644
- let leftSize = sizes[leftIdx] ?? 0;
2645
- let rightSize = sizes[rightIdx] ?? 0;
2646
- const growKey = orientation === "horizontal" ? Keys.ArrowRight : Keys.ArrowDown;
2647
- const shrinkKey = orientation === "horizontal" ? Keys.ArrowLeft : Keys.ArrowUp;
2648
- if (isKey(event, growKey)) {
2649
- event.preventDefault();
2650
- const delta = Math.min(STEP, rightSize - rightPanel.minSize, leftPanel.maxSize - leftSize);
2651
- leftSize += delta;
2652
- rightSize -= delta;
2653
- } else if (isKey(event, shrinkKey)) {
2654
- event.preventDefault();
2655
- const delta = Math.min(STEP, leftSize - leftPanel.minSize, rightPanel.maxSize - rightSize);
2656
- leftSize -= delta;
2657
- rightSize += delta;
2658
- } else if (isKey(event, Keys.Home)) {
2659
- event.preventDefault();
2660
- const delta = leftSize - leftPanel.minSize;
2661
- leftSize -= delta;
2662
- rightSize += delta;
2663
- } else if (isKey(event, Keys.End)) {
2664
- event.preventDefault();
2665
- const delta = rightSize - rightPanel.minSize;
2666
- leftSize += delta;
2667
- rightSize -= delta;
2668
- } else {
2669
- return;
2670
- }
2671
- sizes[leftIdx] = leftSize;
2672
- sizes[rightIdx] = rightSize;
2673
- updateSizes(sizes);
2674
- });
2675
- handle.addEventListener("pointerdown", (event) => {
2676
- event.preventDefault();
2677
- handle.setPointerCapture(event.pointerId);
2678
- setDataState(handle, "dragging");
2679
- const startPos = orientation === "horizontal" ? event.clientX : event.clientY;
2680
- const rootSize = orientation === "horizontal" ? root.offsetWidth : root.offsetHeight;
2681
- const startSizes = [...state.sizes.peek()];
2682
- function onMove(e) {
2683
- const currentPos = orientation === "horizontal" ? e.clientX : e.clientY;
2684
- const delta = (currentPos - startPos) / rootSize * 100;
2685
- const sizes = [...startSizes];
2686
- const leftIdx = handleIndex;
2687
- const rightIdx = handleIndex + 1;
2688
- const leftPanel = panels[leftIdx];
2689
- const rightPanel = panels[rightIdx];
2690
- if (!leftPanel || !rightPanel)
2691
- return;
2692
- let newLeft = (startSizes[leftIdx] ?? 0) + delta;
2693
- let newRight = (startSizes[rightIdx] ?? 0) - delta;
2694
- newLeft = Math.max(leftPanel.minSize, Math.min(leftPanel.maxSize, newLeft));
2695
- newRight = Math.max(rightPanel.minSize, Math.min(rightPanel.maxSize, newRight));
2696
- sizes[leftIdx] = newLeft;
2697
- sizes[rightIdx] = newRight;
2698
- updateSizes(sizes);
2699
- }
2700
- function onUp(e) {
2701
- handle.releasePointerCapture(e.pointerId);
2702
- setDataState(handle, "idle");
2703
- handle.removeEventListener("pointermove", onMove);
2704
- handle.removeEventListener("pointerup", onUp);
2705
- }
2706
- handle.addEventListener("pointermove", onMove);
2707
- handle.addEventListener("pointerup", onUp);
2708
- });
2709
- root.appendChild(handle);
2710
- return handle;
2711
- }
2712
- return { root, state, Panel, Handle };
2713
- }
2714
- };
2715
- // src/scroll-area/scroll-area.ts
2716
- import { signal as signal21 } from "@vertz/ui";
2717
- var ScrollArea = {
2718
- Root(options = {}) {
2719
- const { orientation = "vertical" } = options;
2720
- const state = {
2721
- scrollTop: signal21(0),
2722
- scrollLeft: signal21(0)
2723
- };
2724
- const root = document.createElement("div");
2725
- root.style.position = "relative";
2726
- root.style.overflow = "hidden";
2727
- const viewport = document.createElement("div");
2728
- viewport.style.overflow = "scroll";
2729
- viewport.style.scrollbarWidth = "none";
2730
- const content = document.createElement("div");
2731
- const scrollbarY = document.createElement("div");
2732
- scrollbarY.setAttribute("aria-hidden", "true");
2733
- scrollbarY.setAttribute("data-orientation", "vertical");
2734
- const thumbY = document.createElement("div");
2735
- scrollbarY.appendChild(thumbY);
2736
- const scrollbarX = document.createElement("div");
2737
- scrollbarX.setAttribute("aria-hidden", "true");
2738
- scrollbarX.setAttribute("data-orientation", "horizontal");
2739
- const thumbX = document.createElement("div");
2740
- scrollbarX.appendChild(thumbX);
2741
- function syncThumbY() {
2742
- const { scrollTop, scrollHeight, clientHeight } = viewport;
2743
- if (scrollHeight <= clientHeight) {
2744
- thumbY.style.height = "0";
2745
- return;
2746
- }
2747
- const ratio = clientHeight / scrollHeight;
2748
- thumbY.style.height = `${ratio * 100}%`;
2749
- const scrollRatio = scrollTop / (scrollHeight - clientHeight);
2750
- thumbY.style.transform = `translateY(${scrollRatio * (1 / ratio - 1) * 100}%)`;
2751
- state.scrollTop.value = scrollTop;
2752
- }
2753
- function syncThumbX() {
2754
- const { scrollLeft, scrollWidth, clientWidth } = viewport;
2755
- if (scrollWidth <= clientWidth) {
2756
- thumbX.style.width = "0";
2757
- return;
2758
- }
2759
- const ratio = clientWidth / scrollWidth;
2760
- thumbX.style.width = `${ratio * 100}%`;
2761
- const scrollRatio = scrollLeft / (scrollWidth - clientWidth);
2762
- thumbX.style.transform = `translateX(${scrollRatio * (1 / ratio - 1) * 100}%)`;
2763
- state.scrollLeft.value = scrollLeft;
2764
- }
2765
- viewport.addEventListener("scroll", () => {
2766
- if (orientation === "vertical" || orientation === "both")
2767
- syncThumbY();
2768
- if (orientation === "horizontal" || orientation === "both")
2769
- syncThumbX();
2770
- });
2771
- let isDraggingY = false;
2772
- let startY = 0;
2773
- let startScrollTop = 0;
2774
- thumbY.addEventListener("pointerdown", (e) => {
2775
- isDraggingY = true;
2776
- startY = e.clientY;
2777
- startScrollTop = viewport.scrollTop;
2778
- thumbY.setPointerCapture(e.pointerId);
2779
- e.preventDefault();
2780
- });
2781
- thumbY.addEventListener("pointermove", (e) => {
2782
- if (!isDraggingY)
2783
- return;
2784
- const delta = e.clientY - startY;
2785
- const scrollbarHeight = scrollbarY.clientHeight;
2786
- const scrollRange = viewport.scrollHeight - viewport.clientHeight;
2787
- if (scrollbarHeight > 0) {
2788
- viewport.scrollTop = startScrollTop + delta / scrollbarHeight * scrollRange;
2789
- }
2790
- });
2791
- thumbY.addEventListener("pointerup", (e) => {
2792
- isDraggingY = false;
2793
- thumbY.releasePointerCapture(e.pointerId);
2794
- });
2795
- let isDraggingX = false;
2796
- let startX = 0;
2797
- let startScrollLeft = 0;
2798
- thumbX.addEventListener("pointerdown", (e) => {
2799
- isDraggingX = true;
2800
- startX = e.clientX;
2801
- startScrollLeft = viewport.scrollLeft;
2802
- thumbX.setPointerCapture(e.pointerId);
2803
- e.preventDefault();
2804
- });
2805
- thumbX.addEventListener("pointermove", (e) => {
2806
- if (!isDraggingX)
2807
- return;
2808
- const delta = e.clientX - startX;
2809
- const scrollbarWidth = scrollbarX.clientWidth;
2810
- const scrollRange = viewport.scrollWidth - viewport.clientWidth;
2811
- if (scrollbarWidth > 0) {
2812
- viewport.scrollLeft = startScrollLeft + delta / scrollbarWidth * scrollRange;
2813
- }
2814
- });
2815
- thumbX.addEventListener("pointerup", (e) => {
2816
- isDraggingX = false;
2817
- thumbX.releasePointerCapture(e.pointerId);
2818
- });
2819
- function update() {
2820
- syncThumbY();
2821
- syncThumbX();
2822
- }
2823
- viewport.appendChild(content);
2824
- root.appendChild(viewport);
2825
- if (orientation === "vertical" || orientation === "both")
2826
- root.appendChild(scrollbarY);
2827
- if (orientation === "horizontal" || orientation === "both")
2828
- root.appendChild(scrollbarX);
2829
- return { root, viewport, content, scrollbarY, thumbY, scrollbarX, thumbX, state, update };
2830
- }
2831
- };
2832
- // src/select/select.ts
2833
- import { signal as signal22 } from "@vertz/ui";
2834
- var Select = {
2835
- Root(options = {}) {
2836
- const { defaultValue = "", placeholder = "", onValueChange, positioning } = options;
2837
- const ids = linkedIds("select");
2838
- const state = {
2839
- open: signal22(false),
2840
- value: signal22(defaultValue),
2841
- activeIndex: signal22(-1)
2842
- };
2843
- const items = [];
2844
- let floatingCleanup = null;
2845
- let dismissCleanup = null;
2846
- const trigger = document.createElement("button");
2847
- trigger.setAttribute("type", "button");
2848
- trigger.setAttribute("role", "combobox");
2849
- trigger.id = ids.triggerId;
2850
- trigger.setAttribute("aria-controls", ids.contentId);
2851
- trigger.setAttribute("aria-haspopup", "listbox");
2852
- setExpanded(trigger, false);
2853
- setDataState(trigger, "closed");
2854
- const triggerText = document.createElement("span");
2855
- triggerText.setAttribute("data-part", "value");
2856
- triggerText.textContent = defaultValue || placeholder;
2857
- trigger.appendChild(triggerText);
2858
- const content = document.createElement("div");
2859
- content.setAttribute("role", "listbox");
2860
- content.setAttribute("tabindex", "-1");
2861
- content.id = ids.contentId;
2862
- setHidden(content, true);
2863
- setDataState(content, "closed");
2864
- function open() {
2865
- state.open.value = true;
2866
- setExpanded(trigger, true);
2867
- setHidden(content, false);
2868
- setDataState(trigger, "open");
2869
- setDataState(content, "open");
2870
- if (positioning) {
2871
- const result = createFloatingPosition(trigger, content, positioning);
2872
- floatingCleanup = result.cleanup;
2873
- dismissCleanup = createDismiss({
2874
- onDismiss: close,
2875
- insideElements: [trigger, content],
2876
- escapeKey: false
2877
- });
2878
- } else {
2879
- const rect = trigger.getBoundingClientRect();
2880
- const side = window.innerHeight - rect.bottom >= rect.top ? "bottom" : "top";
2881
- content.setAttribute("data-side", side);
2882
- }
2883
- const selectedIdx = items.findIndex((item) => item.getAttribute("data-value") === state.value.peek());
2884
- if (selectedIdx >= 0) {
2885
- state.activeIndex.value = selectedIdx;
2886
- updateActiveItem(selectedIdx);
2887
- items[selectedIdx]?.focus();
2888
- } else {
2889
- state.activeIndex.value = -1;
2890
- updateActiveItem(-1);
2891
- content.focus();
2892
- }
2893
- }
2894
- function close() {
2895
- state.open.value = false;
2896
- setExpanded(trigger, false);
2897
- setDataState(trigger, "closed");
2898
- setDataState(content, "closed");
2899
- setHiddenAnimated(content, true);
2900
- floatingCleanup?.();
2901
- floatingCleanup = null;
2902
- dismissCleanup?.();
2903
- dismissCleanup = null;
2904
- trigger.focus();
2905
- }
2906
- function selectItem(value) {
2907
- state.value.value = value;
2908
- for (const item of items) {
2909
- const isActive = item.getAttribute("data-value") === value;
2910
- setSelected(item, isActive);
2911
- setDataState(item, isActive ? "active" : "inactive");
2912
- if (isActive) {
2913
- triggerText.textContent = item.textContent ?? value;
2914
- }
2915
- }
2916
- onValueChange?.(value);
2917
- close();
2918
- }
2919
- function updateActiveItem(index) {
2920
- for (let i = 0;i < items.length; i++) {
2921
- items[i]?.setAttribute("tabindex", i === index ? "0" : "-1");
2922
- }
2923
- }
2924
- trigger.addEventListener("click", () => {
2925
- if (state.open.peek()) {
2926
- close();
2927
- } else {
2928
- open();
2929
- }
2930
- });
2931
- trigger.addEventListener("keydown", (event) => {
2932
- if (isKey(event, Keys.ArrowDown, Keys.ArrowUp, Keys.Enter, Keys.Space)) {
2933
- event.preventDefault();
2934
- if (!state.open.peek()) {
2935
- open();
2936
- }
2937
- }
2938
- });
2939
- content.addEventListener("keydown", (event) => {
2940
- if (isKey(event, Keys.Escape)) {
2941
- event.preventDefault();
2942
- close();
2943
- return;
2944
- }
2945
- if (isKey(event, Keys.Enter, Keys.Space)) {
2946
- event.preventDefault();
2947
- const active = items[state.activeIndex.peek()];
2948
- if (active) {
2949
- const val = active.getAttribute("data-value");
2950
- if (val !== null)
2951
- selectItem(val);
2952
- }
2953
- return;
2954
- }
2955
- if (state.activeIndex.peek() === -1) {
2956
- if (isKey(event, Keys.ArrowDown)) {
2957
- event.preventDefault();
2958
- state.activeIndex.value = 0;
2959
- updateActiveItem(0);
2960
- items[0]?.focus();
2961
- return;
2962
- }
2963
- if (isKey(event, Keys.ArrowUp)) {
2964
- event.preventDefault();
2965
- const last = items.length - 1;
2966
- state.activeIndex.value = last;
2967
- updateActiveItem(last);
2968
- items[last]?.focus();
2969
- return;
2970
- }
2971
- }
2972
- const result = handleListNavigation(event, items, { orientation: "vertical" });
2973
- if (result) {
2974
- const idx = items.indexOf(result);
2975
- if (idx >= 0) {
2976
- state.activeIndex.value = idx;
2977
- updateActiveItem(idx);
2978
- }
2979
- return;
2980
- }
2981
- if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) {
2982
- const char = event.key.toLowerCase();
2983
- const match = items.find((item) => item.textContent?.toLowerCase().startsWith(char));
2984
- if (match) {
2985
- const idx = items.indexOf(match);
2986
- state.activeIndex.value = idx;
2987
- updateActiveItem(idx);
2988
- match.focus();
2989
- }
2990
- }
2991
- });
2992
- function createItem(value, label, parent) {
2993
- const item = document.createElement("div");
2994
- item.setAttribute("role", "option");
2995
- item.setAttribute("data-value", value);
2996
- item.setAttribute("tabindex", "-1");
2997
- item.textContent = label ?? value;
2998
- const isSelected = value === defaultValue;
2999
- setSelected(item, isSelected);
3000
- setDataState(item, isSelected ? "active" : "inactive");
3001
- if (isSelected) {
3002
- triggerText.textContent = item.textContent ?? value;
3003
- }
3004
- item.addEventListener("click", () => {
3005
- selectItem(value);
3006
- });
3007
- items.push(item);
3008
- (parent ?? content).appendChild(item);
3009
- return item;
3010
- }
3011
- function Item(value, label) {
3012
- return createItem(value, label);
3013
- }
3014
- function Group(label) {
3015
- const el = document.createElement("div");
3016
- el.setAttribute("role", "group");
3017
- el.setAttribute("aria-label", label);
3018
- content.appendChild(el);
3019
- return {
3020
- el,
3021
- Item: (value, itemLabel) => createItem(value, itemLabel, el)
3022
- };
3023
- }
3024
- function Separator() {
3025
- const hr = document.createElement("hr");
3026
- hr.setAttribute("role", "separator");
3027
- content.appendChild(hr);
3028
- return hr;
3029
- }
3030
- return { trigger, content, state, Item, Group, Separator };
3031
- }
3032
- };
3033
- // src/sheet/sheet.tsx
3034
- import { __element as __element3, __on as __on2 } from "@vertz/ui/internals";
3035
- import { signal as signal23 } from "@vertz/ui";
3036
- function SheetRoot(options = {}) {
3037
- const { side = "right", defaultOpen = false, onOpenChange } = options;
3038
- const ids = linkedIds("sheet");
3039
- const state = { open: signal23(defaultOpen) };
3040
- let restoreFocus = null;
3041
- let removeTrap = null;
3042
- function show() {
3043
- state.open.value = true;
3044
- setExpanded(trigger, true);
3045
- setHidden(overlay, false);
3046
- setHidden(content, false);
3047
- setDataState(trigger, "open");
3048
- setDataState(overlay, "open");
3049
- setDataState(content, "open");
3050
- restoreFocus = saveFocus();
3051
- removeTrap = trapFocus(content);
3052
- queueMicrotask(() => focusFirst(content));
3053
- onOpenChange?.(true);
3054
- }
3055
- function hide() {
3056
- state.open.value = false;
3057
- setExpanded(trigger, false);
3058
- setDataState(trigger, "closed");
3059
- setDataState(overlay, "closed");
3060
- setDataState(content, "closed");
3061
- setHiddenAnimated(overlay, true);
3062
- setHiddenAnimated(content, true);
3063
- removeTrap?.();
3064
- removeTrap = null;
3065
- restoreFocus?.();
3066
- restoreFocus = null;
3067
- onOpenChange?.(false);
3068
- }
3069
- const SWIPE_THRESHOLD = 50;
3070
- let startX = 0;
3071
- let startY = 0;
3072
- function handlePointerDown(e) {
3073
- startX = e.clientX;
3074
- startY = e.clientY;
3075
- }
3076
- function handlePointerUp(e) {
3077
- if (!state.open.peek())
3078
- return;
3079
- const deltaX = e.clientX - startX;
3080
- const deltaY = e.clientY - startY;
3081
- const shouldDismiss = side === "right" && deltaX >= SWIPE_THRESHOLD || side === "left" && deltaX <= -SWIPE_THRESHOLD || side === "bottom" && deltaY >= SWIPE_THRESHOLD || side === "top" && deltaY <= -SWIPE_THRESHOLD;
3082
- if (shouldDismiss) {
3083
- hide();
3084
- }
3085
- }
3086
- const trigger = (() => {
3087
- const __el0 = __element3("button");
3088
- __el0.setAttribute("type", "button");
3089
- {
3090
- const __v = ids.triggerId;
3091
- if (__v != null && __v !== false)
3092
- __el0.setAttribute("id", __v === true ? "" : __v);
3093
- }
3094
- {
3095
- const __v = ids.contentId;
3096
- if (__v != null && __v !== false)
3097
- __el0.setAttribute("aria-controls", __v === true ? "" : __v);
3098
- }
3099
- {
3100
- const __v = defaultOpen ? "true" : "false";
3101
- if (__v != null && __v !== false)
3102
- __el0.setAttribute("aria-expanded", __v === true ? "" : __v);
3103
- }
3104
- {
3105
- const __v = defaultOpen ? "open" : "closed";
3106
- if (__v != null && __v !== false)
3107
- __el0.setAttribute("data-state", __v === true ? "" : __v);
3108
- }
3109
- __on2(__el0, "click", () => {
3110
- state.open.peek() ? hide() : show();
3111
- });
3112
- return __el0;
3113
- })();
3114
- const overlay = (() => {
3115
- const __el1 = __element3("div");
3116
- __el1.setAttribute("data-sheet-overlay", "");
3117
- {
3118
- const __v = defaultOpen ? "false" : "true";
3119
- if (__v != null && __v !== false)
3120
- __el1.setAttribute("aria-hidden", __v === true ? "" : __v);
3121
- }
3122
- {
3123
- const __v = defaultOpen ? "open" : "closed";
3124
- if (__v != null && __v !== false)
3125
- __el1.setAttribute("data-state", __v === true ? "" : __v);
3126
- }
3127
- {
3128
- const __v = defaultOpen ? "" : "display: none";
3129
- if (__v != null && __v !== false)
3130
- __el1.setAttribute("style", __v === true ? "" : __v);
3131
- }
3132
- __on2(__el1, "click", () => hide());
3133
- return __el1;
3134
- })();
3135
- const content = (() => {
3136
- const __el2 = __element3("div");
3137
- __el2.setAttribute("role", "dialog");
3138
- __el2.setAttribute("aria-modal", "true");
3139
- {
3140
- const __v = ids.contentId;
3141
- if (__v != null && __v !== false)
3142
- __el2.setAttribute("id", __v === true ? "" : __v);
3143
- }
3144
- {
3145
- const __v = side;
3146
- if (__v != null && __v !== false)
3147
- __el2.setAttribute("data-side", __v === true ? "" : __v);
3148
- }
3149
- {
3150
- const __v = defaultOpen ? "false" : "true";
3151
- if (__v != null && __v !== false)
3152
- __el2.setAttribute("aria-hidden", __v === true ? "" : __v);
3153
- }
3154
- {
3155
- const __v = defaultOpen ? "open" : "closed";
3156
- if (__v != null && __v !== false)
3157
- __el2.setAttribute("data-state", __v === true ? "" : __v);
3158
- }
3159
- {
3160
- const __v = defaultOpen ? "" : "display: none";
3161
- if (__v != null && __v !== false)
3162
- __el2.setAttribute("style", __v === true ? "" : __v);
3163
- }
3164
- __on2(__el2, "keydown", (event) => {
3165
- if (isKey(event, Keys.Escape)) {
3166
- event.preventDefault();
3167
- event.stopPropagation();
3168
- hide();
3169
- }
3170
- });
3171
- __on2(__el2, "pointerdown", handlePointerDown);
3172
- __on2(__el2, "pointerup", handlePointerUp);
3173
- return __el2;
3174
- })();
3175
- const close = (() => {
3176
- const __el3 = __element3("button");
3177
- __el3.setAttribute("type", "button");
3178
- __el3.setAttribute("aria-label", "Close");
3179
- __on2(__el3, "click", () => hide());
3180
- return __el3;
3181
- })();
3182
- return { trigger, overlay, content, close, state, show, hide };
3183
- }
3184
- var Sheet = {
3185
- Root: SheetRoot
3186
- };
3187
- // src/slider/slider.ts
3188
- import { signal as signal24 } from "@vertz/ui";
3189
- var Slider = {
3190
- Root(options = {}) {
3191
- const {
3192
- defaultValue = 0,
3193
- min = 0,
3194
- max = 100,
3195
- step = 1,
3196
- disabled = false,
3197
- onValueChange
3198
- } = options;
3199
- const state = {
3200
- value: signal24(defaultValue),
3201
- disabled: signal24(disabled)
3202
- };
3203
- const root = document.createElement("div");
3204
- root.id = uniqueId("slider");
3205
- setDataState(root, disabled ? "disabled" : "active");
3206
- const track = document.createElement("div");
3207
- track.setAttribute("data-part", "track");
3208
- const thumb = document.createElement("div");
3209
- thumb.setAttribute("role", "slider");
3210
- thumb.setAttribute("tabindex", disabled ? "-1" : "0");
3211
- thumb.setAttribute("data-part", "thumb");
3212
- setValueRange(thumb, defaultValue, min, max);
3213
- if (disabled) {
3214
- thumb.setAttribute("aria-disabled", "true");
3215
- }
3216
- function clamp(val) {
3217
- return Math.min(max, Math.max(min, val));
3218
- }
3219
- const fill = document.createElement("div");
3220
- fill.setAttribute("data-part", "fill");
3221
- fill.style.cssText = "position: absolute; height: 100%; border-radius: inherit;";
3222
- function updatePosition(pct2) {
3223
- thumb.style.left = `${pct2}%`;
3224
- fill.style.width = `${pct2}%`;
3225
- }
3226
- function setValue(val) {
3227
- if (state.disabled.peek())
3228
- return;
3229
- const clamped = clamp(val);
3230
- state.value.value = clamped;
3231
- setValueRange(thumb, clamped, min, max);
3232
- const pct2 = (clamped - min) / (max - min) * 100;
3233
- updatePosition(pct2);
3234
- setDataState(root, "active");
3235
- onValueChange?.(clamped);
3236
- }
3237
- function valueFromPointer(event) {
3238
- const rect = track.getBoundingClientRect();
3239
- const pct2 = Math.max(0, Math.min(1, (event.clientX - rect.left) / rect.width));
3240
- const raw = min + pct2 * (max - min);
3241
- return Math.round(raw / step) * step;
3242
- }
3243
- thumb.addEventListener("keydown", (event) => {
3244
- if (state.disabled.peek())
3245
- return;
3246
- const current = state.value.peek();
3247
- if (isKey(event, Keys.ArrowRight, Keys.ArrowUp)) {
3248
- event.preventDefault();
3249
- setValue(current + step);
3250
- } else if (isKey(event, Keys.ArrowLeft, Keys.ArrowDown)) {
3251
- event.preventDefault();
3252
- setValue(current - step);
3253
- } else if (isKey(event, Keys.Home)) {
3254
- event.preventDefault();
3255
- setValue(min);
3256
- } else if (isKey(event, Keys.End)) {
3257
- event.preventDefault();
3258
- setValue(max);
3259
- }
3260
- });
3261
- root.addEventListener("pointerdown", (event) => {
3262
- if (state.disabled.peek())
3263
- return;
3264
- event.preventDefault();
3265
- setValue(valueFromPointer(event));
3266
- thumb.focus();
3267
- function onMove(e) {
3268
- setValue(valueFromPointer(e));
3269
- }
3270
- function onUp() {
3271
- document.removeEventListener("pointermove", onMove);
3272
- document.removeEventListener("pointerup", onUp);
3273
- }
3274
- document.addEventListener("pointermove", onMove);
3275
- document.addEventListener("pointerup", onUp);
3276
- });
3277
- thumb.style.position = "absolute";
3278
- thumb.style.transform = "translate(-50%, -50%)";
3279
- track.style.position = "relative";
3280
- track.appendChild(fill);
3281
- track.appendChild(thumb);
3282
- root.appendChild(track);
3283
- const pct = (defaultValue - min) / (max - min) * 100;
3284
- updatePosition(pct);
3285
- return { root, thumb, track, state };
3286
- }
3287
- };
3288
- // src/switch/switch.tsx
3289
- import { signal as signal25 } from "@vertz/ui";
3290
- import { __attr as __attr4, __element as __element4, __on as __on3 } from "@vertz/ui/internals";
3291
- function SwitchRoot(options = {}) {
3292
- const { defaultChecked = false, disabled = false, onCheckedChange } = options;
3293
- const checked = signal25(defaultChecked, "checked");
3294
- function toggle() {
3295
- if (disabled)
3296
- return;
3297
- checked.value = !checked.value;
3298
- onCheckedChange?.(checked.value);
3299
- }
3300
- return (() => {
3301
- const __el0 = __element4("button");
3302
- __el0.setAttribute("data-v-id", "SwitchRoot");
3303
- __el0.setAttribute("type", "button");
3304
- __el0.setAttribute("role", "switch");
3305
- {
3306
- const __v = uniqueId("switch");
3307
- if (__v != null && __v !== false)
3308
- __el0.setAttribute("id", __v === true ? "" : __v);
3309
- }
3310
- __attr4(__el0, "aria-checked", () => checked.value ? "true" : "false");
3311
- __attr4(__el0, "data-state", () => checked.value ? "checked" : "unchecked");
3312
- {
3313
- const __v = disabled;
3314
- if (__v != null && __v !== false)
3315
- __el0.setAttribute("disabled", __v === true ? "" : __v);
3316
- }
3317
- {
3318
- const __v = disabled ? "true" : undefined;
3319
- if (__v != null && __v !== false)
3320
- __el0.setAttribute("aria-disabled", __v === true ? "" : __v);
3321
- }
3322
- __on3(__el0, "click", toggle);
3323
- __on3(__el0, "keydown", (e) => {
3324
- if (isKey(e, Keys.Space)) {
3325
- e.preventDefault();
3326
- toggle();
3327
- }
3328
- });
3329
- return __el0;
3330
- })();
3331
- }
3332
- var Switch = {
3333
- Root: SwitchRoot
3334
- };
3335
- // src/tabs/tabs.ts
3336
- import { signal as signal26 } from "@vertz/ui";
3337
- var Tabs = {
3338
- Root(options = {}) {
3339
- const { defaultValue = "", orientation = "horizontal", onValueChange } = options;
3340
- const state = { value: signal26(defaultValue) };
3341
- const triggers = [];
3342
- const panels = [];
3343
- const tabValues = [];
3344
- const root = document.createElement("div");
3345
- const list = document.createElement("div");
3346
- list.setAttribute("role", "tablist");
3347
- if (orientation === "vertical") {
3348
- list.setAttribute("aria-orientation", "vertical");
3349
- }
3350
- root.appendChild(list);
3351
- function selectTab(value) {
3352
- state.value.value = value;
3353
- for (let i = 0;i < tabValues.length; i++) {
3354
- const isActive = tabValues[i] === value;
3355
- const trig = triggers[i];
3356
- const panel = panels[i];
3357
- if (!trig || !panel)
3358
- continue;
3359
- setSelected(trig, isActive);
3360
- setDataState(trig, isActive ? "active" : "inactive");
3361
- trig.setAttribute("tabindex", isActive ? "0" : "-1");
3362
- setHidden(panel, !isActive);
3363
- setDataState(panel, isActive ? "active" : "inactive");
3364
- }
3365
- onValueChange?.(value);
3366
- }
3367
- list.addEventListener("keydown", (event) => {
3368
- const result = handleListNavigation(event, triggers, {
3369
- orientation
3370
- });
3371
- if (result) {
3372
- const idx = triggers.indexOf(result);
3373
- if (idx >= 0) {
3374
- const val = tabValues[idx];
3375
- if (val !== undefined)
3376
- selectTab(val);
3377
- }
3378
- }
3379
- });
3380
- function Tab(value, label) {
3381
- const baseId = uniqueId("tab");
3382
- const triggerId = `${baseId}-trigger`;
3383
- const panelId = `${baseId}-panel`;
3384
- const isActive = value === state.value.peek();
3385
- const trig = document.createElement("button");
3386
- trig.setAttribute("type", "button");
3387
- trig.setAttribute("role", "tab");
3388
- trig.id = triggerId;
3389
- trig.setAttribute("aria-controls", panelId);
3390
- trig.setAttribute("data-value", value);
3391
- trig.textContent = label ?? value;
3392
- setSelected(trig, isActive);
3393
- setDataState(trig, isActive ? "active" : "inactive");
3394
- const panel = document.createElement("div");
3395
- panel.setAttribute("role", "tabpanel");
3396
- panel.id = panelId;
3397
- panel.setAttribute("aria-labelledby", triggerId);
3398
- panel.setAttribute("tabindex", "0");
3399
- setHidden(panel, !isActive);
3400
- setDataState(panel, isActive ? "active" : "inactive");
3401
- trig.addEventListener("click", () => {
3402
- selectTab(value);
3403
- trig.focus();
3404
- });
3405
- triggers.push(trig);
3406
- panels.push(panel);
3407
- tabValues.push(value);
3408
- list.appendChild(trig);
3409
- root.appendChild(panel);
3410
- setRovingTabindex(triggers, triggers.findIndex((t) => tabValues[triggers.indexOf(t)] === state.value.peek()));
3411
- return { trigger: trig, panel };
3412
- }
3413
- return { root, list, state, Tab };
3414
- }
3415
- };
3416
- // src/toast/toast.ts
3417
- import { signal as signal27 } from "@vertz/ui";
3418
- var Toast = {
3419
- Root(options = {}) {
3420
- const { duration = 5000, politeness = "polite" } = options;
3421
- const state = { messages: signal27([]) };
3422
- const region = document.createElement("div");
3423
- region.setAttribute("role", "status");
3424
- region.setAttribute("aria-live", politeness);
3425
- region.setAttribute("aria-atomic", "false");
3426
- setDataState(region, "empty");
3427
- function announce(content) {
3428
- const id = uniqueId("toast");
3429
- const el = document.createElement("div");
3430
- el.setAttribute("role", "status");
3431
- el.setAttribute("data-toast-id", id);
3432
- el.textContent = content;
3433
- setDataState(el, "open");
3434
- const msg = { id, content, el };
3435
- const messages = [...state.messages.peek(), msg];
3436
- state.messages.value = messages;
3437
- region.appendChild(el);
3438
- setDataState(region, "active");
3439
- if (duration > 0) {
3440
- setTimeout(() => dismiss(id), duration);
3441
- }
3442
- return msg;
3443
- }
3444
- function dismiss(id) {
3445
- const messages = state.messages.peek().filter((m) => m.id !== id);
3446
- state.messages.value = messages;
3447
- const el = region.querySelector(`[data-toast-id="${id}"]`);
3448
- if (el) {
3449
- setDataState(el, "closed");
3450
- el.remove();
3451
- }
3452
- if (messages.length === 0) {
3453
- setDataState(region, "empty");
3454
- }
3455
- }
3456
- return { region, state, announce, dismiss };
3457
- }
3458
- };
3459
- // src/toggle/toggle.tsx
3460
- import { signal as signal28 } from "@vertz/ui";
3461
- import { __attr as __attr5, __element as __element5, __on as __on4 } from "@vertz/ui/internals";
3462
- function ToggleRoot(options = {}) {
3463
- const { defaultPressed = false, disabled = false, onPressedChange } = options;
3464
- const pressed = signal28(defaultPressed, "pressed");
3465
- function toggle() {
3466
- if (disabled)
3467
- return;
3468
- pressed.value = !pressed.value;
3469
- onPressedChange?.(pressed.value);
3470
- }
3471
- return (() => {
3472
- const __el0 = __element5("button");
3473
- __el0.setAttribute("data-v-id", "ToggleRoot");
3474
- __el0.setAttribute("type", "button");
3475
- {
3476
- const __v = uniqueId("toggle");
3477
- if (__v != null && __v !== false)
3478
- __el0.setAttribute("id", __v === true ? "" : __v);
3479
- }
3480
- __attr5(__el0, "aria-pressed", () => pressed.value ? "true" : "false");
3481
- __attr5(__el0, "data-state", () => pressed.value ? "on" : "off");
3482
- {
3483
- const __v = disabled;
3484
- if (__v != null && __v !== false)
3485
- __el0.setAttribute("disabled", __v === true ? "" : __v);
3486
- }
3487
- {
3488
- const __v = disabled ? "true" : undefined;
3489
- if (__v != null && __v !== false)
3490
- __el0.setAttribute("aria-disabled", __v === true ? "" : __v);
3491
- }
3492
- __on4(__el0, "click", toggle);
3493
- __on4(__el0, "keydown", (e) => {
3494
- if (isKey(e, Keys.Space)) {
3495
- e.preventDefault();
3496
- toggle();
3497
- }
3498
- });
3499
- return __el0;
3500
- })();
3501
- }
3502
- var Toggle = {
3503
- Root: ToggleRoot
3504
- };
3505
- // src/toggle-group/toggle-group.ts
3506
- import { signal as signal29 } from "@vertz/ui";
3507
- var ToggleGroup = {
3508
- Root(options = {}) {
3509
- const {
3510
- type = "single",
3511
- defaultValue = [],
3512
- orientation = "horizontal",
3513
- disabled = false,
3514
- onValueChange
3515
- } = options;
3516
- const state = {
3517
- value: signal29([...defaultValue]),
3518
- disabled: signal29(disabled)
3519
- };
3520
- const items = [];
3521
- const root = document.createElement("div");
3522
- root.setAttribute("role", "group");
3523
- root.setAttribute("data-orientation", orientation);
3524
- function toggleValue(itemValue) {
3525
- if (state.disabled.peek())
3526
- return;
3527
- const current = [...state.value.peek()];
3528
- const idx = current.indexOf(itemValue);
3529
- if (type === "single") {
3530
- if (idx >= 0) {
3531
- current.length = 0;
3532
- } else {
3533
- current.length = 0;
3534
- current.push(itemValue);
3535
- }
3536
- } else {
3537
- if (idx >= 0) {
3538
- current.splice(idx, 1);
3539
- } else {
3540
- current.push(itemValue);
3541
- }
3542
- }
3543
- state.value.value = current;
3544
- onValueChange?.(current);
3545
- for (const item of items) {
3546
- const val = item.getAttribute("data-value") ?? "";
3547
- const isOn = current.includes(val);
3548
- setPressed(item, isOn);
3549
- setDataState(item, isOn ? "on" : "off");
3550
- }
3551
- }
3552
- root.addEventListener("keydown", (event) => {
3553
- if (isKey(event, Keys.ArrowLeft, Keys.ArrowRight, Keys.ArrowUp, Keys.ArrowDown, Keys.Home, Keys.End)) {
3554
- const result = handleListNavigation(event, items, { orientation });
3555
- if (result) {
3556
- const idx = items.indexOf(result);
3557
- if (idx >= 0) {
3558
- setRovingTabindex(items, idx);
3559
- }
3560
- }
3561
- }
3562
- });
3563
- function Item(value) {
3564
- const item = document.createElement("button");
3565
- item.setAttribute("type", "button");
3566
- item.setAttribute("data-value", value);
3567
- const isOn = state.value.peek().includes(value);
3568
- setPressed(item, isOn);
3569
- setDataState(item, isOn ? "on" : "off");
3570
- if (state.disabled.peek()) {
3571
- item.disabled = true;
3572
- item.setAttribute("aria-disabled", "true");
3573
- }
3574
- item.addEventListener("click", () => toggleValue(value));
3575
- items.push(item);
3576
- setRovingTabindex(items, 0);
3577
- root.appendChild(item);
3578
- return item;
3579
- }
3580
- return { root, state, Item };
3581
- }
3582
- };
3583
- // src/tooltip/tooltip.ts
3584
- import { signal as signal30 } from "@vertz/ui";
3585
- var Tooltip = {
3586
- Root(options = {}) {
3587
- const { delay = 300, onOpenChange, positioning } = options;
3588
- const contentId = uniqueId("tooltip");
3589
- const state = { open: signal30(false) };
3590
- let showTimeout = null;
3591
- let floatingCleanup = null;
3592
- const trigger = document.createElement("span");
3593
- setDescribedBy(trigger, contentId);
3594
- const content = document.createElement("div");
3595
- content.setAttribute("role", "tooltip");
3596
- content.id = contentId;
3597
- setHidden(content, true);
3598
- setDataState(content, "closed");
3599
- function show() {
3600
- if (showTimeout !== null)
3601
- return;
3602
- showTimeout = setTimeout(() => {
3603
- state.open.value = true;
3604
- setHidden(content, false);
3605
- setDataState(content, "open");
3606
- if (positioning) {
3607
- const effectivePlacement = positioning.placement ?? "top";
3608
- const result = createFloatingPosition(trigger, content, {
3609
- ...positioning,
3610
- placement: effectivePlacement
3611
- });
3612
- floatingCleanup = result.cleanup;
3613
- }
3614
- onOpenChange?.(true);
3615
- showTimeout = null;
3616
- }, delay);
3617
- }
3618
- function hide() {
3619
- if (showTimeout !== null) {
3620
- clearTimeout(showTimeout);
3621
- showTimeout = null;
3622
- }
3623
- state.open.value = false;
3624
- setDataState(content, "closed");
3625
- setHiddenAnimated(content, true);
3626
- floatingCleanup?.();
3627
- floatingCleanup = null;
3628
- onOpenChange?.(false);
3629
- }
3630
- trigger.addEventListener("mouseenter", show);
3631
- trigger.addEventListener("mouseleave", hide);
3632
- trigger.addEventListener("focus", show);
3633
- trigger.addEventListener("blur", hide);
3634
- trigger.addEventListener("keydown", (event) => {
3635
- if (isKey(event, Keys.Escape)) {
3636
- hide();
3637
- }
3638
- });
3639
- return { trigger, content, state };
3640
- }
3641
- };
3642
- export {
3643
- Tooltip,
3644
- ToggleGroup,
3645
- Toggle,
3646
- Toast,
3647
- Tabs,
3648
- Switch,
3649
- Slider,
3650
- Sheet,
3651
- Select,
3652
- ScrollArea,
3653
- ResizablePanel,
3654
- Radio,
3655
- Progress,
3656
- Popover,
3657
- NavigationMenu,
3658
- Menubar,
3659
- Menu,
3660
- HoverCard,
3661
- DropdownMenu,
3662
- Dialog,
3663
- DatePicker,
3664
- ContextMenu,
3665
- Command,
3666
- Combobox,
3667
- Collapsible,
3668
- Checkbox,
3669
- Carousel,
3670
- Calendar,
3671
- Button,
3672
- Badge,
3673
- AlertDialog,
3674
- Accordion
3675
- };