@ansh-ui/react 0.2.0

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 (111) hide show
  1. package/LICENSE +21 -0
  2. package/dist/chunk-5CFQFMP5.js +178 -0
  3. package/dist/chunk-5CFQFMP5.js.map +1 -0
  4. package/dist/chunk-6VRF7X5C.cjs +164 -0
  5. package/dist/chunk-6VRF7X5C.cjs.map +1 -0
  6. package/dist/chunk-AVPEA5PB.cjs +718 -0
  7. package/dist/chunk-AVPEA5PB.cjs.map +1 -0
  8. package/dist/chunk-C32LKF23.cjs +198 -0
  9. package/dist/chunk-C32LKF23.cjs.map +1 -0
  10. package/dist/chunk-C5JG6TMM.cjs +1200 -0
  11. package/dist/chunk-C5JG6TMM.cjs.map +1 -0
  12. package/dist/chunk-DATBU46V.cjs +614 -0
  13. package/dist/chunk-DATBU46V.cjs.map +1 -0
  14. package/dist/chunk-EGG4CP7C.js +320 -0
  15. package/dist/chunk-EGG4CP7C.js.map +1 -0
  16. package/dist/chunk-H34OXXJU.js +55 -0
  17. package/dist/chunk-H34OXXJU.js.map +1 -0
  18. package/dist/chunk-HO2YSF5O.js +187 -0
  19. package/dist/chunk-HO2YSF5O.js.map +1 -0
  20. package/dist/chunk-HPGCILO4.js +760 -0
  21. package/dist/chunk-HPGCILO4.js.map +1 -0
  22. package/dist/chunk-IBXLC5IE.js +154 -0
  23. package/dist/chunk-IBXLC5IE.js.map +1 -0
  24. package/dist/chunk-LDCZQP3R.js +1185 -0
  25. package/dist/chunk-LDCZQP3R.js.map +1 -0
  26. package/dist/chunk-LXCIXR5T.js +27 -0
  27. package/dist/chunk-LXCIXR5T.js.map +1 -0
  28. package/dist/chunk-O2PX54KX.js +94 -0
  29. package/dist/chunk-O2PX54KX.js.map +1 -0
  30. package/dist/chunk-OHBWBXLO.cjs +101 -0
  31. package/dist/chunk-OHBWBXLO.cjs.map +1 -0
  32. package/dist/chunk-OJN5JBNP.cjs +776 -0
  33. package/dist/chunk-OJN5JBNP.cjs.map +1 -0
  34. package/dist/chunk-OLTS6G5M.js +606 -0
  35. package/dist/chunk-OLTS6G5M.js.map +1 -0
  36. package/dist/chunk-PO5DU3FU.cjs +29 -0
  37. package/dist/chunk-PO5DU3FU.cjs.map +1 -0
  38. package/dist/chunk-QO3E7TJS.js +2940 -0
  39. package/dist/chunk-QO3E7TJS.js.map +1 -0
  40. package/dist/chunk-RHTLNSVW.cjs +2976 -0
  41. package/dist/chunk-RHTLNSVW.cjs.map +1 -0
  42. package/dist/chunk-SFU5EPSN.cjs +61 -0
  43. package/dist/chunk-SFU5EPSN.cjs.map +1 -0
  44. package/dist/chunk-T4AK2KLM.js +699 -0
  45. package/dist/chunk-T4AK2KLM.js.map +1 -0
  46. package/dist/chunk-WGYNCSTP.cjs +333 -0
  47. package/dist/chunk-WGYNCSTP.cjs.map +1 -0
  48. package/dist/chunk-XEP6P7E6.js +279 -0
  49. package/dist/chunk-XEP6P7E6.js.map +1 -0
  50. package/dist/chunk-XMXECSQO.cjs +286 -0
  51. package/dist/chunk-XMXECSQO.cjs.map +1 -0
  52. package/dist/chunk-ZWAFLHC2.cjs +181 -0
  53. package/dist/chunk-ZWAFLHC2.cjs.map +1 -0
  54. package/dist/data.cjs +71 -0
  55. package/dist/data.cjs.map +1 -0
  56. package/dist/data.d.cts +316 -0
  57. package/dist/data.d.ts +316 -0
  58. package/dist/data.js +6 -0
  59. package/dist/data.js.map +1 -0
  60. package/dist/form.cjs +153 -0
  61. package/dist/form.cjs.map +1 -0
  62. package/dist/form.d.cts +660 -0
  63. package/dist/form.d.ts +660 -0
  64. package/dist/form.js +8 -0
  65. package/dist/form.js.map +1 -0
  66. package/dist/index.cjs +1641 -0
  67. package/dist/index.cjs.map +1 -0
  68. package/dist/index.d.cts +552 -0
  69. package/dist/index.d.ts +552 -0
  70. package/dist/index.js +956 -0
  71. package/dist/index.js.map +1 -0
  72. package/dist/layout.cjs +68 -0
  73. package/dist/layout.cjs.map +1 -0
  74. package/dist/layout.d.cts +169 -0
  75. package/dist/layout.d.ts +169 -0
  76. package/dist/layout.js +7 -0
  77. package/dist/layout.js.map +1 -0
  78. package/dist/motion-CQmCq6_k.d.ts +395 -0
  79. package/dist/motion-CSX4g2N8.d.cts +395 -0
  80. package/dist/motion.cjs +79 -0
  81. package/dist/motion.cjs.map +1 -0
  82. package/dist/motion.d.cts +4 -0
  83. package/dist/motion.d.ts +4 -0
  84. package/dist/motion.js +6 -0
  85. package/dist/motion.js.map +1 -0
  86. package/dist/navigation.cjs +48 -0
  87. package/dist/navigation.cjs.map +1 -0
  88. package/dist/navigation.d.cts +210 -0
  89. package/dist/navigation.d.ts +210 -0
  90. package/dist/navigation.js +7 -0
  91. package/dist/navigation.js.map +1 -0
  92. package/dist/overlay.cjs +69 -0
  93. package/dist/overlay.cjs.map +1 -0
  94. package/dist/overlay.d.cts +330 -0
  95. package/dist/overlay.d.ts +330 -0
  96. package/dist/overlay.js +8 -0
  97. package/dist/overlay.js.map +1 -0
  98. package/dist/position-DVScKcaa.d.cts +66 -0
  99. package/dist/position-DVScKcaa.d.ts +66 -0
  100. package/dist/primitives.cjs +162 -0
  101. package/dist/primitives.cjs.map +1 -0
  102. package/dist/primitives.d.cts +294 -0
  103. package/dist/primitives.d.ts +294 -0
  104. package/dist/primitives.js +9 -0
  105. package/dist/primitives.js.map +1 -0
  106. package/dist/sidebar-D-PafAXw.d.cts +71 -0
  107. package/dist/sidebar-D-PafAXw.d.ts +71 -0
  108. package/dist/styles.css +5575 -0
  109. package/dist/use-observers-B9qtimrk.d.cts +99 -0
  110. package/dist/use-observers-B9qtimrk.d.ts +99 -0
  111. package/package.json +92 -0
@@ -0,0 +1,1200 @@
1
+ 'use strict';
2
+
3
+ var chunkC32LKF23_cjs = require('./chunk-C32LKF23.cjs');
4
+ var chunkXMXECSQO_cjs = require('./chunk-XMXECSQO.cjs');
5
+ var chunkPO5DU3FU_cjs = require('./chunk-PO5DU3FU.cjs');
6
+ var chunkSFU5EPSN_cjs = require('./chunk-SFU5EPSN.cjs');
7
+ var react = require('react');
8
+ var jsxRuntime = require('react/jsx-runtime');
9
+
10
+ function score(query, text) {
11
+ if (query.length === 0) return 0;
12
+ const q = query.toLowerCase();
13
+ const t = text.toLowerCase();
14
+ let queryIndex = 0;
15
+ let total = 0;
16
+ let run = 0;
17
+ for (let i = 0; i < t.length && queryIndex < q.length; i++) {
18
+ if (t[i] === q[queryIndex]) {
19
+ run++;
20
+ total += run * 2 + (i === 0 ? 8 : 0);
21
+ queryIndex++;
22
+ } else {
23
+ run = 0;
24
+ }
25
+ }
26
+ return queryIndex === q.length ? total : -1;
27
+ }
28
+ function CommandPalette({
29
+ items,
30
+ open,
31
+ onOpenChange,
32
+ placeholder = "Type a command or search\u2026",
33
+ emptyMessage = "No results found."
34
+ }) {
35
+ const [query, setQuery] = react.useState("");
36
+ const [active, setActive] = react.useState(0);
37
+ const inputRef = react.useRef(null);
38
+ const dialogRef = react.useRef(null);
39
+ const restoreFocusRef = react.useRef(null);
40
+ const listId = react.useId();
41
+ const results = react.useMemo(() => {
42
+ if (query.trim() === "") return [...items];
43
+ return items.map((item) => ({
44
+ item,
45
+ score: Math.max(score(query, item.label), score(query, item.keywords ?? ""))
46
+ })).filter((entry) => entry.score >= 0).sort((a, b) => b.score - a.score).map((entry) => entry.item);
47
+ }, [items, query]);
48
+ react.useEffect(() => setActive(0), [query, items]);
49
+ const close = react.useCallback(() => {
50
+ onOpenChange(false);
51
+ setQuery("");
52
+ }, [onOpenChange]);
53
+ const select = react.useCallback(
54
+ (item) => {
55
+ if (!item) return;
56
+ item.onSelect?.();
57
+ close();
58
+ },
59
+ [close]
60
+ );
61
+ react.useEffect(() => {
62
+ if (!open) return;
63
+ restoreFocusRef.current = document.activeElement;
64
+ const raf = requestAnimationFrame(() => inputRef.current?.focus());
65
+ const previousOverflow = document.body.style.overflow;
66
+ document.body.style.overflow = "hidden";
67
+ return () => {
68
+ cancelAnimationFrame(raf);
69
+ document.body.style.overflow = previousOverflow;
70
+ restoreFocusRef.current?.focus?.();
71
+ };
72
+ }, [open]);
73
+ const onKeyDown = (event) => {
74
+ switch (event.key) {
75
+ case "ArrowDown":
76
+ event.preventDefault();
77
+ setActive((i) => results.length === 0 ? 0 : (i + 1) % results.length);
78
+ break;
79
+ case "ArrowUp":
80
+ event.preventDefault();
81
+ setActive((i) => results.length === 0 ? 0 : (i - 1 + results.length) % results.length);
82
+ break;
83
+ case "Home":
84
+ event.preventDefault();
85
+ setActive(0);
86
+ break;
87
+ case "End":
88
+ event.preventDefault();
89
+ setActive(Math.max(0, results.length - 1));
90
+ break;
91
+ case "Enter":
92
+ event.preventDefault();
93
+ select(results[active]);
94
+ break;
95
+ case "Escape":
96
+ event.preventDefault();
97
+ close();
98
+ break;
99
+ case "Tab": {
100
+ event.preventDefault();
101
+ break;
102
+ }
103
+ }
104
+ };
105
+ react.useEffect(() => {
106
+ if (!open) return;
107
+ const node = document.getElementById(`${listId}-option-${active}`);
108
+ node?.scrollIntoView?.({ block: "nearest" });
109
+ }, [active, listId, open]);
110
+ if (!open) return null;
111
+ let lastGroup;
112
+ return /* @__PURE__ */ jsxRuntime.jsx(
113
+ "div",
114
+ {
115
+ className: "ansh-cmdk__backdrop",
116
+ onMouseDown: (event) => {
117
+ if (event.target === event.currentTarget) close();
118
+ },
119
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
120
+ "div",
121
+ {
122
+ ref: dialogRef,
123
+ className: "ansh-cmdk",
124
+ role: "dialog",
125
+ "aria-modal": "true",
126
+ "aria-label": "Command palette",
127
+ children: [
128
+ /* @__PURE__ */ jsxRuntime.jsx(
129
+ "input",
130
+ {
131
+ ref: inputRef,
132
+ className: "ansh-cmdk__input",
133
+ value: query,
134
+ onChange: (event) => setQuery(event.target.value),
135
+ onKeyDown,
136
+ placeholder,
137
+ role: "combobox",
138
+ "aria-expanded": "true",
139
+ "aria-controls": listId,
140
+ "aria-autocomplete": "list",
141
+ "aria-activedescendant": results.length > 0 ? `${listId}-option-${active}` : void 0,
142
+ autoComplete: "off",
143
+ spellCheck: false
144
+ }
145
+ ),
146
+ results.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ansh-cmdk__empty", children: emptyMessage }) : /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "ansh-cmdk__list", id: listId, role: "listbox", "aria-label": "Commands", children: results.map((item, index) => {
147
+ const heading = item.group && item.group !== lastGroup ? item.group : null;
148
+ lastGroup = item.group;
149
+ return /* @__PURE__ */ jsxRuntime.jsxs("li", { role: "presentation", children: [
150
+ heading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ansh-cmdk__group", role: "presentation", children: heading }) : null,
151
+ /* @__PURE__ */ jsxRuntime.jsxs(
152
+ "div",
153
+ {
154
+ id: `${listId}-option-${index}`,
155
+ className: "ansh-cmdk__item",
156
+ role: "option",
157
+ "aria-selected": index === active,
158
+ onMouseEnter: () => setActive(index),
159
+ onClick: () => select(item),
160
+ children: [
161
+ item.icon,
162
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: item.label }),
163
+ item.shortcut ? /* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "ansh-cmdk__kbd", children: item.shortcut }) : null
164
+ ]
165
+ }
166
+ )
167
+ ] }, item.id);
168
+ }) })
169
+ ]
170
+ }
171
+ )
172
+ }
173
+ );
174
+ }
175
+ function useCommandShortcut(toggle, key = "k") {
176
+ const toggleRef = react.useRef(toggle);
177
+ toggleRef.current = toggle;
178
+ react.useEffect(() => {
179
+ const onKeyDown = (event) => {
180
+ if (event.key.toLowerCase() === key && (event.metaKey || event.ctrlKey)) {
181
+ event.preventDefault();
182
+ toggleRef.current();
183
+ }
184
+ };
185
+ window.addEventListener("keydown", onKeyDown);
186
+ return () => window.removeEventListener("keydown", onKeyDown);
187
+ }, [key]);
188
+ }
189
+ var PopoverContext = react.createContext(null);
190
+ function usePopover(component) {
191
+ const context = react.useContext(PopoverContext);
192
+ if (!context) {
193
+ throw new Error(`<${component}> must be rendered inside <Popover>.`);
194
+ }
195
+ return context;
196
+ }
197
+ function Popover({
198
+ open,
199
+ defaultOpen = false,
200
+ onOpenChange,
201
+ placement = "bottom",
202
+ offset = 8,
203
+ modal = false,
204
+ children
205
+ }) {
206
+ const [isOpen, setOpen] = chunkPO5DU3FU_cjs.useControllableState({
207
+ value: open,
208
+ defaultValue: defaultOpen,
209
+ onChange: onOpenChange
210
+ });
211
+ const triggerRef = react.useRef(null);
212
+ const contentId = react.useId();
213
+ const context = react.useMemo(
214
+ () => ({ open: isOpen, setOpen, triggerRef, contentId, placement, offset, modal }),
215
+ [isOpen, setOpen, contentId, placement, offset, modal]
216
+ );
217
+ return /* @__PURE__ */ jsxRuntime.jsx(PopoverContext.Provider, { value: context, children });
218
+ }
219
+ function PopoverTrigger({ asChild = false, children, ...rest }) {
220
+ const { open, setOpen, triggerRef, contentId } = usePopover("PopoverTrigger");
221
+ const Component = asChild ? chunkC32LKF23_cjs.Slot : "button";
222
+ return /* @__PURE__ */ jsxRuntime.jsx(
223
+ Component,
224
+ {
225
+ ref: triggerRef,
226
+ ...asChild ? null : { type: "button" },
227
+ "aria-haspopup": "dialog",
228
+ "aria-expanded": open,
229
+ "aria-controls": open ? contentId : void 0,
230
+ ...rest,
231
+ onClick: (event) => {
232
+ rest.onClick?.(event);
233
+ if (event.defaultPrevented) return;
234
+ setOpen(!open);
235
+ },
236
+ children
237
+ }
238
+ );
239
+ }
240
+ function PopoverContent({
241
+ arrow = false,
242
+ matchWidth = false,
243
+ label,
244
+ className,
245
+ style,
246
+ children,
247
+ ...rest
248
+ }) {
249
+ const { open, setOpen, triggerRef, contentId, placement, offset, modal } = usePopover("PopoverContent");
250
+ const contentRef = react.useRef(null);
251
+ const { mounted, state } = chunkC32LKF23_cjs.usePresence(open, contentRef);
252
+ const position = chunkXMXECSQO_cjs.useAnchoredPosition(triggerRef, contentRef, mounted, {
253
+ placement,
254
+ offset,
255
+ matchWidth,
256
+ arrowSize: arrow ? 10 : 0
257
+ });
258
+ chunkXMXECSQO_cjs.useDismiss(contentRef, open, () => setOpen(false), { ignore: [triggerRef] });
259
+ chunkC32LKF23_cjs.useFocusTrap(contentRef, open && modal);
260
+ chunkC32LKF23_cjs.useAutoFocus(contentRef, open);
261
+ chunkC32LKF23_cjs.useFocusRestore(open);
262
+ if (!mounted) return null;
263
+ return /* @__PURE__ */ jsxRuntime.jsx(chunkXMXECSQO_cjs.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
264
+ "div",
265
+ {
266
+ ref: contentRef,
267
+ id: contentId,
268
+ role: "dialog",
269
+ "aria-modal": modal || void 0,
270
+ ...label ? { "aria-label": label } : null,
271
+ tabIndex: -1,
272
+ "data-state": state,
273
+ "data-side": position.side,
274
+ className: chunkSFU5EPSN_cjs.cx("ansh-popover", className),
275
+ style: { ...position.style, ...style },
276
+ ...rest,
277
+ children: [
278
+ children,
279
+ arrow && position.arrowStyle ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-popover__arrow", style: position.arrowStyle, "aria-hidden": "true" }) : null
280
+ ]
281
+ }
282
+ ) });
283
+ }
284
+ function HoverCard({
285
+ content,
286
+ openDelay = 500,
287
+ closeDelay = 200,
288
+ placement = "bottom",
289
+ className,
290
+ children
291
+ }) {
292
+ const [open, setOpen] = react.useState(false);
293
+ const triggerRef = react.useRef(null);
294
+ const cardRef = react.useRef(null);
295
+ const timerRef = react.useRef(void 0);
296
+ const id = react.useId();
297
+ const { mounted, state } = chunkC32LKF23_cjs.usePresence(open, cardRef);
298
+ const position = chunkXMXECSQO_cjs.useAnchoredPosition(triggerRef, cardRef, mounted, { placement, offset: 8 });
299
+ const schedule = (next) => {
300
+ clearTimeout(timerRef.current);
301
+ timerRef.current = setTimeout(() => setOpen(next), next ? openDelay : closeDelay);
302
+ };
303
+ react.useEffect(() => () => clearTimeout(timerRef.current), []);
304
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
305
+ /* @__PURE__ */ jsxRuntime.jsx(
306
+ "span",
307
+ {
308
+ ref: triggerRef,
309
+ className: "ansh-hovercard__trigger",
310
+ "aria-describedby": open ? id : void 0,
311
+ onMouseEnter: () => schedule(true),
312
+ onMouseLeave: () => schedule(false),
313
+ onFocus: () => setOpen(true),
314
+ onBlur: () => setOpen(false),
315
+ children
316
+ }
317
+ ),
318
+ mounted ? /* @__PURE__ */ jsxRuntime.jsx(chunkXMXECSQO_cjs.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
319
+ "div",
320
+ {
321
+ ref: cardRef,
322
+ id,
323
+ role: "tooltip",
324
+ "data-state": state,
325
+ className: chunkSFU5EPSN_cjs.cx("ansh-hovercard", className),
326
+ style: position.style,
327
+ onMouseEnter: () => schedule(true),
328
+ onMouseLeave: () => schedule(false),
329
+ children: content
330
+ }
331
+ ) }) : null
332
+ ] });
333
+ }
334
+ var TooltipGroupContext = react.createContext(null);
335
+ function TooltipProvider({ delay = 600, children }) {
336
+ const [active, setActive] = react.useState(false);
337
+ const value = react.useMemo(() => ({ active, setActive, delay }), [active, delay]);
338
+ return /* @__PURE__ */ jsxRuntime.jsx(TooltipGroupContext.Provider, { value, children });
339
+ }
340
+ function Tooltip({
341
+ content,
342
+ placement = "top",
343
+ delay,
344
+ arrow = true,
345
+ disabled = false,
346
+ className,
347
+ children
348
+ }) {
349
+ const group = react.useContext(TooltipGroupContext);
350
+ const [open, setOpen] = react.useState(false);
351
+ const triggerRef = react.useRef(null);
352
+ const tipRef = react.useRef(null);
353
+ const timerRef = react.useRef(void 0);
354
+ const id = react.useId();
355
+ const { mounted, state } = chunkC32LKF23_cjs.usePresence(open, tipRef);
356
+ const position = chunkXMXECSQO_cjs.useAnchoredPosition(triggerRef, tipRef, mounted, {
357
+ placement,
358
+ offset: 6,
359
+ arrowSize: arrow ? 8 : 0
360
+ });
361
+ const effectiveDelay = delay ?? group?.delay ?? 600;
362
+ const show = (immediate = false) => {
363
+ if (disabled) return;
364
+ clearTimeout(timerRef.current);
365
+ if (immediate || group?.active) {
366
+ setOpen(true);
367
+ group?.setActive(true);
368
+ return;
369
+ }
370
+ timerRef.current = setTimeout(() => {
371
+ setOpen(true);
372
+ group?.setActive(true);
373
+ }, effectiveDelay);
374
+ };
375
+ const hide = () => {
376
+ clearTimeout(timerRef.current);
377
+ setOpen(false);
378
+ timerRef.current = setTimeout(() => group?.setActive(false), 200);
379
+ };
380
+ react.useEffect(() => () => clearTimeout(timerRef.current), []);
381
+ react.useEffect(() => {
382
+ if (!open) return;
383
+ const onKeyDown = (event) => {
384
+ if (event.key === "Escape") {
385
+ setOpen(false);
386
+ group?.setActive(false);
387
+ }
388
+ };
389
+ document.addEventListener("keydown", onKeyDown);
390
+ return () => document.removeEventListener("keydown", onKeyDown);
391
+ }, [open, group]);
392
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
393
+ /* @__PURE__ */ jsxRuntime.jsx(
394
+ chunkC32LKF23_cjs.Slot,
395
+ {
396
+ ref: triggerRef,
397
+ "aria-describedby": open ? id : void 0,
398
+ onMouseEnter: () => show(),
399
+ onMouseLeave: hide,
400
+ onFocus: () => show(true),
401
+ onBlur: hide,
402
+ children
403
+ }
404
+ ),
405
+ mounted && !disabled ? /* @__PURE__ */ jsxRuntime.jsx(chunkXMXECSQO_cjs.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
406
+ "div",
407
+ {
408
+ ref: tipRef,
409
+ id,
410
+ role: "tooltip",
411
+ "data-state": state,
412
+ "data-side": position.side,
413
+ className: chunkSFU5EPSN_cjs.cx("ansh-tooltip", className),
414
+ style: position.style,
415
+ children: [
416
+ content,
417
+ arrow && position.arrowStyle ? /* @__PURE__ */ jsxRuntime.jsx(
418
+ "span",
419
+ {
420
+ className: "ansh-tooltip__arrow",
421
+ style: position.arrowStyle,
422
+ "aria-hidden": "true"
423
+ }
424
+ ) : null
425
+ ]
426
+ }
427
+ ) }) : null
428
+ ] });
429
+ }
430
+ function Dialog({
431
+ open,
432
+ onOpenChange,
433
+ title,
434
+ description,
435
+ size = "md",
436
+ footer,
437
+ showClose = true,
438
+ dismissable = true,
439
+ initialFocus,
440
+ className,
441
+ children
442
+ }) {
443
+ const panelRef = react.useRef(null);
444
+ const id = react.useId();
445
+ const titleId = `${id}-title`;
446
+ const descriptionId = `${id}-description`;
447
+ const { mounted, state } = chunkC32LKF23_cjs.usePresence(open, panelRef);
448
+ const close = react.useCallback(() => {
449
+ if (dismissable) onOpenChange(false);
450
+ }, [dismissable, onOpenChange]);
451
+ chunkXMXECSQO_cjs.useDismiss(panelRef, open, close, { outsidePress: dismissable, escapeKey: dismissable });
452
+ chunkC32LKF23_cjs.useFocusTrap(panelRef, open);
453
+ chunkC32LKF23_cjs.useAutoFocus(panelRef, open, initialFocus);
454
+ chunkC32LKF23_cjs.useFocusRestore(open);
455
+ chunkXMXECSQO_cjs.useScrollLock(open);
456
+ if (!mounted) return null;
457
+ return /* @__PURE__ */ jsxRuntime.jsx(chunkXMXECSQO_cjs.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ansh-dialog__layer", "data-state": state, children: [
458
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ansh-dialog__scrim", "data-state": state, "aria-hidden": "true" }),
459
+ /* @__PURE__ */ jsxRuntime.jsxs(
460
+ "div",
461
+ {
462
+ ref: panelRef,
463
+ role: "dialog",
464
+ "aria-modal": "true",
465
+ "aria-labelledby": titleId,
466
+ ...description ? { "aria-describedby": descriptionId } : null,
467
+ tabIndex: -1,
468
+ "data-state": state,
469
+ className: chunkSFU5EPSN_cjs.cx("ansh-dialog", `ansh-dialog--${size}`, className),
470
+ children: [
471
+ /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "ansh-dialog__header", children: [
472
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ansh-dialog__heading", children: [
473
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "ansh-dialog__title", id: titleId, children: title }),
474
+ description ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "ansh-dialog__description", id: descriptionId, children: description }) : null
475
+ ] }),
476
+ showClose ? /* @__PURE__ */ jsxRuntime.jsx(
477
+ "button",
478
+ {
479
+ type: "button",
480
+ className: "ansh-dialog__close ansh-focusable",
481
+ "aria-label": "Close dialog",
482
+ onClick: () => onOpenChange(false),
483
+ children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 16 16", width: "14", height: "14", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(
484
+ "path",
485
+ {
486
+ d: "M4 4l8 8M12 4l-8 8",
487
+ stroke: "currentColor",
488
+ strokeWidth: "1.75",
489
+ strokeLinecap: "round",
490
+ fill: "none"
491
+ }
492
+ ) })
493
+ }
494
+ ) : null
495
+ ] }),
496
+ children ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ansh-dialog__body", children }) : null,
497
+ footer ? /* @__PURE__ */ jsxRuntime.jsx("footer", { className: "ansh-dialog__footer", children: footer }) : null
498
+ ]
499
+ }
500
+ )
501
+ ] }) });
502
+ }
503
+ function AlertDialog({
504
+ open,
505
+ onOpenChange,
506
+ title,
507
+ description,
508
+ confirmLabel = "Confirm",
509
+ cancelLabel = "Cancel",
510
+ destructive = false,
511
+ onConfirm,
512
+ onCancel,
513
+ busy = false,
514
+ className
515
+ }) {
516
+ const panelRef = react.useRef(null);
517
+ const cancelRef = react.useRef(null);
518
+ const id = react.useId();
519
+ const { mounted, state } = chunkC32LKF23_cjs.usePresence(open, panelRef);
520
+ const cancel = react.useCallback(() => {
521
+ onCancel?.();
522
+ onOpenChange(false);
523
+ }, [onCancel, onOpenChange]);
524
+ chunkXMXECSQO_cjs.useDismiss(panelRef, open, cancel, { outsidePress: false, escapeKey: true });
525
+ chunkC32LKF23_cjs.useFocusTrap(panelRef, open);
526
+ chunkC32LKF23_cjs.useAutoFocus(panelRef, open, cancelRef);
527
+ chunkC32LKF23_cjs.useFocusRestore(open);
528
+ chunkXMXECSQO_cjs.useScrollLock(open);
529
+ if (!mounted) return null;
530
+ return /* @__PURE__ */ jsxRuntime.jsx(chunkXMXECSQO_cjs.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ansh-dialog__layer", "data-state": state, children: [
531
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ansh-dialog__scrim", "data-state": state, "aria-hidden": "true" }),
532
+ /* @__PURE__ */ jsxRuntime.jsxs(
533
+ "div",
534
+ {
535
+ ref: panelRef,
536
+ role: "alertdialog",
537
+ "aria-modal": "true",
538
+ "aria-labelledby": `${id}-title`,
539
+ "aria-describedby": `${id}-description`,
540
+ tabIndex: -1,
541
+ "data-state": state,
542
+ className: chunkSFU5EPSN_cjs.cx("ansh-dialog", "ansh-dialog--sm", "ansh-dialog--alert", className),
543
+ children: [
544
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ansh-dialog__body", children: [
545
+ destructive ? /* @__PURE__ */ jsxRuntime.jsx(
546
+ "span",
547
+ {
548
+ className: "ansh-dialog__alert-icon ansh-dialog__alert-icon--danger",
549
+ "aria-hidden": "true",
550
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
551
+ "svg",
552
+ {
553
+ viewBox: "0 0 24 24",
554
+ width: "20",
555
+ height: "20",
556
+ fill: "none",
557
+ stroke: "currentColor",
558
+ strokeWidth: "1.75",
559
+ children: [
560
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 8v5", strokeLinecap: "round" }),
561
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "16.5", r: "1", fill: "currentColor", stroke: "none" }),
562
+ /* @__PURE__ */ jsxRuntime.jsx(
563
+ "path",
564
+ {
565
+ d: "M10.3 3.9L2.6 17.4A2 2 0 004.3 20.4h15.4a2 2 0 001.7-3L13.7 3.9a2 2 0 00-3.4 0z",
566
+ strokeLinejoin: "round"
567
+ }
568
+ )
569
+ ]
570
+ }
571
+ )
572
+ }
573
+ ) : null,
574
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "ansh-dialog__title", id: `${id}-title`, children: title }),
575
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "ansh-dialog__description", id: `${id}-description`, children: description })
576
+ ] }),
577
+ /* @__PURE__ */ jsxRuntime.jsxs("footer", { className: "ansh-dialog__footer", children: [
578
+ /* @__PURE__ */ jsxRuntime.jsx(
579
+ "button",
580
+ {
581
+ ref: cancelRef,
582
+ type: "button",
583
+ className: "ansh-btn ansh-btn--ghost ansh-btn--sm ansh-focusable",
584
+ disabled: busy,
585
+ onClick: cancel,
586
+ children: cancelLabel
587
+ }
588
+ ),
589
+ /* @__PURE__ */ jsxRuntime.jsxs(
590
+ "button",
591
+ {
592
+ type: "button",
593
+ className: chunkSFU5EPSN_cjs.cx(
594
+ "ansh-btn",
595
+ "ansh-btn--sm",
596
+ destructive ? "ansh-btn--danger" : "ansh-btn--solid",
597
+ "ansh-focusable"
598
+ ),
599
+ disabled: busy,
600
+ onClick: () => void onConfirm(),
601
+ children: [
602
+ busy ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-spinner ansh-spinner--sm", "aria-hidden": "true" }) : null,
603
+ confirmLabel
604
+ ]
605
+ }
606
+ )
607
+ ] })
608
+ ]
609
+ }
610
+ )
611
+ ] }) });
612
+ }
613
+ function DialogFooter({ children, className }) {
614
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: chunkSFU5EPSN_cjs.cx("ansh-dialog__actions", className), children });
615
+ }
616
+ function Drawer({
617
+ open,
618
+ onOpenChange,
619
+ side = "right",
620
+ title,
621
+ description,
622
+ size = "22rem",
623
+ footer,
624
+ showClose = true,
625
+ modal = true,
626
+ dismissable = true,
627
+ className,
628
+ children
629
+ }) {
630
+ const panelRef = react.useRef(null);
631
+ const id = react.useId();
632
+ const { mounted, state } = chunkC32LKF23_cjs.usePresence(open, panelRef);
633
+ const close = react.useCallback(() => {
634
+ if (dismissable) onOpenChange(false);
635
+ }, [dismissable, onOpenChange]);
636
+ chunkXMXECSQO_cjs.useDismiss(panelRef, open, close, { outsidePress: dismissable && modal, escapeKey: dismissable });
637
+ chunkC32LKF23_cjs.useFocusTrap(panelRef, open && modal);
638
+ chunkC32LKF23_cjs.useAutoFocus(panelRef, open);
639
+ chunkC32LKF23_cjs.useFocusRestore(open);
640
+ chunkXMXECSQO_cjs.useScrollLock(open && modal);
641
+ if (!mounted) return null;
642
+ const horizontal = side === "left" || side === "right";
643
+ return /* @__PURE__ */ jsxRuntime.jsx(chunkXMXECSQO_cjs.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
644
+ "div",
645
+ {
646
+ className: chunkSFU5EPSN_cjs.cx("ansh-drawer__layer", !modal && "ansh-drawer__layer--inline"),
647
+ "data-state": state,
648
+ children: [
649
+ modal ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ansh-dialog__scrim", "data-state": state, "aria-hidden": "true" }) : null,
650
+ /* @__PURE__ */ jsxRuntime.jsxs(
651
+ "div",
652
+ {
653
+ ref: panelRef,
654
+ role: "dialog",
655
+ "aria-modal": modal || void 0,
656
+ "aria-labelledby": `${id}-title`,
657
+ ...description ? { "aria-describedby": `${id}-description` } : null,
658
+ tabIndex: -1,
659
+ "data-state": state,
660
+ "data-side": side,
661
+ className: chunkSFU5EPSN_cjs.cx("ansh-drawer", `ansh-drawer--${side}`, className),
662
+ style: {
663
+ [horizontal ? "width" : "height"]: size,
664
+ ["--ansh-drawer-size"]: size
665
+ },
666
+ children: [
667
+ /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "ansh-drawer__header", children: [
668
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ansh-dialog__heading", children: [
669
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "ansh-dialog__title", id: `${id}-title`, children: title }),
670
+ description ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "ansh-dialog__description", id: `${id}-description`, children: description }) : null
671
+ ] }),
672
+ showClose ? /* @__PURE__ */ jsxRuntime.jsx(
673
+ "button",
674
+ {
675
+ type: "button",
676
+ className: "ansh-dialog__close ansh-focusable",
677
+ "aria-label": "Close panel",
678
+ onClick: () => onOpenChange(false),
679
+ children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 16 16", width: "14", height: "14", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(
680
+ "path",
681
+ {
682
+ d: "M4 4l8 8M12 4l-8 8",
683
+ stroke: "currentColor",
684
+ strokeWidth: "1.75",
685
+ strokeLinecap: "round",
686
+ fill: "none"
687
+ }
688
+ ) })
689
+ }
690
+ ) : null
691
+ ] }),
692
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ansh-drawer__body", children }),
693
+ footer ? /* @__PURE__ */ jsxRuntime.jsx("footer", { className: "ansh-drawer__footer", children: footer }) : null
694
+ ]
695
+ }
696
+ )
697
+ ]
698
+ }
699
+ ) });
700
+ }
701
+ function flatten(items) {
702
+ const rows = [];
703
+ for (const entry of items) {
704
+ if ("type" in entry && (entry.type === "separator" || entry.type === "label")) continue;
705
+ if ("type" in entry && entry.type === "radio") {
706
+ entry.options.forEach((option, optionIndex) => {
707
+ rows.push({ entry, optionIndex, disabled: option.disabled ?? false });
708
+ });
709
+ continue;
710
+ }
711
+ rows.push({ entry, disabled: entry.disabled ?? false });
712
+ }
713
+ return rows;
714
+ }
715
+ function DropdownMenu({
716
+ items,
717
+ placement = "bottom-start",
718
+ label = "Menu",
719
+ className,
720
+ children,
721
+ open: controlledOpen,
722
+ onOpenChange
723
+ }) {
724
+ const [uncontrolledOpen, setUncontrolledOpen] = react.useState(false);
725
+ const open = controlledOpen ?? uncontrolledOpen;
726
+ const setOpen = react.useCallback(
727
+ (next) => {
728
+ setUncontrolledOpen(next);
729
+ onOpenChange?.(next);
730
+ },
731
+ [onOpenChange]
732
+ );
733
+ const triggerRef = react.useRef(null);
734
+ const menuRef = react.useRef(null);
735
+ const menuId = react.useId();
736
+ const { mounted, state } = chunkC32LKF23_cjs.usePresence(open, menuRef);
737
+ const position = chunkXMXECSQO_cjs.useAnchoredPosition(triggerRef, menuRef, mounted, { placement, offset: 6 });
738
+ chunkXMXECSQO_cjs.useDismiss(menuRef, open, () => setOpen(false), { ignore: [triggerRef] });
739
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
740
+ /* @__PURE__ */ jsxRuntime.jsx(
741
+ chunkC32LKF23_cjs.Slot,
742
+ {
743
+ ref: triggerRef,
744
+ "aria-haspopup": "menu",
745
+ "aria-expanded": open,
746
+ "aria-controls": open ? menuId : void 0,
747
+ onClick: () => setOpen(!open),
748
+ onKeyDown: (event) => {
749
+ if (event.key === "ArrowDown" || event.key === "ArrowUp") {
750
+ event.preventDefault();
751
+ setOpen(true);
752
+ }
753
+ },
754
+ children
755
+ }
756
+ ),
757
+ mounted ? /* @__PURE__ */ jsxRuntime.jsx(chunkXMXECSQO_cjs.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
758
+ MenuSurface,
759
+ {
760
+ ref: menuRef,
761
+ id: menuId,
762
+ items,
763
+ label,
764
+ state,
765
+ style: position.style,
766
+ className,
767
+ onClose: () => {
768
+ setOpen(false);
769
+ triggerRef.current?.focus?.();
770
+ }
771
+ }
772
+ ) }) : null
773
+ ] });
774
+ }
775
+ function ContextMenu({
776
+ items,
777
+ label = "Context menu",
778
+ className,
779
+ children
780
+ }) {
781
+ const [point, setPoint] = react.useState(null);
782
+ const menuRef = react.useRef(null);
783
+ const anchorRef = react.useRef(null);
784
+ const menuId = react.useId();
785
+ const open = point !== null;
786
+ const { mounted, state } = chunkC32LKF23_cjs.usePresence(open, menuRef);
787
+ const position = chunkXMXECSQO_cjs.useAnchoredPosition(anchorRef, menuRef, mounted, {
788
+ placement: "bottom-start",
789
+ offset: 2
790
+ });
791
+ chunkXMXECSQO_cjs.useDismiss(menuRef, open, () => setPoint(null));
792
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
793
+ /* @__PURE__ */ jsxRuntime.jsx(
794
+ "span",
795
+ {
796
+ className: "ansh-contextmenu__area",
797
+ onContextMenu: (event) => {
798
+ event.preventDefault();
799
+ setPoint({ x: event.clientX, y: event.clientY });
800
+ },
801
+ onKeyDown: (event) => {
802
+ if (event.key === "ContextMenu" || event.shiftKey && event.key === "F10") {
803
+ event.preventDefault();
804
+ const rect = event.currentTarget.getBoundingClientRect();
805
+ setPoint({ x: rect.left + 8, y: rect.top + 8 });
806
+ }
807
+ },
808
+ children
809
+ }
810
+ ),
811
+ point ? /* @__PURE__ */ jsxRuntime.jsx(
812
+ "span",
813
+ {
814
+ ref: anchorRef,
815
+ "aria-hidden": "true",
816
+ style: { position: "fixed", left: point.x, top: point.y, width: 0, height: 0 }
817
+ }
818
+ ) : null,
819
+ mounted ? /* @__PURE__ */ jsxRuntime.jsx(chunkXMXECSQO_cjs.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
820
+ MenuSurface,
821
+ {
822
+ ref: menuRef,
823
+ id: menuId,
824
+ items,
825
+ label,
826
+ state,
827
+ style: position.style,
828
+ className,
829
+ onClose: () => setPoint(null)
830
+ }
831
+ ) }) : null
832
+ ] });
833
+ }
834
+ var MenuSurface = function MenuSurface2({
835
+ ref,
836
+ id,
837
+ items,
838
+ label,
839
+ state,
840
+ style,
841
+ className,
842
+ onClose
843
+ }) {
844
+ const rows = flatten(items);
845
+ const itemRefs = react.useRef([]);
846
+ const [active, setActive] = react.useState(() => rows.findIndex((row) => !row.disabled));
847
+ const [openSubmenu, setOpenSubmenu] = react.useState(null);
848
+ const typeaheadRef = react.useRef({
849
+ buffer: "",
850
+ timer: void 0
851
+ });
852
+ react.useEffect(() => {
853
+ itemRefs.current[active]?.focus();
854
+ }, []);
855
+ const move = (delta) => {
856
+ if (rows.length === 0) return;
857
+ let next = active;
858
+ for (let attempts = 0; attempts < rows.length; attempts++) {
859
+ next = (next + delta + rows.length) % rows.length;
860
+ if (!rows[next]?.disabled) break;
861
+ }
862
+ setActive(next);
863
+ itemRefs.current[next]?.focus();
864
+ };
865
+ const activate = (index) => {
866
+ const row = rows[index];
867
+ if (!row || row.disabled) return;
868
+ const { entry } = row;
869
+ if ("type" in entry && entry.type === "submenu") {
870
+ setOpenSubmenu(index);
871
+ return;
872
+ }
873
+ if ("type" in entry && entry.type === "checkbox") {
874
+ entry.onChange(!entry.checked);
875
+ return;
876
+ }
877
+ if ("type" in entry && entry.type === "radio") {
878
+ entry.onChange(entry.options[row.optionIndex].value);
879
+ onClose();
880
+ return;
881
+ }
882
+ entry.onSelect?.();
883
+ onClose();
884
+ };
885
+ const onKeyDown = (event) => {
886
+ switch (event.key) {
887
+ case "ArrowDown":
888
+ event.preventDefault();
889
+ move(1);
890
+ break;
891
+ case "ArrowUp":
892
+ event.preventDefault();
893
+ move(-1);
894
+ break;
895
+ case "Home":
896
+ event.preventDefault();
897
+ setActive(0);
898
+ itemRefs.current[0]?.focus();
899
+ break;
900
+ case "End":
901
+ event.preventDefault();
902
+ setActive(rows.length - 1);
903
+ itemRefs.current[rows.length - 1]?.focus();
904
+ break;
905
+ case "Enter":
906
+ case " ":
907
+ event.preventDefault();
908
+ activate(active);
909
+ break;
910
+ case "ArrowRight": {
911
+ const row = rows[active];
912
+ if (row && "type" in row.entry && row.entry.type === "submenu") {
913
+ event.preventDefault();
914
+ setOpenSubmenu(active);
915
+ }
916
+ break;
917
+ }
918
+ case "Escape":
919
+ event.preventDefault();
920
+ onClose();
921
+ break;
922
+ case "Tab":
923
+ event.preventDefault();
924
+ onClose();
925
+ break;
926
+ default: {
927
+ if (event.key.length !== 1) return;
928
+ const state2 = typeaheadRef.current;
929
+ clearTimeout(state2.timer);
930
+ state2.buffer += event.key.toLowerCase();
931
+ state2.timer = setTimeout(() => {
932
+ state2.buffer = "";
933
+ }, 600);
934
+ const match = rows.findIndex((row, index) => {
935
+ if (row.disabled || index === active) return false;
936
+ const text = typeof row.entry.label === "string" ? row.entry.label : "";
937
+ return text.toLowerCase().startsWith(state2.buffer);
938
+ });
939
+ if (match >= 0) {
940
+ setActive(match);
941
+ itemRefs.current[match]?.focus();
942
+ }
943
+ }
944
+ }
945
+ };
946
+ let rowIndex = -1;
947
+ return /* @__PURE__ */ jsxRuntime.jsx(
948
+ "div",
949
+ {
950
+ ref,
951
+ id,
952
+ role: "menu",
953
+ "aria-label": label,
954
+ "data-state": state,
955
+ className: chunkSFU5EPSN_cjs.cx("ansh-menu", className),
956
+ style,
957
+ onKeyDown,
958
+ children: items.map((entry, entryIndex) => {
959
+ if ("type" in entry && entry.type === "separator") {
960
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { role: "separator", className: "ansh-menu__separator" }, `sep-${entryIndex}`);
961
+ }
962
+ if ("type" in entry && entry.type === "label") {
963
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { role: "presentation", className: "ansh-menu__label", children: entry.label }, `label-${entryIndex}`);
964
+ }
965
+ if ("type" in entry && entry.type === "radio") {
966
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { role: "group", className: "ansh-menu__group", children: entry.options.map((option) => {
967
+ rowIndex++;
968
+ const index2 = rowIndex;
969
+ return /* @__PURE__ */ jsxRuntime.jsxs(
970
+ "div",
971
+ {
972
+ ref: (node) => {
973
+ itemRefs.current[index2] = node;
974
+ },
975
+ role: "menuitemradio",
976
+ "aria-checked": entry.value === option.value,
977
+ "aria-disabled": option.disabled || void 0,
978
+ tabIndex: index2 === active ? 0 : -1,
979
+ className: chunkSFU5EPSN_cjs.cx(
980
+ "ansh-menu__item",
981
+ option.disabled && "ansh-menu__item--disabled"
982
+ ),
983
+ onClick: () => activate(index2),
984
+ onMouseEnter: () => !option.disabled && setActive(index2),
985
+ children: [
986
+ /* @__PURE__ */ jsxRuntime.jsx(
987
+ "span",
988
+ {
989
+ className: chunkSFU5EPSN_cjs.cx(
990
+ "ansh-menu__indicator",
991
+ entry.value === option.value && "ansh-menu__indicator--on"
992
+ ),
993
+ "aria-hidden": "true"
994
+ }
995
+ ),
996
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-menu__text", children: option.label })
997
+ ]
998
+ },
999
+ option.value
1000
+ );
1001
+ }) }, `radio-${entryIndex}`);
1002
+ }
1003
+ rowIndex++;
1004
+ const index = rowIndex;
1005
+ if ("type" in entry && entry.type === "checkbox") {
1006
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1007
+ "div",
1008
+ {
1009
+ ref: (node) => {
1010
+ itemRefs.current[index] = node;
1011
+ },
1012
+ role: "menuitemcheckbox",
1013
+ "aria-checked": entry.checked,
1014
+ "aria-disabled": entry.disabled || void 0,
1015
+ tabIndex: index === active ? 0 : -1,
1016
+ className: chunkSFU5EPSN_cjs.cx("ansh-menu__item", entry.disabled && "ansh-menu__item--disabled"),
1017
+ onClick: () => activate(index),
1018
+ onMouseEnter: () => !entry.disabled && setActive(index),
1019
+ children: [
1020
+ /* @__PURE__ */ jsxRuntime.jsx(
1021
+ "span",
1022
+ {
1023
+ className: chunkSFU5EPSN_cjs.cx(
1024
+ "ansh-menu__indicator",
1025
+ "ansh-menu__indicator--check",
1026
+ entry.checked && "ansh-menu__indicator--on"
1027
+ ),
1028
+ "aria-hidden": "true",
1029
+ children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 14 14", width: "10", height: "10", children: /* @__PURE__ */ jsxRuntime.jsx(
1030
+ "path",
1031
+ {
1032
+ d: "M2.5 7.5l3 3 6-6.5",
1033
+ stroke: "currentColor",
1034
+ strokeWidth: "2",
1035
+ strokeLinecap: "round",
1036
+ strokeLinejoin: "round",
1037
+ fill: "none"
1038
+ }
1039
+ ) })
1040
+ }
1041
+ ),
1042
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-menu__text", children: entry.label }),
1043
+ entry.shortcut ? /* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "ansh-menu__shortcut", children: entry.shortcut }) : null
1044
+ ]
1045
+ },
1046
+ entry.id ?? `check-${entryIndex}`
1047
+ );
1048
+ }
1049
+ if ("type" in entry && entry.type === "submenu") {
1050
+ return /* @__PURE__ */ jsxRuntime.jsx(
1051
+ Submenu,
1052
+ {
1053
+ ref: (node) => {
1054
+ itemRefs.current[index] = node;
1055
+ },
1056
+ entry,
1057
+ active: index === active,
1058
+ open: openSubmenu === index,
1059
+ onOpenChange: (next) => setOpenSubmenu(next ? index : null),
1060
+ onHover: () => setActive(index),
1061
+ onCloseAll: onClose
1062
+ },
1063
+ entry.id ?? `sub-${entryIndex}`
1064
+ );
1065
+ }
1066
+ const action = entry;
1067
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1068
+ "div",
1069
+ {
1070
+ ref: (node) => {
1071
+ itemRefs.current[index] = node;
1072
+ },
1073
+ role: "menuitem",
1074
+ "aria-disabled": action.disabled || void 0,
1075
+ tabIndex: index === active ? 0 : -1,
1076
+ className: chunkSFU5EPSN_cjs.cx(
1077
+ "ansh-menu__item",
1078
+ action.danger && "ansh-menu__item--danger",
1079
+ action.disabled && "ansh-menu__item--disabled"
1080
+ ),
1081
+ onClick: () => activate(index),
1082
+ onMouseEnter: () => !action.disabled && setActive(index),
1083
+ children: [
1084
+ action.icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-menu__icon", children: action.icon }) : null,
1085
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-menu__text", children: action.label }),
1086
+ action.shortcut ? /* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "ansh-menu__shortcut", children: action.shortcut }) : null
1087
+ ]
1088
+ },
1089
+ action.id ?? `item-${entryIndex}`
1090
+ );
1091
+ })
1092
+ }
1093
+ );
1094
+ };
1095
+ function Submenu({ ref, entry, active, open, onOpenChange, onHover, onCloseAll }) {
1096
+ const triggerRef = react.useRef(null);
1097
+ const panelRef = react.useRef(null);
1098
+ const timerRef = react.useRef(void 0);
1099
+ const id = react.useId();
1100
+ const { mounted, state } = chunkC32LKF23_cjs.usePresence(open, panelRef);
1101
+ const position = chunkXMXECSQO_cjs.useAnchoredPosition(triggerRef, panelRef, mounted, {
1102
+ placement: "right-start",
1103
+ offset: 2
1104
+ });
1105
+ react.useEffect(() => () => clearTimeout(timerRef.current), []);
1106
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1107
+ /* @__PURE__ */ jsxRuntime.jsxs(
1108
+ "div",
1109
+ {
1110
+ ref: (node) => {
1111
+ triggerRef.current = node;
1112
+ if (typeof ref === "function") ref(node);
1113
+ else if (ref) ref.current = node;
1114
+ },
1115
+ role: "menuitem",
1116
+ "aria-haspopup": "menu",
1117
+ "aria-expanded": open,
1118
+ "aria-controls": open ? id : void 0,
1119
+ "aria-disabled": entry.disabled || void 0,
1120
+ tabIndex: active ? 0 : -1,
1121
+ className: chunkSFU5EPSN_cjs.cx(
1122
+ "ansh-menu__item",
1123
+ "ansh-menu__item--submenu",
1124
+ entry.disabled && "ansh-menu__item--disabled"
1125
+ ),
1126
+ onMouseEnter: () => {
1127
+ onHover();
1128
+ clearTimeout(timerRef.current);
1129
+ timerRef.current = setTimeout(() => onOpenChange(true), 120);
1130
+ },
1131
+ onMouseLeave: () => {
1132
+ clearTimeout(timerRef.current);
1133
+ timerRef.current = setTimeout(() => onOpenChange(false), 200);
1134
+ },
1135
+ onClick: () => onOpenChange(!open),
1136
+ children: [
1137
+ entry.icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-menu__icon", children: entry.icon }) : null,
1138
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-menu__text", children: entry.label }),
1139
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ansh-menu__chevron", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 12 12", width: "12", height: "12", children: /* @__PURE__ */ jsxRuntime.jsx(
1140
+ "path",
1141
+ {
1142
+ d: "M4.5 2.5L8 6l-3.5 3.5",
1143
+ stroke: "currentColor",
1144
+ strokeWidth: "1.5",
1145
+ fill: "none",
1146
+ strokeLinecap: "round",
1147
+ strokeLinejoin: "round"
1148
+ }
1149
+ ) }) })
1150
+ ]
1151
+ }
1152
+ ),
1153
+ mounted ? /* @__PURE__ */ jsxRuntime.jsx(chunkXMXECSQO_cjs.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
1154
+ "div",
1155
+ {
1156
+ onMouseEnter: () => clearTimeout(timerRef.current),
1157
+ onMouseLeave: () => {
1158
+ timerRef.current = setTimeout(() => onOpenChange(false), 200);
1159
+ },
1160
+ onKeyDown: (event) => {
1161
+ if (event.key === "ArrowLeft") {
1162
+ event.preventDefault();
1163
+ event.stopPropagation();
1164
+ onOpenChange(false);
1165
+ triggerRef.current?.focus();
1166
+ }
1167
+ },
1168
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1169
+ MenuSurface,
1170
+ {
1171
+ ref: panelRef,
1172
+ id,
1173
+ items: entry.items,
1174
+ label: typeof entry.label === "string" ? entry.label : "Submenu",
1175
+ state,
1176
+ style: position.style,
1177
+ onClose: onCloseAll
1178
+ }
1179
+ )
1180
+ }
1181
+ ) }) : null
1182
+ ] });
1183
+ }
1184
+
1185
+ exports.AlertDialog = AlertDialog;
1186
+ exports.CommandPalette = CommandPalette;
1187
+ exports.ContextMenu = ContextMenu;
1188
+ exports.Dialog = Dialog;
1189
+ exports.DialogFooter = DialogFooter;
1190
+ exports.Drawer = Drawer;
1191
+ exports.DropdownMenu = DropdownMenu;
1192
+ exports.HoverCard = HoverCard;
1193
+ exports.Popover = Popover;
1194
+ exports.PopoverContent = PopoverContent;
1195
+ exports.PopoverTrigger = PopoverTrigger;
1196
+ exports.Tooltip = Tooltip;
1197
+ exports.TooltipProvider = TooltipProvider;
1198
+ exports.useCommandShortcut = useCommandShortcut;
1199
+ //# sourceMappingURL=chunk-C5JG6TMM.cjs.map
1200
+ //# sourceMappingURL=chunk-C5JG6TMM.cjs.map