@revealui/presentation 0.3.0 → 0.3.3

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 (73) hide show
  1. package/README.md +14 -0
  2. package/dist/Text-mMOCv1lF.js +204 -0
  3. package/dist/Text-mMOCv1lF.js.map +1 -0
  4. package/dist/client.d.ts +3 -2
  5. package/dist/client.d.ts.map +1 -1
  6. package/dist/client.js +92 -266
  7. package/dist/client.js.map +1 -1
  8. package/dist/components/BuiltWithRevealUI.d.ts +6 -3
  9. package/dist/components/BuiltWithRevealUI.d.ts.map +1 -1
  10. package/dist/components/Button.d.ts +6 -3
  11. package/dist/components/Button.d.ts.map +1 -1
  12. package/dist/components/Card.d.ts.map +1 -1
  13. package/dist/components/Input.d.ts.map +1 -1
  14. package/dist/components/accordion.d.ts.map +1 -1
  15. package/dist/components/alert.d.ts.map +1 -1
  16. package/dist/components/avatar.d.ts.map +1 -1
  17. package/dist/components/badge.d.ts.map +1 -1
  18. package/dist/components/breadcrumb.d.ts.map +1 -1
  19. package/dist/components/button-headless.d.ts.map +1 -1
  20. package/dist/components/callout.d.ts.map +1 -1
  21. package/dist/components/checkbox-headless.d.ts.map +1 -1
  22. package/dist/components/combobox.d.ts.map +1 -1
  23. package/dist/components/dialog.d.ts.map +1 -1
  24. package/dist/components/drawer.d.ts.map +1 -1
  25. package/dist/components/dropdown.d.ts.map +1 -1
  26. package/dist/components/empty-state.d.ts.map +1 -1
  27. package/dist/components/fieldset.d.ts.map +1 -1
  28. package/dist/components/form-field.d.ts +23 -0
  29. package/dist/components/form-field.d.ts.map +1 -0
  30. package/dist/components/icon.d.ts +53 -0
  31. package/dist/components/icon.d.ts.map +1 -0
  32. package/dist/components/index.d.ts +1 -0
  33. package/dist/components/index.d.ts.map +1 -1
  34. package/dist/components/input-headless.d.ts.map +1 -1
  35. package/dist/components/kbd.d.ts.map +1 -1
  36. package/dist/components/listbox.d.ts.map +1 -1
  37. package/dist/components/navbar.d.ts.map +1 -1
  38. package/dist/components/radio.d.ts.map +1 -1
  39. package/dist/components/select-headless.d.ts.map +1 -1
  40. package/dist/components/sidebar.d.ts.map +1 -1
  41. package/dist/components/skeleton.d.ts.map +1 -1
  42. package/dist/components/stat.d.ts.map +1 -1
  43. package/dist/components/switch.d.ts.map +1 -1
  44. package/dist/components/table.d.ts.map +1 -1
  45. package/dist/components/tabs.d.ts.map +1 -1
  46. package/dist/components/textarea-headless.d.ts.map +1 -1
  47. package/dist/components/timeline.d.ts.map +1 -1
  48. package/dist/components/toast.d.ts.map +1 -1
  49. package/dist/components/tooltip.d.ts.map +1 -1
  50. package/dist/hooks/index.d.ts +1 -0
  51. package/dist/hooks/index.d.ts.map +1 -1
  52. package/dist/hooks/use-theme.d.ts +26 -0
  53. package/dist/hooks/use-theme.d.ts.map +1 -0
  54. package/dist/index.js +65 -224
  55. package/dist/index.js.map +1 -1
  56. package/dist/server.d.ts +5 -0
  57. package/dist/server.d.ts.map +1 -1
  58. package/dist/server.js +402 -32
  59. package/dist/server.js.map +1 -1
  60. package/dist/skeleton-CHPpiyJj.js +472 -0
  61. package/dist/skeleton-CHPpiyJj.js.map +1 -0
  62. package/dist/tokens.css +265 -0
  63. package/dist/use-theme-QxeZadnD.js +4024 -0
  64. package/dist/use-theme-QxeZadnD.js.map +1 -0
  65. package/dist/utils/cn.d.ts +21 -4
  66. package/dist/utils/cn.d.ts.map +1 -1
  67. package/package.json +13 -15
  68. package/dist/Box-DC3F8eRf.js +0 -430
  69. package/dist/Box-DC3F8eRf.js.map +0 -1
  70. package/dist/Text-jQVi12Hi.js +0 -218
  71. package/dist/Text-jQVi12Hi.js.map +0 -1
  72. package/dist/tooltip-DQYjYWbe.js +0 -5085
  73. package/dist/tooltip-DQYjYWbe.js.map +0 -1
@@ -0,0 +1,4024 @@
1
+ import { i as Box, v as cn } from "./skeleton-CHPpiyJj.js";
2
+ import React, { Children, createContext, isValidElement, use, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useReducer, useRef, useState, useSyncExternalStore } from "react";
3
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
+ import { createPortal } from "react-dom";
5
+ //#region src/components/accordion.tsx
6
+ function Accordion({ className, children }) {
7
+ return /* @__PURE__ */ jsx("div", {
8
+ className: cn("divide-y divide-zinc-200 dark:divide-zinc-700", className),
9
+ children
10
+ });
11
+ }
12
+ function AccordionItem({ title, defaultOpen = false, className, children }) {
13
+ const [open, setOpen] = useState(defaultOpen);
14
+ const id = useId();
15
+ return /* @__PURE__ */ jsxs("div", {
16
+ className,
17
+ children: [/* @__PURE__ */ jsxs("button", {
18
+ type: "button",
19
+ id: `${id}-trigger`,
20
+ "aria-expanded": open,
21
+ "aria-controls": `${id}-content`,
22
+ onClick: () => setOpen((prev) => !prev),
23
+ className: "flex w-full items-center justify-between gap-4 py-4 text-left text-sm font-medium text-zinc-950 transition-colors hover:text-zinc-700 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-500 dark:text-white dark:hover:text-zinc-300",
24
+ children: [/* @__PURE__ */ jsx("span", { children: title }), /* @__PURE__ */ jsx("svg", {
25
+ "aria-hidden": "true",
26
+ viewBox: "0 0 16 16",
27
+ fill: "none",
28
+ className: cn("size-4 shrink-0 text-zinc-400 transition-transform duration-200", open && "rotate-180"),
29
+ children: /* @__PURE__ */ jsx("path", {
30
+ d: "M4 6l4 4 4-4",
31
+ stroke: "currentColor",
32
+ strokeWidth: "1.5",
33
+ strokeLinecap: "round",
34
+ strokeLinejoin: "round"
35
+ })
36
+ })]
37
+ }), open && /* @__PURE__ */ jsx("section", {
38
+ id: `${id}-content`,
39
+ "aria-labelledby": `${id}-trigger`,
40
+ className: "pb-4 text-sm text-zinc-600 dark:text-zinc-400",
41
+ children
42
+ })]
43
+ });
44
+ }
45
+ //#endregion
46
+ //#region src/hooks/use-escape-key.ts
47
+ function useEscapeKey(onEscape, enabled = true) {
48
+ const callbackRef = useRef(onEscape);
49
+ callbackRef.current = onEscape;
50
+ useEffect(() => {
51
+ if (!enabled) return;
52
+ function handleKeyDown(e) {
53
+ if (e.key === "Escape") {
54
+ e.stopPropagation();
55
+ callbackRef.current();
56
+ }
57
+ }
58
+ document.addEventListener("keydown", handleKeyDown);
59
+ return () => document.removeEventListener("keydown", handleKeyDown);
60
+ }, [enabled]);
61
+ }
62
+ //#endregion
63
+ //#region src/hooks/use-focus-trap.ts
64
+ var FOCUSABLE_SELECTOR = [
65
+ "a[href]",
66
+ "button:not([disabled])",
67
+ "input:not([disabled]):not([type=\"hidden\"])",
68
+ "textarea:not([disabled])",
69
+ "select:not([disabled])",
70
+ "[tabindex]:not([tabindex=\"-1\"])"
71
+ ].join(", ");
72
+ function getFocusableElements(container) {
73
+ return Array.from(container.querySelectorAll(FOCUSABLE_SELECTOR));
74
+ }
75
+ function useFocusTrap(containerRef, enabled = true) {
76
+ useEffect(() => {
77
+ if (!enabled) return;
78
+ const container = containerRef.current;
79
+ if (!container) return;
80
+ const previouslyFocused = document.activeElement;
81
+ const focusableElements = getFocusableElements(container);
82
+ if (focusableElements.length > 0) focusableElements[0]?.focus();
83
+ else {
84
+ container.setAttribute("tabindex", "-1");
85
+ container.focus();
86
+ }
87
+ function handleKeyDown(e) {
88
+ if (e.key !== "Tab" || !container) return;
89
+ const focusable = getFocusableElements(container);
90
+ if (focusable.length === 0) {
91
+ e.preventDefault();
92
+ return;
93
+ }
94
+ const first = focusable[0];
95
+ const last = focusable[focusable.length - 1];
96
+ if (e.shiftKey && document.activeElement === first) {
97
+ e.preventDefault();
98
+ last?.focus();
99
+ } else if (!e.shiftKey && document.activeElement === last) {
100
+ e.preventDefault();
101
+ first?.focus();
102
+ }
103
+ }
104
+ document.addEventListener("keydown", handleKeyDown, true);
105
+ return () => {
106
+ document.removeEventListener("keydown", handleKeyDown, true);
107
+ previouslyFocused?.focus();
108
+ };
109
+ }, [containerRef, enabled]);
110
+ }
111
+ //#endregion
112
+ //#region src/hooks/use-scroll-lock.ts
113
+ function useScrollLock(enabled = true) {
114
+ useEffect(() => {
115
+ if (!enabled) return;
116
+ const originalOverflow = document.body.style.overflow;
117
+ const originalPaddingRight = document.body.style.paddingRight;
118
+ const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
119
+ document.body.style.overflow = "hidden";
120
+ if (scrollbarWidth > 0) document.body.style.paddingRight = `${scrollbarWidth}px`;
121
+ return () => {
122
+ document.body.style.overflow = originalOverflow;
123
+ document.body.style.paddingRight = originalPaddingRight;
124
+ };
125
+ }, [enabled]);
126
+ }
127
+ //#endregion
128
+ //#region src/hooks/use-transition.ts
129
+ /**
130
+ * Manages CSS transition lifecycle using data attributes.
131
+ *
132
+ * Enter sequence:
133
+ * 1. Mount with `data-closed` + `data-enter` (element in hidden state)
134
+ * 2. Next frame: remove `data-closed` (CSS transition triggers)
135
+ * 3. On transitionend: remove `data-enter`
136
+ *
137
+ * Leave sequence:
138
+ * 1. Add `data-closed` + `data-leave` (CSS transition to hidden state)
139
+ * 2. On transitionend: unmount
140
+ */
141
+ function useTransition(show) {
142
+ const nodeRef = useRef(null);
143
+ const [, setTick] = useState(0);
144
+ const rerender = useCallback(() => setTick((t) => t + 1), []);
145
+ const phase = useRef(show ? "visible" : "hidden");
146
+ const prevShow = useRef(show);
147
+ const cleanupRef = useRef(null);
148
+ useEffect(() => {
149
+ cleanupRef.current?.();
150
+ cleanupRef.current = null;
151
+ if (show && !prevShow.current) {
152
+ phase.current = "enter-from";
153
+ rerender();
154
+ const frame1 = requestAnimationFrame(() => {
155
+ const frame2 = requestAnimationFrame(() => {
156
+ if (phase.current !== "enter-from") return;
157
+ phase.current = "enter-to";
158
+ rerender();
159
+ const node = nodeRef.current;
160
+ if (!node) {
161
+ phase.current = "visible";
162
+ rerender();
163
+ return;
164
+ }
165
+ let cleaned = false;
166
+ const done = () => {
167
+ if (cleaned) return;
168
+ cleaned = true;
169
+ phase.current = "visible";
170
+ rerender();
171
+ };
172
+ node.addEventListener("transitionend", done, { once: true });
173
+ const fallback = setTimeout(done, 500);
174
+ cleanupRef.current = () => {
175
+ cleaned = true;
176
+ node.removeEventListener("transitionend", done);
177
+ clearTimeout(fallback);
178
+ };
179
+ });
180
+ cleanupRef.current = () => cancelAnimationFrame(frame2);
181
+ });
182
+ cleanupRef.current = () => cancelAnimationFrame(frame1);
183
+ } else if (!show && prevShow.current) {
184
+ phase.current = "leave";
185
+ rerender();
186
+ const node = nodeRef.current;
187
+ if (!node) {
188
+ phase.current = "hidden";
189
+ rerender();
190
+ prevShow.current = show;
191
+ return;
192
+ }
193
+ let cleaned = false;
194
+ const done = () => {
195
+ if (cleaned) return;
196
+ cleaned = true;
197
+ phase.current = "hidden";
198
+ rerender();
199
+ };
200
+ node.addEventListener("transitionend", done, { once: true });
201
+ const fallback = setTimeout(done, 500);
202
+ cleanupRef.current = () => {
203
+ cleaned = true;
204
+ node.removeEventListener("transitionend", done);
205
+ clearTimeout(fallback);
206
+ };
207
+ }
208
+ prevShow.current = show;
209
+ }, [show, rerender]);
210
+ useEffect(() => {
211
+ return () => {
212
+ cleanupRef.current?.();
213
+ };
214
+ }, []);
215
+ const p = phase.current;
216
+ return {
217
+ mounted: p !== "hidden",
218
+ nodeRef,
219
+ transitionProps: {
220
+ "data-closed": p === "enter-from" || p === "leave" || p === "hidden" ? "" : void 0,
221
+ "data-enter": p === "enter-from" || p === "enter-to" ? "" : void 0,
222
+ "data-leave": p === "leave" ? "" : void 0,
223
+ "data-transition": p === "enter-from" || p === "enter-to" || p === "leave" ? "" : void 0
224
+ }
225
+ };
226
+ }
227
+ //#endregion
228
+ //#region src/hooks/use-data-interactive.ts
229
+ function useDataInteractive({ disabled = false } = {}) {
230
+ const [hover, setHover] = useState(false);
231
+ const [focus, setFocus] = useState(false);
232
+ const [active, setActive] = useState(false);
233
+ const onPointerEnter = useCallback(() => {
234
+ if (!disabled) setHover(true);
235
+ }, [disabled]);
236
+ const onPointerLeave = useCallback(() => {
237
+ setHover(false);
238
+ setActive(false);
239
+ }, []);
240
+ const onPointerDown = useCallback(() => {
241
+ if (!disabled) setActive(true);
242
+ }, [disabled]);
243
+ const onPointerUp = useCallback(() => {
244
+ setActive(false);
245
+ }, []);
246
+ const onFocus = useCallback((e) => {
247
+ if (!disabled && e.currentTarget.matches(":focus-visible")) setFocus(true);
248
+ }, [disabled]);
249
+ const onBlur = useCallback(() => {
250
+ setFocus(false);
251
+ }, []);
252
+ return {
253
+ "data-hover": hover ? "" : void 0,
254
+ "data-focus": focus ? "" : void 0,
255
+ "data-active": active ? "" : void 0,
256
+ "data-disabled": disabled ? "" : void 0,
257
+ onPointerEnter,
258
+ onPointerLeave,
259
+ onPointerDown,
260
+ onPointerUp,
261
+ onFocus,
262
+ onBlur
263
+ };
264
+ }
265
+ //#endregion
266
+ //#region src/components/link.tsx
267
+ function Link({ ref, ...props }) {
268
+ const interactiveProps = useDataInteractive();
269
+ return /* @__PURE__ */ jsx("a", {
270
+ ...props,
271
+ ...interactiveProps,
272
+ ref
273
+ });
274
+ }
275
+ //#endregion
276
+ //#region src/components/text.tsx
277
+ function Text({ className, ...props }) {
278
+ return /* @__PURE__ */ jsx("p", {
279
+ "data-slot": "text",
280
+ ...props,
281
+ className: cn(className, "text-base/6 text-zinc-500 sm:text-sm/6 dark:text-zinc-400")
282
+ });
283
+ }
284
+ function TextLink({ className, ...props }) {
285
+ return /* @__PURE__ */ jsx(Link, {
286
+ ...props,
287
+ className: cn(className, "text-zinc-950 underline decoration-zinc-950/50 data-hover:decoration-zinc-950 dark:text-white dark:decoration-white/50 dark:data-hover:decoration-white")
288
+ });
289
+ }
290
+ function Strong({ className, ...props }) {
291
+ return /* @__PURE__ */ jsx("strong", {
292
+ ...props,
293
+ className: cn(className, "font-medium text-zinc-950 dark:text-white")
294
+ });
295
+ }
296
+ function Code({ className, ...props }) {
297
+ return /* @__PURE__ */ jsx("code", {
298
+ ...props,
299
+ className: cn(className, "rounded-sm border border-zinc-950/10 bg-zinc-950/2.5 px-0.5 text-sm font-medium text-zinc-950 sm:text-[0.8125rem] dark:border-white/20 dark:bg-white/5 dark:text-white")
300
+ });
301
+ }
302
+ //#endregion
303
+ //#region src/components/alert.tsx
304
+ var sizes$1 = {
305
+ xs: "sm:max-w-xs",
306
+ sm: "sm:max-w-sm",
307
+ md: "sm:max-w-md",
308
+ lg: "sm:max-w-lg",
309
+ xl: "sm:max-w-xl",
310
+ "2xl": "sm:max-w-2xl",
311
+ "3xl": "sm:max-w-3xl",
312
+ "4xl": "sm:max-w-4xl",
313
+ "5xl": "sm:max-w-5xl"
314
+ };
315
+ function Alert({ size = "md", className, children, open, onClose }) {
316
+ const panelRef = useRef(null);
317
+ const titleId = useId();
318
+ const backdrop = useTransition(open);
319
+ const panel = useTransition(open);
320
+ useScrollLock(open);
321
+ useFocusTrap(panelRef, open);
322
+ useEscapeKey(onClose, open);
323
+ if (!(backdrop.mounted || panel.mounted)) return null;
324
+ return createPortal(/* @__PURE__ */ jsxs("div", {
325
+ role: "alertdialog",
326
+ "aria-modal": "true",
327
+ "aria-labelledby": titleId,
328
+ children: [backdrop.mounted && /* @__PURE__ */ jsx("button", {
329
+ type: "button",
330
+ "aria-label": "Close alert",
331
+ ref: backdrop.nodeRef,
332
+ ...backdrop.transitionProps,
333
+ onClick: onClose,
334
+ className: "fixed inset-0 flex w-screen justify-center overflow-y-auto bg-zinc-950/15 px-2 py-2 transition duration-100 focus:outline-0 data-closed:opacity-0 data-enter:ease-out data-leave:ease-in sm:px-6 sm:py-8 lg:px-8 lg:py-16 dark:bg-zinc-950/50"
335
+ }), panel.mounted && /* @__PURE__ */ jsx("div", {
336
+ className: "fixed inset-0 w-screen overflow-y-auto pt-6 sm:pt-0",
337
+ children: /* @__PURE__ */ jsx("div", {
338
+ className: "grid min-h-full grid-rows-[1fr_auto_1fr] justify-items-center p-8 sm:grid-rows-[1fr_auto_3fr] sm:p-4",
339
+ children: /* @__PURE__ */ jsx("div", {
340
+ ref: (node) => {
341
+ panelRef.current = node;
342
+ panel.nodeRef.current = node;
343
+ },
344
+ ...panel.transitionProps,
345
+ className: cn(className, sizes$1[size], "row-start-2 w-full rounded-2xl bg-white p-8 shadow-lg ring-1 ring-zinc-950/10 sm:rounded-2xl sm:p-6 dark:bg-zinc-900 dark:ring-white/10 forced-colors:outline", "transition duration-100 will-change-transform data-closed:opacity-0 data-enter:ease-out data-closed:data-enter:scale-95 data-leave:ease-in"),
346
+ children
347
+ })
348
+ })
349
+ })]
350
+ }), document.body);
351
+ }
352
+ function AlertTitle({ className, ...props }) {
353
+ return /* @__PURE__ */ jsx("h2", {
354
+ ...props,
355
+ className: cn(className, "text-center text-base/6 font-semibold text-balance text-zinc-950 sm:text-left sm:text-sm/6 sm:text-wrap dark:text-white")
356
+ });
357
+ }
358
+ function AlertDescription({ className, ...props }) {
359
+ return /* @__PURE__ */ jsx(Text, {
360
+ ...props,
361
+ className: cn(className, "mt-2 text-center text-pretty sm:text-left")
362
+ });
363
+ }
364
+ function AlertBody({ className, ...props }) {
365
+ return /* @__PURE__ */ jsx("div", {
366
+ ...props,
367
+ className: cn(className, "mt-4")
368
+ });
369
+ }
370
+ function AlertActions({ className, ...props }) {
371
+ return /* @__PURE__ */ jsx("div", {
372
+ ...props,
373
+ className: cn(className, "mt-6 flex flex-col-reverse items-center justify-end gap-3 *:w-full sm:mt-4 sm:flex-row sm:*:w-auto")
374
+ });
375
+ }
376
+ //#endregion
377
+ //#region src/components/button-headless.tsx
378
+ var styles = {
379
+ base: [
380
+ "relative isolate inline-flex items-baseline justify-center gap-x-2 rounded-lg border text-base/6 font-semibold",
381
+ "px-[calc(--spacing(3.5)-1px)] py-[calc(--spacing(2.5)-1px)] sm:px-[calc(--spacing(3)-1px)] sm:py-[calc(--spacing(1.5)-1px)] sm:text-sm/6",
382
+ "focus:not-data-focus:outline-hidden data-focus:outline-2 data-focus:outline-offset-2 data-focus:outline-blue-500",
383
+ "data-disabled:opacity-50",
384
+ "*:data-[slot=icon]:-mx-0.5 *:data-[slot=icon]:my-0.5 *:data-[slot=icon]:size-5 *:data-[slot=icon]:shrink-0 *:data-[slot=icon]:self-center *:data-[slot=icon]:text-(--btn-icon) sm:*:data-[slot=icon]:my-1 sm:*:data-[slot=icon]:size-4 forced-colors:[--btn-icon:ButtonText] forced-colors:data-hover:[--btn-icon:ButtonText]"
385
+ ],
386
+ solid: [
387
+ "border-transparent bg-(--btn-border)",
388
+ "dark:bg-(--btn-bg)",
389
+ "before:absolute before:inset-0 before:-z-10 before:rounded-[calc(var(--radius-lg)-1px)] before:bg-(--btn-bg)",
390
+ "before:shadow-sm",
391
+ "dark:before:hidden",
392
+ "dark:border-white/5",
393
+ "after:absolute after:inset-0 after:-z-10 after:rounded-[calc(var(--radius-lg)-1px)]",
394
+ "after:shadow-[inset_0_1px_--theme(--color-white/15%)]",
395
+ "data-active:after:bg-(--btn-hover-overlay) data-hover:after:bg-(--btn-hover-overlay)",
396
+ "dark:after:-inset-px dark:after:rounded-lg",
397
+ "data-disabled:before:shadow-none data-disabled:after:shadow-none"
398
+ ],
399
+ outline: [
400
+ "border-zinc-950/10 text-zinc-950 data-active:bg-zinc-950/2.5 data-hover:bg-zinc-950/2.5",
401
+ "dark:border-white/15 dark:text-white dark:[--btn-bg:transparent] dark:data-active:bg-white/5 dark:data-hover:bg-white/5",
402
+ "[--btn-icon:var(--color-zinc-500)] data-active:[--btn-icon:var(--color-zinc-700)] data-hover:[--btn-icon:var(--color-zinc-700)] dark:data-active:[--btn-icon:var(--color-zinc-400)] dark:data-hover:[--btn-icon:var(--color-zinc-400)]"
403
+ ],
404
+ plain: [
405
+ "border-transparent text-zinc-950 data-active:bg-zinc-950/5 data-hover:bg-zinc-950/5",
406
+ "dark:text-white dark:data-active:bg-white/10 dark:data-hover:bg-white/10",
407
+ "[--btn-icon:var(--color-zinc-500)] data-active:[--btn-icon:var(--color-zinc-700)] data-hover:[--btn-icon:var(--color-zinc-700)] dark:[--btn-icon:var(--color-zinc-500)] dark:data-active:[--btn-icon:var(--color-zinc-400)] dark:data-hover:[--btn-icon:var(--color-zinc-400)]"
408
+ ],
409
+ colors: {
410
+ "dark/zinc": [
411
+ "text-white [--btn-bg:var(--color-zinc-900)] [--btn-border:var(--color-zinc-950)]/90 [--btn-hover-overlay:var(--color-white)]/10",
412
+ "dark:text-white dark:[--btn-bg:var(--color-zinc-600)] dark:[--btn-hover-overlay:var(--color-white)]/5",
413
+ "[--btn-icon:var(--color-zinc-400)] data-active:[--btn-icon:var(--color-zinc-300)] data-hover:[--btn-icon:var(--color-zinc-300)]"
414
+ ],
415
+ light: [
416
+ "text-zinc-950 [--btn-bg:white] [--btn-border:var(--color-zinc-950)]/10 [--btn-hover-overlay:var(--color-zinc-950)]/2.5 data-active:[--btn-border:var(--color-zinc-950)]/15 data-hover:[--btn-border:var(--color-zinc-950)]/15",
417
+ "dark:text-white dark:[--btn-hover-overlay:var(--color-white)]/5 dark:[--btn-bg:var(--color-zinc-800)]",
418
+ "[--btn-icon:var(--color-zinc-500)] data-active:[--btn-icon:var(--color-zinc-700)] data-hover:[--btn-icon:var(--color-zinc-700)] dark:[--btn-icon:var(--color-zinc-500)] dark:data-active:[--btn-icon:var(--color-zinc-400)] dark:data-hover:[--btn-icon:var(--color-zinc-400)]"
419
+ ],
420
+ "dark/white": [
421
+ "text-white [--btn-bg:var(--color-zinc-900)] [--btn-border:var(--color-zinc-950)]/90 [--btn-hover-overlay:var(--color-white)]/10",
422
+ "dark:text-zinc-950 dark:[--btn-bg:white] dark:[--btn-hover-overlay:var(--color-zinc-950)]/5",
423
+ "[--btn-icon:var(--color-zinc-400)] data-active:[--btn-icon:var(--color-zinc-300)] data-hover:[--btn-icon:var(--color-zinc-300)] dark:[--btn-icon:var(--color-zinc-500)] dark:data-active:[--btn-icon:var(--color-zinc-400)] dark:data-hover:[--btn-icon:var(--color-zinc-400)]"
424
+ ],
425
+ dark: [
426
+ "text-white [--btn-bg:var(--color-zinc-900)] [--btn-border:var(--color-zinc-950)]/90 [--btn-hover-overlay:var(--color-white)]/10",
427
+ "dark:[--btn-hover-overlay:var(--color-white)]/5 dark:[--btn-bg:var(--color-zinc-800)]",
428
+ "[--btn-icon:var(--color-zinc-400)] data-active:[--btn-icon:var(--color-zinc-300)] data-hover:[--btn-icon:var(--color-zinc-300)]"
429
+ ],
430
+ white: [
431
+ "text-zinc-950 [--btn-bg:white] [--btn-border:var(--color-zinc-950)]/10 [--btn-hover-overlay:var(--color-zinc-950)]/2.5 data-active:[--btn-border:var(--color-zinc-950)]/15 data-hover:[--btn-border:var(--color-zinc-950)]/15",
432
+ "dark:[--btn-hover-overlay:var(--color-zinc-950)]/5",
433
+ "[--btn-icon:var(--color-zinc-400)] data-active:[--btn-icon:var(--color-zinc-500)] data-hover:[--btn-icon:var(--color-zinc-500)]"
434
+ ],
435
+ zinc: [
436
+ "text-white [--btn-hover-overlay:var(--color-white)]/10 [--btn-bg:var(--color-zinc-600)] [--btn-border:var(--color-zinc-700)]/90",
437
+ "dark:[--btn-hover-overlay:var(--color-white)]/5",
438
+ "[--btn-icon:var(--color-zinc-400)] data-active:[--btn-icon:var(--color-zinc-300)] data-hover:[--btn-icon:var(--color-zinc-300)]"
439
+ ],
440
+ indigo: ["text-white [--btn-hover-overlay:var(--color-white)]/10 [--btn-bg:var(--color-indigo-500)] [--btn-border:var(--color-indigo-600)]/90", "[--btn-icon:var(--color-indigo-300)] data-active:[--btn-icon:var(--color-indigo-200)] data-hover:[--btn-icon:var(--color-indigo-200)]"],
441
+ cyan: ["text-cyan-950 [--btn-bg:var(--color-cyan-300)] [--btn-border:var(--color-cyan-400)]/80 [--btn-hover-overlay:var(--color-white)]/25", "[--btn-icon:var(--color-cyan-500)]"],
442
+ red: ["text-white [--btn-hover-overlay:var(--color-white)]/10 [--btn-bg:var(--color-red-600)] [--btn-border:var(--color-red-700)]/90", "[--btn-icon:var(--color-red-300)] data-active:[--btn-icon:var(--color-red-200)] data-hover:[--btn-icon:var(--color-red-200)]"],
443
+ orange: ["text-white [--btn-hover-overlay:var(--color-white)]/10 [--btn-bg:var(--color-orange-500)] [--btn-border:var(--color-orange-600)]/90", "[--btn-icon:var(--color-orange-300)] data-active:[--btn-icon:var(--color-orange-200)] data-hover:[--btn-icon:var(--color-orange-200)]"],
444
+ amber: ["text-amber-950 [--btn-hover-overlay:var(--color-white)]/25 [--btn-bg:var(--color-amber-400)] [--btn-border:var(--color-amber-500)]/80", "[--btn-icon:var(--color-amber-600)]"],
445
+ yellow: ["text-yellow-950 [--btn-hover-overlay:var(--color-white)]/25 [--btn-bg:var(--color-yellow-300)] [--btn-border:var(--color-yellow-400)]/80", "[--btn-icon:var(--color-yellow-600)] data-active:[--btn-icon:var(--color-yellow-700)] data-hover:[--btn-icon:var(--color-yellow-700)]"],
446
+ lime: ["text-lime-950 [--btn-hover-overlay:var(--color-white)]/25 [--btn-bg:var(--color-lime-300)] [--btn-border:var(--color-lime-400)]/80", "[--btn-icon:var(--color-lime-600)] data-active:[--btn-icon:var(--color-lime-700)] data-hover:[--btn-icon:var(--color-lime-700)]"],
447
+ green: ["text-white [--btn-hover-overlay:var(--color-white)]/10 [--btn-bg:var(--color-green-600)] [--btn-border:var(--color-green-700)]/90", "[--btn-icon:var(--color-white)]/60 data-active:[--btn-icon:var(--color-white)]/80 data-hover:[--btn-icon:var(--color-white)]/80"],
448
+ emerald: ["text-white [--btn-hover-overlay:var(--color-white)]/10 [--btn-bg:var(--color-emerald-600)] [--btn-border:var(--color-emerald-700)]/90", "[--btn-icon:var(--color-white)]/60 data-active:[--btn-icon:var(--color-white)]/80 data-hover:[--btn-icon:var(--color-white)]/80"],
449
+ teal: ["text-white [--btn-hover-overlay:var(--color-white)]/10 [--btn-bg:var(--color-teal-600)] [--btn-border:var(--color-teal-700)]/90", "[--btn-icon:var(--color-white)]/60 data-active:[--btn-icon:var(--color-white)]/80 data-hover:[--btn-icon:var(--color-white)]/80"],
450
+ sky: ["text-white [--btn-hover-overlay:var(--color-white)]/10 [--btn-bg:var(--color-sky-500)] [--btn-border:var(--color-sky-600)]/80", "[--btn-icon:var(--color-white)]/60 data-active:[--btn-icon:var(--color-white)]/80 data-hover:[--btn-icon:var(--color-white)]/80"],
451
+ blue: ["text-white [--btn-hover-overlay:var(--color-white)]/10 [--btn-bg:var(--color-blue-600)] [--btn-border:var(--color-blue-700)]/90", "[--btn-icon:var(--color-blue-400)] data-active:[--btn-icon:var(--color-blue-300)] data-hover:[--btn-icon:var(--color-blue-300)]"],
452
+ violet: ["text-white [--btn-hover-overlay:var(--color-white)]/10 [--btn-bg:var(--color-violet-500)] [--btn-border:var(--color-violet-600)]/90", "[--btn-icon:var(--color-violet-300)] data-active:[--btn-icon:var(--color-violet-200)] data-hover:[--btn-icon:var(--color-violet-200)]"],
453
+ purple: ["text-white [--btn-hover-overlay:var(--color-white)]/10 [--btn-bg:var(--color-purple-500)] [--btn-border:var(--color-purple-600)]/90", "[--btn-icon:var(--color-purple-300)] data-active:[--btn-icon:var(--color-purple-200)] data-hover:[--btn-icon:var(--color-purple-200)]"],
454
+ fuchsia: ["text-white [--btn-hover-overlay:var(--color-white)]/10 [--btn-bg:var(--color-fuchsia-500)] [--btn-border:var(--color-fuchsia-600)]/90", "[--btn-icon:var(--color-fuchsia-300)] data-active:[--btn-icon:var(--color-fuchsia-200)] data-hover:[--btn-icon:var(--color-fuchsia-200)]"],
455
+ pink: ["text-white [--btn-hover-overlay:var(--color-white)]/10 [--btn-bg:var(--color-pink-500)] [--btn-border:var(--color-pink-600)]/90", "[--btn-icon:var(--color-pink-300)] data-active:[--btn-icon:var(--color-pink-200)] data-hover:[--btn-icon:var(--color-pink-200)]"],
456
+ rose: ["text-white [--btn-hover-overlay:var(--color-white)]/10 [--btn-bg:var(--color-rose-500)] [--btn-border:var(--color-rose-600)]/90", "[--btn-icon:var(--color-rose-300)] data-active:[--btn-icon:var(--color-rose-200)] data-hover:[--btn-icon:var(--color-rose-200)]"]
457
+ }
458
+ };
459
+ function Button({ color, outline, plain, className, children, ref, ...props }) {
460
+ const interactiveProps = useDataInteractive({ disabled: ("disabled" in props ? props.disabled : false) ?? false });
461
+ const classes = cn(className, styles.base, outline ? styles.outline : plain ? styles.plain : cn(styles.solid, styles.colors[color ?? "dark/zinc"]));
462
+ return typeof props.href === "string" ? /* @__PURE__ */ jsx(Link, {
463
+ ...props,
464
+ className: classes,
465
+ ref,
466
+ children: /* @__PURE__ */ jsx(TouchTarget, { children })
467
+ }) : /* @__PURE__ */ jsx("button", {
468
+ type: "button",
469
+ ...props,
470
+ ...interactiveProps,
471
+ className: cn(classes, "cursor-default"),
472
+ ref,
473
+ children: /* @__PURE__ */ jsx(TouchTarget, { children })
474
+ });
475
+ }
476
+ /**
477
+ * Expand the hit area to at least 44x44px on touch devices
478
+ */
479
+ function TouchTarget({ children }) {
480
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
481
+ className: "absolute top-1/2 left-1/2 size-[max(100%,2.75rem)] -translate-x-1/2 -translate-y-1/2 pointer-fine:hidden",
482
+ "aria-hidden": "true"
483
+ }), children] });
484
+ }
485
+ //#endregion
486
+ //#region src/components/avatar.tsx
487
+ function Avatar({ src = null, square = false, initials, alt = "", className, ...props }) {
488
+ const title = alt && alt.trim().length > 0 ? alt.trim() : "Avatar";
489
+ return /* @__PURE__ */ jsxs("span", {
490
+ "data-slot": "avatar",
491
+ ...props,
492
+ className: cn(className, "inline-grid shrink-0 align-middle [--avatar-radius:20%] *:col-start-1 *:row-start-1", "outline -outline-offset-1 outline-black/10 dark:outline-white/10", square ? "rounded-(--avatar-radius) *:rounded-(--avatar-radius)" : "rounded-full *:rounded-full"),
493
+ children: [initials && /* @__PURE__ */ jsxs("svg", {
494
+ className: "size-full fill-current p-[5%] text-[48px] font-medium uppercase select-none",
495
+ viewBox: "0 0 100 100",
496
+ "aria-hidden": alt && alt.trim().length > 0 ? void 0 : "true",
497
+ children: [/* @__PURE__ */ jsx("title", { children: title }), /* @__PURE__ */ jsx("text", {
498
+ x: "50%",
499
+ y: "50%",
500
+ alignmentBaseline: "middle",
501
+ dominantBaseline: "middle",
502
+ textAnchor: "middle",
503
+ dy: ".125em",
504
+ children: initials
505
+ })]
506
+ }), src && /* @__PURE__ */ jsx("img", {
507
+ className: "size-full",
508
+ src,
509
+ alt
510
+ })]
511
+ });
512
+ }
513
+ function AvatarButton({ src, square = false, initials, alt, className, ref, ...props }) {
514
+ const interactiveProps = useDataInteractive({ disabled: ("disabled" in props ? props.disabled : false) ?? false });
515
+ const classes = cn(className, square ? "rounded-[20%]" : "rounded-full", "relative inline-grid focus:not-data-focus:outline-hidden data-focus:outline-2 data-focus:outline-offset-2 data-focus:outline-blue-500");
516
+ return typeof props.href === "string" ? /* @__PURE__ */ jsx(Link, {
517
+ ...props,
518
+ className: classes,
519
+ ref,
520
+ children: /* @__PURE__ */ jsx(TouchTarget, { children: /* @__PURE__ */ jsx(Avatar, {
521
+ src,
522
+ square,
523
+ initials,
524
+ alt
525
+ }) })
526
+ }) : /* @__PURE__ */ jsx("button", {
527
+ type: "button",
528
+ ...props,
529
+ ...interactiveProps,
530
+ className: classes,
531
+ ref,
532
+ children: /* @__PURE__ */ jsx(TouchTarget, { children: /* @__PURE__ */ jsx(Avatar, {
533
+ src,
534
+ square,
535
+ initials,
536
+ alt
537
+ }) })
538
+ });
539
+ }
540
+ //#endregion
541
+ //#region src/components/avatar-group.tsx
542
+ function AvatarGroup({ items, max = 5, size = "md", className }) {
543
+ const sizeClasses = {
544
+ xs: "size-6",
545
+ sm: "size-8",
546
+ md: "size-10",
547
+ lg: "size-12"
548
+ };
549
+ const overlapClass = {
550
+ xs: "-ml-1.5",
551
+ sm: "-ml-2",
552
+ md: "-ml-3",
553
+ lg: "-ml-4"
554
+ };
555
+ const visible = items.slice(0, max);
556
+ const overflow = items.length - max;
557
+ return /* @__PURE__ */ jsxs("div", {
558
+ className: cn("flex items-center", className),
559
+ children: [visible.map((item, i) => {
560
+ return /* @__PURE__ */ jsx("div", {
561
+ className: cn("ring-2 ring-white dark:ring-zinc-900", sizeClasses[size], i > 0 && overlapClass[size], "rounded-full"),
562
+ children: /* @__PURE__ */ jsx(Avatar, {
563
+ src: item.src,
564
+ initials: item.initials,
565
+ alt: item.alt ?? "",
566
+ className: "size-full"
567
+ })
568
+ }, i);
569
+ }), overflow > 0 && /* @__PURE__ */ jsxs("div", {
570
+ className: cn(overlapClass[size], sizeClasses[size], "flex items-center justify-center rounded-full bg-zinc-200 text-xs font-medium text-zinc-600 ring-2 ring-white dark:bg-zinc-700 dark:text-zinc-300 dark:ring-zinc-900"),
571
+ role: "img",
572
+ "aria-label": `${overflow} more`,
573
+ children: ["+", overflow]
574
+ })]
575
+ });
576
+ }
577
+ //#endregion
578
+ //#region src/components/badge.tsx
579
+ var colors$2 = {
580
+ red: "bg-red-500/15 text-red-700 group-data-hover:bg-red-500/25 dark:bg-red-500/10 dark:text-red-400 dark:group-data-hover:bg-red-500/20",
581
+ orange: "bg-orange-500/15 text-orange-700 group-data-hover:bg-orange-500/25 dark:bg-orange-500/10 dark:text-orange-400 dark:group-data-hover:bg-orange-500/20",
582
+ amber: "bg-amber-400/20 text-amber-700 group-data-hover:bg-amber-400/30 dark:bg-amber-400/10 dark:text-amber-400 dark:group-data-hover:bg-amber-400/15",
583
+ yellow: "bg-yellow-400/20 text-yellow-700 group-data-hover:bg-yellow-400/30 dark:bg-yellow-400/10 dark:text-yellow-300 dark:group-data-hover:bg-yellow-400/15",
584
+ lime: "bg-lime-400/20 text-lime-700 group-data-hover:bg-lime-400/30 dark:bg-lime-400/10 dark:text-lime-300 dark:group-data-hover:bg-lime-400/15",
585
+ green: "bg-green-500/15 text-green-700 group-data-hover:bg-green-500/25 dark:bg-green-500/10 dark:text-green-400 dark:group-data-hover:bg-green-500/20",
586
+ emerald: "bg-emerald-500/15 text-emerald-700 group-data-hover:bg-emerald-500/25 dark:bg-emerald-500/10 dark:text-emerald-400 dark:group-data-hover:bg-emerald-500/20",
587
+ teal: "bg-teal-500/15 text-teal-700 group-data-hover:bg-teal-500/25 dark:bg-teal-500/10 dark:text-teal-300 dark:group-data-hover:bg-teal-500/20",
588
+ cyan: "bg-cyan-400/20 text-cyan-700 group-data-hover:bg-cyan-400/30 dark:bg-cyan-400/10 dark:text-cyan-300 dark:group-data-hover:bg-cyan-400/15",
589
+ sky: "bg-sky-500/15 text-sky-700 group-data-hover:bg-sky-500/25 dark:bg-sky-500/10 dark:text-sky-300 dark:group-data-hover:bg-sky-500/20",
590
+ blue: "bg-blue-500/15 text-blue-700 group-data-hover:bg-blue-500/25 dark:text-blue-400 dark:group-data-hover:bg-blue-500/25",
591
+ indigo: "bg-indigo-500/15 text-indigo-700 group-data-hover:bg-indigo-500/25 dark:text-indigo-400 dark:group-data-hover:bg-indigo-500/20",
592
+ violet: "bg-violet-500/15 text-violet-700 group-data-hover:bg-violet-500/25 dark:text-violet-400 dark:group-data-hover:bg-violet-500/20",
593
+ purple: "bg-purple-500/15 text-purple-700 group-data-hover:bg-purple-500/25 dark:text-purple-400 dark:group-data-hover:bg-purple-500/20",
594
+ fuchsia: "bg-fuchsia-400/15 text-fuchsia-700 group-data-hover:bg-fuchsia-400/25 dark:bg-fuchsia-400/10 dark:text-fuchsia-400 dark:group-data-hover:bg-fuchsia-400/20",
595
+ pink: "bg-pink-400/15 text-pink-700 group-data-hover:bg-pink-400/25 dark:bg-pink-400/10 dark:text-pink-400 dark:group-data-hover:bg-pink-400/20",
596
+ rose: "bg-rose-400/15 text-rose-700 group-data-hover:bg-rose-400/25 dark:bg-rose-400/10 dark:text-rose-400 dark:group-data-hover:bg-rose-400/20",
597
+ zinc: "bg-zinc-600/10 text-zinc-700 group-data-hover:bg-zinc-600/20 dark:bg-white/5 dark:text-zinc-400 dark:group-data-hover:bg-white/10"
598
+ };
599
+ function Badge({ color = "zinc", className, ...props }) {
600
+ return /* @__PURE__ */ jsx("span", {
601
+ ...props,
602
+ className: cn(className, "inline-flex items-center gap-x-1.5 rounded-md px-1.5 py-0.5 text-sm/5 font-medium sm:text-xs/5 forced-colors:outline", colors$2[color]),
603
+ style: {
604
+ borderRadius: "var(--rvui-radius-full, 9999px)",
605
+ transition: "background-color var(--rvui-duration-fast, 120ms) var(--rvui-ease, cubic-bezier(0.22, 1, 0.36, 1))"
606
+ }
607
+ });
608
+ }
609
+ function BadgeButton({ color = "zinc", className, children, ref, ...props }) {
610
+ const interactiveProps = useDataInteractive({ disabled: ("disabled" in props ? props.disabled : false) ?? false });
611
+ const classes = cn(className, "group relative inline-flex rounded-md focus:not-data-focus:outline-hidden data-focus:outline-2 data-focus:outline-offset-2 data-focus:outline-blue-500");
612
+ return typeof props.href === "string" ? /* @__PURE__ */ jsx(Link, {
613
+ ...props,
614
+ className: classes,
615
+ ref,
616
+ children: /* @__PURE__ */ jsx(TouchTarget, { children: /* @__PURE__ */ jsx(Badge, {
617
+ color,
618
+ children
619
+ }) })
620
+ }) : /* @__PURE__ */ jsx("button", {
621
+ type: "button",
622
+ ...props,
623
+ ...interactiveProps,
624
+ className: classes,
625
+ ref,
626
+ children: /* @__PURE__ */ jsx(TouchTarget, { children: /* @__PURE__ */ jsx(Badge, {
627
+ color,
628
+ children
629
+ }) })
630
+ });
631
+ }
632
+ //#endregion
633
+ //#region src/components/Checkbox.tsx
634
+ var CheckboxContext = React.createContext(null);
635
+ function Checkbox$1({ checked, defaultChecked, disabled, onCheckedChange, className, ref, ...props }) {
636
+ const [internalChecked, setInternalChecked] = React.useState(defaultChecked ?? false);
637
+ const handleChange = (e) => {
638
+ if (disabled) return;
639
+ const newChecked = e.target.checked;
640
+ setInternalChecked(newChecked);
641
+ onCheckedChange?.(newChecked);
642
+ };
643
+ React.useEffect(() => {
644
+ if (checked !== void 0) setInternalChecked(checked);
645
+ }, [checked]);
646
+ return /* @__PURE__ */ jsx(CheckboxContext.Provider, {
647
+ value: {
648
+ state: internalChecked,
649
+ disabled,
650
+ onCheckedChange
651
+ },
652
+ children: /* @__PURE__ */ jsx("input", {
653
+ type: "checkbox",
654
+ disabled,
655
+ checked: checked !== void 0 ? checked : internalChecked === "indeterminate" ? false : internalChecked,
656
+ ref: (el) => {
657
+ if (el) el.indeterminate = internalChecked === "indeterminate";
658
+ if (ref) if (typeof ref === "function") ref(el);
659
+ else ref.current = el;
660
+ },
661
+ onChange: handleChange,
662
+ className: cn("peer h-4 w-4 shrink-0 rounded border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground", className),
663
+ "data-state": internalChecked === "indeterminate" ? "indeterminate" : internalChecked ? "checked" : "unchecked",
664
+ ...props
665
+ })
666
+ });
667
+ }
668
+ function CheckboxIndicator({ className, ref, ...props }) {
669
+ const context = React.use(CheckboxContext);
670
+ if (!context) throw new Error("CheckboxIndicator must be used within a Checkbox");
671
+ return /* @__PURE__ */ jsxs("span", {
672
+ "data-state": context.state === "indeterminate" ? "indeterminate" : context.state ? "checked" : "unchecked",
673
+ ref,
674
+ className: cn("flex items-center justify-center text-current", className),
675
+ ...props,
676
+ children: [context.state === true && "✔", context.state === "indeterminate" && "−"]
677
+ });
678
+ }
679
+ //#endregion
680
+ //#region src/components/callout.tsx
681
+ var variantStyles = {
682
+ info: {
683
+ wrapper: "bg-blue-50 ring-blue-200 dark:bg-blue-950/30 dark:ring-blue-800",
684
+ icon: "text-blue-600 dark:text-blue-400",
685
+ iconChar: "i"
686
+ },
687
+ warning: {
688
+ wrapper: "bg-amber-50 ring-amber-200 dark:bg-amber-950/30 dark:ring-amber-800",
689
+ icon: "text-amber-600 dark:text-amber-400",
690
+ iconChar: "!"
691
+ },
692
+ error: {
693
+ wrapper: "bg-red-50 ring-red-200 dark:bg-red-950/30 dark:ring-red-800",
694
+ icon: "text-red-600 dark:text-red-400",
695
+ iconChar: "✕"
696
+ },
697
+ success: {
698
+ wrapper: "bg-green-50 ring-green-200 dark:bg-green-950/30 dark:ring-green-800",
699
+ icon: "text-green-600 dark:text-green-400",
700
+ iconChar: "✓"
701
+ },
702
+ tip: {
703
+ wrapper: "bg-violet-50 ring-violet-200 dark:bg-violet-950/30 dark:ring-violet-800",
704
+ icon: "text-violet-600 dark:text-violet-400",
705
+ iconChar: "★"
706
+ }
707
+ };
708
+ function Callout({ variant = "info", title, icon, className, children }) {
709
+ const styles = variantStyles[variant];
710
+ return /* @__PURE__ */ jsx("div", {
711
+ role: "note",
712
+ className: cn("rounded-xl p-4 ring-1", styles.wrapper, className),
713
+ children: /* @__PURE__ */ jsxs("div", {
714
+ className: "flex gap-3",
715
+ children: [/* @__PURE__ */ jsx("span", {
716
+ className: cn("mt-0.5 shrink-0 text-sm font-bold", styles.icon),
717
+ "aria-hidden": "true",
718
+ children: icon ?? styles.iconChar
719
+ }), /* @__PURE__ */ jsxs("div", {
720
+ className: "min-w-0 flex-1",
721
+ children: [title && /* @__PURE__ */ jsx("p", {
722
+ className: "text-sm font-semibold text-zinc-950 dark:text-white",
723
+ children: title
724
+ }), /* @__PURE__ */ jsx("div", {
725
+ className: cn("text-sm text-zinc-700 dark:text-zinc-300", title && "mt-1"),
726
+ children
727
+ })]
728
+ })]
729
+ })
730
+ });
731
+ }
732
+ //#endregion
733
+ //#region src/hooks/use-field-context.tsx
734
+ var FieldContext = createContext(null);
735
+ function useFieldContext() {
736
+ return use(FieldContext);
737
+ }
738
+ function FieldProvider({ children, disabled = false }) {
739
+ const id = useId();
740
+ return /* @__PURE__ */ jsx(FieldContext, {
741
+ value: useMemo(() => ({
742
+ controlId: `${id}-control`,
743
+ labelId: `${id}-label`,
744
+ descriptionId: `${id}-description`,
745
+ errorId: `${id}-error`,
746
+ disabled
747
+ }), [id, disabled]),
748
+ children
749
+ });
750
+ }
751
+ /**
752
+ * Returns ARIA props for a form control that participates in a Field.
753
+ * Safe to call outside a Field — returns empty object if no context.
754
+ */
755
+ function useFieldControlProps() {
756
+ const ctx = useFieldContext();
757
+ if (!ctx) return {};
758
+ return {
759
+ id: ctx.controlId,
760
+ "aria-labelledby": ctx.labelId,
761
+ "aria-describedby": ctx.descriptionId,
762
+ "data-disabled": ctx.disabled ? "" : void 0
763
+ };
764
+ }
765
+ /**
766
+ * Returns props for a label element within a Field.
767
+ */
768
+ function useFieldLabelProps() {
769
+ const ctx = useFieldContext();
770
+ if (!ctx) return {};
771
+ return {
772
+ id: ctx.labelId,
773
+ htmlFor: ctx.controlId,
774
+ "data-disabled": ctx.disabled ? "" : void 0
775
+ };
776
+ }
777
+ /**
778
+ * Returns props for a description element within a Field.
779
+ */
780
+ function useFieldDescriptionProps() {
781
+ const ctx = useFieldContext();
782
+ if (!ctx) return {};
783
+ return {
784
+ id: ctx.descriptionId,
785
+ "data-disabled": ctx.disabled ? "" : void 0
786
+ };
787
+ }
788
+ /**
789
+ * Returns props for an error message element within a Field.
790
+ */
791
+ function useFieldErrorProps() {
792
+ const ctx = useFieldContext();
793
+ if (!ctx) return {};
794
+ return {
795
+ id: ctx.errorId,
796
+ "data-disabled": ctx.disabled ? "" : void 0
797
+ };
798
+ }
799
+ //#endregion
800
+ //#region src/hooks/use-controllable-state.ts
801
+ function useControllableState({ value: controlledValue, defaultValue, onChange }) {
802
+ const isControlled = controlledValue !== void 0;
803
+ const [internalValue, setInternalValue] = useState(defaultValue);
804
+ const value = isControlled ? controlledValue : internalValue;
805
+ const onChangeRef = useRef(onChange);
806
+ onChangeRef.current = onChange;
807
+ return [value, useCallback((next) => {
808
+ const resolvedValue = typeof next === "function" ? next(value) : next;
809
+ if (!isControlled) setInternalValue(resolvedValue);
810
+ onChangeRef.current?.(resolvedValue);
811
+ }, [isControlled, value])];
812
+ }
813
+ //#endregion
814
+ //#region src/hooks/use-toggle.ts
815
+ function useToggle({ checked: controlledChecked, defaultChecked = false, onChange, disabled = false } = {}) {
816
+ const [checked, setChecked] = useControllableState({
817
+ value: controlledChecked,
818
+ defaultValue: defaultChecked,
819
+ onChange
820
+ });
821
+ const toggle = useCallback(() => {
822
+ if (!disabled) setChecked((prev) => !prev);
823
+ }, [disabled, setChecked]);
824
+ const onClick = useCallback(() => {
825
+ toggle();
826
+ }, [toggle]);
827
+ const onKeyDown = useCallback((e) => {
828
+ if (e.key === " ") {
829
+ e.preventDefault();
830
+ toggle();
831
+ }
832
+ }, [toggle]);
833
+ return {
834
+ checked,
835
+ toggle,
836
+ toggleProps: {
837
+ "aria-checked": checked,
838
+ "data-checked": checked ? "" : void 0,
839
+ tabIndex: 0,
840
+ onClick,
841
+ onKeyDown
842
+ }
843
+ };
844
+ }
845
+ //#endregion
846
+ //#region src/components/checkbox-headless.tsx
847
+ function CheckboxGroup({ className, ...props }) {
848
+ return /* @__PURE__ */ jsx("div", {
849
+ "data-slot": "control",
850
+ ...props,
851
+ className: cn(className, "space-y-3", "has-data-[slot=description]:space-y-6 has-data-[slot=description]:**:data-[slot=label]:font-medium")
852
+ });
853
+ }
854
+ function CheckboxField({ className, disabled, ...props }) {
855
+ return /* @__PURE__ */ jsx(FieldProvider, {
856
+ disabled,
857
+ children: /* @__PURE__ */ jsx("div", {
858
+ "data-slot": "field",
859
+ "data-disabled": disabled ? "" : void 0,
860
+ ...props,
861
+ className: cn(className, "grid grid-cols-[1.125rem_1fr] gap-x-4 gap-y-1 sm:grid-cols-[1rem_1fr]", "*:data-[slot=control]:col-start-1 *:data-[slot=control]:row-start-1 *:data-[slot=control]:mt-0.75 sm:*:data-[slot=control]:mt-1", "*:data-[slot=label]:col-start-2 *:data-[slot=label]:row-start-1", "*:data-[slot=description]:col-start-2 *:data-[slot=description]:row-start-2", "has-data-[slot=description]:**:data-[slot=label]:font-medium")
862
+ })
863
+ });
864
+ }
865
+ var base$1 = [
866
+ "relative isolate flex size-4.5 items-center justify-center rounded-[0.3125rem] sm:size-4",
867
+ "before:absolute before:inset-0 before:-z-10 before:rounded-[calc(0.3125rem-1px)] before:bg-white before:shadow-sm",
868
+ "group-data-checked:before:bg-(--checkbox-checked-bg)",
869
+ "dark:before:hidden",
870
+ "dark:bg-white/5 dark:group-data-checked:bg-(--checkbox-checked-bg)",
871
+ "border border-zinc-950/15 group-data-checked:border-transparent group-data-hover:group-data-checked:border-transparent group-data-hover:border-zinc-950/30 group-data-checked:bg-(--checkbox-checked-border)",
872
+ "dark:border-white/15 dark:group-data-checked:border-white/5 dark:group-data-hover:group-data-checked:border-white/5 dark:group-data-hover:border-white/30",
873
+ "after:absolute after:inset-0 after:rounded-[calc(0.3125rem-1px)] after:shadow-[inset_0_1px_--theme(--color-white/15%)]",
874
+ "dark:after:-inset-px dark:after:hidden dark:after:rounded-[0.3125rem] dark:group-data-checked:after:block",
875
+ "group-data-focus:outline-2 group-data-focus:outline-offset-2 group-data-focus:outline-blue-500",
876
+ "group-data-disabled:opacity-50",
877
+ "group-data-disabled:border-zinc-950/25 group-data-disabled:bg-zinc-950/5 group-data-disabled:[--checkbox-check:var(--color-zinc-950)]/50 group-data-disabled:before:bg-transparent",
878
+ "dark:group-data-disabled:border-white/20 dark:group-data-disabled:bg-white/2.5 dark:group-data-disabled:[--checkbox-check:var(--color-white)]/50 dark:group-data-checked:group-data-disabled:after:hidden",
879
+ "forced-colors:[--checkbox-check:HighlightText] forced-colors:[--checkbox-checked-bg:Highlight] forced-colors:group-data-disabled:[--checkbox-check:Highlight]",
880
+ "dark:forced-colors:[--checkbox-check:HighlightText] dark:forced-colors:[--checkbox-checked-bg:Highlight] dark:forced-colors:group-data-disabled:[--checkbox-check:Highlight]"
881
+ ];
882
+ var colors$1 = {
883
+ "dark/zinc": ["[--checkbox-check:var(--color-white)] [--checkbox-checked-bg:var(--color-zinc-900)] [--checkbox-checked-border:var(--color-zinc-950)]/90", "dark:[--checkbox-checked-bg:var(--color-zinc-600)]"],
884
+ "dark/white": ["[--checkbox-check:var(--color-white)] [--checkbox-checked-bg:var(--color-zinc-900)] [--checkbox-checked-border:var(--color-zinc-950)]/90", "dark:[--checkbox-check:var(--color-zinc-900)] dark:[--checkbox-checked-bg:var(--color-white)] dark:[--checkbox-checked-border:var(--color-zinc-950)]/15"],
885
+ white: "[--checkbox-check:var(--color-zinc-900)] [--checkbox-checked-bg:var(--color-white)] [--checkbox-checked-border:var(--color-zinc-950)]/15",
886
+ dark: "[--checkbox-check:var(--color-white)] [--checkbox-checked-bg:var(--color-zinc-900)] [--checkbox-checked-border:var(--color-zinc-950)]/90",
887
+ zinc: "[--checkbox-check:var(--color-white)] [--checkbox-checked-bg:var(--color-zinc-600)] [--checkbox-checked-border:var(--color-zinc-700)]/90",
888
+ red: "[--checkbox-check:var(--color-white)] [--checkbox-checked-bg:var(--color-red-600)] [--checkbox-checked-border:var(--color-red-700)]/90",
889
+ orange: "[--checkbox-check:var(--color-white)] [--checkbox-checked-bg:var(--color-orange-500)] [--checkbox-checked-border:var(--color-orange-600)]/90",
890
+ amber: "[--checkbox-check:var(--color-amber-950)] [--checkbox-checked-bg:var(--color-amber-400)] [--checkbox-checked-border:var(--color-amber-500)]/80",
891
+ yellow: "[--checkbox-check:var(--color-yellow-950)] [--checkbox-checked-bg:var(--color-yellow-300)] [--checkbox-checked-border:var(--color-yellow-400)]/80",
892
+ lime: "[--checkbox-check:var(--color-lime-950)] [--checkbox-checked-bg:var(--color-lime-300)] [--checkbox-checked-border:var(--color-lime-400)]/80",
893
+ green: "[--checkbox-check:var(--color-white)] [--checkbox-checked-bg:var(--color-green-600)] [--checkbox-checked-border:var(--color-green-700)]/90",
894
+ emerald: "[--checkbox-check:var(--color-white)] [--checkbox-checked-bg:var(--color-emerald-600)] [--checkbox-checked-border:var(--color-emerald-700)]/90",
895
+ teal: "[--checkbox-check:var(--color-white)] [--checkbox-checked-bg:var(--color-teal-600)] [--checkbox-checked-border:var(--color-teal-700)]/90",
896
+ cyan: "[--checkbox-check:var(--color-cyan-950)] [--checkbox-checked-bg:var(--color-cyan-300)] [--checkbox-checked-border:var(--color-cyan-400)]/80",
897
+ sky: "[--checkbox-check:var(--color-white)] [--checkbox-checked-bg:var(--color-sky-500)] [--checkbox-checked-border:var(--color-sky-600)]/80",
898
+ blue: "[--checkbox-check:var(--color-white)] [--checkbox-checked-bg:var(--color-blue-600)] [--checkbox-checked-border:var(--color-blue-700)]/90",
899
+ indigo: "[--checkbox-check:var(--color-white)] [--checkbox-checked-bg:var(--color-indigo-500)] [--checkbox-checked-border:var(--color-indigo-600)]/90",
900
+ violet: "[--checkbox-check:var(--color-white)] [--checkbox-checked-bg:var(--color-violet-500)] [--checkbox-checked-border:var(--color-violet-600)]/90",
901
+ purple: "[--checkbox-check:var(--color-white)] [--checkbox-checked-bg:var(--color-purple-500)] [--checkbox-checked-border:var(--color-purple-600)]/90",
902
+ fuchsia: "[--checkbox-check:var(--color-white)] [--checkbox-checked-bg:var(--color-fuchsia-500)] [--checkbox-checked-border:var(--color-fuchsia-600)]/90",
903
+ pink: "[--checkbox-check:var(--color-white)] [--checkbox-checked-bg:var(--color-pink-500)] [--checkbox-checked-border:var(--color-pink-600)]/90",
904
+ rose: "[--checkbox-check:var(--color-white)] [--checkbox-checked-bg:var(--color-rose-500)] [--checkbox-checked-border:var(--color-rose-600)]/90"
905
+ };
906
+ function Checkbox({ color = "dark/zinc", className, checked: controlledChecked, defaultChecked, onChange, disabled, indeterminate, name, value, ...props }) {
907
+ const { checked, toggleProps } = useToggle({
908
+ checked: controlledChecked,
909
+ defaultChecked,
910
+ onChange,
911
+ disabled
912
+ });
913
+ const interactiveProps = useDataInteractive({ disabled });
914
+ const handleKeyDown = useCallback((e) => {
915
+ if (e.key === " ") {
916
+ e.preventDefault();
917
+ toggleProps.onKeyDown(e);
918
+ }
919
+ }, [toggleProps]);
920
+ return /* @__PURE__ */ jsxs("span", {
921
+ "data-slot": "control",
922
+ role: "checkbox",
923
+ "aria-checked": indeterminate ? "mixed" : checked,
924
+ "data-checked": checked ? "" : void 0,
925
+ "data-indeterminate": indeterminate ? "" : void 0,
926
+ "data-disabled": disabled ? "" : void 0,
927
+ tabIndex: disabled ? void 0 : 0,
928
+ onClick: disabled ? void 0 : toggleProps.onClick,
929
+ onKeyDown: disabled ? void 0 : handleKeyDown,
930
+ ...interactiveProps,
931
+ ...props,
932
+ className: cn(className, "group inline-flex focus:outline-hidden"),
933
+ children: [name && /* @__PURE__ */ jsx("input", {
934
+ type: "hidden",
935
+ name,
936
+ value: checked ? value ?? "on" : ""
937
+ }), /* @__PURE__ */ jsx("span", {
938
+ className: cn([base$1, colors$1[color]]),
939
+ children: /* @__PURE__ */ jsxs("svg", {
940
+ className: "size-4 stroke-(--checkbox-check) opacity-0 group-data-checked:opacity-100 sm:h-3.5 sm:w-3.5",
941
+ viewBox: "0 0 14 14",
942
+ fill: "none",
943
+ children: [
944
+ /* @__PURE__ */ jsx("title", { children: "Checkmark" }),
945
+ /* @__PURE__ */ jsx("path", {
946
+ className: "opacity-100 group-data-indeterminate:opacity-0",
947
+ d: "M3 8L6 11L11 3.5",
948
+ strokeWidth: 2,
949
+ strokeLinecap: "round",
950
+ strokeLinejoin: "round"
951
+ }),
952
+ /* @__PURE__ */ jsx("path", {
953
+ className: "opacity-0 group-data-indeterminate:opacity-100",
954
+ d: "M3 7H11",
955
+ strokeWidth: 2,
956
+ strokeLinecap: "round",
957
+ strokeLinejoin: "round"
958
+ })
959
+ ]
960
+ })
961
+ })]
962
+ });
963
+ }
964
+ //#endregion
965
+ //#region src/components/code-block.tsx
966
+ function CodeBlock({ code, language, filename, showCopy = true, className }) {
967
+ const [copied, setCopied] = useState(false);
968
+ const handleCopy = useCallback(async () => {
969
+ await navigator.clipboard.writeText(code);
970
+ setCopied(true);
971
+ setTimeout(() => setCopied(false), 2e3);
972
+ }, [code]);
973
+ return /* @__PURE__ */ jsxs("div", {
974
+ className: cn("overflow-hidden rounded-xl bg-zinc-950 ring-1 ring-zinc-800", className),
975
+ children: [(filename || language || showCopy) && /* @__PURE__ */ jsxs("div", {
976
+ className: "flex items-center justify-between border-b border-zinc-800 px-4 py-2.5",
977
+ children: [/* @__PURE__ */ jsxs("div", {
978
+ className: "flex items-center gap-2",
979
+ children: [filename && /* @__PURE__ */ jsx("span", {
980
+ className: "text-xs text-zinc-400",
981
+ children: filename
982
+ }), language && !filename && /* @__PURE__ */ jsx("span", {
983
+ className: "rounded bg-zinc-800 px-1.5 py-0.5 text-xs text-zinc-400",
984
+ children: language
985
+ })]
986
+ }), showCopy && /* @__PURE__ */ jsx("button", {
987
+ type: "button",
988
+ onClick: () => void handleCopy(),
989
+ "aria-label": copied ? "Copied" : "Copy code",
990
+ className: "rounded px-2 py-1 text-xs text-zinc-400 transition-colors hover:bg-zinc-800 hover:text-zinc-200 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-500",
991
+ children: copied ? "Copied!" : "Copy"
992
+ })]
993
+ }), /* @__PURE__ */ jsx("pre", {
994
+ className: "overflow-x-auto p-4 text-sm leading-relaxed text-zinc-300",
995
+ children: /* @__PURE__ */ jsx("code", { children: code })
996
+ })]
997
+ });
998
+ }
999
+ //#endregion
1000
+ //#region src/hooks/use-click-outside.ts
1001
+ function useClickOutside(refs, onClickOutside, enabled = true) {
1002
+ const callbackRef = useRef(onClickOutside);
1003
+ callbackRef.current = onClickOutside;
1004
+ useEffect(() => {
1005
+ if (!enabled) return;
1006
+ function handlePointerDown(e) {
1007
+ const target = e.target;
1008
+ if ((Array.isArray(refs) ? refs : [refs]).every((ref) => !ref.current?.contains(target))) callbackRef.current();
1009
+ }
1010
+ document.addEventListener("pointerdown", handlePointerDown, true);
1011
+ return () => document.removeEventListener("pointerdown", handlePointerDown, true);
1012
+ }, [refs, enabled]);
1013
+ }
1014
+ //#endregion
1015
+ //#region src/hooks/use-popover.ts
1016
+ function computePosition(trigger, popover, anchor, gap, padding) {
1017
+ const triggerRect = trigger.getBoundingClientRect();
1018
+ const popoverRect = popover.getBoundingClientRect();
1019
+ const viewportHeight = window.innerHeight;
1020
+ const viewportWidth = window.innerWidth;
1021
+ let top;
1022
+ let left;
1023
+ let maxHeight;
1024
+ const isTop = anchor.startsWith("top");
1025
+ const spaceBelow = viewportHeight - triggerRect.bottom - gap - padding;
1026
+ const spaceAbove = triggerRect.top - gap - padding;
1027
+ if (anchor === "selection start") {
1028
+ top = triggerRect.top;
1029
+ maxHeight = viewportHeight - top - padding;
1030
+ } else if (isTop) {
1031
+ top = triggerRect.top - popoverRect.height - gap;
1032
+ maxHeight = spaceAbove;
1033
+ if (top < padding && spaceBelow > spaceAbove) {
1034
+ top = triggerRect.bottom + gap;
1035
+ maxHeight = spaceBelow;
1036
+ }
1037
+ } else {
1038
+ top = triggerRect.bottom + gap;
1039
+ maxHeight = spaceBelow;
1040
+ if (top + popoverRect.height > viewportHeight - padding && spaceAbove > spaceBelow) {
1041
+ top = triggerRect.top - popoverRect.height - gap;
1042
+ maxHeight = spaceAbove;
1043
+ }
1044
+ }
1045
+ const isEnd = anchor.endsWith("end");
1046
+ const isStart = anchor.endsWith("start");
1047
+ if (isEnd) left = triggerRect.right - popoverRect.width;
1048
+ else if (isStart || anchor === "selection start") left = triggerRect.left;
1049
+ else left = triggerRect.left + (triggerRect.width - popoverRect.width) / 2;
1050
+ left = Math.max(padding, Math.min(left, viewportWidth - popoverRect.width - padding));
1051
+ top = Math.max(padding, top);
1052
+ return {
1053
+ top,
1054
+ left,
1055
+ maxHeight: Math.max(100, maxHeight)
1056
+ };
1057
+ }
1058
+ function usePopover({ open, anchor = "bottom", gap = 8, padding = 4 }) {
1059
+ const triggerRef = useRef(null);
1060
+ const popoverRef = useRef(null);
1061
+ const [position, setPosition] = useState({
1062
+ top: 0,
1063
+ left: 0,
1064
+ maxHeight: 300
1065
+ });
1066
+ const updatePosition = useCallback(() => {
1067
+ if (!(triggerRef.current && popoverRef.current && open)) return;
1068
+ setPosition(computePosition(triggerRef.current, popoverRef.current, anchor, gap, padding));
1069
+ }, [
1070
+ open,
1071
+ anchor,
1072
+ gap,
1073
+ padding
1074
+ ]);
1075
+ useEffect(() => {
1076
+ if (!open) return;
1077
+ requestAnimationFrame(updatePosition);
1078
+ window.addEventListener("scroll", updatePosition, true);
1079
+ window.addEventListener("resize", updatePosition);
1080
+ return () => {
1081
+ window.removeEventListener("scroll", updatePosition, true);
1082
+ window.removeEventListener("resize", updatePosition);
1083
+ };
1084
+ }, [open, updatePosition]);
1085
+ return {
1086
+ triggerRef,
1087
+ popoverRef,
1088
+ position,
1089
+ popoverProps: { style: {
1090
+ position: "fixed",
1091
+ top: position.top,
1092
+ left: position.left,
1093
+ maxHeight: position.maxHeight,
1094
+ zIndex: 50
1095
+ } }
1096
+ };
1097
+ }
1098
+ //#endregion
1099
+ //#region src/components/combobox.tsx
1100
+ var ComboboxContext = createContext(null);
1101
+ function useComboboxContext() {
1102
+ const ctx = use(ComboboxContext);
1103
+ if (!ctx) throw new Error("Combobox compound components must be used within <Combobox>");
1104
+ return ctx;
1105
+ }
1106
+ function Combobox({ options, displayValue, filter, anchor = "bottom", className, placeholder, autoFocus = false, "aria-label": ariaLabel, children, value: controlledValue, defaultValue, onChange, disabled = false, name }) {
1107
+ const [selectedValue, setSelectedValue] = useControllableState({
1108
+ value: controlledValue,
1109
+ defaultValue: defaultValue ?? null,
1110
+ onChange
1111
+ });
1112
+ const [query, setQuery] = useState("");
1113
+ const [isOpen, setIsOpen] = useState(false);
1114
+ const [activeIndex, setActiveIndex] = useState(-1);
1115
+ const inputRef = useRef(null);
1116
+ const controlRef = useRef(null);
1117
+ const listboxId = useId();
1118
+ const filteredOptions = query === "" ? options : options.filter((option) => filter ? filter(option, query) : displayValue(option)?.toLowerCase().includes(query.toLowerCase()));
1119
+ const { triggerRef, popoverRef, popoverProps } = usePopover({
1120
+ open: isOpen,
1121
+ anchor,
1122
+ gap: 8,
1123
+ padding: 16
1124
+ });
1125
+ useEffect(() => {
1126
+ if (controlRef.current) triggerRef.current = controlRef.current;
1127
+ }, [triggerRef]);
1128
+ useEffect(() => {
1129
+ if (autoFocus && !disabled) inputRef.current?.focus();
1130
+ }, [autoFocus, disabled]);
1131
+ const { mounted, nodeRef: transitionRef, transitionProps } = useTransition(isOpen);
1132
+ useClickOutside([controlRef, popoverRef], () => {
1133
+ if (isOpen) close();
1134
+ }, isOpen);
1135
+ useEscapeKey(() => {
1136
+ if (isOpen) close();
1137
+ }, isOpen);
1138
+ const open = useCallback(() => {
1139
+ if (disabled) return;
1140
+ setIsOpen(true);
1141
+ setActiveIndex(-1);
1142
+ }, [disabled]);
1143
+ const close = useCallback(() => {
1144
+ setIsOpen(false);
1145
+ setQuery("");
1146
+ setActiveIndex(-1);
1147
+ }, []);
1148
+ const select = useCallback((value) => {
1149
+ setSelectedValue(value);
1150
+ close();
1151
+ requestAnimationFrame(() => {
1152
+ inputRef.current?.focus();
1153
+ });
1154
+ }, [setSelectedValue, close]);
1155
+ const handleInputKeyDown = useCallback((e) => {
1156
+ switch (e.key) {
1157
+ case "ArrowDown":
1158
+ e.preventDefault();
1159
+ if (!isOpen) open();
1160
+ else setActiveIndex((prev) => prev < filteredOptions.length - 1 ? prev + 1 : 0);
1161
+ break;
1162
+ case "ArrowUp":
1163
+ e.preventDefault();
1164
+ if (!isOpen) open();
1165
+ else setActiveIndex((prev) => prev > 0 ? prev - 1 : filteredOptions.length - 1);
1166
+ break;
1167
+ case "Home":
1168
+ if (isOpen) {
1169
+ e.preventDefault();
1170
+ setActiveIndex(0);
1171
+ }
1172
+ break;
1173
+ case "End":
1174
+ if (isOpen) {
1175
+ e.preventDefault();
1176
+ setActiveIndex(filteredOptions.length - 1);
1177
+ }
1178
+ break;
1179
+ case "Enter":
1180
+ e.preventDefault();
1181
+ if (isOpen && activeIndex >= 0 && activeIndex < filteredOptions.length) select(filteredOptions[activeIndex]);
1182
+ break;
1183
+ case "Tab":
1184
+ if (isOpen) close();
1185
+ break;
1186
+ }
1187
+ }, [
1188
+ isOpen,
1189
+ open,
1190
+ close,
1191
+ select,
1192
+ activeIndex,
1193
+ filteredOptions
1194
+ ]);
1195
+ useEffect(() => {
1196
+ if (!isOpen || activeIndex < 0) return;
1197
+ const listbox = popoverRef.current;
1198
+ if (!listbox) return;
1199
+ const activeOption = listbox.querySelector(`[data-combobox-option-index="${activeIndex}"]`);
1200
+ if (activeOption) activeOption.scrollIntoView({ block: "nearest" });
1201
+ }, [
1202
+ activeIndex,
1203
+ isOpen,
1204
+ popoverRef
1205
+ ]);
1206
+ const contextValue = {
1207
+ selectedValue,
1208
+ activeIndex,
1209
+ filteredOptions,
1210
+ select,
1211
+ setActiveIndex
1212
+ };
1213
+ return /* @__PURE__ */ jsxs(ComboboxContext.Provider, {
1214
+ value: contextValue,
1215
+ children: [/* @__PURE__ */ jsxs("span", {
1216
+ ref: controlRef,
1217
+ "data-slot": "control",
1218
+ ...disabled ? { "data-disabled": "" } : {},
1219
+ className: cn([
1220
+ className,
1221
+ "relative block w-full",
1222
+ "before:absolute before:inset-px before:rounded-[calc(var(--radius-lg)-1px)] before:bg-white before:shadow-sm",
1223
+ "dark:before:hidden",
1224
+ "after:pointer-events-none after:absolute after:inset-0 after:rounded-lg after:ring-transparent after:ring-inset sm:focus-within:after:ring-2 sm:focus-within:after:ring-blue-500",
1225
+ "has-data-disabled:opacity-50 has-data-disabled:before:bg-zinc-950/5 has-data-disabled:before:shadow-none",
1226
+ "has-data-invalid:before:shadow-red-500/10"
1227
+ ]),
1228
+ children: [/* @__PURE__ */ jsx("input", {
1229
+ ref: inputRef,
1230
+ "data-slot": "control",
1231
+ role: "combobox",
1232
+ "aria-label": ariaLabel,
1233
+ "aria-expanded": isOpen,
1234
+ "aria-controls": listboxId,
1235
+ "aria-activedescendant": isOpen && activeIndex >= 0 ? `${listboxId}-option-${activeIndex}` : void 0,
1236
+ "aria-autocomplete": "list",
1237
+ "aria-haspopup": "listbox",
1238
+ disabled,
1239
+ name,
1240
+ value: isOpen ? query : displayValue(selectedValue) ?? "",
1241
+ onChange: (e) => {
1242
+ setQuery(e.target.value);
1243
+ if (!isOpen) open();
1244
+ setActiveIndex(-1);
1245
+ },
1246
+ onFocus: () => {
1247
+ if (!isOpen) open();
1248
+ },
1249
+ onKeyDown: handleInputKeyDown,
1250
+ placeholder,
1251
+ ...disabled ? { "data-disabled": "" } : {},
1252
+ className: cn([
1253
+ className,
1254
+ "relative block w-full appearance-none rounded-lg py-[calc(--spacing(2.5)-1px)] sm:py-[calc(--spacing(1.5)-1px)]",
1255
+ "pr-[calc(--spacing(10)-1px)] pl-[calc(--spacing(3.5)-1px)] sm:pr-[calc(--spacing(9)-1px)] sm:pl-[calc(--spacing(3)-1px)]",
1256
+ "text-base/6 text-zinc-950 placeholder:text-zinc-500 sm:text-sm/6 dark:text-white",
1257
+ "border border-zinc-950/10 data-hover:border-zinc-950/20 dark:border-white/10 dark:data-hover:border-white/20",
1258
+ "bg-transparent dark:bg-white/5",
1259
+ "focus:outline-hidden",
1260
+ "data-invalid:border-red-500 data-invalid:data-hover:border-red-500 dark:data-invalid:border-red-500 dark:data-invalid:data-hover:border-red-500",
1261
+ "data-disabled:border-zinc-950/20 dark:data-disabled:border-white/15 dark:data-disabled:bg-white/2.5 dark:data-hover:data-disabled:border-white/15",
1262
+ "dark:scheme-dark"
1263
+ ])
1264
+ }), /* @__PURE__ */ jsx("button", {
1265
+ type: "button",
1266
+ tabIndex: -1,
1267
+ "aria-label": "Toggle options",
1268
+ disabled,
1269
+ onClick: () => {
1270
+ if (isOpen) close();
1271
+ else {
1272
+ open();
1273
+ inputRef.current?.focus();
1274
+ }
1275
+ },
1276
+ className: "group absolute inset-y-0 right-0 flex items-center px-2",
1277
+ ...disabled ? { "data-disabled": "" } : {},
1278
+ children: /* @__PURE__ */ jsxs("svg", {
1279
+ className: "size-5 stroke-zinc-500 group-data-disabled:stroke-zinc-600 group-data-hover:stroke-zinc-700 sm:size-4 dark:stroke-zinc-400 dark:group-data-hover:stroke-zinc-300 forced-colors:stroke-[CanvasText]",
1280
+ viewBox: "0 0 16 16",
1281
+ "aria-hidden": "true",
1282
+ fill: "none",
1283
+ children: [/* @__PURE__ */ jsx("path", {
1284
+ d: "M5.75 10.75L8 13L10.25 10.75",
1285
+ strokeWidth: 1.5,
1286
+ strokeLinecap: "round",
1287
+ strokeLinejoin: "round"
1288
+ }), /* @__PURE__ */ jsx("path", {
1289
+ d: "M10.25 5.25L8 3L5.75 5.25",
1290
+ strokeWidth: 1.5,
1291
+ strokeLinecap: "round",
1292
+ strokeLinejoin: "round"
1293
+ })]
1294
+ })
1295
+ })]
1296
+ }), mounted && createPortal(/* @__PURE__ */ jsx("div", {
1297
+ ref: (node) => {
1298
+ popoverRef.current = node;
1299
+ transitionRef.current = node;
1300
+ },
1301
+ role: "listbox",
1302
+ id: listboxId,
1303
+ ...popoverProps,
1304
+ ...transitionProps,
1305
+ className: cn("[--anchor-gap:--spacing(2)] [--anchor-padding:--spacing(4)] sm:data-[anchor~=start]:[--anchor-offset:-4px]", "isolate min-w-[calc(var(--input-width)+8px)] scroll-py-1 rounded-xl p-1 select-none empty:invisible", "outline outline-transparent focus:outline-hidden", "overflow-y-scroll overscroll-contain", "bg-white/75 backdrop-blur-xl dark:bg-zinc-800/75", "shadow-lg ring-1 ring-zinc-950/10 dark:ring-white/10 dark:ring-inset", "transition-opacity duration-100 ease-in data-closed:data-leave:opacity-0 data-transition:pointer-events-none"),
1306
+ style: {
1307
+ ...popoverProps.style,
1308
+ minWidth: controlRef.current?.offsetWidth
1309
+ },
1310
+ children: filteredOptions.map((option, index) => option == null ? null : /* @__PURE__ */ jsx(ComboboxOptionIndexProvider, {
1311
+ index,
1312
+ children: children(option)
1313
+ }, index))
1314
+ }), document.body)]
1315
+ });
1316
+ }
1317
+ var ComboboxOptionIndexContext = createContext(-1);
1318
+ function ComboboxOptionIndexProvider({ index, children }) {
1319
+ return /* @__PURE__ */ jsx(ComboboxOptionIndexContext.Provider, {
1320
+ value: index,
1321
+ children
1322
+ });
1323
+ }
1324
+ function ComboboxOption({ children, className, value, disabled = false }) {
1325
+ const { selectedValue, activeIndex, select, setActiveIndex } = useComboboxContext();
1326
+ const index = use(ComboboxOptionIndexContext);
1327
+ const isSelected = selectedValue === value;
1328
+ const isActive = activeIndex === index;
1329
+ const sharedClasses = cn("flex min-w-0 items-center", "*:data-[slot=icon]:size-5 *:data-[slot=icon]:shrink-0 sm:*:data-[slot=icon]:size-4", "*:data-[slot=icon]:text-zinc-500 group-data-focus/option:*:data-[slot=icon]:text-white dark:*:data-[slot=icon]:text-zinc-400", "forced-colors:*:data-[slot=icon]:text-[CanvasText] forced-colors:group-data-focus/option:*:data-[slot=icon]:text-[Canvas]", "*:data-[slot=avatar]:-mx-0.5 *:data-[slot=avatar]:size-6 sm:*:data-[slot=avatar]:size-5");
1330
+ return /* @__PURE__ */ jsxs("div", {
1331
+ role: "option",
1332
+ "aria-selected": isSelected,
1333
+ "aria-disabled": disabled,
1334
+ "data-combobox-option-index": index,
1335
+ ...isActive ? { "data-focus": "" } : {},
1336
+ ...isSelected ? { "data-selected": "" } : {},
1337
+ ...disabled ? { "data-disabled": "" } : {},
1338
+ onPointerEnter: () => {
1339
+ if (!disabled) setActiveIndex(index);
1340
+ },
1341
+ onPointerLeave: () => {
1342
+ setActiveIndex(-1);
1343
+ },
1344
+ onClick: () => {
1345
+ if (!disabled) select(value);
1346
+ },
1347
+ className: cn("group/option grid w-full cursor-default grid-cols-[1fr_--spacing(5)] items-baseline gap-x-2 rounded-lg py-2.5 pr-2 pl-3.5 sm:grid-cols-[1fr_--spacing(4)] sm:py-1.5 sm:pr-2 sm:pl-3", "text-base/6 text-zinc-950 sm:text-sm/6 dark:text-white forced-colors:text-[CanvasText]", "outline-hidden data-focus:bg-blue-500 data-focus:text-white", "forced-color-adjust-none forced-colors:data-focus:bg-[Highlight] forced-colors:data-focus:text-[HighlightText]", "data-disabled:opacity-50"),
1348
+ children: [/* @__PURE__ */ jsx("span", {
1349
+ className: cn(className, sharedClasses),
1350
+ children
1351
+ }), /* @__PURE__ */ jsx("svg", {
1352
+ className: "relative col-start-2 hidden size-5 self-center stroke-current group-data-selected/option:inline sm:size-4",
1353
+ viewBox: "0 0 16 16",
1354
+ fill: "none",
1355
+ "aria-hidden": "true",
1356
+ children: /* @__PURE__ */ jsx("path", {
1357
+ d: "M4 8.5l3 3L12 4",
1358
+ strokeWidth: 1.5,
1359
+ strokeLinecap: "round",
1360
+ strokeLinejoin: "round"
1361
+ })
1362
+ })]
1363
+ });
1364
+ }
1365
+ function ComboboxLabel({ className, ...props }) {
1366
+ return /* @__PURE__ */ jsx("span", {
1367
+ ...props,
1368
+ className: cn(className, "ml-2.5 truncate first:ml-0 sm:ml-2 sm:first:ml-0")
1369
+ });
1370
+ }
1371
+ function ComboboxDescription({ className, children, ...props }) {
1372
+ return /* @__PURE__ */ jsx("span", {
1373
+ ...props,
1374
+ className: cn(className, "flex flex-1 overflow-hidden text-zinc-500 group-data-focus/option:text-white before:w-2 before:min-w-0 before:shrink dark:text-zinc-400"),
1375
+ children: /* @__PURE__ */ jsx("span", {
1376
+ className: "flex-1 truncate",
1377
+ children
1378
+ })
1379
+ });
1380
+ }
1381
+ //#endregion
1382
+ //#region src/components/description-list.tsx
1383
+ function DescriptionList({ className, ...props }) {
1384
+ return /* @__PURE__ */ jsx("dl", {
1385
+ ...props,
1386
+ className: cn(className, "grid grid-cols-1 text-base/6 sm:grid-cols-[min(50%,--spacing(80))_auto] sm:text-sm/6")
1387
+ });
1388
+ }
1389
+ function DescriptionTerm({ className, ...props }) {
1390
+ return /* @__PURE__ */ jsx("dt", {
1391
+ ...props,
1392
+ className: cn(className, "col-start-1 border-t border-zinc-950/5 pt-3 text-zinc-500 first:border-none sm:border-t sm:border-zinc-950/5 sm:py-3 dark:border-white/5 dark:text-zinc-400 sm:dark:border-white/5")
1393
+ });
1394
+ }
1395
+ function DescriptionDetails({ className, ...props }) {
1396
+ return /* @__PURE__ */ jsx("dd", {
1397
+ ...props,
1398
+ className: cn(className, "pt-1 pb-3 text-zinc-950 sm:border-t sm:border-zinc-950/5 sm:py-3 sm:nth-2:border-none dark:text-white dark:sm:border-white/5")
1399
+ });
1400
+ }
1401
+ //#endregion
1402
+ //#region src/components/dialog.tsx
1403
+ var DialogContext = createContext(void 0);
1404
+ var sizes = {
1405
+ xs: "sm:max-w-xs",
1406
+ sm: "sm:max-w-sm",
1407
+ md: "sm:max-w-md",
1408
+ lg: "sm:max-w-lg",
1409
+ xl: "sm:max-w-xl",
1410
+ "2xl": "sm:max-w-2xl",
1411
+ "3xl": "sm:max-w-3xl",
1412
+ "4xl": "sm:max-w-4xl",
1413
+ "5xl": "sm:max-w-5xl"
1414
+ };
1415
+ function Dialog({ size = "lg", className, children, open, onClose }) {
1416
+ const panelRef = useRef(null);
1417
+ const titleId = useId();
1418
+ const backdrop = useTransition(open);
1419
+ const panel = useTransition(open);
1420
+ useScrollLock(open);
1421
+ useFocusTrap(panelRef, open);
1422
+ useEscapeKey(onClose, open);
1423
+ if (!(backdrop.mounted || panel.mounted)) return null;
1424
+ return createPortal(/* @__PURE__ */ jsx(DialogContext.Provider, {
1425
+ value: titleId,
1426
+ children: /* @__PURE__ */ jsxs("div", {
1427
+ role: "dialog",
1428
+ "aria-modal": "true",
1429
+ "aria-labelledby": titleId,
1430
+ children: [backdrop.mounted && /* @__PURE__ */ jsx("button", {
1431
+ type: "button",
1432
+ "aria-label": "Close dialog",
1433
+ ref: backdrop.nodeRef,
1434
+ ...backdrop.transitionProps,
1435
+ onClick: onClose,
1436
+ className: "fixed inset-0 flex w-screen justify-center overflow-y-auto px-2 py-2 transition duration-100 focus:outline-0 data-closed:opacity-0 data-enter:ease-out data-leave:ease-in sm:px-6 sm:py-8 lg:px-8 lg:py-16",
1437
+ style: {
1438
+ backgroundColor: "oklch(0.13 0.004 228 / 0.6)",
1439
+ backdropFilter: "blur(4px)"
1440
+ }
1441
+ }), panel.mounted && /* @__PURE__ */ jsx("div", {
1442
+ className: "fixed inset-0 w-screen overflow-y-auto pt-6 sm:pt-0",
1443
+ children: /* @__PURE__ */ jsx("div", {
1444
+ className: "grid min-h-full grid-rows-[1fr_auto] justify-items-center sm:grid-rows-[1fr_auto_3fr] sm:p-4",
1445
+ children: /* @__PURE__ */ jsx("div", {
1446
+ ref: (node) => {
1447
+ panelRef.current = node;
1448
+ panel.nodeRef.current = node;
1449
+ },
1450
+ ...panel.transitionProps,
1451
+ className: cn(className, sizes[size], "row-start-2 w-full min-w-0 rounded-t-3xl p-(--gutter) shadow-lg ring-1 [--gutter:--spacing(8)] sm:mb-auto sm:rounded-2xl forced-colors:outline", "transition will-change-transform data-closed:translate-y-12 data-closed:opacity-0 data-enter:ease-out data-leave:ease-in sm:data-closed:translate-y-0 sm:data-closed:data-enter:scale-95"),
1452
+ style: {
1453
+ backgroundColor: "var(--rvui-surface-1, oklch(0.18 0.006 225))",
1454
+ boxShadow: "var(--rvui-shadow-lg, 0 12px 40px oklch(0 0 0 / 0.35))",
1455
+ "--tw-ring-color": "var(--rvui-border-subtle, oklch(0.28 0.006 222 / 0.4))",
1456
+ transitionDuration: "var(--rvui-duration-normal, 200ms)",
1457
+ transitionTimingFunction: "var(--rvui-ease-spring, cubic-bezier(0.34, 1.56, 0.64, 1))"
1458
+ },
1459
+ children
1460
+ })
1461
+ })
1462
+ })]
1463
+ })
1464
+ }), document.body);
1465
+ }
1466
+ function DialogTitle({ className, ...props }) {
1467
+ return /* @__PURE__ */ jsx("h2", {
1468
+ id: use(DialogContext),
1469
+ ...props,
1470
+ className: cn(className, "text-lg/6 font-semibold text-balance sm:text-base/6"),
1471
+ style: { color: "var(--rvui-text-0, oklch(0.95 0.002 210))" }
1472
+ });
1473
+ }
1474
+ function DialogDescription({ className, ...props }) {
1475
+ return /* @__PURE__ */ jsx(Text, {
1476
+ ...props,
1477
+ className: cn(className, "mt-2 text-pretty")
1478
+ });
1479
+ }
1480
+ function DialogBody({ className, ...props }) {
1481
+ return /* @__PURE__ */ jsx("div", {
1482
+ ...props,
1483
+ className: cn(className, "mt-6")
1484
+ });
1485
+ }
1486
+ function DialogActions({ className, ...props }) {
1487
+ return /* @__PURE__ */ jsx("div", {
1488
+ ...props,
1489
+ className: cn(className, "mt-8 flex flex-col-reverse items-center justify-end gap-3 *:w-full sm:flex-row sm:*:w-auto")
1490
+ });
1491
+ }
1492
+ //#endregion
1493
+ //#region src/components/divider.tsx
1494
+ function Divider({ soft = false, className, ...props }) {
1495
+ return /* @__PURE__ */ jsx("hr", {
1496
+ ...props,
1497
+ className: cn(className, "w-full border-t", soft && "border-zinc-950/5 dark:border-white/5", !soft && "border-zinc-950/10 dark:border-white/10")
1498
+ });
1499
+ }
1500
+ //#endregion
1501
+ //#region src/components/drawer.tsx
1502
+ var DrawerContext = createContext(void 0);
1503
+ var sideClasses$1 = {
1504
+ left: "inset-y-0 left-0 h-full w-full max-w-sm data-closed:-translate-x-full",
1505
+ right: "inset-y-0 right-0 h-full w-full max-w-sm data-closed:translate-x-full",
1506
+ top: "inset-x-0 top-0 w-full max-h-[50vh] data-closed:-translate-y-full",
1507
+ bottom: "inset-x-0 bottom-0 w-full max-h-[50vh] data-closed:translate-y-full"
1508
+ };
1509
+ function Drawer({ open, onClose, side = "right", className, children }) {
1510
+ const panelRef = useRef(null);
1511
+ const titleId = useId();
1512
+ const backdrop = useTransition(open);
1513
+ const panel = useTransition(open);
1514
+ useScrollLock(open);
1515
+ useFocusTrap(panelRef, open);
1516
+ useEscapeKey(onClose, open);
1517
+ const handleBackdropClick = (e) => {
1518
+ if (e.target === e.currentTarget) onClose();
1519
+ };
1520
+ if (!(backdrop.mounted || panel.mounted)) return null;
1521
+ return createPortal(/* @__PURE__ */ jsx(DrawerContext.Provider, {
1522
+ value: titleId,
1523
+ children: /* @__PURE__ */ jsxs("div", {
1524
+ role: "dialog",
1525
+ "aria-modal": "true",
1526
+ "aria-labelledby": titleId,
1527
+ children: [backdrop.mounted && /* @__PURE__ */ jsx("button", {
1528
+ type: "button",
1529
+ "aria-label": "Close drawer",
1530
+ ref: backdrop.nodeRef,
1531
+ ...backdrop.transitionProps,
1532
+ onClick: handleBackdropClick,
1533
+ className: "fixed inset-0 z-40 bg-zinc-950/25 transition duration-200 data-closed:opacity-0 data-enter:ease-out data-leave:ease-in dark:bg-zinc-950/50"
1534
+ }), panel.mounted && /* @__PURE__ */ jsx("div", {
1535
+ ref: (node) => {
1536
+ panelRef.current = node;
1537
+ panel.nodeRef.current = node;
1538
+ },
1539
+ ...panel.transitionProps,
1540
+ className: cn("fixed z-50 overflow-y-auto bg-white shadow-xl ring-1 ring-zinc-950/10 transition duration-300 ease-in-out dark:bg-zinc-900 dark:ring-white/10", sideClasses$1[side], className),
1541
+ children
1542
+ })]
1543
+ })
1544
+ }), document.body);
1545
+ }
1546
+ function DrawerHeader({ onClose, className, children }) {
1547
+ const titleId = use(DrawerContext);
1548
+ return /* @__PURE__ */ jsxs("div", {
1549
+ className: cn("flex items-center justify-between border-b border-zinc-200 px-6 py-4 dark:border-zinc-700", className),
1550
+ children: [/* @__PURE__ */ jsx("h2", {
1551
+ id: titleId,
1552
+ className: "text-base font-semibold text-zinc-950 dark:text-white",
1553
+ children
1554
+ }), onClose && /* @__PURE__ */ jsx("button", {
1555
+ type: "button",
1556
+ "aria-label": "Close drawer",
1557
+ onClick: onClose,
1558
+ className: "rounded-md p-1 text-zinc-400 hover:text-zinc-600 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-500 dark:hover:text-zinc-200",
1559
+ children: /* @__PURE__ */ jsx("svg", {
1560
+ viewBox: "0 0 16 16",
1561
+ fill: "none",
1562
+ className: "size-4",
1563
+ "aria-hidden": "true",
1564
+ children: /* @__PURE__ */ jsx("path", {
1565
+ d: "M4 4l8 8M12 4l-8 8",
1566
+ stroke: "currentColor",
1567
+ strokeWidth: "1.5",
1568
+ strokeLinecap: "round"
1569
+ })
1570
+ })
1571
+ })]
1572
+ });
1573
+ }
1574
+ function DrawerBody({ className, ...props }) {
1575
+ return /* @__PURE__ */ jsx("div", {
1576
+ ...props,
1577
+ className: cn("px-6 py-4", className)
1578
+ });
1579
+ }
1580
+ function DrawerFooter({ className, ...props }) {
1581
+ return /* @__PURE__ */ jsx("div", {
1582
+ ...props,
1583
+ className: cn("flex items-center justify-end gap-3 border-t border-zinc-200 px-6 py-4 dark:border-zinc-700", className)
1584
+ });
1585
+ }
1586
+ //#endregion
1587
+ //#region src/hooks/use-roving-tabindex.ts
1588
+ function useRovingTabindex({ itemCount, initialIndex = -1, orientation = "vertical", loop = true, onActiveChange }) {
1589
+ const [activeIndex, setActiveIndexState] = useState(initialIndex);
1590
+ const itemRefs = useRef(/* @__PURE__ */ new Map());
1591
+ const onActiveChangeRef = useRef(onActiveChange);
1592
+ onActiveChangeRef.current = onActiveChange;
1593
+ const setActiveIndex = useCallback((index) => {
1594
+ setActiveIndexState(index);
1595
+ onActiveChangeRef.current?.(index);
1596
+ itemRefs.current.get(index)?.focus();
1597
+ }, []);
1598
+ const moveFocus = useCallback((direction) => {
1599
+ if (itemCount === 0) return;
1600
+ let next = activeIndex + direction;
1601
+ if (loop) {
1602
+ if (next < 0) next = itemCount - 1;
1603
+ else if (next >= itemCount) next = 0;
1604
+ } else next = Math.max(0, Math.min(itemCount - 1, next));
1605
+ if (itemRefs.current.get(next)?.hasAttribute("data-disabled")) {
1606
+ const nextNext = next + direction;
1607
+ if (nextNext >= 0 && nextNext < itemCount) {
1608
+ setActiveIndex(nextNext);
1609
+ return;
1610
+ }
1611
+ }
1612
+ setActiveIndex(next);
1613
+ }, [
1614
+ activeIndex,
1615
+ itemCount,
1616
+ loop,
1617
+ setActiveIndex
1618
+ ]);
1619
+ const onKeyDown = useCallback((e) => {
1620
+ const prevKey = orientation === "vertical" ? "ArrowUp" : "ArrowLeft";
1621
+ const nextKey = orientation === "vertical" ? "ArrowDown" : "ArrowRight";
1622
+ switch (e.key) {
1623
+ case prevKey:
1624
+ e.preventDefault();
1625
+ moveFocus(-1);
1626
+ break;
1627
+ case nextKey:
1628
+ e.preventDefault();
1629
+ moveFocus(1);
1630
+ break;
1631
+ case "Home":
1632
+ e.preventDefault();
1633
+ setActiveIndex(0);
1634
+ break;
1635
+ case "End":
1636
+ e.preventDefault();
1637
+ setActiveIndex(itemCount - 1);
1638
+ break;
1639
+ }
1640
+ }, [
1641
+ moveFocus,
1642
+ setActiveIndex,
1643
+ itemCount,
1644
+ orientation
1645
+ ]);
1646
+ const getItemProps = useCallback((index) => ({
1647
+ tabIndex: index === activeIndex ? 0 : -1,
1648
+ "data-focus": index === activeIndex ? "" : void 0,
1649
+ ref: (el) => {
1650
+ if (el) itemRefs.current.set(index, el);
1651
+ else itemRefs.current.delete(index);
1652
+ },
1653
+ onPointerEnter: () => setActiveIndex(index),
1654
+ onClick: () => setActiveIndex(index)
1655
+ }), [activeIndex, setActiveIndex]);
1656
+ return {
1657
+ activeIndex,
1658
+ setActiveIndex,
1659
+ containerProps: {
1660
+ role: orientation === "vertical" ? "listbox" : "group",
1661
+ onKeyDown
1662
+ },
1663
+ getItemProps
1664
+ };
1665
+ }
1666
+ //#endregion
1667
+ //#region src/hooks/use-type-ahead.ts
1668
+ function useTypeAhead({ getItemText, itemCount, onMatch, timeout = 350 }) {
1669
+ const searchBuffer = useRef("");
1670
+ const timeoutRef = useRef(void 0);
1671
+ return { onKeyDown: useCallback((e) => {
1672
+ if (e.key.length !== 1 || e.ctrlKey || e.metaKey || e.altKey) return;
1673
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
1674
+ searchBuffer.current += e.key.toLowerCase();
1675
+ timeoutRef.current = setTimeout(() => {
1676
+ searchBuffer.current = "";
1677
+ }, timeout);
1678
+ const query = searchBuffer.current;
1679
+ for (let i = 0; i < itemCount; i++) if (getItemText(i).toLowerCase().startsWith(query)) {
1680
+ onMatch(i);
1681
+ return;
1682
+ }
1683
+ }, [
1684
+ getItemText,
1685
+ itemCount,
1686
+ onMatch,
1687
+ timeout
1688
+ ]) };
1689
+ }
1690
+ //#endregion
1691
+ //#region src/components/dropdown.tsx
1692
+ var DropdownContext = createContext(null);
1693
+ function useDropdownContext() {
1694
+ const ctx = use(DropdownContext);
1695
+ if (!ctx) throw new Error("Dropdown compound components must be used within <Dropdown>");
1696
+ return ctx;
1697
+ }
1698
+ var DropdownItemContext = createContext(null);
1699
+ function Dropdown({ children, ...props }) {
1700
+ const [open, setOpen] = useState(false);
1701
+ const triggerRef = useRef(null);
1702
+ const close = useCallback(() => {
1703
+ setOpen(false);
1704
+ triggerRef.current?.focus();
1705
+ }, []);
1706
+ const value = useMemo(() => ({
1707
+ open,
1708
+ setOpen,
1709
+ close,
1710
+ triggerRef
1711
+ }), [open, close]);
1712
+ return /* @__PURE__ */ jsx(DropdownContext.Provider, {
1713
+ value,
1714
+ children: /* @__PURE__ */ jsx("div", {
1715
+ ...props,
1716
+ children
1717
+ })
1718
+ });
1719
+ }
1720
+ function DropdownButton({ as, className, ...props }) {
1721
+ const { open, setOpen, triggerRef } = useDropdownContext();
1722
+ const interactiveProps = useDataInteractive();
1723
+ const Component = as ?? Button;
1724
+ const handleClick = useCallback(() => {
1725
+ setOpen(!open);
1726
+ }, [open, setOpen]);
1727
+ const handleKeyDown = useCallback((e) => {
1728
+ if (e.key === "ArrowDown" || e.key === "Enter" || e.key === " ") {
1729
+ e.preventDefault();
1730
+ setOpen(true);
1731
+ }
1732
+ }, [setOpen]);
1733
+ return /* @__PURE__ */ jsx(Component, {
1734
+ ref: triggerRef,
1735
+ ...interactiveProps,
1736
+ ...props,
1737
+ className,
1738
+ "aria-haspopup": "menu",
1739
+ "aria-expanded": open,
1740
+ onClick: handleClick,
1741
+ onKeyDown: handleKeyDown
1742
+ });
1743
+ }
1744
+ function DropdownMenu({ anchor = "bottom", className, children, ...props }) {
1745
+ const { open, close, triggerRef } = useDropdownContext();
1746
+ const { mounted, nodeRef, transitionProps } = useTransition(open);
1747
+ const popover = usePopover({
1748
+ open,
1749
+ anchor,
1750
+ gap: 8,
1751
+ padding: 4
1752
+ });
1753
+ const menuRef = useRef(null);
1754
+ const combinedRef = useCallback((el) => {
1755
+ menuRef.current = el;
1756
+ popover.popoverRef.current = el;
1757
+ nodeRef.current = el;
1758
+ }, [popover.popoverRef, nodeRef]);
1759
+ popover.triggerRef.current = triggerRef.current;
1760
+ useClickOutside([triggerRef, menuRef], close, open);
1761
+ useEscapeKey(close, open);
1762
+ const itemElements = useRef([]);
1763
+ const [itemCount, setItemCount] = useState(0);
1764
+ const register = useCallback((el) => {
1765
+ if (!itemElements.current.includes(el)) {
1766
+ itemElements.current.push(el);
1767
+ setItemCount(itemElements.current.length);
1768
+ }
1769
+ return itemElements.current.indexOf(el);
1770
+ }, []);
1771
+ const unregister = useCallback((el) => {
1772
+ const idx = itemElements.current.indexOf(el);
1773
+ if (idx !== -1) {
1774
+ itemElements.current.splice(idx, 1);
1775
+ setItemCount(itemElements.current.length);
1776
+ }
1777
+ }, []);
1778
+ const roving = useRovingTabindex({
1779
+ itemCount,
1780
+ initialIndex: -1,
1781
+ orientation: "vertical",
1782
+ loop: true
1783
+ });
1784
+ const typeAhead = useTypeAhead({
1785
+ getItemText: (index) => itemElements.current[index]?.textContent ?? "",
1786
+ itemCount,
1787
+ onMatch: (index) => roving.setActiveIndex(index)
1788
+ });
1789
+ const handleKeyDown = useCallback((e) => {
1790
+ roving.containerProps.onKeyDown(e);
1791
+ typeAhead.onKeyDown(e);
1792
+ if (e.key === "Enter" || e.key === " ") {
1793
+ e.preventDefault();
1794
+ const activeEl = itemElements.current[roving.activeIndex];
1795
+ if (activeEl) activeEl.click();
1796
+ }
1797
+ }, [roving, typeAhead]);
1798
+ const itemContextValue = useMemo(() => ({
1799
+ register,
1800
+ unregister,
1801
+ getItemProps: roving.getItemProps
1802
+ }), [
1803
+ register,
1804
+ unregister,
1805
+ roving.getItemProps
1806
+ ]);
1807
+ if (!mounted) return null;
1808
+ return createPortal(/* @__PURE__ */ jsx(DropdownItemContext.Provider, {
1809
+ value: itemContextValue,
1810
+ children: /* @__PURE__ */ jsx("div", {
1811
+ ref: combinedRef,
1812
+ ...transitionProps,
1813
+ ...props,
1814
+ role: "menu",
1815
+ "aria-orientation": "vertical",
1816
+ style: popover.popoverProps.style,
1817
+ onKeyDown: handleKeyDown,
1818
+ className: cn(className, "[--anchor-gap:--spacing(2)] [--anchor-padding:--spacing(1)] data-[anchor~=end]:[--anchor-offset:6px] data-[anchor~=start]:[--anchor-offset:-6px] sm:data-[anchor~=end]:[--anchor-offset:4px] sm:data-[anchor~=start]:[--anchor-offset:-4px]", "isolate w-max rounded-xl p-1", "outline outline-transparent focus:outline-hidden", "overflow-y-auto", "bg-white/75 backdrop-blur-xl dark:bg-zinc-800/75", "shadow-lg ring-1 ring-zinc-950/10 dark:ring-white/10 dark:ring-inset", "supports-[grid-template-columns:subgrid]:grid supports-[grid-template-columns:subgrid]:grid-cols-[auto_1fr_1.5rem_0.5rem_auto]", "transition data-leave:duration-100 data-leave:ease-in data-closed:data-leave:opacity-0"),
1819
+ children
1820
+ })
1821
+ }), document.body);
1822
+ }
1823
+ function DropdownItem({ className, ...props }) {
1824
+ const { close } = useDropdownContext();
1825
+ const itemCtx = use(DropdownItemContext);
1826
+ const interactiveProps = useDataInteractive({ disabled: "disabled" in props ? props.disabled ?? false : false });
1827
+ const elRef = useRef(null);
1828
+ const indexRef = useRef(-1);
1829
+ const setRef = useCallback((el) => {
1830
+ if (el && itemCtx) {
1831
+ elRef.current = el;
1832
+ indexRef.current = itemCtx.register(el);
1833
+ } else if (!el && elRef.current && itemCtx) {
1834
+ itemCtx.unregister(elRef.current);
1835
+ elRef.current = null;
1836
+ indexRef.current = -1;
1837
+ }
1838
+ }, [itemCtx]);
1839
+ const rovingProps = itemCtx && indexRef.current >= 0 ? itemCtx.getItemProps(indexRef.current) : {
1840
+ tabIndex: -1,
1841
+ "data-focus": void 0,
1842
+ ref: () => {},
1843
+ onPointerEnter: () => {},
1844
+ onClick: () => {}
1845
+ };
1846
+ const propsDisabled = "disabled" in props ? props.disabled : false;
1847
+ const propsOnClick = "onClick" in props && typeof props.onClick === "function" ? props.onClick : void 0;
1848
+ const handleClick = useCallback((e) => {
1849
+ if (propsDisabled) return;
1850
+ rovingProps.onClick();
1851
+ propsOnClick?.(e);
1852
+ close();
1853
+ }, [
1854
+ close,
1855
+ propsDisabled,
1856
+ propsOnClick,
1857
+ rovingProps
1858
+ ]);
1859
+ const classes = cn(className, "group cursor-default rounded-lg px-3.5 py-2.5 focus:outline-hidden sm:px-3 sm:py-1.5", "text-left text-base/6 text-zinc-950 sm:text-sm/6 dark:text-white forced-colors:text-[CanvasText]", "data-focus:bg-blue-500 data-focus:text-white", "data-disabled:opacity-50", "forced-color-adjust-none forced-colors:data-focus:bg-[Highlight] forced-colors:data-focus:text-[HighlightText] forced-colors:data-focus:*:data-[slot=icon]:text-[HighlightText]", "col-span-full grid grid-cols-[auto_1fr_1.5rem_0.5rem_auto] items-center supports-[grid-template-columns:subgrid]:grid-cols-subgrid", "*:data-[slot=icon]:col-start-1 *:data-[slot=icon]:row-start-1 *:data-[slot=icon]:mr-2.5 *:data-[slot=icon]:-ml-0.5 *:data-[slot=icon]:size-5 sm:*:data-[slot=icon]:mr-2 sm:*:data-[slot=icon]:size-4", "*:data-[slot=icon]:text-zinc-500 data-focus:*:data-[slot=icon]:text-white dark:*:data-[slot=icon]:text-zinc-400 dark:data-focus:*:data-[slot=icon]:text-white", "*:data-[slot=avatar]:mr-2.5 *:data-[slot=avatar]:-ml-1 *:data-[slot=avatar]:size-6 sm:*:data-[slot=avatar]:mr-2 sm:*:data-[slot=avatar]:size-5");
1860
+ if (typeof props.href === "string") {
1861
+ const { href, children, ...linkProps } = props;
1862
+ return /* @__PURE__ */ jsx(Link, {
1863
+ ref: setRef,
1864
+ role: "menuitem",
1865
+ href,
1866
+ ...linkProps,
1867
+ ...interactiveProps,
1868
+ tabIndex: rovingProps.tabIndex,
1869
+ "data-focus": rovingProps["data-focus"],
1870
+ onPointerEnter: rovingProps.onPointerEnter,
1871
+ onClick: handleClick,
1872
+ className: classes,
1873
+ children
1874
+ });
1875
+ }
1876
+ const { disabled, children, onClick: _onClick, ...buttonProps } = props;
1877
+ return /* @__PURE__ */ jsx("button", {
1878
+ ref: setRef,
1879
+ role: "menuitem",
1880
+ type: "button",
1881
+ disabled,
1882
+ ...buttonProps,
1883
+ ...interactiveProps,
1884
+ tabIndex: rovingProps.tabIndex,
1885
+ "data-focus": rovingProps["data-focus"],
1886
+ onPointerEnter: rovingProps.onPointerEnter,
1887
+ onClick: handleClick,
1888
+ className: classes,
1889
+ children
1890
+ });
1891
+ }
1892
+ function DropdownHeader({ className, ...props }) {
1893
+ return /* @__PURE__ */ jsx("div", {
1894
+ ...props,
1895
+ className: cn(className, "col-span-5 px-3.5 pt-2.5 pb-1 sm:px-3")
1896
+ });
1897
+ }
1898
+ function DropdownSection({ className, ...props }) {
1899
+ return /* @__PURE__ */ jsx("div", {
1900
+ role: "group",
1901
+ ...props,
1902
+ className: cn(className, "col-span-full supports-[grid-template-columns:subgrid]:grid supports-[grid-template-columns:subgrid]:grid-cols-[auto_1fr_1.5rem_0.5rem_auto]")
1903
+ });
1904
+ }
1905
+ function DropdownHeading({ className, ...props }) {
1906
+ return /* @__PURE__ */ jsx("div", {
1907
+ role: "presentation",
1908
+ ...props,
1909
+ className: cn(className, "col-span-full grid grid-cols-[1fr_auto] gap-x-12 px-3.5 pt-2 pb-1 text-sm/5 font-medium text-zinc-500 sm:px-3 sm:text-xs/5 dark:text-zinc-400")
1910
+ });
1911
+ }
1912
+ function DropdownDivider({ className, ...props }) {
1913
+ return /* @__PURE__ */ jsx("hr", {
1914
+ ...props,
1915
+ className: cn(className, "col-span-full mx-3.5 my-1 h-px border-0 bg-zinc-950/5 sm:mx-3 dark:bg-white/10 forced-colors:bg-[CanvasText]")
1916
+ });
1917
+ }
1918
+ function DropdownLabel({ className, ...props }) {
1919
+ return /* @__PURE__ */ jsx("div", {
1920
+ ...props,
1921
+ "data-slot": "label",
1922
+ className: cn(className, "col-start-2 row-start-1")
1923
+ });
1924
+ }
1925
+ function DropdownDescription({ className, ...props }) {
1926
+ return /* @__PURE__ */ jsx("span", {
1927
+ "data-slot": "description",
1928
+ ...props,
1929
+ className: cn(className, "col-span-2 col-start-2 row-start-2 text-sm/5 text-zinc-500 group-data-focus:text-white sm:text-xs/5 dark:text-zinc-400 forced-colors:group-data-focus:text-[HighlightText]")
1930
+ });
1931
+ }
1932
+ function DropdownShortcut({ keys, className, ...props }) {
1933
+ return /* @__PURE__ */ jsx("kbd", {
1934
+ ...props,
1935
+ className: cn(className, "col-start-5 row-start-1 flex justify-self-end"),
1936
+ children: (Array.isArray(keys) ? keys : keys.split("")).map((char, index) => {
1937
+ return /* @__PURE__ */ jsx("kbd", {
1938
+ className: cn(["min-w-[2ch] text-center font-sans text-zinc-400 capitalize group-data-focus:text-white forced-colors:group-data-focus:text-[HighlightText]", index > 0 && char.length > 1 && "pl-1"]),
1939
+ children: char
1940
+ }, `${char}-${index}`);
1941
+ })
1942
+ });
1943
+ }
1944
+ //#endregion
1945
+ //#region src/components/fieldset.tsx
1946
+ function Fieldset({ className, disabled, ...props }) {
1947
+ return /* @__PURE__ */ jsx("fieldset", {
1948
+ disabled,
1949
+ ...props,
1950
+ className: cn(className, "*:data-[slot=text]:mt-1 [&>*+[data-slot=control]]:mt-6")
1951
+ });
1952
+ }
1953
+ function Legend({ className, ...props }) {
1954
+ return /* @__PURE__ */ jsx("legend", {
1955
+ "data-slot": "legend",
1956
+ ...props,
1957
+ className: cn(className, "text-base/6 font-semibold text-zinc-950 data-disabled:opacity-50 sm:text-sm/6 dark:text-white")
1958
+ });
1959
+ }
1960
+ function FieldGroup({ className, ...props }) {
1961
+ return /* @__PURE__ */ jsx("div", {
1962
+ "data-slot": "control",
1963
+ ...props,
1964
+ className: cn(className, "space-y-8")
1965
+ });
1966
+ }
1967
+ function Field({ className, disabled, ...props }) {
1968
+ return /* @__PURE__ */ jsx(FieldProvider, {
1969
+ disabled,
1970
+ children: /* @__PURE__ */ jsx("div", {
1971
+ ...props,
1972
+ "data-disabled": disabled ? "" : void 0,
1973
+ className: cn(className, "[&>[data-slot=label]+[data-slot=control]]:mt-3", "[&>[data-slot=label]+[data-slot=description]]:mt-1", "[&>[data-slot=description]+[data-slot=control]]:mt-3", "[&>[data-slot=control]+[data-slot=description]]:mt-3", "[&>[data-slot=control]+[data-slot=error]]:mt-3", "*:data-[slot=label]:font-medium")
1974
+ })
1975
+ });
1976
+ }
1977
+ function Label({ className, ...props }) {
1978
+ const fieldLabelProps = useFieldLabelProps();
1979
+ return /* @__PURE__ */ jsx("label", {
1980
+ "data-slot": "label",
1981
+ ...fieldLabelProps,
1982
+ ...props,
1983
+ className: cn(className, "text-base/6 text-zinc-950 select-none data-disabled:opacity-50 sm:text-sm/6 dark:text-white")
1984
+ });
1985
+ }
1986
+ function Description({ className, ...props }) {
1987
+ const fieldDescriptionProps = useFieldDescriptionProps();
1988
+ return /* @__PURE__ */ jsx("p", {
1989
+ "data-slot": "description",
1990
+ ...fieldDescriptionProps,
1991
+ ...props,
1992
+ className: cn(className, "text-base/6 text-zinc-500 data-disabled:opacity-50 sm:text-sm/6 dark:text-zinc-400")
1993
+ });
1994
+ }
1995
+ function ErrorMessage({ className, ...props }) {
1996
+ const fieldErrorProps = useFieldErrorProps();
1997
+ return /* @__PURE__ */ jsx("p", {
1998
+ "data-slot": "error",
1999
+ ...fieldErrorProps,
2000
+ ...props,
2001
+ className: cn(className, "text-base/6 text-red-600 data-disabled:opacity-50 sm:text-sm/6 dark:text-red-500")
2002
+ });
2003
+ }
2004
+ //#endregion
2005
+ //#region src/components/input-headless.tsx
2006
+ function InputGroup({ children }) {
2007
+ return /* @__PURE__ */ jsx("span", {
2008
+ "data-slot": "control",
2009
+ className: cn("relative isolate block", "has-[[data-slot=icon]:first-child]:[&_input]:pl-10 has-[[data-slot=icon]:last-child]:[&_input]:pr-10 sm:has-[[data-slot=icon]:first-child]:[&_input]:pl-8 sm:has-[[data-slot=icon]:last-child]:[&_input]:pr-8", "*:data-[slot=icon]:pointer-events-none *:data-[slot=icon]:absolute *:data-[slot=icon]:top-3 *:data-[slot=icon]:z-10 *:data-[slot=icon]:size-5 sm:*:data-[slot=icon]:top-2.5 sm:*:data-[slot=icon]:size-4", "[&>[data-slot=icon]:first-child]:left-3 sm:[&>[data-slot=icon]:first-child]:left-2.5 [&>[data-slot=icon]:last-child]:right-3 sm:[&>[data-slot=icon]:last-child]:right-2.5", "*:data-[slot=icon]:text-zinc-500 dark:*:data-[slot=icon]:text-zinc-400"),
2010
+ children
2011
+ });
2012
+ }
2013
+ var dateTypes = [
2014
+ "date",
2015
+ "datetime-local",
2016
+ "month",
2017
+ "time",
2018
+ "week"
2019
+ ];
2020
+ function Input({ className, disabled, invalid, ref, ...props }) {
2021
+ const interactiveProps = useDataInteractive({ disabled });
2022
+ const fieldProps = useFieldControlProps();
2023
+ return /* @__PURE__ */ jsx("span", {
2024
+ "data-slot": "control",
2025
+ className: cn([
2026
+ className,
2027
+ "relative block w-full",
2028
+ "before:absolute before:inset-px before:rounded-[calc(var(--radius-lg)-1px)] before:bg-white before:shadow-sm",
2029
+ "dark:before:hidden",
2030
+ "after:pointer-events-none after:absolute after:inset-0 after:rounded-lg after:ring-transparent after:ring-inset sm:focus-within:after:ring-2 sm:focus-within:after:ring-blue-500",
2031
+ "has-data-disabled:opacity-50 has-data-disabled:before:bg-zinc-950/5 has-data-disabled:before:shadow-none"
2032
+ ]),
2033
+ children: /* @__PURE__ */ jsx("input", {
2034
+ ref,
2035
+ disabled,
2036
+ ...props,
2037
+ ...interactiveProps,
2038
+ ...fieldProps,
2039
+ "data-invalid": invalid ? "" : void 0,
2040
+ "data-disabled": disabled ? "" : void 0,
2041
+ className: cn([
2042
+ props.type && dateTypes.includes(props.type) && [
2043
+ "[&::-webkit-datetime-edit-fields-wrapper]:p-0",
2044
+ "[&::-webkit-date-and-time-value]:min-h-[1.5em]",
2045
+ "[&::-webkit-datetime-edit]:inline-flex",
2046
+ "[&::-webkit-datetime-edit]:p-0",
2047
+ "[&::-webkit-datetime-edit-year-field]:p-0",
2048
+ "[&::-webkit-datetime-edit-month-field]:p-0",
2049
+ "[&::-webkit-datetime-edit-day-field]:p-0",
2050
+ "[&::-webkit-datetime-edit-hour-field]:p-0",
2051
+ "[&::-webkit-datetime-edit-minute-field]:p-0",
2052
+ "[&::-webkit-datetime-edit-second-field]:p-0",
2053
+ "[&::-webkit-datetime-edit-millisecond-field]:p-0",
2054
+ "[&::-webkit-datetime-edit-meridiem-field]:p-0"
2055
+ ],
2056
+ "relative block w-full appearance-none rounded-lg px-[calc(--spacing(3.5)-1px)] py-[calc(--spacing(2.5)-1px)] sm:px-[calc(--spacing(3)-1px)] sm:py-[calc(--spacing(1.5)-1px)]",
2057
+ "text-base/6 text-zinc-950 placeholder:text-zinc-500 sm:text-sm/6 dark:text-white",
2058
+ "border border-zinc-950/10 data-hover:border-zinc-950/20 dark:border-white/10 dark:data-hover:border-white/20",
2059
+ "bg-transparent dark:bg-white/5",
2060
+ "focus:outline-hidden",
2061
+ "data-invalid:border-red-500 data-invalid:data-hover:border-red-500 dark:data-invalid:border-red-600 dark:data-invalid:data-hover:border-red-600",
2062
+ "data-disabled:border-zinc-950/20 dark:data-disabled:border-white/15 dark:data-disabled:bg-white/2.5 dark:data-hover:data-disabled:border-white/15",
2063
+ "dark:scheme-dark"
2064
+ ])
2065
+ })
2066
+ });
2067
+ }
2068
+ //#endregion
2069
+ //#region src/components/kbd.tsx
2070
+ function Kbd({ className, children, ...props }) {
2071
+ return /* @__PURE__ */ jsx("kbd", {
2072
+ ...props,
2073
+ className: cn("inline-flex items-center rounded border border-zinc-300 bg-zinc-100 px-1.5 py-0.5 font-mono text-xs font-medium text-zinc-700 dark:border-zinc-600 dark:bg-zinc-800 dark:text-zinc-300", className),
2074
+ children
2075
+ });
2076
+ }
2077
+ function KbdShortcut({ keys, separator = "+", className }) {
2078
+ return /* @__PURE__ */ jsx("span", {
2079
+ className: cn("inline-flex items-center gap-1", className),
2080
+ children: keys.map((key, i) => /* @__PURE__ */ jsxs("span", {
2081
+ className: "inline-flex items-center gap-1",
2082
+ children: [/* @__PURE__ */ jsx(Kbd, { children: key }), i < keys.length - 1 && /* @__PURE__ */ jsx("span", {
2083
+ className: "text-xs text-zinc-400",
2084
+ children: separator
2085
+ })]
2086
+ }, i))
2087
+ });
2088
+ }
2089
+ //#endregion
2090
+ //#region src/components/listbox.tsx
2091
+ var ListboxContext = createContext(null);
2092
+ function useListboxContext() {
2093
+ const ctx = use(ListboxContext);
2094
+ if (!ctx) throw new Error("Listbox compound components must be used within <Listbox>");
2095
+ return ctx;
2096
+ }
2097
+ function countOptions(children) {
2098
+ let count = 0;
2099
+ Children.forEach(children, (child) => {
2100
+ if (!isValidElement(child)) return;
2101
+ if (child.type === ListboxOption) count++;
2102
+ });
2103
+ return count;
2104
+ }
2105
+ var OptionIndexContext = createContext(-1);
2106
+ function OptionIndexProvider({ children }) {
2107
+ let index = 0;
2108
+ return /* @__PURE__ */ jsx(Fragment, { children: Children.map(children, (child) => {
2109
+ if (!isValidElement(child)) return child;
2110
+ if (child.type === ListboxOption) {
2111
+ const currentIndex = index++;
2112
+ return /* @__PURE__ */ jsx(OptionIndexContext.Provider, {
2113
+ value: currentIndex,
2114
+ children: child
2115
+ });
2116
+ }
2117
+ return child;
2118
+ }) });
2119
+ }
2120
+ function Listbox({ className, placeholder, autoFocus = false, "aria-label": ariaLabel, children: options, value: controlledValue, defaultValue, onChange, disabled = false, name }) {
2121
+ const [value, setValue] = useControllableState({
2122
+ value: controlledValue,
2123
+ defaultValue,
2124
+ onChange
2125
+ });
2126
+ const [open, setOpen] = useState(false);
2127
+ const [activeIndex, setActiveIndex] = useState(-1);
2128
+ const [optionCount, setOptionCount] = useState(0);
2129
+ const buttonId = useId();
2130
+ const listId = useId();
2131
+ const optionMapRef = useRef(/* @__PURE__ */ new Map());
2132
+ const registerOption = useCallback((index, optValue, element) => {
2133
+ optionMapRef.current.set(index, {
2134
+ value: optValue,
2135
+ element
2136
+ });
2137
+ }, []);
2138
+ const { triggerRef, popoverRef, popoverProps } = usePopover({
2139
+ open,
2140
+ anchor: "selection start",
2141
+ gap: 0,
2142
+ padding: 16
2143
+ });
2144
+ const { mounted, nodeRef, transitionProps } = useTransition(open);
2145
+ const focusTrigger = useCallback(() => {
2146
+ triggerRef.current?.focus();
2147
+ }, [triggerRef]);
2148
+ useEffect(() => {
2149
+ setOptionCount(countOptions(options));
2150
+ }, [options]);
2151
+ useEffect(() => {
2152
+ if (autoFocus && !disabled) focusTrigger();
2153
+ }, [
2154
+ autoFocus,
2155
+ disabled,
2156
+ focusTrigger
2157
+ ]);
2158
+ useClickOutside([triggerRef, popoverRef], () => setOpen(false), open);
2159
+ useEscapeKey(() => {
2160
+ setOpen(false);
2161
+ focusTrigger();
2162
+ }, open);
2163
+ const selectActiveOption = useCallback(() => {
2164
+ const entry = optionMapRef.current.get(activeIndex);
2165
+ if (entry) {
2166
+ setValue(entry.value);
2167
+ setOpen(false);
2168
+ focusTrigger();
2169
+ }
2170
+ }, [
2171
+ activeIndex,
2172
+ focusTrigger,
2173
+ setValue
2174
+ ]);
2175
+ const handleOptionsKeyDown = useCallback((e) => {
2176
+ switch (e.key) {
2177
+ case "ArrowDown":
2178
+ e.preventDefault();
2179
+ setActiveIndex((prev) => {
2180
+ const next = prev + 1;
2181
+ return next >= optionCount ? 0 : next;
2182
+ });
2183
+ break;
2184
+ case "ArrowUp":
2185
+ e.preventDefault();
2186
+ setActiveIndex((prev) => {
2187
+ const next = prev - 1;
2188
+ return next < 0 ? optionCount - 1 : next;
2189
+ });
2190
+ break;
2191
+ case "Home":
2192
+ e.preventDefault();
2193
+ setActiveIndex(0);
2194
+ break;
2195
+ case "End":
2196
+ e.preventDefault();
2197
+ setActiveIndex(optionCount - 1);
2198
+ break;
2199
+ case "Enter":
2200
+ case " ":
2201
+ e.preventDefault();
2202
+ selectActiveOption();
2203
+ break;
2204
+ }
2205
+ }, [optionCount, selectActiveOption]);
2206
+ useEffect(() => {
2207
+ if (!open || activeIndex < 0) return;
2208
+ optionMapRef.current.get(activeIndex)?.element?.scrollIntoView({ block: "nearest" });
2209
+ }, [activeIndex, open]);
2210
+ useEffect(() => {
2211
+ if (open) {
2212
+ let selectedIdx = -1;
2213
+ for (const [idx, entry] of optionMapRef.current.entries()) if (entry.value === value) {
2214
+ selectedIdx = idx;
2215
+ break;
2216
+ }
2217
+ setActiveIndex(selectedIdx >= 0 ? selectedIdx : 0);
2218
+ }
2219
+ }, [open, value]);
2220
+ useEffect(() => {
2221
+ if (mounted && popoverRef.current) popoverRef.current.focus({ preventScroll: true });
2222
+ }, [mounted, popoverRef]);
2223
+ const selectedContent = useMemo(() => {
2224
+ let matched = null;
2225
+ Children.forEach(options, (child) => {
2226
+ if (!isValidElement(child)) return;
2227
+ if (child.type === ListboxOption && child.props.value === value) matched = child.props.children;
2228
+ });
2229
+ return matched;
2230
+ }, [options, value]);
2231
+ const ctx = useMemo(() => ({
2232
+ value,
2233
+ setValue,
2234
+ open,
2235
+ setOpen,
2236
+ disabled,
2237
+ activeIndex,
2238
+ setActiveIndex,
2239
+ registerOption,
2240
+ optionCount,
2241
+ buttonId,
2242
+ listId
2243
+ }), [
2244
+ value,
2245
+ setValue,
2246
+ open,
2247
+ disabled,
2248
+ activeIndex,
2249
+ registerOption,
2250
+ optionCount,
2251
+ buttonId,
2252
+ listId
2253
+ ]);
2254
+ const handleButtonClick = useCallback(() => {
2255
+ if (!disabled) setOpen((prev) => !prev);
2256
+ }, [disabled]);
2257
+ const handleButtonKeyDown = useCallback((e) => {
2258
+ if (disabled) return;
2259
+ if (e.key === "ArrowDown" || e.key === "ArrowUp" || e.key === "Enter" || e.key === " ") {
2260
+ e.preventDefault();
2261
+ setOpen(true);
2262
+ }
2263
+ }, [disabled]);
2264
+ const selectedSharedClasses = cn("flex min-w-0 items-center", "*:data-[slot=icon]:size-5 *:data-[slot=icon]:shrink-0 sm:*:data-[slot=icon]:size-4", "*:data-[slot=icon]:text-zinc-500 group-data-focus/option:*:data-[slot=icon]:text-white dark:*:data-[slot=icon]:text-zinc-400", "forced-colors:*:data-[slot=icon]:text-[CanvasText] forced-colors:group-data-focus/option:*:data-[slot=icon]:text-[Canvas]", "*:data-[slot=avatar]:-mx-0.5 *:data-[slot=avatar]:size-6 sm:*:data-[slot=avatar]:size-5");
2265
+ const displayContent = selectedContent != null ? /* @__PURE__ */ jsx("span", {
2266
+ className: selectedSharedClasses,
2267
+ children: selectedContent
2268
+ }) : placeholder ? /* @__PURE__ */ jsx("span", {
2269
+ className: "block truncate text-zinc-500",
2270
+ children: placeholder
2271
+ }) : null;
2272
+ return /* @__PURE__ */ jsxs(ListboxContext.Provider, {
2273
+ value: ctx,
2274
+ children: [
2275
+ name && /* @__PURE__ */ jsx("input", {
2276
+ type: "hidden",
2277
+ name,
2278
+ value: String(value ?? "")
2279
+ }),
2280
+ /* @__PURE__ */ jsxs("button", {
2281
+ ref: triggerRef,
2282
+ id: buttonId,
2283
+ type: "button",
2284
+ role: "combobox",
2285
+ "aria-expanded": open,
2286
+ "aria-haspopup": "listbox",
2287
+ "aria-controls": open ? listId : void 0,
2288
+ "aria-label": ariaLabel,
2289
+ "aria-disabled": disabled || void 0,
2290
+ "data-slot": "control",
2291
+ "data-disabled": disabled ? "" : void 0,
2292
+ "data-active": open ? "" : void 0,
2293
+ disabled,
2294
+ onClick: handleButtonClick,
2295
+ onKeyDown: handleButtonKeyDown,
2296
+ className: cn([
2297
+ className,
2298
+ "group relative block w-full",
2299
+ "before:absolute before:inset-px before:rounded-[calc(var(--radius-lg)-1px)] before:bg-white before:shadow-sm",
2300
+ "dark:before:hidden",
2301
+ "focus:outline-hidden",
2302
+ "after:pointer-events-none after:absolute after:inset-0 after:rounded-lg after:ring-transparent after:ring-inset data-focus:after:ring-2 data-focus:after:ring-blue-500",
2303
+ "data-disabled:opacity-50 data-disabled:before:bg-zinc-950/5 data-disabled:before:shadow-none"
2304
+ ]),
2305
+ children: [/* @__PURE__ */ jsx("span", {
2306
+ className: cn([
2307
+ "relative block w-full appearance-none rounded-lg py-[calc(--spacing(2.5)-1px)] sm:py-[calc(--spacing(1.5)-1px)]",
2308
+ "min-h-11 sm:min-h-9",
2309
+ "pr-[calc(--spacing(7)-1px)] pl-[calc(--spacing(3.5)-1px)] sm:pl-[calc(--spacing(3)-1px)]",
2310
+ "text-left text-base/6 text-zinc-950 placeholder:text-zinc-500 sm:text-sm/6 dark:text-white forced-colors:text-[CanvasText]",
2311
+ "border border-zinc-950/10 group-data-active:border-zinc-950/20 group-data-hover:border-zinc-950/20 dark:border-white/10 dark:group-data-active:border-white/20 dark:group-data-hover:border-white/20",
2312
+ "bg-transparent dark:bg-white/5",
2313
+ "group-data-invalid:border-red-500 group-data-hover:group-data-invalid:border-red-500 dark:group-data-invalid:border-red-600 dark:data-hover:group-data-invalid:border-red-600",
2314
+ "group-data-disabled:border-zinc-950/20 group-data-disabled:opacity-100 dark:group-data-disabled:border-white/15 dark:group-data-disabled:bg-white/2.5 dark:group-data-disabled:data-hover:border-white/15"
2315
+ ]),
2316
+ children: displayContent
2317
+ }), /* @__PURE__ */ jsx("span", {
2318
+ className: "pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2",
2319
+ children: /* @__PURE__ */ jsxs("svg", {
2320
+ className: "size-5 stroke-zinc-500 group-data-disabled:stroke-zinc-600 sm:size-4 dark:stroke-zinc-400 forced-colors:stroke-[CanvasText]",
2321
+ viewBox: "0 0 16 16",
2322
+ "aria-hidden": "true",
2323
+ fill: "none",
2324
+ children: [/* @__PURE__ */ jsx("path", {
2325
+ d: "M5.75 10.75L8 13L10.25 10.75",
2326
+ strokeWidth: 1.5,
2327
+ strokeLinecap: "round",
2328
+ strokeLinejoin: "round"
2329
+ }), /* @__PURE__ */ jsx("path", {
2330
+ d: "M10.25 5.25L8 3L5.75 5.25",
2331
+ strokeWidth: 1.5,
2332
+ strokeLinecap: "round",
2333
+ strokeLinejoin: "round"
2334
+ })]
2335
+ })
2336
+ })]
2337
+ }),
2338
+ mounted && createPortal(/* @__PURE__ */ jsx("div", {
2339
+ ref: (node) => {
2340
+ popoverRef.current = node;
2341
+ nodeRef.current = node;
2342
+ },
2343
+ ...popoverProps,
2344
+ ...transitionProps,
2345
+ id: listId,
2346
+ role: "listbox",
2347
+ "aria-labelledby": buttonId,
2348
+ tabIndex: -1,
2349
+ onKeyDown: handleOptionsKeyDown,
2350
+ className: cn("[--anchor-offset:-1.625rem] [--anchor-padding:--spacing(4)] sm:[--anchor-offset:-1.375rem]", "isolate w-max min-w-[calc(var(--button-width)+1.75rem)] scroll-py-1 rounded-xl p-1 select-none", "outline outline-transparent focus:outline-hidden", "overflow-y-scroll overscroll-contain", "bg-white/75 backdrop-blur-xl dark:bg-zinc-800/75", "shadow-lg ring-1 ring-zinc-950/10 dark:ring-white/10 dark:ring-inset", "transition-opacity duration-100 ease-in data-closed:data-leave:opacity-0 data-transition:pointer-events-none"),
2351
+ style: {
2352
+ ...popoverProps.style,
2353
+ minWidth: triggerRef.current ? `${triggerRef.current.getBoundingClientRect().width + 28}px` : void 0
2354
+ },
2355
+ children: /* @__PURE__ */ jsx(OptionIndexProvider, { children: options })
2356
+ }), document.body)
2357
+ ]
2358
+ });
2359
+ }
2360
+ function ListboxOption({ children, className, value: optionValue, disabled: optionDisabled = false }) {
2361
+ const ctx = useListboxContext();
2362
+ const index = use(OptionIndexContext);
2363
+ const optionRef = useRef(null);
2364
+ const isSelected = ctx.value === optionValue;
2365
+ const isFocused = ctx.activeIndex === index;
2366
+ useEffect(() => {
2367
+ ctx.registerOption(index, optionValue, optionRef.current);
2368
+ }, [
2369
+ index,
2370
+ optionValue,
2371
+ ctx.registerOption,
2372
+ ctx
2373
+ ]);
2374
+ const sharedClasses = cn("flex min-w-0 items-center", "*:data-[slot=icon]:size-5 *:data-[slot=icon]:shrink-0 sm:*:data-[slot=icon]:size-4", "*:data-[slot=icon]:text-zinc-500 group-data-focus/option:*:data-[slot=icon]:text-white dark:*:data-[slot=icon]:text-zinc-400", "forced-colors:*:data-[slot=icon]:text-[CanvasText] forced-colors:group-data-focus/option:*:data-[slot=icon]:text-[Canvas]", "*:data-[slot=avatar]:-mx-0.5 *:data-[slot=avatar]:size-6 sm:*:data-[slot=avatar]:size-5");
2375
+ const handleClick = useCallback(() => {
2376
+ if (optionDisabled) return;
2377
+ ctx.setValue(optionValue);
2378
+ ctx.setOpen(false);
2379
+ }, [
2380
+ optionDisabled,
2381
+ ctx.setValue,
2382
+ ctx.setOpen,
2383
+ optionValue,
2384
+ ctx
2385
+ ]);
2386
+ const handlePointerEnter = useCallback(() => {
2387
+ if (!optionDisabled) ctx.setActiveIndex(index);
2388
+ }, [
2389
+ optionDisabled,
2390
+ ctx.setActiveIndex,
2391
+ index,
2392
+ ctx
2393
+ ]);
2394
+ return /* @__PURE__ */ jsxs("div", {
2395
+ ref: optionRef,
2396
+ role: "option",
2397
+ "aria-selected": isSelected,
2398
+ "aria-disabled": optionDisabled || void 0,
2399
+ "data-selected": isSelected ? "" : void 0,
2400
+ "data-focus": isFocused ? "" : void 0,
2401
+ "data-disabled": optionDisabled ? "" : void 0,
2402
+ onClick: handleClick,
2403
+ onPointerEnter: handlePointerEnter,
2404
+ tabIndex: -1,
2405
+ className: cn("group/option grid cursor-default grid-cols-[--spacing(5)_1fr] items-baseline gap-x-2 rounded-lg py-2.5 pr-3.5 pl-2 sm:grid-cols-[--spacing(4)_1fr] sm:py-1.5 sm:pr-3 sm:pl-1.5", "text-base/6 text-zinc-950 sm:text-sm/6 dark:text-white forced-colors:text-[CanvasText]", "outline-hidden data-focus:bg-blue-500 data-focus:text-white", "forced-color-adjust-none forced-colors:data-focus:bg-[Highlight] forced-colors:data-focus:text-[HighlightText]", "data-disabled:opacity-50"),
2406
+ children: [/* @__PURE__ */ jsx("svg", {
2407
+ className: "relative hidden size-5 self-center stroke-current group-data-selected/option:inline sm:size-4",
2408
+ viewBox: "0 0 16 16",
2409
+ fill: "none",
2410
+ "aria-hidden": "true",
2411
+ children: /* @__PURE__ */ jsx("path", {
2412
+ d: "M4 8.5l3 3L12 4",
2413
+ strokeWidth: 1.5,
2414
+ strokeLinecap: "round",
2415
+ strokeLinejoin: "round"
2416
+ })
2417
+ }), /* @__PURE__ */ jsx("span", {
2418
+ className: cn(className, sharedClasses, "col-start-2"),
2419
+ children
2420
+ })]
2421
+ });
2422
+ }
2423
+ function ListboxLabel({ className, ...props }) {
2424
+ return /* @__PURE__ */ jsx("span", {
2425
+ ...props,
2426
+ className: cn(className, "ml-2.5 truncate first:ml-0 sm:ml-2 sm:first:ml-0")
2427
+ });
2428
+ }
2429
+ function ListboxDescription({ className, children, ...props }) {
2430
+ return /* @__PURE__ */ jsx("span", {
2431
+ ...props,
2432
+ className: cn(className, "flex flex-1 overflow-hidden text-zinc-500 group-data-focus/option:text-white before:w-2 before:min-w-0 before:shrink dark:text-zinc-400"),
2433
+ children: /* @__PURE__ */ jsx("span", {
2434
+ className: "flex-1 truncate",
2435
+ children
2436
+ })
2437
+ });
2438
+ }
2439
+ //#endregion
2440
+ //#region src/hooks/use-layout-animation.tsx
2441
+ /**
2442
+ * Layout Animation Hook (FLIP Technique)
2443
+ *
2444
+ * Replaces motion/react's LayoutGroup + motion.span + layoutId pattern
2445
+ * with a native implementation using Web Animations API.
2446
+ *
2447
+ * The FLIP (First, Last, Invert, Play) technique:
2448
+ * 1. Record the element's position before it unmounts (First)
2449
+ * 2. Mount the new element and record its position (Last)
2450
+ * 3. Calculate the delta between positions (Invert)
2451
+ * 4. Animate from old position to new position (Play)
2452
+ *
2453
+ * @example
2454
+ * ```tsx
2455
+ * function NavSection({ children }) {
2456
+ * return <LayoutGroup>{children}</LayoutGroup>
2457
+ * }
2458
+ *
2459
+ * function NavItem({ current }) {
2460
+ * return (
2461
+ * <span>
2462
+ * {current && <LayoutIndicator layoutId="indicator" className="..." />}
2463
+ * ...
2464
+ * </span>
2465
+ * )
2466
+ * }
2467
+ * ```
2468
+ */
2469
+ var LayoutGroupContext = createContext(null);
2470
+ /**
2471
+ * Scopes layout animations to a group.
2472
+ * Elements with the same `layoutId` within a group share position data.
2473
+ */
2474
+ function LayoutGroup({ children }) {
2475
+ return /* @__PURE__ */ jsx(LayoutGroupContext, {
2476
+ value: useRef(/* @__PURE__ */ new Map()),
2477
+ children
2478
+ });
2479
+ }
2480
+ /** Spring-like easing approximation (matches motion's default layout spring) */
2481
+ var LAYOUT_EASING = "cubic-bezier(0.25, 0.8, 0.25, 1)";
2482
+ var LAYOUT_DURATION = 350;
2483
+ /**
2484
+ * Hook that implements FLIP layout animation for an element.
2485
+ *
2486
+ * When an element with the same `layoutId` unmounts from one position
2487
+ * and mounts in another, this hook animates the transition smoothly.
2488
+ *
2489
+ * @param layoutId - Shared identifier linking old and new positions
2490
+ * @returns Ref to attach to the animated element
2491
+ */
2492
+ function useLayoutAnimation(layoutId) {
2493
+ const ref = useRef(null);
2494
+ const rectsCtx = use(LayoutGroupContext);
2495
+ useLayoutEffect(() => {
2496
+ const el = ref.current;
2497
+ const rects = rectsCtx?.current;
2498
+ if (!(el && rects)) return;
2499
+ const prevRect = rects.get(layoutId);
2500
+ const currentRect = el.getBoundingClientRect();
2501
+ rects.set(layoutId, currentRect);
2502
+ if (prevRect) {
2503
+ const deltaX = prevRect.left - currentRect.left;
2504
+ const deltaY = prevRect.top - currentRect.top;
2505
+ if (Math.abs(deltaX) > .5 || Math.abs(deltaY) > .5) el.animate([{ transform: `translate(${deltaX}px, ${deltaY}px)` }, { transform: "translate(0, 0)" }], {
2506
+ duration: LAYOUT_DURATION,
2507
+ easing: LAYOUT_EASING,
2508
+ fill: "none"
2509
+ });
2510
+ }
2511
+ return () => {
2512
+ if (el) rects.set(layoutId, el.getBoundingClientRect());
2513
+ };
2514
+ });
2515
+ return ref;
2516
+ }
2517
+ /**
2518
+ * Animated indicator span that smoothly transitions between positions.
2519
+ * Drop-in replacement for `<motion.span layoutId="...">`.
2520
+ */
2521
+ function LayoutIndicator({ layoutId, ...props }) {
2522
+ return /* @__PURE__ */ jsx("span", {
2523
+ ref: useLayoutAnimation(layoutId),
2524
+ ...props
2525
+ });
2526
+ }
2527
+ //#endregion
2528
+ //#region src/components/navbar.tsx
2529
+ function Navbar({ className, ...props }) {
2530
+ return /* @__PURE__ */ jsx("nav", {
2531
+ ...props,
2532
+ className: cn(className, "flex flex-1 items-center gap-4 py-2.5")
2533
+ });
2534
+ }
2535
+ function NavbarDivider({ className, ...props }) {
2536
+ return /* @__PURE__ */ jsx("div", {
2537
+ "aria-hidden": "true",
2538
+ ...props,
2539
+ className: cn(className, "h-6 w-px bg-zinc-950/10 dark:bg-white/10")
2540
+ });
2541
+ }
2542
+ function NavbarSection({ className, ...props }) {
2543
+ return /* @__PURE__ */ jsx(LayoutGroup, {
2544
+ id: useId(),
2545
+ children: /* @__PURE__ */ jsx("div", {
2546
+ ...props,
2547
+ className: cn(className, "flex items-center gap-3")
2548
+ })
2549
+ });
2550
+ }
2551
+ function NavbarSpacer({ className, ...props }) {
2552
+ return /* @__PURE__ */ jsx("div", {
2553
+ "aria-hidden": "true",
2554
+ ...props,
2555
+ className: cn(className, "-ml-4 flex-1")
2556
+ });
2557
+ }
2558
+ function NavbarItem({ current, className, children, ref, ...props }) {
2559
+ const interactiveProps = useDataInteractive({ disabled: ("disabled" in props ? props.disabled : false) ?? false });
2560
+ const classes = cn("relative flex min-w-0 items-center gap-3 rounded-lg p-2 text-left text-base/6 font-medium text-zinc-950 sm:text-sm/5", "*:data-[slot=icon]:size-6 *:data-[slot=icon]:shrink-0 *:data-[slot=icon]:fill-zinc-500 sm:*:data-[slot=icon]:size-5", "*:not-nth-2:last:data-[slot=icon]:ml-auto *:not-nth-2:last:data-[slot=icon]:size-5 sm:*:not-nth-2:last:data-[slot=icon]:size-4", "*:data-[slot=avatar]:-m-0.5 *:data-[slot=avatar]:size-7 *:data-[slot=avatar]:[--avatar-radius:var(--radius-md)] sm:*:data-[slot=avatar]:size-6", "data-hover:bg-zinc-950/5 data-hover:*:data-[slot=icon]:fill-zinc-950", "data-active:bg-zinc-950/5 data-active:*:data-[slot=icon]:fill-zinc-950", "dark:text-white dark:*:data-[slot=icon]:fill-zinc-400", "dark:data-hover:bg-white/5 dark:data-hover:*:data-[slot=icon]:fill-white", "dark:data-active:bg-white/5 dark:data-active:*:data-[slot=icon]:fill-white");
2561
+ return /* @__PURE__ */ jsxs("span", {
2562
+ className: cn(className, "relative"),
2563
+ children: [current && /* @__PURE__ */ jsx(LayoutIndicator, {
2564
+ layoutId: "current-indicator",
2565
+ className: "absolute inset-x-2 -bottom-2.5 h-0.5 rounded-full bg-zinc-950 dark:bg-white"
2566
+ }), typeof props.href === "string" ? /* @__PURE__ */ jsx(Link, {
2567
+ ...props,
2568
+ className: classes,
2569
+ "data-current": current ? "true" : void 0,
2570
+ ref,
2571
+ children: /* @__PURE__ */ jsx(TouchTarget, { children })
2572
+ }) : /* @__PURE__ */ jsx("button", {
2573
+ type: "button",
2574
+ ...props,
2575
+ ...interactiveProps,
2576
+ className: cn("cursor-default", classes),
2577
+ "data-current": current ? "true" : void 0,
2578
+ ref,
2579
+ children: /* @__PURE__ */ jsx(TouchTarget, { children })
2580
+ })]
2581
+ });
2582
+ }
2583
+ function NavbarLabel({ className, ...props }) {
2584
+ return /* @__PURE__ */ jsx("span", {
2585
+ ...props,
2586
+ className: cn(className, "truncate")
2587
+ });
2588
+ }
2589
+ //#endregion
2590
+ //#region src/components/progress.tsx
2591
+ var trackClasses = {
2592
+ blue: "bg-blue-600 dark:bg-blue-500",
2593
+ green: "bg-green-600 dark:bg-green-500",
2594
+ red: "bg-red-600 dark:bg-red-500",
2595
+ amber: "bg-amber-500 dark:bg-amber-400",
2596
+ violet: "bg-violet-600 dark:bg-violet-500",
2597
+ zinc: "bg-zinc-600 dark:bg-zinc-400"
2598
+ };
2599
+ function Progress({ value, max = 100, color = "blue", size = "md", label, showValue = false, className }) {
2600
+ const percentage = Math.min(100, Math.max(0, value / max * 100));
2601
+ const heightClass = {
2602
+ xs: "h-1",
2603
+ sm: "h-1.5",
2604
+ md: "h-2.5",
2605
+ lg: "h-4"
2606
+ }[size];
2607
+ return /* @__PURE__ */ jsxs("div", {
2608
+ className: cn("w-full", className),
2609
+ children: [(label || showValue) && /* @__PURE__ */ jsxs("div", {
2610
+ className: "mb-1.5 flex items-center justify-between",
2611
+ children: [label && /* @__PURE__ */ jsx("span", {
2612
+ className: "text-sm font-medium text-zinc-700 dark:text-zinc-300",
2613
+ children: label
2614
+ }), showValue && /* @__PURE__ */ jsxs("span", {
2615
+ className: "text-sm text-zinc-500 dark:text-zinc-400",
2616
+ children: [Math.round(percentage), "%"]
2617
+ })]
2618
+ }), /* @__PURE__ */ jsx("div", {
2619
+ role: "progressbar",
2620
+ "aria-valuenow": value,
2621
+ "aria-valuemin": 0,
2622
+ "aria-valuemax": max,
2623
+ "aria-label": label ?? "Progress",
2624
+ className: cn("w-full overflow-hidden rounded-full bg-zinc-200 dark:bg-zinc-700", heightClass),
2625
+ children: /* @__PURE__ */ jsx("div", {
2626
+ className: cn("h-full rounded-full transition-all duration-300 ease-in-out", trackClasses[color]),
2627
+ style: { width: `${percentage}%` }
2628
+ })
2629
+ })]
2630
+ });
2631
+ }
2632
+ //#endregion
2633
+ //#region src/components/radio.tsx
2634
+ var RadioGroupContext = createContext(null);
2635
+ function useRadioGroupContext() {
2636
+ const ctx = use(RadioGroupContext);
2637
+ if (!ctx) throw new Error("Radio must be used within a RadioGroup");
2638
+ return ctx;
2639
+ }
2640
+ function RadioGroup({ className, value: controlledValue, defaultValue, onChange, disabled = false, name, children, ...props }) {
2641
+ const [value, setValue] = useControllableState({
2642
+ value: controlledValue,
2643
+ defaultValue: defaultValue ?? "",
2644
+ onChange
2645
+ });
2646
+ const handleKeyDown = useCallback((e) => {
2647
+ const radios = Array.from(e.currentTarget.querySelectorAll("[role=\"radio\"]:not([data-disabled])"));
2648
+ if (radios.length === 0) return;
2649
+ const currentIndex = radios.indexOf(document.activeElement);
2650
+ let nextIndex = currentIndex;
2651
+ switch (e.key) {
2652
+ case "ArrowDown":
2653
+ case "ArrowRight":
2654
+ e.preventDefault();
2655
+ nextIndex = currentIndex + 1 >= radios.length ? 0 : currentIndex + 1;
2656
+ break;
2657
+ case "ArrowUp":
2658
+ case "ArrowLeft":
2659
+ e.preventDefault();
2660
+ nextIndex = currentIndex - 1 < 0 ? radios.length - 1 : currentIndex - 1;
2661
+ break;
2662
+ case "Home":
2663
+ e.preventDefault();
2664
+ nextIndex = 0;
2665
+ break;
2666
+ case "End":
2667
+ e.preventDefault();
2668
+ nextIndex = radios.length - 1;
2669
+ break;
2670
+ default: return;
2671
+ }
2672
+ const nextRadio = radios[nextIndex];
2673
+ if (!nextRadio) return;
2674
+ nextRadio.focus();
2675
+ const radioValue = nextRadio.getAttribute("data-value");
2676
+ if (radioValue != null) setValue(radioValue);
2677
+ }, [setValue]);
2678
+ return /* @__PURE__ */ jsx(RadioGroupContext, {
2679
+ value: {
2680
+ value,
2681
+ onChange: setValue,
2682
+ disabled,
2683
+ name
2684
+ },
2685
+ children: /* @__PURE__ */ jsx("div", {
2686
+ role: "radiogroup",
2687
+ "data-slot": "control",
2688
+ onKeyDown: handleKeyDown,
2689
+ ...props,
2690
+ className: cn(className, "space-y-3 **:data-[slot=label]:font-normal", "has-data-[slot=description]:space-y-6 has-data-[slot=description]:**:data-[slot=label]:font-medium"),
2691
+ children
2692
+ })
2693
+ });
2694
+ }
2695
+ function RadioField({ className, disabled, ...props }) {
2696
+ return /* @__PURE__ */ jsx(FieldProvider, {
2697
+ disabled,
2698
+ children: /* @__PURE__ */ jsx("div", {
2699
+ "data-slot": "field",
2700
+ "data-disabled": disabled ? "" : void 0,
2701
+ ...props,
2702
+ className: cn(className, "grid grid-cols-[1.125rem_1fr] gap-x-4 gap-y-1 sm:grid-cols-[1rem_1fr]", "*:data-[slot=control]:col-start-1 *:data-[slot=control]:row-start-1 *:data-[slot=control]:mt-0.75 sm:*:data-[slot=control]:mt-1", "*:data-[slot=label]:col-start-2 *:data-[slot=label]:row-start-1", "*:data-[slot=description]:col-start-2 *:data-[slot=description]:row-start-2", "has-data-[slot=description]:**:data-[slot=label]:font-medium")
2703
+ })
2704
+ });
2705
+ }
2706
+ var base = [
2707
+ "relative isolate flex size-4.75 shrink-0 rounded-full sm:size-4.25",
2708
+ "before:absolute before:inset-0 before:-z-10 before:rounded-full before:bg-white before:shadow-sm",
2709
+ "group-data-checked:before:bg-(--radio-checked-bg)",
2710
+ "dark:before:hidden",
2711
+ "dark:bg-white/5 dark:group-data-checked:bg-(--radio-checked-bg)",
2712
+ "border border-zinc-950/15 group-data-checked:border-transparent group-data-hover:group-data-checked:border-transparent group-data-hover:border-zinc-950/30 group-data-checked:bg-(--radio-checked-border)",
2713
+ "dark:border-white/15 dark:group-data-checked:border-white/5 dark:group-data-hover:group-data-checked:border-white/5 dark:group-data-hover:border-white/30",
2714
+ "after:absolute after:inset-0 after:rounded-full after:shadow-[inset_0_1px_--theme(--color-white/15%)]",
2715
+ "dark:after:-inset-px dark:after:hidden dark:after:rounded-full dark:group-data-checked:after:block",
2716
+ "[--radio-indicator:transparent] group-data-checked:[--radio-indicator:var(--radio-checked-indicator)] group-data-hover:group-data-checked:[--radio-indicator:var(--radio-checked-indicator)] group-data-hover:[--radio-indicator:var(--color-zinc-900)]/10",
2717
+ "dark:group-data-hover:group-data-checked:[--radio-indicator:var(--radio-checked-indicator)] dark:group-data-hover:[--radio-indicator:var(--color-zinc-700)]",
2718
+ "group-data-focus:outline group-data-focus:outline-2 group-data-focus:outline-offset-2 group-data-focus:outline-blue-500",
2719
+ "group-data-disabled:opacity-50",
2720
+ "group-data-disabled:border-zinc-950/25 group-data-disabled:bg-zinc-950/5 group-data-disabled:[--radio-checked-indicator:var(--color-zinc-950)]/50 group-data-disabled:before:bg-transparent",
2721
+ "dark:group-data-disabled:border-white/20 dark:group-data-disabled:bg-white/2.5 dark:group-data-disabled:[--radio-checked-indicator:var(--color-white)]/50 dark:group-data-checked:group-data-disabled:after:hidden"
2722
+ ];
2723
+ var radioColors = {
2724
+ "dark/zinc": ["[--radio-checked-bg:var(--color-zinc-900)] [--radio-checked-border:var(--color-zinc-950)]/90 [--radio-checked-indicator:var(--color-white)]", "dark:[--radio-checked-bg:var(--color-zinc-600)]"],
2725
+ "dark/white": ["[--radio-checked-bg:var(--color-zinc-900)] [--radio-checked-border:var(--color-zinc-950)]/90 [--radio-checked-indicator:var(--color-white)]", "dark:[--radio-checked-bg:var(--color-white)] dark:[--radio-checked-border:var(--color-zinc-950)]/15 dark:[--radio-checked-indicator:var(--color-zinc-900)]"],
2726
+ white: "[--radio-checked-bg:var(--color-white)] [--radio-checked-border:var(--color-zinc-950)]/15 [--radio-checked-indicator:var(--color-zinc-900)]",
2727
+ dark: "[--radio-checked-bg:var(--color-zinc-900)] [--radio-checked-border:var(--color-zinc-950)]/90 [--radio-checked-indicator:var(--color-white)]",
2728
+ zinc: "[--radio-checked-indicator:var(--color-white)] [--radio-checked-bg:var(--color-zinc-600)] [--radio-checked-border:var(--color-zinc-700)]/90",
2729
+ red: "[--radio-checked-indicator:var(--color-white)] [--radio-checked-bg:var(--color-red-600)] [--radio-checked-border:var(--color-red-700)]/90",
2730
+ orange: "[--radio-checked-indicator:var(--color-white)] [--radio-checked-bg:var(--color-orange-500)] [--radio-checked-border:var(--color-orange-600)]/90",
2731
+ amber: "[--radio-checked-bg:var(--color-amber-400)] [--radio-checked-border:var(--color-amber-500)]/80 [--radio-checked-indicator:var(--color-amber-950)]",
2732
+ yellow: "[--radio-checked-bg:var(--color-yellow-300)] [--radio-checked-border:var(--color-yellow-400)]/80 [--radio-checked-indicator:var(--color-yellow-950)]",
2733
+ lime: "[--radio-checked-bg:var(--color-lime-300)] [--radio-checked-border:var(--color-lime-400)]/80 [--radio-checked-indicator:var(--color-lime-950)]",
2734
+ green: "[--radio-checked-indicator:var(--color-white)] [--radio-checked-bg:var(--color-green-600)] [--radio-checked-border:var(--color-green-700)]/90",
2735
+ emerald: "[--radio-checked-indicator:var(--color-white)] [--radio-checked-bg:var(--color-emerald-600)] [--radio-checked-border:var(--color-emerald-700)]/90",
2736
+ teal: "[--radio-checked-indicator:var(--color-white)] [--radio-checked-bg:var(--color-teal-600)] [--radio-checked-border:var(--color-teal-700)]/90",
2737
+ cyan: "[--radio-checked-bg:var(--color-cyan-300)] [--radio-checked-border:var(--color-cyan-400)]/80 [--radio-checked-indicator:var(--color-cyan-950)]",
2738
+ sky: "[--radio-checked-indicator:var(--color-white)] [--radio-checked-bg:var(--color-sky-500)] [--radio-checked-border:var(--color-sky-600)]/80",
2739
+ blue: "[--radio-checked-indicator:var(--color-white)] [--radio-checked-bg:var(--color-blue-600)] [--radio-checked-border:var(--color-blue-700)]/90",
2740
+ indigo: "[--radio-checked-indicator:var(--color-white)] [--radio-checked-bg:var(--color-indigo-500)] [--radio-checked-border:var(--color-indigo-600)]/90",
2741
+ violet: "[--radio-checked-indicator:var(--color-white)] [--radio-checked-bg:var(--color-violet-500)] [--radio-checked-border:var(--color-violet-600)]/90",
2742
+ purple: "[--radio-checked-indicator:var(--color-white)] [--radio-checked-bg:var(--color-purple-500)] [--radio-checked-border:var(--color-purple-600)]/90",
2743
+ fuchsia: "[--radio-checked-indicator:var(--color-white)] [--radio-checked-bg:var(--color-fuchsia-500)] [--radio-checked-border:var(--color-fuchsia-600)]/90",
2744
+ pink: "[--radio-checked-indicator:var(--color-white)] [--radio-checked-bg:var(--color-pink-500)] [--radio-checked-border:var(--color-pink-600)]/90",
2745
+ rose: "[--radio-checked-indicator:var(--color-white)] [--radio-checked-bg:var(--color-rose-500)] [--radio-checked-border:var(--color-rose-600)]/90"
2746
+ };
2747
+ function Radio({ color = "dark/zinc", className, value, disabled: localDisabled, ...props }) {
2748
+ const group = useRadioGroupContext();
2749
+ const disabled = localDisabled || group.disabled;
2750
+ const checked = group.value === value;
2751
+ const interactiveProps = useDataInteractive({ disabled });
2752
+ const handleClick = useCallback(() => {
2753
+ if (!disabled) group.onChange(value);
2754
+ }, [
2755
+ disabled,
2756
+ group,
2757
+ value
2758
+ ]);
2759
+ const handleKeyDown = useCallback((e) => {
2760
+ if ((e.key === " " || e.key === "Enter") && !disabled) {
2761
+ e.preventDefault();
2762
+ group.onChange(value);
2763
+ }
2764
+ }, [
2765
+ disabled,
2766
+ group,
2767
+ value
2768
+ ]);
2769
+ return /* @__PURE__ */ jsxs("span", {
2770
+ role: "radio",
2771
+ "data-slot": "control",
2772
+ "aria-checked": checked,
2773
+ "data-checked": checked ? "" : void 0,
2774
+ "data-disabled": disabled ? "" : void 0,
2775
+ "data-value": value,
2776
+ tabIndex: checked ? 0 : -1,
2777
+ onClick: handleClick,
2778
+ onKeyDown: handleKeyDown,
2779
+ ...interactiveProps,
2780
+ ...props,
2781
+ className: cn(className, "group inline-flex focus:outline-hidden"),
2782
+ children: [group.name && checked && /* @__PURE__ */ jsx("input", {
2783
+ type: "hidden",
2784
+ name: group.name,
2785
+ value
2786
+ }), /* @__PURE__ */ jsx("span", {
2787
+ className: cn([base, radioColors[color]]),
2788
+ children: /* @__PURE__ */ jsx("span", { className: cn("size-full rounded-full border-[4.5px] border-transparent bg-(--radio-indicator) bg-clip-padding", "forced-colors:border-[Canvas] forced-colors:group-data-checked:border-[Highlight]") })
2789
+ })]
2790
+ });
2791
+ }
2792
+ //#endregion
2793
+ //#region src/components/rating.tsx
2794
+ function Rating({ value: controlledValue, defaultValue = 0, max = 5, onChange, readOnly = false, size = "md", label, className }) {
2795
+ const [internalValue, setInternalValue] = useState(defaultValue);
2796
+ const [hovered, setHovered] = useState(0);
2797
+ const id = useId();
2798
+ const value = controlledValue ?? internalValue;
2799
+ const sizeClass = {
2800
+ sm: "size-4",
2801
+ md: "size-6",
2802
+ lg: "size-8"
2803
+ }[size];
2804
+ const handleClick = useCallback((star) => {
2805
+ if (readOnly) return;
2806
+ setInternalValue(star);
2807
+ onChange?.(star);
2808
+ }, [readOnly, onChange]);
2809
+ const display = hovered > 0 ? hovered : value;
2810
+ return /* @__PURE__ */ jsxs("div", {
2811
+ className,
2812
+ children: [label && /* @__PURE__ */ jsx("span", {
2813
+ id,
2814
+ className: "sr-only",
2815
+ children: label
2816
+ }), /* @__PURE__ */ jsx("div", {
2817
+ role: readOnly ? "img" : "radiogroup",
2818
+ "aria-label": label ?? `Rating: ${value} out of ${max}`,
2819
+ "aria-labelledby": label ? id : void 0,
2820
+ className: "flex items-center gap-0.5",
2821
+ children: Array.from({ length: max }).map((_, i) => {
2822
+ const star = i + 1;
2823
+ const filled = star <= display;
2824
+ return /* @__PURE__ */ jsx("button", {
2825
+ type: "button",
2826
+ role: readOnly ? void 0 : "radio",
2827
+ "aria-checked": readOnly ? void 0 : value === star,
2828
+ "aria-label": readOnly ? void 0 : `${star} star${star !== 1 ? "s" : ""}`,
2829
+ disabled: readOnly,
2830
+ onClick: () => handleClick(star),
2831
+ onMouseEnter: () => !readOnly && setHovered(star),
2832
+ onMouseLeave: () => !readOnly && setHovered(0),
2833
+ className: cn(sizeClass, "transition-colors", readOnly ? "cursor-default" : "cursor-pointer focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-500"),
2834
+ children: /* @__PURE__ */ jsx("svg", {
2835
+ viewBox: "0 0 20 20",
2836
+ "aria-hidden": "true",
2837
+ className: cn("size-full", filled ? "fill-amber-400 text-amber-400" : "fill-zinc-200 text-zinc-200 dark:fill-zinc-700 dark:text-zinc-700"),
2838
+ children: /* @__PURE__ */ jsx("path", { d: "M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" })
2839
+ })
2840
+ }, star);
2841
+ })
2842
+ })]
2843
+ });
2844
+ }
2845
+ //#endregion
2846
+ //#region src/components/Select.tsx
2847
+ var Check = ({ className }) => {
2848
+ return /* @__PURE__ */ jsxs("svg", {
2849
+ xmlns: "http://www.w3.org/2000/svg",
2850
+ fill: "none",
2851
+ viewBox: "0 0 24 24",
2852
+ strokeWidth: 1.5,
2853
+ stroke: "currentColor",
2854
+ className: cn("size-6", className),
2855
+ children: [/* @__PURE__ */ jsx("title", { children: "Selected" }), /* @__PURE__ */ jsx("path", {
2856
+ strokeLinecap: "round",
2857
+ strokeLinejoin: "round",
2858
+ d: "M6 12l4 4L18 8"
2859
+ })]
2860
+ });
2861
+ };
2862
+ var ChevronUp = ({ className }) => {
2863
+ return /* @__PURE__ */ jsxs("svg", {
2864
+ xmlns: "http://www.w3.org/2000/svg",
2865
+ fill: "none",
2866
+ viewBox: "0 0 24 24",
2867
+ strokeWidth: 1.5,
2868
+ stroke: "currentColor",
2869
+ className: cn("size-6", className),
2870
+ children: [/* @__PURE__ */ jsx("title", { children: "Scroll up" }), /* @__PURE__ */ jsx("path", {
2871
+ strokeLinecap: "round",
2872
+ strokeLinejoin: "round",
2873
+ d: "M19.5 15.75l-7.5-7.5-7.5 7.5"
2874
+ })]
2875
+ });
2876
+ };
2877
+ var ChevronDown = ({ className }) => {
2878
+ return /* @__PURE__ */ jsxs("svg", {
2879
+ xmlns: "http://www.w3.org/2000/svg",
2880
+ fill: "none",
2881
+ viewBox: "0 0 24 24",
2882
+ strokeWidth: 1.5,
2883
+ stroke: "currentColor",
2884
+ className: cn("size-6", className),
2885
+ children: [/* @__PURE__ */ jsx("title", { children: "Scroll down" }), /* @__PURE__ */ jsx("path", {
2886
+ strokeLinecap: "round",
2887
+ strokeLinejoin: "round",
2888
+ d: "M4.5 8.25l7.5 7.5 7.5-7.5"
2889
+ })]
2890
+ });
2891
+ };
2892
+ function Select$1({ children, className, ref, ...props }) {
2893
+ return /* @__PURE__ */ jsx(Box, {
2894
+ ref,
2895
+ className: cn(className),
2896
+ ...props,
2897
+ children
2898
+ });
2899
+ }
2900
+ Select$1.displayName = "Select";
2901
+ function SelectGroup({ children, className, ref, ...props }) {
2902
+ return /* @__PURE__ */ jsx(Box, {
2903
+ ref,
2904
+ className: cn(className),
2905
+ ...props,
2906
+ children
2907
+ });
2908
+ }
2909
+ function SelectValue({ placeholder, children, value, ref, ...props }) {
2910
+ return /* @__PURE__ */ jsx("span", {
2911
+ ref,
2912
+ ...props,
2913
+ children: children || placeholder || value
2914
+ });
2915
+ }
2916
+ function SelectTrigger({ children, className, ref, ...props }) {
2917
+ return /* @__PURE__ */ jsxs(Box, {
2918
+ className: cn("flex h-10 w-full items-center justify-between rounded border border-input bg-background px-3 py-2 text-inherit ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1", className),
2919
+ ref,
2920
+ ...props,
2921
+ children: [children, /* @__PURE__ */ jsx(ChevronDown, { className: "size-4 opacity-50" })]
2922
+ });
2923
+ }
2924
+ SelectTrigger.displayName = "SelectTrigger";
2925
+ function SelectScrollUpButton({ className, ref, ...props }) {
2926
+ return /* @__PURE__ */ jsx("button", {
2927
+ className: cn("flex cursor-default items-center justify-center py-1", className),
2928
+ ref,
2929
+ ...props,
2930
+ children: /* @__PURE__ */ jsx(ChevronUp, { className: "size-4" })
2931
+ });
2932
+ }
2933
+ function SelectScrollDownButton({ className, ref, ...props }) {
2934
+ return /* @__PURE__ */ jsx("button", {
2935
+ className: cn("flex cursor-default items-center justify-center py-1", className),
2936
+ ref,
2937
+ ...props,
2938
+ children: /* @__PURE__ */ jsx(ChevronDown, { className: "size-4" })
2939
+ });
2940
+ }
2941
+ function SelectContent({ children, className, ref, ...props }) {
2942
+ return /* @__PURE__ */ jsxs(Box, {
2943
+ className: cn("relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded border bg-card text-popover-foreground shadow-md", className),
2944
+ ref,
2945
+ ...props,
2946
+ children: [
2947
+ /* @__PURE__ */ jsx(SelectScrollUpButton, {}),
2948
+ /* @__PURE__ */ jsx("div", {
2949
+ className: "p-1",
2950
+ children
2951
+ }),
2952
+ /* @__PURE__ */ jsx(SelectScrollDownButton, {})
2953
+ ]
2954
+ });
2955
+ }
2956
+ SelectContent.displayName = "SelectContent";
2957
+ function SelectLabel({ className, ref, ...props }) {
2958
+ return /* @__PURE__ */ jsx("div", {
2959
+ className: cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className),
2960
+ ref,
2961
+ ...props
2962
+ });
2963
+ }
2964
+ function SelectItem({ children, className, value, ref, ...props }) {
2965
+ return /* @__PURE__ */ jsxs(Box, {
2966
+ className: cn("relative flex w-full cursor-default select-none items-center rounded py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", className),
2967
+ "data-value": value,
2968
+ ref,
2969
+ ...props,
2970
+ children: [/* @__PURE__ */ jsx("span", {
2971
+ className: "absolute left-2 flex size-3.5 items-center justify-center",
2972
+ children: /* @__PURE__ */ jsx(Check, { className: "size-4" })
2973
+ }), /* @__PURE__ */ jsx("span", { children })]
2974
+ });
2975
+ }
2976
+ SelectItem.displayName = "SelectItem";
2977
+ function SelectSeparator({ className, ref, ...props }) {
2978
+ return /* @__PURE__ */ jsx(Box, {
2979
+ className: cn("-mx-1 my-1 h-px bg-muted", className),
2980
+ ref,
2981
+ ...props
2982
+ });
2983
+ }
2984
+ SelectSeparator.displayName = "SelectSeparator";
2985
+ //#endregion
2986
+ //#region src/components/select-headless.tsx
2987
+ function Select({ className, multiple, disabled, invalid, ref, ...props }) {
2988
+ const interactiveProps = useDataInteractive({ disabled });
2989
+ const fieldProps = useFieldControlProps();
2990
+ return /* @__PURE__ */ jsxs("span", {
2991
+ "data-slot": "control",
2992
+ className: cn([
2993
+ className,
2994
+ "group relative block w-full",
2995
+ "before:absolute before:inset-px before:rounded-[calc(var(--radius-lg)-1px)] before:bg-white before:shadow-sm",
2996
+ "dark:before:hidden",
2997
+ "after:pointer-events-none after:absolute after:inset-0 after:rounded-lg after:ring-transparent after:ring-inset has-data-focus:after:ring-2 has-data-focus:after:ring-blue-500",
2998
+ "has-data-disabled:opacity-50 has-data-disabled:before:bg-zinc-950/5 has-data-disabled:before:shadow-none"
2999
+ ]),
3000
+ children: [/* @__PURE__ */ jsx("select", {
3001
+ ref,
3002
+ multiple,
3003
+ disabled,
3004
+ ...props,
3005
+ ...interactiveProps,
3006
+ ...fieldProps,
3007
+ "data-invalid": invalid ? "" : void 0,
3008
+ "data-disabled": disabled ? "" : void 0,
3009
+ className: cn([
3010
+ "relative block w-full appearance-none rounded-lg py-[calc(--spacing(2.5)-1px)] sm:py-[calc(--spacing(1.5)-1px)]",
3011
+ multiple ? "px-[calc(--spacing(3.5)-1px)] sm:px-[calc(--spacing(3)-1px)]" : "pr-[calc(--spacing(10)-1px)] pl-[calc(--spacing(3.5)-1px)] sm:pr-[calc(--spacing(9)-1px)] sm:pl-[calc(--spacing(3)-1px)]",
3012
+ "[&_optgroup]:font-semibold",
3013
+ "text-base/6 text-zinc-950 placeholder:text-zinc-500 sm:text-sm/6 dark:text-white dark:*:text-white",
3014
+ "border border-zinc-950/10 data-hover:border-zinc-950/20 dark:border-white/10 dark:data-hover:border-white/20",
3015
+ "bg-transparent dark:bg-white/5 dark:*:bg-zinc-800",
3016
+ "focus:outline-hidden",
3017
+ "data-invalid:border-red-500 data-invalid:data-hover:border-red-500 dark:data-invalid:border-red-600 dark:data-invalid:data-hover:border-red-600",
3018
+ "data-disabled:border-zinc-950/20 data-disabled:opacity-100 dark:data-disabled:border-white/15 dark:data-disabled:bg-white/2.5 dark:data-hover:data-disabled:border-white/15"
3019
+ ])
3020
+ }), !multiple && /* @__PURE__ */ jsx("span", {
3021
+ className: "pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2",
3022
+ children: /* @__PURE__ */ jsxs("svg", {
3023
+ className: "size-5 stroke-zinc-500 group-has-data-disabled:stroke-zinc-600 sm:size-4 dark:stroke-zinc-400 forced-colors:stroke-[CanvasText]",
3024
+ viewBox: "0 0 16 16",
3025
+ "aria-hidden": "true",
3026
+ fill: "none",
3027
+ children: [/* @__PURE__ */ jsx("path", {
3028
+ d: "M5.75 10.75L8 13L10.25 10.75",
3029
+ strokeWidth: 1.5,
3030
+ strokeLinecap: "round",
3031
+ strokeLinejoin: "round"
3032
+ }), /* @__PURE__ */ jsx("path", {
3033
+ d: "M10.25 5.25L8 3L5.75 5.25",
3034
+ strokeWidth: 1.5,
3035
+ strokeLinecap: "round",
3036
+ strokeLinejoin: "round"
3037
+ })]
3038
+ })
3039
+ })]
3040
+ });
3041
+ }
3042
+ //#endregion
3043
+ //#region src/hooks/use-close-context.ts
3044
+ var CloseContext = createContext(null);
3045
+ function useCloseContext() {
3046
+ return useContext(CloseContext);
3047
+ }
3048
+ //#endregion
3049
+ //#region src/components/sidebar.tsx
3050
+ function Sidebar({ className, ...props }) {
3051
+ return /* @__PURE__ */ jsx("nav", {
3052
+ ...props,
3053
+ className: cn(className, "flex h-full min-h-0 flex-col")
3054
+ });
3055
+ }
3056
+ function SidebarHeader({ className, ...props }) {
3057
+ return /* @__PURE__ */ jsx("div", {
3058
+ ...props,
3059
+ className: cn(className, "flex flex-col border-b border-zinc-950/5 p-4 dark:border-white/5 [&>[data-slot=section]+[data-slot=section]]:mt-2.5")
3060
+ });
3061
+ }
3062
+ function SidebarBody({ className, ...props }) {
3063
+ return /* @__PURE__ */ jsx("div", {
3064
+ ...props,
3065
+ className: cn(className, "flex flex-1 flex-col overflow-y-auto p-4 [&>[data-slot=section]+[data-slot=section]]:mt-8")
3066
+ });
3067
+ }
3068
+ function SidebarFooter({ className, ...props }) {
3069
+ return /* @__PURE__ */ jsx("div", {
3070
+ ...props,
3071
+ className: cn(className, "flex flex-col border-t border-zinc-950/5 p-4 dark:border-white/5 [&>[data-slot=section]+[data-slot=section]]:mt-2.5")
3072
+ });
3073
+ }
3074
+ function SidebarSection({ className, ...props }) {
3075
+ return /* @__PURE__ */ jsx(LayoutGroup, {
3076
+ id: useId(),
3077
+ children: /* @__PURE__ */ jsx("div", {
3078
+ ...props,
3079
+ "data-slot": "section",
3080
+ className: cn(className, "flex flex-col gap-0.5")
3081
+ })
3082
+ });
3083
+ }
3084
+ function SidebarDivider({ className, ...props }) {
3085
+ return /* @__PURE__ */ jsx("hr", {
3086
+ ...props,
3087
+ className: cn(className, "my-4 border-t border-zinc-950/5 lg:-mx-4 dark:border-white/5")
3088
+ });
3089
+ }
3090
+ function SidebarSpacer({ className, ...props }) {
3091
+ return /* @__PURE__ */ jsx("div", {
3092
+ "aria-hidden": "true",
3093
+ ...props,
3094
+ className: cn(className, "mt-8 flex-1")
3095
+ });
3096
+ }
3097
+ function SidebarHeading({ className, ...props }) {
3098
+ return /* @__PURE__ */ jsx("h3", {
3099
+ ...props,
3100
+ className: cn(className, "mb-1 px-2 text-xs/6 font-medium text-zinc-500 dark:text-zinc-400")
3101
+ });
3102
+ }
3103
+ function SidebarItem({ current, className, children, ref, ...props }) {
3104
+ const interactiveProps = useDataInteractive({ disabled: ("disabled" in props ? props.disabled : false) ?? false });
3105
+ const closeFn = useCloseContext();
3106
+ const propsOnClick = "onClick" in props ? props.onClick : void 0;
3107
+ const handleLinkClick = useCallback((e) => {
3108
+ propsOnClick?.(e);
3109
+ closeFn?.();
3110
+ }, [propsOnClick, closeFn]);
3111
+ const classes = cn("flex w-full items-center gap-3 rounded-lg px-2 py-2.5 text-left text-base/6 font-medium text-zinc-950 sm:py-2 sm:text-sm/5", "*:data-[slot=icon]:size-6 *:data-[slot=icon]:shrink-0 *:data-[slot=icon]:fill-zinc-500 sm:*:data-[slot=icon]:size-5", "*:last:data-[slot=icon]:ml-auto *:last:data-[slot=icon]:size-5 sm:*:last:data-[slot=icon]:size-4", "*:data-[slot=avatar]:-m-0.5 *:data-[slot=avatar]:size-7 sm:*:data-[slot=avatar]:size-6", "data-hover:bg-zinc-950/5 data-hover:*:data-[slot=icon]:fill-zinc-950", "data-active:bg-zinc-950/5 data-active:*:data-[slot=icon]:fill-zinc-950", "data-current:*:data-[slot=icon]:fill-zinc-950", "dark:text-white dark:*:data-[slot=icon]:fill-zinc-400", "dark:data-hover:bg-white/5 dark:data-hover:*:data-[slot=icon]:fill-white", "dark:data-active:bg-white/5 dark:data-active:*:data-[slot=icon]:fill-white", "dark:data-current:*:data-[slot=icon]:fill-white");
3112
+ return /* @__PURE__ */ jsxs("span", {
3113
+ className: cn(className, "relative"),
3114
+ children: [current && /* @__PURE__ */ jsx(LayoutIndicator, {
3115
+ layoutId: "current-indicator",
3116
+ className: "absolute inset-y-2 -left-4 w-0.5 rounded-full bg-zinc-950 dark:bg-white"
3117
+ }), typeof props.href === "string" ? /* @__PURE__ */ jsx(Link, {
3118
+ ...props,
3119
+ className: classes,
3120
+ "data-current": current ? "true" : void 0,
3121
+ ref,
3122
+ onClick: handleLinkClick,
3123
+ children: /* @__PURE__ */ jsx(TouchTarget, { children })
3124
+ }) : /* @__PURE__ */ jsx("button", {
3125
+ type: "button",
3126
+ ...props,
3127
+ ...interactiveProps,
3128
+ className: cn("cursor-default", classes),
3129
+ "data-current": current ? "true" : void 0,
3130
+ ref,
3131
+ children: /* @__PURE__ */ jsx(TouchTarget, { children })
3132
+ })]
3133
+ });
3134
+ }
3135
+ function SidebarLabel({ className, ...props }) {
3136
+ return /* @__PURE__ */ jsx("span", {
3137
+ ...props,
3138
+ className: cn(className, "truncate")
3139
+ });
3140
+ }
3141
+ //#endregion
3142
+ //#region src/components/sidebar-layout.tsx
3143
+ function OpenMenuIcon$1() {
3144
+ return /* @__PURE__ */ jsx("svg", {
3145
+ "data-slot": "icon",
3146
+ viewBox: "0 0 20 20",
3147
+ "aria-hidden": "true",
3148
+ children: /* @__PURE__ */ jsx("path", { d: "M2 6.75C2 6.33579 2.33579 6 2.75 6H17.25C17.6642 6 18 6.33579 18 6.75C18 7.16421 17.6642 7.5 17.25 7.5H2.75C2.33579 7.5 2 7.16421 2 6.75ZM2 13.25C2 12.8358 2.33579 12.5 2.75 12.5H17.25C17.6642 12.5 18 12.8358 18 13.25C18 13.6642 17.6642 14 17.25 14H2.75C2.33579 14 2 13.6642 2 13.25Z" })
3149
+ });
3150
+ }
3151
+ function CloseMenuIcon$1() {
3152
+ return /* @__PURE__ */ jsx("svg", {
3153
+ "data-slot": "icon",
3154
+ viewBox: "0 0 20 20",
3155
+ "aria-hidden": "true",
3156
+ children: /* @__PURE__ */ jsx("path", { d: "M6.28 5.22a.75.75 0 0 0-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 1 0 1.06 1.06L10 11.06l3.72 3.72a.75.75 0 1 0 1.06-1.06L11.06 10l3.72-3.72a.75.75 0 0 0-1.06-1.06L10 8.94 6.28 5.22Z" })
3157
+ });
3158
+ }
3159
+ function MobileSidebar$1({ open, close, children }) {
3160
+ const panelRef = useRef(null);
3161
+ const backdrop = useTransition(open);
3162
+ const panel = useTransition(open);
3163
+ useScrollLock(open);
3164
+ useFocusTrap(panelRef, open);
3165
+ useEscapeKey(close, open);
3166
+ if (!(backdrop.mounted || panel.mounted)) return null;
3167
+ return createPortal(/* @__PURE__ */ jsx(CloseContext.Provider, {
3168
+ value: close,
3169
+ children: /* @__PURE__ */ jsxs("div", {
3170
+ role: "dialog",
3171
+ "aria-modal": "true",
3172
+ className: "lg:hidden",
3173
+ children: [backdrop.mounted && /* @__PURE__ */ jsx("button", {
3174
+ type: "button",
3175
+ "aria-label": "Close navigation",
3176
+ ref: backdrop.nodeRef,
3177
+ ...backdrop.transitionProps,
3178
+ onClick: close,
3179
+ className: "fixed inset-0 bg-black/30 transition data-closed:opacity-0 data-enter:duration-300 data-enter:ease-out data-leave:duration-200 data-leave:ease-in"
3180
+ }), panel.mounted && /* @__PURE__ */ jsx("div", {
3181
+ ref: (node) => {
3182
+ panelRef.current = node;
3183
+ panel.nodeRef.current = node;
3184
+ },
3185
+ ...panel.transitionProps,
3186
+ className: "fixed inset-y-0 w-full max-w-80 p-2 transition duration-300 ease-in-out data-closed:-translate-x-full",
3187
+ children: /* @__PURE__ */ jsxs("div", {
3188
+ className: "flex h-full flex-col rounded-lg bg-white shadow-xs ring-1 ring-zinc-950/5 dark:bg-zinc-900 dark:ring-white/10",
3189
+ children: [/* @__PURE__ */ jsx("div", {
3190
+ className: "-mb-3 px-4 pt-3",
3191
+ children: /* @__PURE__ */ jsx(NavbarItem, {
3192
+ onClick: close,
3193
+ "aria-label": "Close navigation",
3194
+ children: /* @__PURE__ */ jsx(CloseMenuIcon$1, {})
3195
+ })
3196
+ }), children]
3197
+ })
3198
+ })]
3199
+ })
3200
+ }), document.body);
3201
+ }
3202
+ function SidebarLayout({ navbar, sidebar, children }) {
3203
+ const [showSidebar, setShowSidebar] = useState(false);
3204
+ return /* @__PURE__ */ jsxs("div", {
3205
+ className: "relative isolate flex min-h-svh w-full bg-white max-lg:flex-col lg:bg-zinc-100 dark:bg-zinc-900 dark:lg:bg-zinc-950",
3206
+ children: [
3207
+ /* @__PURE__ */ jsx("div", {
3208
+ className: "fixed inset-y-0 left-0 w-64 max-lg:hidden",
3209
+ children: sidebar
3210
+ }),
3211
+ /* @__PURE__ */ jsx(MobileSidebar$1, {
3212
+ open: showSidebar,
3213
+ close: () => setShowSidebar(false),
3214
+ children: sidebar
3215
+ }),
3216
+ /* @__PURE__ */ jsxs("header", {
3217
+ className: "flex items-center px-4 lg:hidden",
3218
+ children: [/* @__PURE__ */ jsx("div", {
3219
+ className: "py-2.5",
3220
+ children: /* @__PURE__ */ jsx(NavbarItem, {
3221
+ onClick: () => setShowSidebar(true),
3222
+ "aria-label": "Open navigation",
3223
+ children: /* @__PURE__ */ jsx(OpenMenuIcon$1, {})
3224
+ })
3225
+ }), /* @__PURE__ */ jsx("div", {
3226
+ className: "min-w-0 flex-1",
3227
+ children: navbar
3228
+ })]
3229
+ }),
3230
+ /* @__PURE__ */ jsx("main", {
3231
+ className: "flex flex-1 flex-col pb-2 lg:min-w-0 lg:pt-2 lg:pr-2 lg:pl-64",
3232
+ children: /* @__PURE__ */ jsx("div", {
3233
+ className: "grow p-6 lg:rounded-lg lg:bg-white lg:p-10 lg:shadow-xs lg:ring-1 lg:ring-zinc-950/5 dark:lg:bg-zinc-900 dark:lg:ring-white/10",
3234
+ children: /* @__PURE__ */ jsx("div", {
3235
+ className: "mx-auto max-w-6xl",
3236
+ children
3237
+ })
3238
+ })
3239
+ })
3240
+ ]
3241
+ });
3242
+ }
3243
+ //#endregion
3244
+ //#region src/components/slider.tsx
3245
+ function Slider({ value: controlledValue, defaultValue = 0, min = 0, max = 100, step = 1, onChange, disabled = false, label, showValue = false, className }) {
3246
+ const [internalValue, setInternalValue] = useState(defaultValue);
3247
+ const value = controlledValue ?? internalValue;
3248
+ const id = useId();
3249
+ const handleChange = useCallback((e) => {
3250
+ const next = Number(e.target.value);
3251
+ setInternalValue(next);
3252
+ onChange?.(next);
3253
+ }, [onChange]);
3254
+ const percentage = (value - min) / (max - min) * 100;
3255
+ return /* @__PURE__ */ jsxs("div", {
3256
+ className: cn("w-full", className),
3257
+ children: [(label || showValue) && /* @__PURE__ */ jsxs("div", {
3258
+ className: "mb-2 flex items-center justify-between",
3259
+ children: [label && /* @__PURE__ */ jsx("label", {
3260
+ htmlFor: id,
3261
+ className: "text-sm font-medium text-zinc-700 dark:text-zinc-300",
3262
+ children: label
3263
+ }), showValue && /* @__PURE__ */ jsx("span", {
3264
+ className: "text-sm text-zinc-500 dark:text-zinc-400",
3265
+ children: value
3266
+ })]
3267
+ }), /* @__PURE__ */ jsx("input", {
3268
+ id,
3269
+ type: "range",
3270
+ min,
3271
+ max,
3272
+ step,
3273
+ value,
3274
+ disabled,
3275
+ onChange: handleChange,
3276
+ style: { "--slider-pct": `${percentage}%` },
3277
+ className: cn("h-2 w-full cursor-pointer appearance-none rounded-full outline-none", "bg-zinc-200 dark:bg-zinc-700", "[&::-webkit-slider-thumb]:size-4 [&::-webkit-slider-thumb]:cursor-pointer [&::-webkit-slider-thumb]:appearance-none", "[&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-blue-600 [&::-webkit-slider-thumb]:shadow-sm", "[&::-webkit-slider-thumb]:ring-2 [&::-webkit-slider-thumb]:ring-white [&::-webkit-slider-thumb]:dark:ring-zinc-900", "[&::-moz-range-thumb]:size-4 [&::-moz-range-thumb]:cursor-pointer [&::-moz-range-thumb]:appearance-none", "[&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:border-none [&::-moz-range-thumb]:bg-blue-600", "focus-visible:[&::-webkit-slider-thumb]:outline-2 focus-visible:[&::-webkit-slider-thumb]:outline-offset-2 focus-visible:[&::-webkit-slider-thumb]:outline-blue-500", disabled && "cursor-not-allowed opacity-50")
3278
+ })]
3279
+ });
3280
+ }
3281
+ //#endregion
3282
+ //#region src/components/stacked-layout.tsx
3283
+ function OpenMenuIcon() {
3284
+ return /* @__PURE__ */ jsx("svg", {
3285
+ "data-slot": "icon",
3286
+ viewBox: "0 0 20 20",
3287
+ "aria-hidden": "true",
3288
+ children: /* @__PURE__ */ jsx("path", { d: "M2 6.75C2 6.33579 2.33579 6 2.75 6H17.25C17.6642 6 18 6.33579 18 6.75C18 7.16421 17.6642 7.5 17.25 7.5H2.75C2.33579 7.5 2 7.16421 2 6.75ZM2 13.25C2 12.8358 2.33579 12.5 2.75 12.5H17.25C17.6642 12.5 18 12.8358 18 13.25C18 13.6642 17.6642 14 17.25 14H2.75C2.33579 14 2 13.6642 2 13.25Z" })
3289
+ });
3290
+ }
3291
+ function CloseMenuIcon() {
3292
+ return /* @__PURE__ */ jsx("svg", {
3293
+ "data-slot": "icon",
3294
+ viewBox: "0 0 20 20",
3295
+ "aria-hidden": "true",
3296
+ children: /* @__PURE__ */ jsx("path", { d: "M6.28 5.22a.75.75 0 0 0-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 1 0 1.06 1.06L10 11.06l3.72 3.72a.75.75 0 1 0 1.06-1.06L11.06 10l3.72-3.72a.75.75 0 0 0-1.06-1.06L10 8.94 6.28 5.22Z" })
3297
+ });
3298
+ }
3299
+ function MobileSidebar({ open, close, children }) {
3300
+ const panelRef = useRef(null);
3301
+ const backdrop = useTransition(open);
3302
+ const panel = useTransition(open);
3303
+ useScrollLock(open);
3304
+ useFocusTrap(panelRef, open);
3305
+ useEscapeKey(close, open);
3306
+ if (!(backdrop.mounted || panel.mounted)) return null;
3307
+ return createPortal(/* @__PURE__ */ jsx(CloseContext.Provider, {
3308
+ value: close,
3309
+ children: /* @__PURE__ */ jsxs("div", {
3310
+ role: "dialog",
3311
+ "aria-modal": "true",
3312
+ className: "lg:hidden",
3313
+ children: [backdrop.mounted && /* @__PURE__ */ jsx("button", {
3314
+ type: "button",
3315
+ "aria-label": "Close navigation",
3316
+ ref: backdrop.nodeRef,
3317
+ ...backdrop.transitionProps,
3318
+ onClick: close,
3319
+ className: "fixed inset-0 bg-black/30 transition data-closed:opacity-0 data-enter:duration-300 data-enter:ease-out data-leave:duration-200 data-leave:ease-in"
3320
+ }), panel.mounted && /* @__PURE__ */ jsx("div", {
3321
+ ref: (node) => {
3322
+ panelRef.current = node;
3323
+ panel.nodeRef.current = node;
3324
+ },
3325
+ ...panel.transitionProps,
3326
+ className: "fixed inset-y-0 w-full max-w-80 p-2 transition duration-300 ease-in-out data-closed:-translate-x-full",
3327
+ children: /* @__PURE__ */ jsxs("div", {
3328
+ className: "flex h-full flex-col rounded-lg bg-white shadow-xs ring-1 ring-zinc-950/5 dark:bg-zinc-900 dark:ring-white/10",
3329
+ children: [/* @__PURE__ */ jsx("div", {
3330
+ className: "-mb-3 px-4 pt-3",
3331
+ children: /* @__PURE__ */ jsx(NavbarItem, {
3332
+ onClick: close,
3333
+ "aria-label": "Close navigation",
3334
+ children: /* @__PURE__ */ jsx(CloseMenuIcon, {})
3335
+ })
3336
+ }), children]
3337
+ })
3338
+ })]
3339
+ })
3340
+ }), document.body);
3341
+ }
3342
+ function StackedLayout({ navbar, sidebar, children }) {
3343
+ const [showSidebar, setShowSidebar] = useState(false);
3344
+ return /* @__PURE__ */ jsxs("div", {
3345
+ className: "relative isolate flex min-h-svh w-full flex-col bg-white lg:bg-zinc-100 dark:bg-zinc-900 dark:lg:bg-zinc-950",
3346
+ children: [
3347
+ /* @__PURE__ */ jsx(MobileSidebar, {
3348
+ open: showSidebar,
3349
+ close: () => setShowSidebar(false),
3350
+ children: sidebar
3351
+ }),
3352
+ /* @__PURE__ */ jsxs("header", {
3353
+ className: "flex items-center px-4",
3354
+ children: [/* @__PURE__ */ jsx("div", {
3355
+ className: "py-2.5 lg:hidden",
3356
+ children: /* @__PURE__ */ jsx(NavbarItem, {
3357
+ onClick: () => setShowSidebar(true),
3358
+ "aria-label": "Open navigation",
3359
+ children: /* @__PURE__ */ jsx(OpenMenuIcon, {})
3360
+ })
3361
+ }), /* @__PURE__ */ jsx("div", {
3362
+ className: "min-w-0 flex-1",
3363
+ children: navbar
3364
+ })]
3365
+ }),
3366
+ /* @__PURE__ */ jsx("main", {
3367
+ className: "flex flex-1 flex-col pb-2 lg:px-2",
3368
+ children: /* @__PURE__ */ jsx("div", {
3369
+ className: "grow p-6 lg:rounded-lg lg:bg-white lg:p-10 lg:shadow-xs lg:ring-1 lg:ring-zinc-950/5 dark:lg:bg-zinc-900 dark:lg:ring-white/10",
3370
+ children: /* @__PURE__ */ jsx("div", {
3371
+ className: "mx-auto max-w-6xl",
3372
+ children
3373
+ })
3374
+ })
3375
+ })
3376
+ ]
3377
+ });
3378
+ }
3379
+ //#endregion
3380
+ //#region src/components/stat.tsx
3381
+ var trendStyles = {
3382
+ up: { color: "var(--rvui-success, oklch(0.72 0.17 155))" },
3383
+ down: { color: "var(--rvui-error, oklch(0.65 0.2 25))" },
3384
+ neutral: { color: "var(--rvui-text-2, oklch(0.55 0.012 218))" }
3385
+ };
3386
+ var trendArrow = {
3387
+ up: "↑",
3388
+ down: "↓",
3389
+ neutral: "→"
3390
+ };
3391
+ function Stat({ label, value, change, trend, description, icon, className }) {
3392
+ return /* @__PURE__ */ jsxs("div", {
3393
+ className: cn("rounded-xl p-6 ring-1", className),
3394
+ style: {
3395
+ backgroundColor: "var(--rvui-surface-1, oklch(0.18 0.006 225))",
3396
+ "--tw-ring-color": "var(--rvui-border-subtle, oklch(0.28 0.006 222 / 0.4))",
3397
+ borderRadius: "var(--rvui-radius-lg, 16px)",
3398
+ transition: "box-shadow var(--rvui-duration-normal, 200ms) var(--rvui-ease, cubic-bezier(0.22, 1, 0.36, 1))"
3399
+ },
3400
+ children: [
3401
+ /* @__PURE__ */ jsxs("div", {
3402
+ className: "flex items-start justify-between",
3403
+ children: [/* @__PURE__ */ jsx("p", {
3404
+ className: "text-sm font-medium",
3405
+ style: { color: "var(--rvui-text-2, oklch(0.55 0.012 218))" },
3406
+ children: label
3407
+ }), icon && /* @__PURE__ */ jsx("div", {
3408
+ className: "rounded-lg p-2",
3409
+ style: { backgroundColor: "var(--rvui-surface-2, oklch(0.22 0.008 222))" },
3410
+ children: icon
3411
+ })]
3412
+ }),
3413
+ /* @__PURE__ */ jsx("p", {
3414
+ className: "mt-2 text-3xl font-semibold tracking-tight",
3415
+ style: { color: "var(--rvui-text-0, oklch(0.95 0.002 210))" },
3416
+ children: value
3417
+ }),
3418
+ (change || description) && /* @__PURE__ */ jsxs("div", {
3419
+ className: "mt-2 flex items-center gap-2",
3420
+ children: [change && trend && /* @__PURE__ */ jsxs("span", {
3421
+ className: "text-sm font-medium",
3422
+ style: trendStyles[trend],
3423
+ children: [
3424
+ trendArrow[trend],
3425
+ " ",
3426
+ change
3427
+ ]
3428
+ }), description && /* @__PURE__ */ jsx("span", {
3429
+ className: "text-sm",
3430
+ style: { color: "var(--rvui-text-2, oklch(0.55 0.012 218))" },
3431
+ children: description
3432
+ })]
3433
+ })
3434
+ ]
3435
+ });
3436
+ }
3437
+ function StatGroup({ className, children }) {
3438
+ return /* @__PURE__ */ jsx("div", {
3439
+ className: cn("grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4", className),
3440
+ children
3441
+ });
3442
+ }
3443
+ //#endregion
3444
+ //#region src/components/stepper.tsx
3445
+ function Stepper({ steps, orientation = "horizontal", className }) {
3446
+ return orientation === "vertical" ? /* @__PURE__ */ jsx(StepperVertical, {
3447
+ steps,
3448
+ className
3449
+ }) : /* @__PURE__ */ jsx(StepperHorizontal, {
3450
+ steps,
3451
+ className
3452
+ });
3453
+ }
3454
+ function StepIcon({ status }) {
3455
+ if (status === "complete") return /* @__PURE__ */ jsx("span", {
3456
+ className: "flex size-8 items-center justify-center rounded-full bg-blue-600",
3457
+ children: /* @__PURE__ */ jsx("svg", {
3458
+ viewBox: "0 0 16 16",
3459
+ fill: "none",
3460
+ className: "size-4 text-white",
3461
+ "aria-hidden": "true",
3462
+ children: /* @__PURE__ */ jsx("path", {
3463
+ d: "M3 8l3.5 3.5L13 4",
3464
+ stroke: "currentColor",
3465
+ strokeWidth: "2",
3466
+ strokeLinecap: "round",
3467
+ strokeLinejoin: "round"
3468
+ })
3469
+ })
3470
+ });
3471
+ if (status === "current") return /* @__PURE__ */ jsx("span", {
3472
+ className: "flex size-8 items-center justify-center rounded-full border-2 border-blue-600 bg-white dark:bg-zinc-900",
3473
+ children: /* @__PURE__ */ jsx("span", { className: "size-2.5 rounded-full bg-blue-600" })
3474
+ });
3475
+ return /* @__PURE__ */ jsx("span", {
3476
+ className: "flex size-8 items-center justify-center rounded-full border-2 border-zinc-300 bg-white dark:border-zinc-600 dark:bg-zinc-900",
3477
+ children: /* @__PURE__ */ jsx("span", { className: "size-2.5 rounded-full bg-transparent" })
3478
+ });
3479
+ }
3480
+ function StepperHorizontal({ steps, className }) {
3481
+ return /* @__PURE__ */ jsx("nav", {
3482
+ "aria-label": "Progress",
3483
+ children: /* @__PURE__ */ jsx("ol", {
3484
+ className: cn("flex items-center", className),
3485
+ children: steps.map((step, index) => {
3486
+ const isLast = index === steps.length - 1;
3487
+ return /* @__PURE__ */ jsxs("li", {
3488
+ "aria-current": step.status === "current" ? "step" : void 0,
3489
+ className: cn("flex items-center", !isLast && "flex-1"),
3490
+ children: [/* @__PURE__ */ jsxs("div", {
3491
+ className: "flex flex-col items-center gap-1.5",
3492
+ children: [/* @__PURE__ */ jsx(StepIcon, { status: step.status }), /* @__PURE__ */ jsx("span", {
3493
+ className: cn("text-xs font-medium", step.status === "current" ? "text-blue-600" : step.status === "complete" ? "text-zinc-950 dark:text-white" : "text-zinc-400 dark:text-zinc-500"),
3494
+ children: step.label
3495
+ })]
3496
+ }), !isLast && /* @__PURE__ */ jsx("div", {
3497
+ "aria-hidden": "true",
3498
+ className: cn("mx-3 h-px flex-1", step.status === "complete" ? "bg-blue-600" : "bg-zinc-200 dark:bg-zinc-700")
3499
+ })]
3500
+ }, index);
3501
+ })
3502
+ })
3503
+ });
3504
+ }
3505
+ function StepperVertical({ steps, className }) {
3506
+ return /* @__PURE__ */ jsx("nav", {
3507
+ "aria-label": "Progress",
3508
+ children: /* @__PURE__ */ jsx("ol", {
3509
+ className: cn("space-y-0", className),
3510
+ children: steps.map((step, index) => {
3511
+ const isLast = index === steps.length - 1;
3512
+ return /* @__PURE__ */ jsxs("li", {
3513
+ "aria-current": step.status === "current" ? "step" : void 0,
3514
+ className: "relative flex gap-4",
3515
+ children: [/* @__PURE__ */ jsxs("div", {
3516
+ className: "flex flex-col items-center",
3517
+ children: [/* @__PURE__ */ jsx(StepIcon, { status: step.status }), !isLast && /* @__PURE__ */ jsx("div", {
3518
+ "aria-hidden": "true",
3519
+ className: cn("w-px flex-1", step.status === "complete" ? "bg-blue-600" : "bg-zinc-200 dark:bg-zinc-700")
3520
+ })]
3521
+ }), /* @__PURE__ */ jsxs("div", {
3522
+ className: cn("pb-6 pt-1", isLast && "pb-0"),
3523
+ children: [/* @__PURE__ */ jsx("p", {
3524
+ className: cn("text-sm font-medium", step.status === "current" ? "text-blue-600" : step.status === "complete" ? "text-zinc-950 dark:text-white" : "text-zinc-400 dark:text-zinc-500"),
3525
+ children: step.label
3526
+ }), step.description && /* @__PURE__ */ jsx("p", {
3527
+ className: "mt-0.5 text-sm text-zinc-500 dark:text-zinc-400",
3528
+ children: step.description
3529
+ })]
3530
+ })]
3531
+ }, index);
3532
+ })
3533
+ })
3534
+ });
3535
+ }
3536
+ //#endregion
3537
+ //#region src/components/switch.tsx
3538
+ function SwitchGroup({ className, ...props }) {
3539
+ return /* @__PURE__ */ jsx("div", {
3540
+ "data-slot": "control",
3541
+ ...props,
3542
+ className: cn(className, "space-y-3 **:data-[slot=label]:font-normal", "has-data-[slot=description]:space-y-6 has-data-[slot=description]:**:data-[slot=label]:font-medium")
3543
+ });
3544
+ }
3545
+ function SwitchField({ className, disabled, ...props }) {
3546
+ return /* @__PURE__ */ jsx(FieldProvider, {
3547
+ disabled,
3548
+ children: /* @__PURE__ */ jsx("div", {
3549
+ "data-slot": "field",
3550
+ "data-disabled": disabled ? "" : void 0,
3551
+ ...props,
3552
+ className: cn(className, "grid grid-cols-[1fr_auto] gap-x-8 gap-y-1 sm:grid-cols-[1fr_auto]", "*:data-[slot=control]:col-start-2 *:data-[slot=control]:self-start sm:*:data-[slot=control]:mt-0.5", "*:data-[slot=label]:col-start-1 *:data-[slot=label]:row-start-1", "*:data-[slot=description]:col-start-1 *:data-[slot=description]:row-start-2", "has-data-[slot=description]:**:data-[slot=label]:font-medium")
3553
+ })
3554
+ });
3555
+ }
3556
+ var colors = {
3557
+ "dark/zinc": ["[--switch-bg-ring:var(--color-zinc-950)]/90 [--switch-bg:var(--color-zinc-900)] dark:[--switch-bg-ring:transparent] dark:[--switch-bg:var(--color-white)]/25", "[--switch-ring:var(--color-zinc-950)]/90 [--switch-shadow:var(--color-black)]/10 [--switch:white] dark:[--switch-ring:var(--color-zinc-700)]/90"],
3558
+ "dark/white": ["[--switch-bg-ring:var(--color-zinc-950)]/90 [--switch-bg:var(--color-zinc-900)] dark:[--switch-bg-ring:transparent] dark:[--switch-bg:var(--color-white)]", "[--switch-ring:var(--color-zinc-950)]/90 [--switch-shadow:var(--color-black)]/10 [--switch:white] dark:[--switch-ring:transparent] dark:[--switch:var(--color-zinc-900)]"],
3559
+ dark: ["[--switch-bg-ring:var(--color-zinc-950)]/90 [--switch-bg:var(--color-zinc-900)] dark:[--switch-bg-ring:var(--color-white)]/15", "[--switch-ring:var(--color-zinc-950)]/90 [--switch-shadow:var(--color-black)]/10 [--switch:white]"],
3560
+ zinc: ["[--switch-bg-ring:var(--color-zinc-700)]/90 [--switch-bg:var(--color-zinc-600)] dark:[--switch-bg-ring:transparent]", "[--switch-shadow:var(--color-black)]/10 [--switch:white] [--switch-ring:var(--color-zinc-700)]/90"],
3561
+ white: ["[--switch-bg-ring:var(--color-black)]/15 [--switch-bg:white] dark:[--switch-bg-ring:transparent]", "[--switch-shadow:var(--color-black)]/10 [--switch-ring:transparent] [--switch:var(--color-zinc-950)]"],
3562
+ red: ["[--switch-bg-ring:var(--color-red-700)]/90 [--switch-bg:var(--color-red-600)] dark:[--switch-bg-ring:transparent]", "[--switch:white] [--switch-ring:var(--color-red-700)]/90 [--switch-shadow:var(--color-red-900)]/20"],
3563
+ orange: ["[--switch-bg-ring:var(--color-orange-600)]/90 [--switch-bg:var(--color-orange-500)] dark:[--switch-bg-ring:transparent]", "[--switch:white] [--switch-ring:var(--color-orange-600)]/90 [--switch-shadow:var(--color-orange-900)]/20"],
3564
+ amber: ["[--switch-bg-ring:var(--color-amber-500)]/80 [--switch-bg:var(--color-amber-400)] dark:[--switch-bg-ring:transparent]", "[--switch-ring:transparent] [--switch-shadow:transparent] [--switch:var(--color-amber-950)]"],
3565
+ yellow: ["[--switch-bg-ring:var(--color-yellow-400)]/80 [--switch-bg:var(--color-yellow-300)] dark:[--switch-bg-ring:transparent]", "[--switch-ring:transparent] [--switch-shadow:transparent] [--switch:var(--color-yellow-950)]"],
3566
+ lime: ["[--switch-bg-ring:var(--color-lime-400)]/80 [--switch-bg:var(--color-lime-300)] dark:[--switch-bg-ring:transparent]", "[--switch-ring:transparent] [--switch-shadow:transparent] [--switch:var(--color-lime-950)]"],
3567
+ green: ["[--switch-bg-ring:var(--color-green-700)]/90 [--switch-bg:var(--color-green-600)] dark:[--switch-bg-ring:transparent]", "[--switch:white] [--switch-ring:var(--color-green-700)]/90 [--switch-shadow:var(--color-green-900)]/20"],
3568
+ emerald: ["[--switch-bg-ring:var(--color-emerald-600)]/90 [--switch-bg:var(--color-emerald-500)] dark:[--switch-bg-ring:transparent]", "[--switch:white] [--switch-ring:var(--color-emerald-600)]/90 [--switch-shadow:var(--color-emerald-900)]/20"],
3569
+ teal: ["[--switch-bg-ring:var(--color-teal-700)]/90 [--switch-bg:var(--color-teal-600)] dark:[--switch-bg-ring:transparent]", "[--switch:white] [--switch-ring:var(--color-teal-700)]/90 [--switch-shadow:var(--color-teal-900)]/20"],
3570
+ cyan: ["[--switch-bg-ring:var(--color-cyan-400)]/80 [--switch-bg:var(--color-cyan-300)] dark:[--switch-bg-ring:transparent]", "[--switch-ring:transparent] [--switch-shadow:transparent] [--switch:var(--color-cyan-950)]"],
3571
+ sky: ["[--switch-bg-ring:var(--color-sky-600)]/80 [--switch-bg:var(--color-sky-500)] dark:[--switch-bg-ring:transparent]", "[--switch:white] [--switch-ring:var(--color-sky-600)]/80 [--switch-shadow:var(--color-sky-900)]/20"],
3572
+ blue: ["[--switch-bg-ring:var(--color-blue-700)]/90 [--switch-bg:var(--color-blue-600)] dark:[--switch-bg-ring:transparent]", "[--switch:white] [--switch-ring:var(--color-blue-700)]/90 [--switch-shadow:var(--color-blue-900)]/20"],
3573
+ indigo: ["[--switch-bg-ring:var(--color-indigo-600)]/90 [--switch-bg:var(--color-indigo-500)] dark:[--switch-bg-ring:transparent]", "[--switch:white] [--switch-ring:var(--color-indigo-600)]/90 [--switch-shadow:var(--color-indigo-900)]/20"],
3574
+ violet: ["[--switch-bg-ring:var(--color-violet-600)]/90 [--switch-bg:var(--color-violet-500)] dark:[--switch-bg-ring:transparent]", "[--switch:white] [--switch-ring:var(--color-violet-600)]/90 [--switch-shadow:var(--color-violet-900)]/20"],
3575
+ purple: ["[--switch-bg-ring:var(--color-purple-600)]/90 [--switch-bg:var(--color-purple-500)] dark:[--switch-bg-ring:transparent]", "[--switch:white] [--switch-ring:var(--color-purple-600)]/90 [--switch-shadow:var(--color-purple-900)]/20"],
3576
+ fuchsia: ["[--switch-bg-ring:var(--color-fuchsia-600)]/90 [--switch-bg:var(--color-fuchsia-500)] dark:[--switch-bg-ring:transparent]", "[--switch:white] [--switch-ring:var(--color-fuchsia-600)]/90 [--switch-shadow:var(--color-fuchsia-900)]/20"],
3577
+ pink: ["[--switch-bg-ring:var(--color-pink-600)]/90 [--switch-bg:var(--color-pink-500)] dark:[--switch-bg-ring:transparent]", "[--switch:white] [--switch-ring:var(--color-pink-600)]/90 [--switch-shadow:var(--color-pink-900)]/20"],
3578
+ rose: ["[--switch-bg-ring:var(--color-rose-600)]/90 [--switch-bg:var(--color-rose-500)] dark:[--switch-bg-ring:transparent]", "[--switch:white] [--switch-ring:var(--color-rose-600)]/90 [--switch-shadow:var(--color-rose-900)]/20"]
3579
+ };
3580
+ function Switch({ color = "dark/zinc", className, checked: controlledChecked, defaultChecked, onChange, disabled, name, value, ...props }) {
3581
+ const { checked, toggleProps } = useToggle({
3582
+ checked: controlledChecked,
3583
+ defaultChecked,
3584
+ onChange,
3585
+ disabled
3586
+ });
3587
+ const interactiveProps = useDataInteractive({ disabled });
3588
+ return /* @__PURE__ */ jsxs("button", {
3589
+ type: "button",
3590
+ role: "switch",
3591
+ "data-slot": "control",
3592
+ "aria-checked": checked,
3593
+ "data-checked": checked ? "" : void 0,
3594
+ "data-disabled": disabled ? "" : void 0,
3595
+ disabled,
3596
+ onClick: toggleProps.onClick,
3597
+ onKeyDown: toggleProps.onKeyDown,
3598
+ ...interactiveProps,
3599
+ ...props,
3600
+ className: cn(className, "group relative isolate inline-flex h-6 w-10 cursor-default rounded-full p-[3px] sm:h-5 sm:w-8", "transition duration-0 ease-in-out data-changing:duration-200", "forced-colors:outline forced-colors:[--switch-bg:Highlight] dark:forced-colors:[--switch-bg:Highlight]", "bg-zinc-200 ring-1 ring-black/5 ring-inset dark:bg-white/5 dark:ring-white/15", "data-checked:bg-(--switch-bg) data-checked:ring-(--switch-bg-ring) dark:data-checked:bg-(--switch-bg) dark:data-checked:ring-(--switch-bg-ring)", "focus:not-data-focus:outline-hidden data-focus:outline-2 data-focus:outline-offset-2 data-focus:outline-blue-500", "data-hover:ring-black/15 data-hover:data-checked:ring-(--switch-bg-ring)", "dark:data-hover:ring-white/25 dark:data-hover:data-checked:ring-(--switch-bg-ring)", "data-disabled:bg-zinc-200 data-disabled:opacity-50 data-disabled:data-checked:bg-zinc-200 data-disabled:data-checked:ring-black/5", "dark:data-disabled:bg-white/15 dark:data-disabled:data-checked:bg-white/15 dark:data-disabled:data-checked:ring-white/15", colors[color]),
3601
+ children: [name && /* @__PURE__ */ jsx("input", {
3602
+ type: "hidden",
3603
+ name,
3604
+ value: checked ? value ?? "on" : ""
3605
+ }), /* @__PURE__ */ jsx("span", {
3606
+ "aria-hidden": "true",
3607
+ className: cn("pointer-events-none relative inline-block size-4.5 rounded-full sm:size-3.5", "translate-x-0 transition duration-200 ease-in-out", "border border-transparent", "bg-white shadow-sm ring-1 ring-black/5", "group-data-checked:bg-(--switch) group-data-checked:shadow-(--switch-shadow) group-data-checked:ring-(--switch-ring)", "group-data-checked:translate-x-4 sm:group-data-checked:translate-x-3", "group-data-checked:group-data-disabled:bg-white group-data-checked:group-data-disabled:shadow-sm group-data-checked:group-data-disabled:ring-black/5")
3608
+ })]
3609
+ });
3610
+ }
3611
+ //#endregion
3612
+ //#region src/components/tabs.tsx
3613
+ var TabsContext = createContext(null);
3614
+ function useTabsContext() {
3615
+ const ctx = use(TabsContext);
3616
+ if (!ctx) throw new Error("Tabs subcomponents must be used inside <Tabs>");
3617
+ return ctx;
3618
+ }
3619
+ function Tabs({ defaultTab, value, onChange, className, children }) {
3620
+ const baseId = useId();
3621
+ const [internalTab, setInternalTab] = useState(defaultTab ?? "");
3622
+ const activeTab = value ?? internalTab;
3623
+ const setActiveTab = (id) => {
3624
+ setInternalTab(id);
3625
+ onChange?.(id);
3626
+ };
3627
+ return /* @__PURE__ */ jsx(TabsContext, {
3628
+ value: {
3629
+ activeTab,
3630
+ setActiveTab,
3631
+ baseId
3632
+ },
3633
+ children: /* @__PURE__ */ jsx("div", {
3634
+ className,
3635
+ children
3636
+ })
3637
+ });
3638
+ }
3639
+ function TabList({ className, children }) {
3640
+ const listRef = useRef(null);
3641
+ const handleKeyDown = (e) => {
3642
+ if (!listRef.current) return;
3643
+ const tabs = Array.from(listRef.current.querySelectorAll("[role=\"tab\"]"));
3644
+ const current = tabs.indexOf(document.activeElement);
3645
+ if (current === -1) return;
3646
+ let next;
3647
+ if (e.key === "ArrowRight") next = (current + 1) % tabs.length;
3648
+ else if (e.key === "ArrowLeft") next = (current - 1 + tabs.length) % tabs.length;
3649
+ else if (e.key === "Home") next = 0;
3650
+ else if (e.key === "End") next = tabs.length - 1;
3651
+ if (next !== void 0) {
3652
+ e.preventDefault();
3653
+ tabs[next]?.focus();
3654
+ tabs[next]?.click();
3655
+ }
3656
+ };
3657
+ return /* @__PURE__ */ jsx("div", {
3658
+ ref: listRef,
3659
+ role: "tablist",
3660
+ onKeyDown: handleKeyDown,
3661
+ className: cn("flex border-b border-zinc-200 dark:border-zinc-700", className),
3662
+ children
3663
+ });
3664
+ }
3665
+ function Tab({ id, className, children }) {
3666
+ const { activeTab, setActiveTab, baseId } = useTabsContext();
3667
+ const isActive = activeTab === id;
3668
+ return /* @__PURE__ */ jsx("button", {
3669
+ type: "button",
3670
+ role: "tab",
3671
+ id: `${baseId}-tab-${id}`,
3672
+ "aria-controls": `${baseId}-panel-${id}`,
3673
+ "aria-selected": isActive,
3674
+ tabIndex: isActive ? 0 : -1,
3675
+ onClick: () => setActiveTab(id),
3676
+ className: cn(className, "relative -mb-px border-b-2 px-4 py-2.5 text-sm font-medium transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-500", isActive ? "border-blue-600 text-blue-600 dark:border-blue-400 dark:text-blue-400" : "border-transparent text-zinc-500 hover:text-zinc-700 dark:text-zinc-400 dark:hover:text-zinc-200"),
3677
+ children
3678
+ });
3679
+ }
3680
+ function TabPanel({ id, className, children }) {
3681
+ const { activeTab, baseId } = useTabsContext();
3682
+ if (activeTab !== id) return null;
3683
+ return /* @__PURE__ */ jsx("div", {
3684
+ role: "tabpanel",
3685
+ id: `${baseId}-panel-${id}`,
3686
+ "aria-labelledby": `${baseId}-tab-${id}`,
3687
+ tabIndex: 0,
3688
+ className: cn("focus-visible:outline-none", className),
3689
+ children
3690
+ });
3691
+ }
3692
+ //#endregion
3693
+ //#region src/components/textarea-headless.tsx
3694
+ function Textarea({ className, resizable = true, disabled, invalid, ref, ...props }) {
3695
+ const interactiveProps = useDataInteractive({ disabled });
3696
+ const fieldProps = useFieldControlProps();
3697
+ return /* @__PURE__ */ jsx("span", {
3698
+ "data-slot": "control",
3699
+ className: cn([
3700
+ className,
3701
+ "relative block w-full",
3702
+ "before:absolute before:inset-px before:rounded-[calc(var(--radius-lg)-1px)] before:bg-white before:shadow-sm",
3703
+ "dark:before:hidden",
3704
+ "after:pointer-events-none after:absolute after:inset-0 after:rounded-lg after:ring-transparent after:ring-inset sm:focus-within:after:ring-2 sm:focus-within:after:ring-blue-500",
3705
+ "has-data-disabled:opacity-50 has-data-disabled:before:bg-zinc-950/5 has-data-disabled:before:shadow-none"
3706
+ ]),
3707
+ children: /* @__PURE__ */ jsx("textarea", {
3708
+ ref,
3709
+ disabled,
3710
+ ...props,
3711
+ ...interactiveProps,
3712
+ ...fieldProps,
3713
+ "data-invalid": invalid ? "" : void 0,
3714
+ "data-disabled": disabled ? "" : void 0,
3715
+ className: cn([
3716
+ "relative block h-full w-full appearance-none rounded-lg px-[calc(--spacing(3.5)-1px)] py-[calc(--spacing(2.5)-1px)] sm:px-[calc(--spacing(3)-1px)] sm:py-[calc(--spacing(1.5)-1px)]",
3717
+ "text-base/6 text-zinc-950 placeholder:text-zinc-500 sm:text-sm/6 dark:text-white",
3718
+ "border border-zinc-950/10 data-hover:border-zinc-950/20 dark:border-white/10 dark:data-hover:border-white/20",
3719
+ "bg-transparent dark:bg-white/5",
3720
+ "focus:outline-hidden",
3721
+ "data-invalid:border-red-500 data-invalid:data-hover:border-red-500 dark:data-invalid:border-red-600 dark:data-invalid:data-hover:border-red-600",
3722
+ "disabled:border-zinc-950/20 dark:disabled:border-white/15 dark:disabled:bg-white/2.5 dark:data-hover:disabled:border-white/15",
3723
+ resizable ? "resize-y" : "resize-none"
3724
+ ])
3725
+ })
3726
+ });
3727
+ }
3728
+ //#endregion
3729
+ //#region src/components/timeline.tsx
3730
+ function Timeline({ className, children }) {
3731
+ return /* @__PURE__ */ jsx("ol", {
3732
+ className: cn("relative", className),
3733
+ children
3734
+ });
3735
+ }
3736
+ function TimelineItem({ icon, date, title, description, isLast = false, className }) {
3737
+ return /* @__PURE__ */ jsxs("li", {
3738
+ className: cn("relative flex gap-4", !isLast && "pb-8", className),
3739
+ children: [
3740
+ !isLast && /* @__PURE__ */ jsx("div", {
3741
+ "aria-hidden": "true",
3742
+ className: "absolute left-4 top-8 -bottom-0 w-px bg-zinc-200 dark:bg-zinc-700"
3743
+ }),
3744
+ /* @__PURE__ */ jsx("div", {
3745
+ className: "relative z-10 flex size-8 shrink-0 items-center justify-center rounded-full bg-white ring-1 ring-zinc-200 dark:bg-zinc-900 dark:ring-zinc-700",
3746
+ children: icon ?? /* @__PURE__ */ jsx("div", { className: "size-2 rounded-full bg-zinc-400 dark:bg-zinc-500" })
3747
+ }),
3748
+ /* @__PURE__ */ jsxs("div", {
3749
+ className: "flex-1 pt-0.5",
3750
+ children: [/* @__PURE__ */ jsxs("div", {
3751
+ className: "flex flex-wrap items-baseline justify-between gap-x-4",
3752
+ children: [/* @__PURE__ */ jsx("p", {
3753
+ className: "text-sm font-semibold text-zinc-950 dark:text-white",
3754
+ children: title
3755
+ }), date && /* @__PURE__ */ jsx("time", {
3756
+ className: "shrink-0 text-xs text-zinc-400 dark:text-zinc-500",
3757
+ children: date
3758
+ })]
3759
+ }), description && /* @__PURE__ */ jsx("p", {
3760
+ className: "mt-1 text-sm text-zinc-600 dark:text-zinc-400",
3761
+ children: description
3762
+ })]
3763
+ })
3764
+ ]
3765
+ });
3766
+ }
3767
+ //#endregion
3768
+ //#region src/components/toast.tsx
3769
+ function toastReducer(state, action) {
3770
+ switch (action.type) {
3771
+ case "ADD": return [...state, action.toast];
3772
+ case "REMOVE": return state.filter((t) => t.id !== action.id);
3773
+ }
3774
+ }
3775
+ var ToastContext = createContext(null);
3776
+ function ToastProvider({ children }) {
3777
+ const [toasts, dispatch] = useReducer(toastReducer, []);
3778
+ const addToast = useCallback((toast) => {
3779
+ const id = crypto.randomUUID();
3780
+ dispatch({
3781
+ type: "ADD",
3782
+ toast: {
3783
+ ...toast,
3784
+ id
3785
+ }
3786
+ });
3787
+ return id;
3788
+ }, []);
3789
+ const removeToast = useCallback((id) => {
3790
+ dispatch({
3791
+ type: "REMOVE",
3792
+ id
3793
+ });
3794
+ }, []);
3795
+ return /* @__PURE__ */ jsxs(ToastContext, {
3796
+ value: {
3797
+ toasts,
3798
+ addToast,
3799
+ removeToast
3800
+ },
3801
+ children: [children, typeof document !== "undefined" && createPortal(/* @__PURE__ */ jsx(ToastList, {
3802
+ toasts,
3803
+ onRemove: removeToast
3804
+ }), document.body)]
3805
+ });
3806
+ }
3807
+ function useToast() {
3808
+ const ctx = use(ToastContext);
3809
+ if (!ctx) throw new Error("useToast must be used within a ToastProvider");
3810
+ return ctx;
3811
+ }
3812
+ var variantClasses = {
3813
+ default: "bg-white dark:bg-zinc-800 ring-zinc-950/10 dark:ring-white/10",
3814
+ success: "bg-white dark:bg-zinc-800 ring-green-500/30",
3815
+ error: "bg-white dark:bg-zinc-800 ring-red-500/30",
3816
+ warning: "bg-white dark:bg-zinc-800 ring-amber-500/30",
3817
+ info: "bg-white dark:bg-zinc-800 ring-blue-500/30"
3818
+ };
3819
+ var variantIconClasses = {
3820
+ default: "hidden",
3821
+ success: "text-green-500",
3822
+ error: "text-red-500",
3823
+ warning: "text-amber-500",
3824
+ info: "text-blue-500"
3825
+ };
3826
+ var variantIcons = {
3827
+ default: "",
3828
+ success: "✓",
3829
+ error: "✕",
3830
+ warning: "!",
3831
+ info: "i"
3832
+ };
3833
+ function ToastList({ toasts, onRemove }) {
3834
+ if (toasts.length === 0) return null;
3835
+ return /* @__PURE__ */ jsx("div", {
3836
+ "aria-live": "assertive",
3837
+ className: "pointer-events-none fixed inset-0 z-50 flex flex-col items-end justify-end gap-2 p-4 sm:p-6",
3838
+ children: toasts.map((toast) => /* @__PURE__ */ jsx(ToastItem, {
3839
+ toast,
3840
+ onRemove
3841
+ }, toast.id))
3842
+ });
3843
+ }
3844
+ var EXIT_DURATION_MS = 150;
3845
+ function ToastItem({ toast, onRemove }) {
3846
+ const variant = toast.variant ?? "default";
3847
+ const [isExiting, setIsExiting] = useState(false);
3848
+ const handleRemove = useCallback(() => {
3849
+ setIsExiting(true);
3850
+ setTimeout(() => onRemove(toast.id), EXIT_DURATION_MS);
3851
+ }, [onRemove, toast.id]);
3852
+ useEffect(() => {
3853
+ const duration = toast.duration ?? 5e3;
3854
+ if (duration <= 0) return;
3855
+ const timer = setTimeout(handleRemove, duration);
3856
+ return () => clearTimeout(timer);
3857
+ }, [toast.duration, handleRemove]);
3858
+ return /* @__PURE__ */ jsxs("div", {
3859
+ role: "alert",
3860
+ className: cn("pointer-events-auto flex w-full max-w-sm items-start gap-3 rounded-xl p-4 shadow-lg ring-1 transition-all duration-200", variantClasses[variant], isExiting ? "translate-y-2 opacity-0" : "translate-y-0 opacity-100 animate-[slide-in-from-bottom_200ms_ease-out]"),
3861
+ children: [
3862
+ variant !== "default" && /* @__PURE__ */ jsx("span", {
3863
+ className: cn("mt-0.5 text-sm font-bold", variantIconClasses[variant]),
3864
+ children: variantIcons[variant]
3865
+ }),
3866
+ /* @__PURE__ */ jsxs("div", {
3867
+ className: "flex-1",
3868
+ children: [/* @__PURE__ */ jsx("p", {
3869
+ className: "text-sm font-semibold text-zinc-950 dark:text-white",
3870
+ children: toast.title
3871
+ }), toast.description && /* @__PURE__ */ jsx("p", {
3872
+ className: "mt-1 text-sm text-zinc-500 dark:text-zinc-400",
3873
+ children: toast.description
3874
+ })]
3875
+ }),
3876
+ /* @__PURE__ */ jsx("button", {
3877
+ type: "button",
3878
+ "aria-label": "Dismiss",
3879
+ onClick: handleRemove,
3880
+ className: "shrink-0 rounded-md text-zinc-400 hover:text-zinc-600 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-500 dark:text-zinc-500 dark:hover:text-zinc-300",
3881
+ children: /* @__PURE__ */ jsx("span", {
3882
+ "aria-hidden": "true",
3883
+ children: "✕"
3884
+ })
3885
+ })
3886
+ ]
3887
+ });
3888
+ }
3889
+ //#endregion
3890
+ //#region src/components/tooltip.tsx
3891
+ var sideClasses = {
3892
+ top: "bottom-full left-1/2 -translate-x-1/2 mb-2",
3893
+ bottom: "top-full left-1/2 -translate-x-1/2 mt-2",
3894
+ left: "right-full top-1/2 -translate-y-1/2 mr-2",
3895
+ right: "left-full top-1/2 -translate-y-1/2 ml-2"
3896
+ };
3897
+ function Tooltip({ content, side = "top", className, delay = 200, children }) {
3898
+ const id = useId();
3899
+ const [visible, setVisible] = useState(false);
3900
+ const timeoutRef = useRef(null);
3901
+ const clear = useCallback(() => {
3902
+ if (timeoutRef.current) {
3903
+ window.clearTimeout(timeoutRef.current);
3904
+ timeoutRef.current = null;
3905
+ }
3906
+ }, []);
3907
+ const show = useCallback(() => {
3908
+ clear();
3909
+ timeoutRef.current = window.setTimeout(() => {
3910
+ setVisible(true);
3911
+ }, delay);
3912
+ }, [delay, clear]);
3913
+ const hide = useCallback(() => {
3914
+ clear();
3915
+ setVisible(false);
3916
+ }, [clear]);
3917
+ useEffect(() => {
3918
+ return clear;
3919
+ }, [clear]);
3920
+ return /* @__PURE__ */ jsxs("span", {
3921
+ className: "relative inline-flex",
3922
+ onPointerEnter: show,
3923
+ onPointerLeave: hide,
3924
+ onMouseEnter: show,
3925
+ onMouseLeave: hide,
3926
+ onFocus: show,
3927
+ onBlur: hide,
3928
+ "aria-describedby": visible ? id : void 0,
3929
+ children: [children, visible && /* @__PURE__ */ jsx("span", {
3930
+ id,
3931
+ role: "tooltip",
3932
+ className: cn("pointer-events-none absolute z-50 w-max max-w-xs rounded-lg bg-zinc-950 px-2.5 py-1.5 text-xs text-white shadow-lg dark:bg-zinc-700", sideClasses[side], className),
3933
+ children: content
3934
+ })]
3935
+ });
3936
+ }
3937
+ //#endregion
3938
+ //#region src/hooks/use-theme.ts
3939
+ var STORAGE_KEY = "rvui-theme";
3940
+ var DATA_ATTR = "data-theme";
3941
+ /** Listeners for theme changes across components */
3942
+ var listeners = /* @__PURE__ */ new Set();
3943
+ function notifyListeners() {
3944
+ for (const listener of listeners) listener();
3945
+ }
3946
+ /** Resolve 'system' to 'light' or 'dark' based on media query */
3947
+ function resolveSystemTheme() {
3948
+ if (typeof window === "undefined") return "dark";
3949
+ return window.matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark";
3950
+ }
3951
+ /** Read stored preference or default to 'system' */
3952
+ function getStoredTheme() {
3953
+ if (typeof window === "undefined") return "system";
3954
+ try {
3955
+ const stored = localStorage.getItem(STORAGE_KEY);
3956
+ if (stored === "light" || stored === "dark" || stored === "system") return stored;
3957
+ } catch {}
3958
+ return "system";
3959
+ }
3960
+ /** Apply theme to the document element */
3961
+ function applyTheme(theme) {
3962
+ if (typeof document === "undefined") return;
3963
+ const resolved = theme === "system" ? resolveSystemTheme() : theme;
3964
+ document.documentElement.setAttribute(DATA_ATTR, resolved);
3965
+ }
3966
+ /** Store and apply theme, notify all subscribers */
3967
+ function setTheme(theme) {
3968
+ try {
3969
+ localStorage.setItem(STORAGE_KEY, theme);
3970
+ } catch {}
3971
+ applyTheme(theme);
3972
+ notifyListeners();
3973
+ }
3974
+ /** Get the current snapshot for useSyncExternalStore */
3975
+ function getSnapshot() {
3976
+ return getStoredTheme();
3977
+ }
3978
+ function getServerSnapshot() {
3979
+ return "system";
3980
+ }
3981
+ function subscribe(listener) {
3982
+ listeners.add(listener);
3983
+ return () => listeners.delete(listener);
3984
+ }
3985
+ /**
3986
+ * Hook to read and set the current theme.
3987
+ *
3988
+ * Persists preference to localStorage under `rvui-theme`.
3989
+ * Applies `data-theme` attribute to the document element.
3990
+ * Supports 'light', 'dark', and 'system' (auto-detect).
3991
+ *
3992
+ * @example
3993
+ * ```tsx
3994
+ * const { theme, resolvedTheme, setTheme } = useTheme();
3995
+ * <button onClick={() => setTheme(resolvedTheme === 'dark' ? 'light' : 'dark')}>
3996
+ * Toggle theme
3997
+ * </button>
3998
+ * ```
3999
+ */
4000
+ function useTheme() {
4001
+ const theme = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
4002
+ const resolved = theme === "system" ? resolveSystemTheme() : theme;
4003
+ useEffect(() => {
4004
+ applyTheme(theme);
4005
+ const mq = window.matchMedia("(prefers-color-scheme: light)");
4006
+ const handleChange = () => {
4007
+ if (getStoredTheme() === "system") {
4008
+ applyTheme("system");
4009
+ notifyListeners();
4010
+ }
4011
+ };
4012
+ mq.addEventListener("change", handleChange);
4013
+ return () => mq.removeEventListener("change", handleChange);
4014
+ }, [theme]);
4015
+ return {
4016
+ theme,
4017
+ resolvedTheme: resolved,
4018
+ setTheme: useCallback((t) => setTheme(t), [])
4019
+ };
4020
+ }
4021
+ //#endregion
4022
+ export { NavbarSection as $, CheckboxField as $t, SidebarSpacer as A, useTransition as An, useTypeAhead as At, SelectScrollUpButton as B, DialogDescription as Bt, SidebarDivider as C, AlertTitle as Cn, DropdownHeader as Ct, SidebarItem as D, TextLink as Dn, DropdownMenu as Dt, SidebarHeading as E, Text as En, DropdownLabel as Et, SelectContent as F, AccordionItem as Fn, DrawerHeader as Ft, Radio as G, Combobox as Gt, SelectTrigger as H, DescriptionDetails as Ht, SelectGroup as I, Divider as It, Progress as J, ComboboxOption as Jt, RadioField as K, ComboboxDescription as Kt, SelectItem as L, Dialog as Lt, useCloseContext as M, useFocusTrap as Mn, Drawer as Mt, Select as N, useEscapeKey as Nn, DrawerBody as Nt, SidebarLabel as O, Link as On, DropdownSection as Ot, Select$1 as P, Accordion as Pn, DrawerFooter as Pt, NavbarLabel as Q, Checkbox as Qt, SelectLabel as R, DialogActions as Rt, SidebarBody as S, AlertDescription as Sn, DropdownDivider as St, SidebarHeader as T, Strong as Tn, DropdownItem as Tt, SelectValue as U, DescriptionList as Ut, SelectSeparator as V, DialogTitle as Vt, Rating as W, DescriptionTerm as Wt, NavbarDivider as X, useClickOutside as Xt, Navbar as Y, usePopover as Yt, NavbarItem as Z, CodeBlock as Zt, StatGroup as _, Button as _n, Label as _t, Timeline as a, useFieldControlProps as an, ListboxDescription as at, SidebarLayout as b, AlertActions as bn, DropdownButton as bt, Tab as c, useFieldLabelProps as cn, Kbd as ct, Tabs as d, CheckboxIndicator as dn, InputGroup as dt, CheckboxGroup as en, NavbarSpacer as et, Switch as f, Badge as fn, Description as ft, Stat as g, AvatarButton as gn, Fieldset as gt, Stepper as h, Avatar as hn, FieldGroup as ht, useToast as i, useFieldContext as in, Listbox as it, CloseContext as j, useScrollLock as jn, useRovingTabindex as jt, SidebarSection as k, useDataInteractive as kn, DropdownShortcut as kt, TabList as l, Callout as ln, KbdShortcut as lt, SwitchGroup as m, AvatarGroup as mn, Field as mt, Tooltip as n, useControllableState as nn, LayoutIndicator as nt, TimelineItem as o, useFieldDescriptionProps as on, ListboxLabel as ot, SwitchField as p, BadgeButton as pn, ErrorMessage as pt, RadioGroup as q, ComboboxLabel as qt, ToastProvider as r, FieldProvider as rn, useLayoutAnimation as rt, Textarea as s, useFieldErrorProps as sn, ListboxOption as st, useTheme as t, useToggle as tn, LayoutGroup as tt, TabPanel as u, Checkbox$1 as un, Input as ut, StackedLayout as v, TouchTarget as vn, Legend as vt, SidebarFooter as w, Code as wn, DropdownHeading as wt, Sidebar as x, AlertBody as xn, DropdownDescription as xt, Slider as y, Alert as yn, Dropdown as yt, SelectScrollDownButton as z, DialogBody as zt };
4023
+
4024
+ //# sourceMappingURL=use-theme-QxeZadnD.js.map