@wow-two-beta/ui 0.0.8 → 0.0.9

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 (64) hide show
  1. package/dist/chunk-3KGYKBW6.js +697 -0
  2. package/dist/chunk-3KGYKBW6.js.map +1 -0
  3. package/dist/{chunk-7SGLT2LM.js → chunk-55Y2JOBV.js} +3 -3
  4. package/dist/{chunk-7SGLT2LM.js.map → chunk-55Y2JOBV.js.map} +1 -1
  5. package/dist/{chunk-SL5YJADS.js → chunk-CZ6FQILQ.js} +30 -5
  6. package/dist/chunk-CZ6FQILQ.js.map +1 -0
  7. package/dist/{chunk-X2LTOZ7F.js → chunk-SBVWECJP.js} +921 -6
  8. package/dist/chunk-SBVWECJP.js.map +1 -0
  9. package/dist/display/index.js +2 -3
  10. package/dist/forms/combobox/Combobox.d.ts +55 -0
  11. package/dist/forms/combobox/Combobox.d.ts.map +1 -0
  12. package/dist/forms/combobox/index.d.ts +2 -0
  13. package/dist/forms/combobox/index.d.ts.map +1 -0
  14. package/dist/forms/index.d.ts +4 -0
  15. package/dist/forms/index.d.ts.map +1 -1
  16. package/dist/forms/index.js +3 -2
  17. package/dist/forms/listbox/Listbox.d.ts +44 -0
  18. package/dist/forms/listbox/Listbox.d.ts.map +1 -0
  19. package/dist/forms/listbox/Listbox.variants.d.ts +58 -0
  20. package/dist/forms/listbox/Listbox.variants.d.ts.map +1 -0
  21. package/dist/forms/listbox/index.d.ts +2 -0
  22. package/dist/forms/listbox/index.d.ts.map +1 -0
  23. package/dist/forms/multiSelect/MultiSelect.d.ts +47 -0
  24. package/dist/forms/multiSelect/MultiSelect.d.ts.map +1 -0
  25. package/dist/forms/multiSelect/index.d.ts +2 -0
  26. package/dist/forms/multiSelect/index.d.ts.map +1 -0
  27. package/dist/forms/select/Select.d.ts +55 -0
  28. package/dist/forms/select/Select.d.ts.map +1 -0
  29. package/dist/forms/select/Select.variants.d.ts +74 -0
  30. package/dist/forms/select/Select.variants.d.ts.map +1 -0
  31. package/dist/forms/select/index.d.ts +2 -0
  32. package/dist/forms/select/index.d.ts.map +1 -0
  33. package/dist/index.js +4 -5
  34. package/dist/nav/contextMenu/ContextMenu.d.ts +31 -0
  35. package/dist/nav/contextMenu/ContextMenu.d.ts.map +1 -0
  36. package/dist/nav/contextMenu/index.d.ts +2 -0
  37. package/dist/nav/contextMenu/index.d.ts.map +1 -0
  38. package/dist/nav/dropdownMenu/DropdownMenu.d.ts +34 -0
  39. package/dist/nav/dropdownMenu/DropdownMenu.d.ts.map +1 -0
  40. package/dist/nav/dropdownMenu/index.d.ts +2 -0
  41. package/dist/nav/dropdownMenu/index.d.ts.map +1 -0
  42. package/dist/nav/index.d.ts +4 -0
  43. package/dist/nav/index.d.ts.map +1 -1
  44. package/dist/nav/index.js +3 -3
  45. package/dist/nav/menu/Menu.d.ts +38 -0
  46. package/dist/nav/menu/Menu.d.ts.map +1 -0
  47. package/dist/nav/menu/Menu.variants.d.ts +50 -0
  48. package/dist/nav/menu/Menu.variants.d.ts.map +1 -0
  49. package/dist/nav/menu/index.d.ts +3 -0
  50. package/dist/nav/menu/index.d.ts.map +1 -0
  51. package/dist/nav/menubar/Menubar.d.ts +40 -0
  52. package/dist/nav/menubar/Menubar.d.ts.map +1 -0
  53. package/dist/nav/menubar/Menubar.variants.d.ts +5 -0
  54. package/dist/nav/menubar/Menubar.variants.d.ts.map +1 -0
  55. package/dist/nav/menubar/index.d.ts +2 -0
  56. package/dist/nav/menubar/index.d.ts.map +1 -0
  57. package/dist/primitives/index.js +1 -2
  58. package/package.json +1 -1
  59. package/dist/chunk-L32PXXQL.js +0 -126
  60. package/dist/chunk-L32PXXQL.js.map +0 -1
  61. package/dist/chunk-SL5YJADS.js.map +0 -1
  62. package/dist/chunk-WEM32VIJ.js +0 -34
  63. package/dist/chunk-WEM32VIJ.js.map +0 -1
  64. package/dist/chunk-X2LTOZ7F.js.map +0 -1
@@ -0,0 +1,697 @@
1
+ import { Portal, AnchoredPositioner, DismissableLayer } from './chunk-CZ6FQILQ.js';
2
+ import { useControlled } from './chunk-4P2TFUVW.js';
3
+ import { Slot } from './chunk-33IOXQYO.js';
4
+ import { dataAttr, tv } from './chunk-BMBIZLO4.js';
5
+ import { Icon } from './chunk-TDX22OWF.js';
6
+ import { composeRefs } from './chunk-DN7WBRIV.js';
7
+ import { cn } from './chunk-KZ4VFY2T.js';
8
+ import { forwardRef, Fragment, createContext, useId, useRef, useEffect, useCallback, useMemo, useContext, useState } from 'react';
9
+ import { ChevronLeft, ChevronRight } from 'lucide-react';
10
+ import { jsx, jsxs } from 'react/jsx-runtime';
11
+ import { FocusScope } from '@radix-ui/react-focus-scope';
12
+
13
+ var Breadcrumb = forwardRef(
14
+ ({ items, separator, className, ...props }, ref) => {
15
+ const sep = separator ?? /* @__PURE__ */ jsx(Icon, { icon: ChevronRight, size: 14 });
16
+ return /* @__PURE__ */ jsx("nav", { ref, "aria-label": "Breadcrumb", className: cn("text-sm", className), ...props, children: /* @__PURE__ */ jsx("ol", { className: "flex flex-wrap items-center gap-1.5", children: items.map((item, i) => {
17
+ const isLast = i === items.length - 1;
18
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
19
+ /* @__PURE__ */ jsx("li", { children: item.href && !isLast ? /* @__PURE__ */ jsx(
20
+ "a",
21
+ {
22
+ href: item.href,
23
+ className: "text-muted-foreground hover:text-foreground hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring rounded-sm",
24
+ children: item.label
25
+ }
26
+ ) : /* @__PURE__ */ jsx("span", { "aria-current": isLast ? "page" : void 0, className: "text-foreground", children: item.label }) }),
27
+ !isLast && /* @__PURE__ */ jsx("li", { "aria-hidden": "true", className: "text-subtle-foreground", children: sep })
28
+ ] }, i);
29
+ }) }) });
30
+ }
31
+ );
32
+ Breadcrumb.displayName = "Breadcrumb";
33
+ function range(start, end) {
34
+ return Array.from({ length: end - start + 1 }, (_, i) => start + i);
35
+ }
36
+ function buildPages(total, page, siblings) {
37
+ if (total <= 1) return [1];
38
+ const left = Math.max(2, page - siblings);
39
+ const right = Math.min(total - 1, page + siblings);
40
+ const pages = [1];
41
+ if (left > 2) pages.push("ellipsis");
42
+ pages.push(...range(left, right));
43
+ if (right < total - 1) pages.push("ellipsis");
44
+ if (total > 1) pages.push(total);
45
+ return pages;
46
+ }
47
+ var Pagination = forwardRef(
48
+ ({ total, page, onPageChange, siblings = 1, className, ...props }, ref) => {
49
+ const pages = buildPages(total, page, siblings);
50
+ const go = (p) => onPageChange(Math.min(total, Math.max(1, p)));
51
+ const baseBtn = "inline-flex h-8 min-w-8 items-center justify-center rounded-md border border-transparent px-2 text-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50";
52
+ return /* @__PURE__ */ jsxs("nav", { ref, "aria-label": "Pagination", className: cn("inline-flex items-center gap-1", className), ...props, children: [
53
+ /* @__PURE__ */ jsx(
54
+ "button",
55
+ {
56
+ type: "button",
57
+ "aria-label": "Previous page",
58
+ disabled: page <= 1,
59
+ onClick: () => go(page - 1),
60
+ className: cn(baseBtn, "hover:bg-muted"),
61
+ children: /* @__PURE__ */ jsx(Icon, { icon: ChevronLeft, size: 16 })
62
+ }
63
+ ),
64
+ pages.map(
65
+ (p, i) => p === "ellipsis" ? /* @__PURE__ */ jsx("span", { className: "px-1 text-muted-foreground", children: "\u2026" }, `e-${i}`) : /* @__PURE__ */ jsx(
66
+ "button",
67
+ {
68
+ type: "button",
69
+ "aria-current": p === page ? "page" : void 0,
70
+ onClick: () => go(p),
71
+ className: cn(
72
+ baseBtn,
73
+ p === page ? "border-primary bg-primary text-primary-foreground" : "hover:bg-muted"
74
+ ),
75
+ children: p
76
+ },
77
+ p
78
+ )
79
+ ),
80
+ /* @__PURE__ */ jsx(
81
+ "button",
82
+ {
83
+ type: "button",
84
+ "aria-label": "Next page",
85
+ disabled: page >= total,
86
+ onClick: () => go(page + 1),
87
+ className: cn(baseBtn, "hover:bg-muted"),
88
+ children: /* @__PURE__ */ jsx(Icon, { icon: ChevronRight, size: 16 })
89
+ }
90
+ )
91
+ ] });
92
+ }
93
+ );
94
+ Pagination.displayName = "Pagination";
95
+ var SIZE = {
96
+ sm: "h-8 px-2 text-sm gap-2",
97
+ md: "h-9 px-2.5 text-sm gap-2.5",
98
+ lg: "h-11 px-3 text-base gap-3"
99
+ };
100
+ var NavItem = forwardRef(
101
+ ({ asChild, icon, children, trailing, isActive, size = "md", className, ...props }, ref) => {
102
+ const Comp = asChild ? Slot : "a";
103
+ return /* @__PURE__ */ jsxs(
104
+ Comp,
105
+ {
106
+ ref,
107
+ "aria-current": isActive ? "page" : void 0,
108
+ "data-active": dataAttr(isActive),
109
+ className: cn(
110
+ "group inline-flex w-full items-center rounded-md font-medium text-foreground transition-colors",
111
+ "hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
112
+ "data-[active]:bg-primary-soft data-[active]:text-primary-soft-foreground",
113
+ SIZE[size],
114
+ className
115
+ ),
116
+ ...props,
117
+ children: [
118
+ icon && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground group-data-[active]:text-current", children: icon }),
119
+ /* @__PURE__ */ jsx("span", { className: "flex-1 truncate text-left", children }),
120
+ trailing && /* @__PURE__ */ jsx("span", { className: "shrink-0", children: trailing })
121
+ ]
122
+ }
123
+ );
124
+ }
125
+ );
126
+ NavItem.displayName = "NavItem";
127
+
128
+ // src/nav/menu/Menu.variants.ts
129
+ var menuVariants = tv({
130
+ base: "flex min-w-[8rem] flex-col gap-0.5 rounded-md border border-border bg-popover p-1 text-sm text-popover-foreground shadow-md outline-none"
131
+ });
132
+ var menuItemVariants = tv({
133
+ base: "relative flex w-full cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-left text-sm outline-none transition-colors focus:bg-muted focus:text-foreground hover:bg-muted hover:text-foreground",
134
+ variants: {
135
+ state: {
136
+ default: "text-popover-foreground",
137
+ destructive: "text-destructive focus:bg-destructive-soft hover:bg-destructive-soft",
138
+ disabled: "pointer-events-none opacity-50"
139
+ }
140
+ },
141
+ defaultVariants: { state: "default" }
142
+ });
143
+ var menuLabelVariants = tv({
144
+ base: "px-2 py-1.5 text-xs font-semibold text-muted-foreground"
145
+ });
146
+ var menuSeparatorVariants = tv({
147
+ base: "-mx-1 my-1 h-px bg-border"
148
+ });
149
+ var MenuContext = createContext(null);
150
+ function useMenuContext() {
151
+ const ctx = useContext(MenuContext);
152
+ if (!ctx) throw new Error("Menu.Item / Group / Label / Separator must be used inside <Menu>");
153
+ return ctx;
154
+ }
155
+ function Menu({
156
+ open,
157
+ anchor,
158
+ onClose,
159
+ placement = "bottom-start",
160
+ offset = 6,
161
+ "aria-label": ariaLabel,
162
+ className,
163
+ children
164
+ }) {
165
+ const itemsRef = useRef([]);
166
+ const registerItem = useCallback((entry) => {
167
+ const idx = itemsRef.current.findIndex((i) => i.id === entry.id);
168
+ if (idx >= 0) itemsRef.current[idx] = entry;
169
+ else itemsRef.current.push(entry);
170
+ }, []);
171
+ const unregisterItem = useCallback((id) => {
172
+ itemsRef.current = itemsRef.current.filter((i) => i.id !== id);
173
+ }, []);
174
+ const ctx = useMemo(
175
+ () => ({ registerItem, unregisterItem, itemsRef, onClose }),
176
+ [registerItem, unregisterItem, onClose]
177
+ );
178
+ if (!open) return null;
179
+ return /* @__PURE__ */ jsx(MenuContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(AnchoredPositioner, { anchor, placement, offset, children: /* @__PURE__ */ jsx(FocusScope, { asChild: true, trapped: true, loop: true, children: /* @__PURE__ */ jsx(
180
+ DismissableLayer,
181
+ {
182
+ onEscape: onClose,
183
+ onOutsidePointerDown: (e) => {
184
+ if (anchor?.contains(e.target)) return;
185
+ onClose();
186
+ },
187
+ children: /* @__PURE__ */ jsx(
188
+ "div",
189
+ {
190
+ role: "menu",
191
+ "aria-label": ariaLabel,
192
+ className: cn(menuVariants(), className),
193
+ onKeyDown: (e) => {
194
+ if (e.key === "Tab") {
195
+ e.preventDefault();
196
+ onClose();
197
+ }
198
+ },
199
+ children
200
+ }
201
+ )
202
+ }
203
+ ) }) }) }) });
204
+ }
205
+ var MenuItem = forwardRef(function MenuItem2({ onSelect, disabled = false, state, className, onClick, onKeyDown, children, ...rest }, forwardedRef) {
206
+ const ctx = useMenuContext();
207
+ const id = useId();
208
+ const ref = useRef(null);
209
+ useEffect(() => {
210
+ ctx.registerItem({ id, ref: ref.current, disabled });
211
+ return () => ctx.unregisterItem(id);
212
+ }, [ctx, id, disabled]);
213
+ const moveFocus = useCallback(
214
+ (direction, jump = 1) => {
215
+ const list = ctx.itemsRef.current.filter((i) => !i.disabled);
216
+ if (list.length === 0) return;
217
+ const idx = list.findIndex((i) => i.id === id);
218
+ let nextIdx = idx + direction * jump;
219
+ if (idx === -1) nextIdx = direction === 1 ? 0 : list.length - 1;
220
+ if (nextIdx < 0) nextIdx = list.length - 1;
221
+ if (nextIdx >= list.length) nextIdx = 0;
222
+ list[nextIdx]?.ref?.focus();
223
+ },
224
+ [ctx, id]
225
+ );
226
+ const handleKeyDown = (e) => {
227
+ onKeyDown?.(e);
228
+ if (e.defaultPrevented || disabled) return;
229
+ switch (e.key) {
230
+ case "ArrowDown":
231
+ e.preventDefault();
232
+ moveFocus(1);
233
+ break;
234
+ case "ArrowUp":
235
+ e.preventDefault();
236
+ moveFocus(-1);
237
+ break;
238
+ case "Home":
239
+ e.preventDefault();
240
+ moveFocus(-1, ctx.itemsRef.current.length);
241
+ break;
242
+ case "End":
243
+ e.preventDefault();
244
+ moveFocus(1, ctx.itemsRef.current.length);
245
+ break;
246
+ case "Enter":
247
+ case " ":
248
+ e.preventDefault();
249
+ onSelect?.();
250
+ ctx.onClose();
251
+ break;
252
+ }
253
+ };
254
+ const itemState = state ?? (disabled ? "disabled" : "default");
255
+ return /* @__PURE__ */ jsx(
256
+ "button",
257
+ {
258
+ ref: composeRefs(forwardedRef, ref),
259
+ type: "button",
260
+ role: "menuitem",
261
+ disabled,
262
+ "aria-disabled": disabled || void 0,
263
+ "data-disabled": disabled ? "" : void 0,
264
+ onClick: (e) => {
265
+ onClick?.(e);
266
+ if (e.defaultPrevented || disabled) return;
267
+ onSelect?.();
268
+ ctx.onClose();
269
+ },
270
+ onKeyDown: handleKeyDown,
271
+ className: cn(menuItemVariants({ state: itemState }), className),
272
+ ...rest,
273
+ children
274
+ }
275
+ );
276
+ });
277
+ function MenuGroup({ label, children, className, ...rest }) {
278
+ const labelId = useId();
279
+ return /* @__PURE__ */ jsxs(
280
+ "div",
281
+ {
282
+ role: "group",
283
+ "aria-labelledby": label ? labelId : void 0,
284
+ className,
285
+ ...rest,
286
+ children: [
287
+ label && /* @__PURE__ */ jsx("div", { id: labelId, className: menuLabelVariants(), children: label }),
288
+ children
289
+ ]
290
+ }
291
+ );
292
+ }
293
+ function MenuLabel({
294
+ children,
295
+ className,
296
+ ...rest
297
+ }) {
298
+ return /* @__PURE__ */ jsx("div", { className: cn(menuLabelVariants(), className), ...rest, children });
299
+ }
300
+ function MenuSeparator(props) {
301
+ return /* @__PURE__ */ jsx("div", { role: "separator", className: menuSeparatorVariants(), ...props });
302
+ }
303
+ Menu.Item = MenuItem;
304
+ Menu.Group = MenuGroup;
305
+ Menu.Label = MenuLabel;
306
+ Menu.Separator = MenuSeparator;
307
+ var DropdownMenuContext = createContext(null);
308
+ function useDropdownMenuContext() {
309
+ const ctx = useContext(DropdownMenuContext);
310
+ if (!ctx) throw new Error("DropdownMenu.* must be used inside <DropdownMenu>");
311
+ return ctx;
312
+ }
313
+ function DropdownMenu({
314
+ open: openProp,
315
+ defaultOpen = false,
316
+ onOpenChange,
317
+ placement = "bottom-start",
318
+ offset = 6,
319
+ children
320
+ }) {
321
+ const [open, setOpen] = useControlled({
322
+ controlled: openProp,
323
+ default: defaultOpen,
324
+ onChange: onOpenChange
325
+ });
326
+ const triggerRef = useRef(null);
327
+ const ctx = useMemo(
328
+ () => ({ open, setOpen, triggerRef, placement, offset }),
329
+ [open, setOpen, placement, offset]
330
+ );
331
+ return /* @__PURE__ */ jsx(DropdownMenuContext.Provider, { value: ctx, children });
332
+ }
333
+ var DropdownMenuTrigger = forwardRef(
334
+ function DropdownMenuTrigger2({ asChild, onClick, onKeyDown, children, ...rest }, forwardedRef) {
335
+ const ctx = useDropdownMenuContext();
336
+ const Component = asChild ? Slot : "button";
337
+ const handleClick = useCallback(
338
+ (e) => {
339
+ onClick?.(e);
340
+ if (e.defaultPrevented) return;
341
+ ctx.setOpen(!ctx.open);
342
+ },
343
+ [ctx, onClick]
344
+ );
345
+ const handleKeyDown = useCallback(
346
+ (e) => {
347
+ onKeyDown?.(e);
348
+ if (e.defaultPrevented) return;
349
+ if (e.key === "ArrowDown" || e.key === "ArrowUp" || e.key === "Enter" || e.key === " ") {
350
+ e.preventDefault();
351
+ ctx.setOpen(true);
352
+ }
353
+ },
354
+ [ctx, onKeyDown]
355
+ );
356
+ return /* @__PURE__ */ jsx(
357
+ Component,
358
+ {
359
+ ref: composeRefs(forwardedRef, ctx.triggerRef),
360
+ type: "button",
361
+ "aria-haspopup": "menu",
362
+ "aria-expanded": ctx.open,
363
+ "data-state": ctx.open ? "open" : "closed",
364
+ onClick: handleClick,
365
+ onKeyDown: handleKeyDown,
366
+ ...rest,
367
+ children
368
+ }
369
+ );
370
+ }
371
+ );
372
+ function DropdownMenuContent({
373
+ className,
374
+ "aria-label": ariaLabel,
375
+ children
376
+ }) {
377
+ const ctx = useDropdownMenuContext();
378
+ return /* @__PURE__ */ jsx(
379
+ Menu,
380
+ {
381
+ open: ctx.open,
382
+ anchor: ctx.triggerRef.current,
383
+ onClose: () => {
384
+ ctx.setOpen(false);
385
+ requestAnimationFrame(() => ctx.triggerRef.current?.focus());
386
+ },
387
+ placement: ctx.placement,
388
+ offset: ctx.offset,
389
+ "aria-label": ariaLabel,
390
+ className,
391
+ children
392
+ }
393
+ );
394
+ }
395
+ DropdownMenu.Trigger = DropdownMenuTrigger;
396
+ DropdownMenu.Content = DropdownMenuContent;
397
+ DropdownMenu.Item = MenuItem;
398
+ DropdownMenu.Group = MenuGroup;
399
+ DropdownMenu.Label = MenuLabel;
400
+ DropdownMenu.Separator = MenuSeparator;
401
+ var ContextMenuContext = createContext(null);
402
+ function useContextMenuContext() {
403
+ const ctx = useContext(ContextMenuContext);
404
+ if (!ctx) throw new Error("ContextMenu.* must be used inside <ContextMenu>");
405
+ return ctx;
406
+ }
407
+ function makeVirtualAnchor(x, y) {
408
+ const el = document.createElement("div");
409
+ el.style.position = "fixed";
410
+ el.style.left = `${x}px`;
411
+ el.style.top = `${y}px`;
412
+ el.style.width = "0px";
413
+ el.style.height = "0px";
414
+ el.style.pointerEvents = "none";
415
+ document.body.appendChild(el);
416
+ return el;
417
+ }
418
+ function ContextMenu({ children }) {
419
+ const [open, setOpen] = useState(false);
420
+ const [anchor, setAnchorState] = useState(null);
421
+ const triggerRef = useRef(null);
422
+ const setAnchor = useCallback((el) => {
423
+ setAnchorState((prev) => {
424
+ if (prev && prev.parentNode === document.body) prev.remove();
425
+ return el;
426
+ });
427
+ }, []);
428
+ const handleSetOpen = useCallback(
429
+ (next) => {
430
+ setOpen(next);
431
+ if (!next) setAnchor(null);
432
+ },
433
+ [setAnchor]
434
+ );
435
+ const ctx = useMemo(
436
+ () => ({ open, setOpen: handleSetOpen, anchor, setAnchor, triggerRef }),
437
+ [open, handleSetOpen, anchor, setAnchor]
438
+ );
439
+ return /* @__PURE__ */ jsx(ContextMenuContext.Provider, { value: ctx, children });
440
+ }
441
+ var ContextMenuTrigger = forwardRef(
442
+ function ContextMenuTrigger2({ asChild, disabled, onContextMenu, onPointerDown, onPointerCancel, onPointerUp, children, ...rest }, forwardedRef) {
443
+ const ctx = useContextMenuContext();
444
+ const longPressTimer = useRef(null);
445
+ const Component = asChild ? Slot : "div";
446
+ const handleContextMenu = useCallback(
447
+ (e) => {
448
+ onContextMenu?.(e);
449
+ if (e.defaultPrevented || disabled) return;
450
+ e.preventDefault();
451
+ ctx.setAnchor(makeVirtualAnchor(e.clientX, e.clientY));
452
+ ctx.setOpen(true);
453
+ },
454
+ [ctx, disabled, onContextMenu]
455
+ );
456
+ const clearLongPress = useCallback(() => {
457
+ if (longPressTimer.current) clearTimeout(longPressTimer.current);
458
+ longPressTimer.current = null;
459
+ }, []);
460
+ return /* @__PURE__ */ jsx(
461
+ Component,
462
+ {
463
+ ref: composeRefs(forwardedRef, ctx.triggerRef),
464
+ onContextMenu: handleContextMenu,
465
+ onPointerDown: (e) => {
466
+ onPointerDown?.(e);
467
+ if (e.defaultPrevented || disabled || e.pointerType !== "touch") return;
468
+ const x = e.clientX;
469
+ const y = e.clientY;
470
+ longPressTimer.current = setTimeout(() => {
471
+ ctx.setAnchor(makeVirtualAnchor(x, y));
472
+ ctx.setOpen(true);
473
+ }, 600);
474
+ },
475
+ onPointerUp: (e) => {
476
+ onPointerUp?.(e);
477
+ clearLongPress();
478
+ },
479
+ onPointerCancel: (e) => {
480
+ onPointerCancel?.(e);
481
+ clearLongPress();
482
+ },
483
+ ...rest,
484
+ children
485
+ }
486
+ );
487
+ }
488
+ );
489
+ function ContextMenuContent({
490
+ className,
491
+ placement = "bottom-start",
492
+ offset = 2,
493
+ "aria-label": ariaLabel,
494
+ children
495
+ }) {
496
+ const ctx = useContextMenuContext();
497
+ return /* @__PURE__ */ jsx(
498
+ Menu,
499
+ {
500
+ open: ctx.open,
501
+ anchor: ctx.anchor,
502
+ onClose: () => ctx.setOpen(false),
503
+ placement,
504
+ offset,
505
+ "aria-label": ariaLabel,
506
+ className,
507
+ children
508
+ }
509
+ );
510
+ }
511
+ ContextMenu.Trigger = ContextMenuTrigger;
512
+ ContextMenu.Content = ContextMenuContent;
513
+ ContextMenu.Item = MenuItem;
514
+ ContextMenu.Group = MenuGroup;
515
+ ContextMenu.Label = MenuLabel;
516
+ ContextMenu.Separator = MenuSeparator;
517
+
518
+ // src/nav/menubar/Menubar.variants.ts
519
+ var menubarVariants = tv({
520
+ base: "flex items-center gap-1 rounded-md border border-border bg-background p-1"
521
+ });
522
+ var menubarTriggerVariants = tv({
523
+ base: "inline-flex select-none items-center rounded-sm px-3 py-1 text-sm font-medium text-foreground outline-none transition-colors hover:bg-muted focus-visible:bg-muted data-[state=open]:bg-muted"
524
+ });
525
+ var MenubarContext = createContext(null);
526
+ function useMenubarContext() {
527
+ const ctx = useContext(MenubarContext);
528
+ if (!ctx) throw new Error("Menubar.* must be used inside <Menubar>");
529
+ return ctx;
530
+ }
531
+ var MenubarMenuContext = createContext(null);
532
+ function useMenubarMenuContext() {
533
+ const ctx = useContext(MenubarMenuContext);
534
+ if (!ctx) throw new Error("Menubar.Trigger / Content must be used inside <Menubar.Menu>");
535
+ return ctx;
536
+ }
537
+ var Menubar = forwardRef(function Menubar2({ value, defaultValue = null, onValueChange, className, children, ...rest }, ref) {
538
+ const [activeId, setActiveId] = useControlled({
539
+ controlled: value,
540
+ default: defaultValue,
541
+ onChange: onValueChange
542
+ });
543
+ const triggersRef = useRef([]);
544
+ const registerTrigger = useCallback((id, triggerRef) => {
545
+ const idx = triggersRef.current.findIndex((t) => t.id === id);
546
+ if (idx >= 0) triggersRef.current[idx] = { id, ref: triggerRef };
547
+ else triggersRef.current.push({ id, ref: triggerRef });
548
+ }, []);
549
+ const unregisterTrigger = useCallback((id) => {
550
+ triggersRef.current = triggersRef.current.filter((t) => t.id !== id);
551
+ }, []);
552
+ const ctx = useMemo(
553
+ () => ({ activeId, setActiveId, registerTrigger, unregisterTrigger, triggersRef }),
554
+ [activeId, setActiveId, registerTrigger, unregisterTrigger]
555
+ );
556
+ return /* @__PURE__ */ jsx(MenubarContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx(
557
+ "div",
558
+ {
559
+ ref,
560
+ role: "menubar",
561
+ className: cn(menubarVariants(), className),
562
+ ...rest,
563
+ children
564
+ }
565
+ ) });
566
+ });
567
+ function MenubarMenu({ value, children }) {
568
+ const ctx = useMenubarContext();
569
+ const triggerRef = useRef(null);
570
+ const open = ctx.activeId === value;
571
+ const setOpen = useCallback(
572
+ (next) => {
573
+ ctx.setActiveId(next ? value : null);
574
+ },
575
+ [ctx, value]
576
+ );
577
+ const menuCtx = useMemo(
578
+ () => ({ id: value, open, setOpen, triggerRef }),
579
+ [value, open, setOpen]
580
+ );
581
+ return /* @__PURE__ */ jsx(MenubarMenuContext.Provider, { value: menuCtx, children });
582
+ }
583
+ var MenubarTrigger = forwardRef(
584
+ function MenubarTrigger2({ className, onClick, onKeyDown, onPointerEnter, children, ...rest }, forwardedRef) {
585
+ const bar = useMenubarContext();
586
+ const menu = useMenubarMenuContext();
587
+ useEffect(() => {
588
+ bar.registerTrigger(menu.id, menu.triggerRef.current);
589
+ return () => bar.unregisterTrigger(menu.id);
590
+ }, [bar, menu.id, menu.triggerRef]);
591
+ const moveAcross = useCallback(
592
+ (direction) => {
593
+ const list = bar.triggersRef.current;
594
+ const idx = list.findIndex((t) => t.id === menu.id);
595
+ if (idx === -1) return;
596
+ let nextIdx = idx + direction;
597
+ if (nextIdx < 0) nextIdx = list.length - 1;
598
+ if (nextIdx >= list.length) nextIdx = 0;
599
+ const next = list[nextIdx];
600
+ next?.ref?.focus();
601
+ if (bar.activeId !== null && next) bar.setActiveId(next.id);
602
+ },
603
+ [bar, menu.id]
604
+ );
605
+ return /* @__PURE__ */ jsx(
606
+ "button",
607
+ {
608
+ ref: composeRefs(forwardedRef, menu.triggerRef),
609
+ type: "button",
610
+ role: "menuitem",
611
+ "aria-haspopup": "menu",
612
+ "aria-expanded": menu.open,
613
+ "data-state": menu.open ? "open" : "closed",
614
+ onClick: (e) => {
615
+ onClick?.(e);
616
+ if (e.defaultPrevented) return;
617
+ menu.setOpen(!menu.open);
618
+ },
619
+ onPointerEnter: (e) => {
620
+ onPointerEnter?.(e);
621
+ if (bar.activeId !== null && bar.activeId !== menu.id) {
622
+ bar.setActiveId(menu.id);
623
+ }
624
+ },
625
+ onKeyDown: (e) => {
626
+ onKeyDown?.(e);
627
+ if (e.defaultPrevented) return;
628
+ switch (e.key) {
629
+ case "ArrowRight":
630
+ e.preventDefault();
631
+ moveAcross(1);
632
+ break;
633
+ case "ArrowLeft":
634
+ e.preventDefault();
635
+ moveAcross(-1);
636
+ break;
637
+ case "ArrowDown":
638
+ case "Enter":
639
+ case " ":
640
+ e.preventDefault();
641
+ menu.setOpen(true);
642
+ break;
643
+ case "Home":
644
+ e.preventDefault();
645
+ bar.triggersRef.current[0]?.ref?.focus();
646
+ break;
647
+ case "End": {
648
+ e.preventDefault();
649
+ const list = bar.triggersRef.current;
650
+ list[list.length - 1]?.ref?.focus();
651
+ break;
652
+ }
653
+ }
654
+ },
655
+ className: cn(menubarTriggerVariants(), className),
656
+ ...rest,
657
+ children
658
+ }
659
+ );
660
+ }
661
+ );
662
+ function MenubarContent({
663
+ className,
664
+ placement = "bottom-start",
665
+ offset = 4,
666
+ "aria-label": ariaLabel,
667
+ children
668
+ }) {
669
+ const menu = useMenubarMenuContext();
670
+ return /* @__PURE__ */ jsx(
671
+ Menu,
672
+ {
673
+ open: menu.open,
674
+ anchor: menu.triggerRef.current,
675
+ onClose: () => {
676
+ menu.setOpen(false);
677
+ requestAnimationFrame(() => menu.triggerRef.current?.focus());
678
+ },
679
+ placement,
680
+ offset,
681
+ "aria-label": ariaLabel,
682
+ className,
683
+ children
684
+ }
685
+ );
686
+ }
687
+ Menubar.Menu = MenubarMenu;
688
+ Menubar.Trigger = MenubarTrigger;
689
+ Menubar.Content = MenubarContent;
690
+ Menubar.Item = MenuItem;
691
+ Menubar.Group = MenuGroup;
692
+ Menubar.Label = MenuLabel;
693
+ Menubar.Separator = MenuSeparator;
694
+
695
+ export { Breadcrumb, ContextMenu, ContextMenuContent, ContextMenuTrigger, DropdownMenu, DropdownMenuContent, DropdownMenuTrigger, Menu, MenuGroup, MenuItem, MenuLabel, MenuSeparator, Menubar, MenubarContent, MenubarMenu, MenubarTrigger, NavItem, Pagination, menuItemVariants, menuLabelVariants, menuSeparatorVariants, menuVariants };
696
+ //# sourceMappingURL=chunk-3KGYKBW6.js.map
697
+ //# sourceMappingURL=chunk-3KGYKBW6.js.map