@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
@@ -0,0 +1,52 @@
1
+ import {
2
+ setDataState
3
+ } from "./chunk-vvjyx7fe.js";
4
+ import {
5
+ uniqueId
6
+ } from "./chunk-8y1jf6xr.js";
7
+
8
+ // src/toast/toast.ts
9
+ import { signal } from "@vertz/ui";
10
+ var Toast = {
11
+ Root(options = {}) {
12
+ const { duration = 5000, politeness = "polite" } = options;
13
+ const state = { messages: signal([]) };
14
+ const region = document.createElement("div");
15
+ region.setAttribute("role", "status");
16
+ region.setAttribute("aria-live", politeness);
17
+ region.setAttribute("aria-atomic", "false");
18
+ setDataState(region, "empty");
19
+ function announce(content) {
20
+ const id = uniqueId("toast");
21
+ const el = document.createElement("div");
22
+ el.setAttribute("role", "status");
23
+ el.setAttribute("data-toast-id", id);
24
+ el.textContent = content;
25
+ setDataState(el, "open");
26
+ const msg = { id, content, el };
27
+ const messages = [...state.messages.peek(), msg];
28
+ state.messages.value = messages;
29
+ region.appendChild(el);
30
+ setDataState(region, "active");
31
+ if (duration > 0) {
32
+ setTimeout(() => dismiss(id), duration);
33
+ }
34
+ return msg;
35
+ }
36
+ function dismiss(id) {
37
+ const messages = state.messages.peek().filter((m) => m.id !== id);
38
+ state.messages.value = messages;
39
+ const el = region.querySelector(`[data-toast-id="${id}"]`);
40
+ if (el) {
41
+ setDataState(el, "closed");
42
+ el.remove();
43
+ }
44
+ if (messages.length === 0) {
45
+ setDataState(region, "empty");
46
+ }
47
+ }
48
+ return { region, state, announce, dismiss };
49
+ }
50
+ };
51
+
52
+ export { Toast };
@@ -0,0 +1,97 @@
1
+ import {
2
+ createDismiss
3
+ } from "./chunk-a6wp8c32.js";
4
+ import {
5
+ focusFirst,
6
+ saveFocus
7
+ } from "./chunk-e2v1c9ex.js";
8
+ import {
9
+ createFloatingPosition
10
+ } from "./chunk-0mcr52hc.js";
11
+ import {
12
+ Keys,
13
+ isKey
14
+ } from "./chunk-jctqs9m4.js";
15
+ import {
16
+ setDataState,
17
+ setExpanded,
18
+ setHidden,
19
+ setHiddenAnimated
20
+ } from "./chunk-vvjyx7fe.js";
21
+ import {
22
+ linkedIds
23
+ } from "./chunk-8y1jf6xr.js";
24
+
25
+ // src/popover/popover.ts
26
+ import { signal } from "@vertz/ui";
27
+ var Popover = {
28
+ Root(options = {}) {
29
+ const { defaultOpen = false, onOpenChange, positioning } = options;
30
+ const ids = linkedIds("popover");
31
+ const state = { open: signal(defaultOpen) };
32
+ let restoreFocus = null;
33
+ let floatingCleanup = null;
34
+ let dismissCleanup = null;
35
+ const trigger = document.createElement("button");
36
+ trigger.setAttribute("type", "button");
37
+ trigger.id = ids.triggerId;
38
+ trigger.setAttribute("aria-controls", ids.contentId);
39
+ trigger.setAttribute("aria-haspopup", "dialog");
40
+ setExpanded(trigger, defaultOpen);
41
+ setDataState(trigger, defaultOpen ? "open" : "closed");
42
+ const content = document.createElement("div");
43
+ content.setAttribute("role", "dialog");
44
+ content.id = ids.contentId;
45
+ setHidden(content, !defaultOpen);
46
+ setDataState(content, defaultOpen ? "open" : "closed");
47
+ function open() {
48
+ state.open.value = true;
49
+ setExpanded(trigger, true);
50
+ setHidden(content, false);
51
+ setDataState(trigger, "open");
52
+ setDataState(content, "open");
53
+ restoreFocus = saveFocus();
54
+ queueMicrotask(() => focusFirst(content));
55
+ if (positioning) {
56
+ const result = createFloatingPosition(trigger, content, positioning);
57
+ floatingCleanup = result.cleanup;
58
+ dismissCleanup = createDismiss({
59
+ onDismiss: close,
60
+ insideElements: [trigger, content],
61
+ escapeKey: false
62
+ });
63
+ }
64
+ onOpenChange?.(true);
65
+ }
66
+ function close() {
67
+ state.open.value = false;
68
+ setExpanded(trigger, false);
69
+ setDataState(trigger, "closed");
70
+ setDataState(content, "closed");
71
+ setHiddenAnimated(content, true);
72
+ floatingCleanup?.();
73
+ floatingCleanup = null;
74
+ dismissCleanup?.();
75
+ dismissCleanup = null;
76
+ restoreFocus?.();
77
+ restoreFocus = null;
78
+ onOpenChange?.(false);
79
+ }
80
+ trigger.addEventListener("click", () => {
81
+ if (state.open.peek()) {
82
+ close();
83
+ } else {
84
+ open();
85
+ }
86
+ });
87
+ content.addEventListener("keydown", (event) => {
88
+ if (isKey(event, Keys.Escape)) {
89
+ event.preventDefault();
90
+ close();
91
+ }
92
+ });
93
+ return { trigger, content, state };
94
+ }
95
+ };
96
+
97
+ export { Popover };
@@ -0,0 +1,62 @@
1
+ // src/utils/focus.ts
2
+ var FOCUSABLE_SELECTOR = [
3
+ "a[href]",
4
+ "button:not([disabled])",
5
+ "input:not([disabled])",
6
+ "select:not([disabled])",
7
+ "textarea:not([disabled])",
8
+ '[tabindex]:not([tabindex="-1"])',
9
+ "[contenteditable]"
10
+ ].join(", ");
11
+ function getFocusableElements(container) {
12
+ return Array.from(container.querySelectorAll(FOCUSABLE_SELECTOR));
13
+ }
14
+ function trapFocus(container) {
15
+ function handleKeyDown(event) {
16
+ if (event.key !== "Tab")
17
+ return;
18
+ const focusable = getFocusableElements(container);
19
+ if (focusable.length === 0)
20
+ return;
21
+ const first = focusable[0];
22
+ const last = focusable[focusable.length - 1];
23
+ if (!first || !last)
24
+ return;
25
+ if (event.shiftKey) {
26
+ if (document.activeElement === first) {
27
+ event.preventDefault();
28
+ last.focus();
29
+ }
30
+ } else {
31
+ if (document.activeElement === last) {
32
+ event.preventDefault();
33
+ first.focus();
34
+ }
35
+ }
36
+ }
37
+ container.addEventListener("keydown", handleKeyDown);
38
+ return () => {
39
+ container.removeEventListener("keydown", handleKeyDown);
40
+ };
41
+ }
42
+ function focusFirst(container) {
43
+ const focusable = getFocusableElements(container);
44
+ if (focusable.length > 0) {
45
+ focusable[0]?.focus();
46
+ }
47
+ }
48
+ function saveFocus() {
49
+ const previously = document.activeElement;
50
+ return () => {
51
+ if (previously && typeof previously.focus === "function") {
52
+ previously.focus();
53
+ }
54
+ };
55
+ }
56
+ function setRovingTabindex(items, activeIndex) {
57
+ for (let i = 0;i < items.length; i++) {
58
+ items[i]?.setAttribute("tabindex", i === activeIndex ? "0" : "-1");
59
+ }
60
+ }
61
+
62
+ export { getFocusableElements, trapFocus, focusFirst, saveFocus, setRovingTabindex };
@@ -0,0 +1,115 @@
1
+ import {
2
+ Keys,
3
+ handleListNavigation,
4
+ isKey
5
+ } from "./chunk-jctqs9m4.js";
6
+ import {
7
+ setDataState,
8
+ setExpanded,
9
+ setHidden,
10
+ setHiddenAnimated
11
+ } from "./chunk-vvjyx7fe.js";
12
+ import {
13
+ uniqueId
14
+ } from "./chunk-8y1jf6xr.js";
15
+
16
+ // src/accordion/accordion.ts
17
+ import { signal } from "@vertz/ui";
18
+ var Accordion = {
19
+ Root(options = {}) {
20
+ const { multiple = false, defaultValue = [], onValueChange } = options;
21
+ const state = { value: signal([...defaultValue]) };
22
+ const triggers = [];
23
+ const itemMap = new Map;
24
+ const root = document.createElement("div");
25
+ root.setAttribute("data-orientation", "vertical");
26
+ function updateItemState(val, open) {
27
+ const entry = itemMap.get(val);
28
+ if (!entry)
29
+ return;
30
+ const { trigger: t, content: c } = entry;
31
+ if (open) {
32
+ setHidden(c, false);
33
+ }
34
+ const height = c.scrollHeight;
35
+ c.style.setProperty("--accordion-content-height", `${height}px`);
36
+ setExpanded(t, open);
37
+ setDataState(t, open ? "open" : "closed");
38
+ setDataState(c, open ? "open" : "closed");
39
+ if (!open) {
40
+ setHiddenAnimated(c, true);
41
+ }
42
+ }
43
+ function toggleItem(value) {
44
+ const prev = [...state.value.peek()];
45
+ const current = [...prev];
46
+ const idx = current.indexOf(value);
47
+ if (idx >= 0) {
48
+ current.splice(idx, 1);
49
+ } else {
50
+ if (multiple) {
51
+ current.push(value);
52
+ } else {
53
+ current.length = 0;
54
+ current.push(value);
55
+ }
56
+ }
57
+ state.value.value = current;
58
+ onValueChange?.(current);
59
+ for (const v of prev) {
60
+ if (!current.includes(v)) {
61
+ updateItemState(v, false);
62
+ }
63
+ }
64
+ for (const v of current) {
65
+ if (!prev.includes(v)) {
66
+ updateItemState(v, true);
67
+ }
68
+ }
69
+ }
70
+ root.addEventListener("keydown", (event) => {
71
+ if (isKey(event, Keys.ArrowUp, Keys.ArrowDown, Keys.Home, Keys.End)) {
72
+ handleListNavigation(event, triggers, { orientation: "vertical" });
73
+ }
74
+ });
75
+ function Item(value) {
76
+ const baseId = uniqueId("accordion");
77
+ const triggerId = `${baseId}-trigger`;
78
+ const contentId = `${baseId}-content`;
79
+ const isOpen = state.value.peek().includes(value);
80
+ const item = document.createElement("div");
81
+ item.setAttribute("data-value", value);
82
+ const trigger = document.createElement("button");
83
+ trigger.setAttribute("type", "button");
84
+ trigger.id = triggerId;
85
+ trigger.setAttribute("aria-controls", contentId);
86
+ trigger.setAttribute("data-value", value);
87
+ setExpanded(trigger, isOpen);
88
+ setDataState(trigger, isOpen ? "open" : "closed");
89
+ const content = document.createElement("div");
90
+ content.setAttribute("role", "region");
91
+ content.id = contentId;
92
+ content.setAttribute("aria-labelledby", triggerId);
93
+ setHidden(content, !isOpen);
94
+ setDataState(content, isOpen ? "open" : "closed");
95
+ trigger.addEventListener("click", () => {
96
+ toggleItem(value);
97
+ });
98
+ itemMap.set(value, { trigger, content });
99
+ triggers.push(trigger);
100
+ item.appendChild(trigger);
101
+ item.appendChild(content);
102
+ root.appendChild(item);
103
+ if (isOpen) {
104
+ requestAnimationFrame(() => {
105
+ const height = content.scrollHeight;
106
+ content.style.setProperty("--accordion-content-height", `${height}px`);
107
+ });
108
+ }
109
+ return { item, trigger, content };
110
+ }
111
+ return { root, state, Item };
112
+ }
113
+ };
114
+
115
+ export { Accordion };
@@ -0,0 +1,225 @@
1
+ import {
2
+ createDismiss
3
+ } from "./chunk-a6wp8c32.js";
4
+ import {
5
+ createFloatingPosition
6
+ } from "./chunk-0mcr52hc.js";
7
+ import {
8
+ Keys,
9
+ handleListNavigation,
10
+ isKey
11
+ } from "./chunk-jctqs9m4.js";
12
+ import {
13
+ setDataState,
14
+ setExpanded,
15
+ setHidden,
16
+ setHiddenAnimated,
17
+ setSelected
18
+ } from "./chunk-vvjyx7fe.js";
19
+ import {
20
+ linkedIds
21
+ } from "./chunk-8y1jf6xr.js";
22
+
23
+ // src/select/select.ts
24
+ import { signal } from "@vertz/ui";
25
+ var Select = {
26
+ Root(options = {}) {
27
+ const { defaultValue = "", placeholder = "", onValueChange, positioning } = options;
28
+ const ids = linkedIds("select");
29
+ const state = {
30
+ open: signal(false),
31
+ value: signal(defaultValue),
32
+ activeIndex: signal(-1)
33
+ };
34
+ const items = [];
35
+ let floatingCleanup = null;
36
+ let dismissCleanup = null;
37
+ const trigger = document.createElement("button");
38
+ trigger.setAttribute("type", "button");
39
+ trigger.setAttribute("role", "combobox");
40
+ trigger.id = ids.triggerId;
41
+ trigger.setAttribute("aria-controls", ids.contentId);
42
+ trigger.setAttribute("aria-haspopup", "listbox");
43
+ setExpanded(trigger, false);
44
+ setDataState(trigger, "closed");
45
+ const triggerText = document.createElement("span");
46
+ triggerText.setAttribute("data-part", "value");
47
+ triggerText.textContent = defaultValue || placeholder;
48
+ trigger.appendChild(triggerText);
49
+ const content = document.createElement("div");
50
+ content.setAttribute("role", "listbox");
51
+ content.setAttribute("tabindex", "-1");
52
+ content.id = ids.contentId;
53
+ setHidden(content, true);
54
+ setDataState(content, "closed");
55
+ function open() {
56
+ state.open.value = true;
57
+ setExpanded(trigger, true);
58
+ setHidden(content, false);
59
+ setDataState(trigger, "open");
60
+ setDataState(content, "open");
61
+ if (positioning) {
62
+ const result = createFloatingPosition(trigger, content, positioning);
63
+ floatingCleanup = result.cleanup;
64
+ dismissCleanup = createDismiss({
65
+ onDismiss: close,
66
+ insideElements: [trigger, content],
67
+ escapeKey: false
68
+ });
69
+ } else {
70
+ const rect = trigger.getBoundingClientRect();
71
+ const side = window.innerHeight - rect.bottom >= rect.top ? "bottom" : "top";
72
+ content.setAttribute("data-side", side);
73
+ }
74
+ const selectedIdx = items.findIndex((item) => item.getAttribute("data-value") === state.value.peek());
75
+ if (selectedIdx >= 0) {
76
+ state.activeIndex.value = selectedIdx;
77
+ updateActiveItem(selectedIdx);
78
+ items[selectedIdx]?.focus();
79
+ } else {
80
+ state.activeIndex.value = -1;
81
+ updateActiveItem(-1);
82
+ content.focus();
83
+ }
84
+ }
85
+ function close() {
86
+ state.open.value = false;
87
+ setExpanded(trigger, false);
88
+ setDataState(trigger, "closed");
89
+ setDataState(content, "closed");
90
+ setHiddenAnimated(content, true);
91
+ floatingCleanup?.();
92
+ floatingCleanup = null;
93
+ dismissCleanup?.();
94
+ dismissCleanup = null;
95
+ trigger.focus();
96
+ }
97
+ function selectItem(value) {
98
+ state.value.value = value;
99
+ for (const item of items) {
100
+ const isActive = item.getAttribute("data-value") === value;
101
+ setSelected(item, isActive);
102
+ setDataState(item, isActive ? "active" : "inactive");
103
+ if (isActive) {
104
+ triggerText.textContent = item.textContent ?? value;
105
+ }
106
+ }
107
+ onValueChange?.(value);
108
+ close();
109
+ }
110
+ function updateActiveItem(index) {
111
+ for (let i = 0;i < items.length; i++) {
112
+ items[i]?.setAttribute("tabindex", i === index ? "0" : "-1");
113
+ }
114
+ }
115
+ trigger.addEventListener("click", () => {
116
+ if (state.open.peek()) {
117
+ close();
118
+ } else {
119
+ open();
120
+ }
121
+ });
122
+ trigger.addEventListener("keydown", (event) => {
123
+ if (isKey(event, Keys.ArrowDown, Keys.ArrowUp, Keys.Enter, Keys.Space)) {
124
+ event.preventDefault();
125
+ if (!state.open.peek()) {
126
+ open();
127
+ }
128
+ }
129
+ });
130
+ content.addEventListener("keydown", (event) => {
131
+ if (isKey(event, Keys.Escape)) {
132
+ event.preventDefault();
133
+ close();
134
+ return;
135
+ }
136
+ if (isKey(event, Keys.Enter, Keys.Space)) {
137
+ event.preventDefault();
138
+ const active = items[state.activeIndex.peek()];
139
+ if (active) {
140
+ const val = active.getAttribute("data-value");
141
+ if (val !== null)
142
+ selectItem(val);
143
+ }
144
+ return;
145
+ }
146
+ if (state.activeIndex.peek() === -1) {
147
+ if (isKey(event, Keys.ArrowDown)) {
148
+ event.preventDefault();
149
+ state.activeIndex.value = 0;
150
+ updateActiveItem(0);
151
+ items[0]?.focus();
152
+ return;
153
+ }
154
+ if (isKey(event, Keys.ArrowUp)) {
155
+ event.preventDefault();
156
+ const last = items.length - 1;
157
+ state.activeIndex.value = last;
158
+ updateActiveItem(last);
159
+ items[last]?.focus();
160
+ return;
161
+ }
162
+ }
163
+ const result = handleListNavigation(event, items, { orientation: "vertical" });
164
+ if (result) {
165
+ const idx = items.indexOf(result);
166
+ if (idx >= 0) {
167
+ state.activeIndex.value = idx;
168
+ updateActiveItem(idx);
169
+ }
170
+ return;
171
+ }
172
+ if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) {
173
+ const char = event.key.toLowerCase();
174
+ const match = items.find((item) => item.textContent?.toLowerCase().startsWith(char));
175
+ if (match) {
176
+ const idx = items.indexOf(match);
177
+ state.activeIndex.value = idx;
178
+ updateActiveItem(idx);
179
+ match.focus();
180
+ }
181
+ }
182
+ });
183
+ function createItem(value, label, parent) {
184
+ const item = document.createElement("div");
185
+ item.setAttribute("role", "option");
186
+ item.setAttribute("data-value", value);
187
+ item.setAttribute("tabindex", "-1");
188
+ item.textContent = label ?? value;
189
+ const isSelected = value === defaultValue;
190
+ setSelected(item, isSelected);
191
+ setDataState(item, isSelected ? "active" : "inactive");
192
+ if (isSelected) {
193
+ triggerText.textContent = item.textContent ?? value;
194
+ }
195
+ item.addEventListener("click", () => {
196
+ selectItem(value);
197
+ });
198
+ items.push(item);
199
+ (parent ?? content).appendChild(item);
200
+ return item;
201
+ }
202
+ function Item(value, label) {
203
+ return createItem(value, label);
204
+ }
205
+ function Group(label) {
206
+ const el = document.createElement("div");
207
+ el.setAttribute("role", "group");
208
+ el.setAttribute("aria-label", label);
209
+ content.appendChild(el);
210
+ return {
211
+ el,
212
+ Item: (value, itemLabel) => createItem(value, itemLabel, el)
213
+ };
214
+ }
215
+ function Separator() {
216
+ const hr = document.createElement("hr");
217
+ hr.setAttribute("role", "separator");
218
+ content.appendChild(hr);
219
+ return hr;
220
+ }
221
+ return { trigger, content, state, Item, Group, Separator };
222
+ }
223
+ };
224
+
225
+ export { Select };
@@ -0,0 +1,58 @@
1
+ import {
2
+ Keys,
3
+ isKey
4
+ } from "./chunk-jctqs9m4.js";
5
+ import {
6
+ setChecked,
7
+ setDataState
8
+ } from "./chunk-vvjyx7fe.js";
9
+ import {
10
+ uniqueId
11
+ } from "./chunk-8y1jf6xr.js";
12
+
13
+ // src/checkbox/checkbox.ts
14
+ import { signal } from "@vertz/ui";
15
+ function dataStateFor(checked) {
16
+ if (checked === "mixed")
17
+ return "indeterminate";
18
+ return checked ? "checked" : "unchecked";
19
+ }
20
+ var Checkbox = {
21
+ Root(options = {}) {
22
+ const { defaultChecked = false, disabled = false, onCheckedChange } = options;
23
+ const state = {
24
+ checked: signal(defaultChecked),
25
+ disabled: signal(disabled)
26
+ };
27
+ const root = document.createElement("button");
28
+ root.setAttribute("type", "button");
29
+ root.setAttribute("role", "checkbox");
30
+ root.id = uniqueId("checkbox");
31
+ setChecked(root, defaultChecked);
32
+ setDataState(root, dataStateFor(defaultChecked));
33
+ if (disabled) {
34
+ root.disabled = true;
35
+ root.setAttribute("aria-disabled", "true");
36
+ }
37
+ function toggle() {
38
+ if (state.disabled.peek())
39
+ return;
40
+ const current = state.checked.peek();
41
+ const next = current === "mixed" ? true : !current;
42
+ state.checked.value = next;
43
+ setChecked(root, next);
44
+ setDataState(root, dataStateFor(next));
45
+ onCheckedChange?.(next);
46
+ }
47
+ root.addEventListener("click", toggle);
48
+ root.addEventListener("keydown", (event) => {
49
+ if (isKey(event, Keys.Space)) {
50
+ event.preventDefault();
51
+ toggle();
52
+ }
53
+ });
54
+ return { root, state };
55
+ }
56
+ };
57
+
58
+ export { Checkbox };