@crimson_/altarev 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,3011 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ var clsx = require('clsx');
5
+ var tailwindMerge = require('tailwind-merge');
6
+ var jsxRuntime = require('react/jsx-runtime');
7
+ var classVarianceAuthority = require('class-variance-authority');
8
+ var react = require('react');
9
+ var reactDom = require('react-dom');
10
+ var reactDayPicker = require('react-day-picker');
11
+
12
+ // src/lib/cn.ts
13
+ function cn(...inputs) {
14
+ return tailwindMerge.twMerge(clsx.clsx(inputs));
15
+ }
16
+ function Container({ className, ...props }) {
17
+ return /* @__PURE__ */ jsxRuntime.jsx(
18
+ "div",
19
+ {
20
+ className: cn(
21
+ "mx-auto w-full max-w-container px-4 md:px-6 lg:px-8",
22
+ className
23
+ ),
24
+ ...props
25
+ }
26
+ );
27
+ }
28
+ var accordion = classVarianceAuthority.cva(
29
+ "group rounded-[8px] bg-surface text-text border border-border [&[open]>summary>svg]:rotate-180",
30
+ {
31
+ variants: {
32
+ size: {
33
+ sm: "text-xs",
34
+ md: "text-sm",
35
+ lg: "text-sm",
36
+ xl: "text-md"
37
+ }
38
+ },
39
+ defaultVariants: { size: "md" }
40
+ }
41
+ );
42
+ var PAD = { sm: "p-2", md: "px-3 py-2", lg: "p-3", xl: "p-4" };
43
+ var summary = classVarianceAuthority.cva(
44
+ "flex cursor-pointer list-none items-center gap-2 font-bold marker:hidden outline-none focus-visible:outline-2 focus-visible:outline-text focus-visible:outline-offset-2",
45
+ {
46
+ variants: { size: PAD },
47
+ defaultVariants: { size: "md" }
48
+ }
49
+ );
50
+ function Accordion({
51
+ size = "md",
52
+ title,
53
+ leading,
54
+ children,
55
+ className,
56
+ ...props
57
+ }) {
58
+ return /* @__PURE__ */ jsxRuntime.jsxs("details", { className: cn(accordion({ size }), className), ...props, children: [
59
+ /* @__PURE__ */ jsxRuntime.jsxs("summary", { className: summary({ size }), children: [
60
+ leading,
61
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: title }),
62
+ /* @__PURE__ */ jsxRuntime.jsx(ChevronDown, {})
63
+ ] }),
64
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-border" }),
65
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: PAD[size ?? "md"], children })
66
+ ] });
67
+ }
68
+ function ChevronDown() {
69
+ return /* @__PURE__ */ jsxRuntime.jsx(
70
+ "svg",
71
+ {
72
+ className: "size-6 shrink-0 transition-transform duration-200 ease-in-out",
73
+ viewBox: "0 0 24 24",
74
+ fill: "none",
75
+ stroke: "currentColor",
76
+ strokeWidth: "2",
77
+ strokeLinecap: "round",
78
+ strokeLinejoin: "round",
79
+ "aria-hidden": true,
80
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m6 9 6 6 6-6" })
81
+ }
82
+ );
83
+ }
84
+ var alert = classVarianceAuthority.cva(
85
+ "flex items-center gap-3 rounded-[8px] p-4 text-sm [&>svg]:size-6 [&>svg]:shrink-0",
86
+ {
87
+ variants: {
88
+ status: {
89
+ success: "",
90
+ error: "",
91
+ warning: "",
92
+ info: ""
93
+ },
94
+ styleVariant: {
95
+ colourful: "",
96
+ outline: "border",
97
+ generic: "bg-surface text-text"
98
+ }
99
+ },
100
+ compoundVariants: [
101
+ {
102
+ styleVariant: "colourful",
103
+ status: "success",
104
+ class: "bg-success-tint text-success"
105
+ },
106
+ {
107
+ styleVariant: "colourful",
108
+ status: "error",
109
+ class: "bg-error-tint text-error"
110
+ },
111
+ {
112
+ styleVariant: "colourful",
113
+ status: "warning",
114
+ class: "bg-warning-tint text-warning"
115
+ },
116
+ {
117
+ styleVariant: "colourful",
118
+ status: "info",
119
+ class: "bg-info-tint text-info"
120
+ },
121
+ {
122
+ styleVariant: "outline",
123
+ status: "success",
124
+ class: "border-success text-success"
125
+ },
126
+ {
127
+ styleVariant: "outline",
128
+ status: "error",
129
+ class: "border-error text-error"
130
+ },
131
+ {
132
+ styleVariant: "outline",
133
+ status: "warning",
134
+ class: "border-warning text-warning"
135
+ },
136
+ {
137
+ styleVariant: "outline",
138
+ status: "info",
139
+ class: "border-info text-info"
140
+ }
141
+ ],
142
+ defaultVariants: { status: "info", styleVariant: "generic" }
143
+ }
144
+ );
145
+ function Alert({
146
+ status = "info",
147
+ variant = "generic",
148
+ icon,
149
+ trailing,
150
+ children,
151
+ className,
152
+ ...props
153
+ }) {
154
+ return /* @__PURE__ */ jsxRuntime.jsxs(
155
+ "div",
156
+ {
157
+ role: "alert",
158
+ className: cn(alert({ status, styleVariant: variant }), className),
159
+ ...props,
160
+ children: [
161
+ icon,
162
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children }),
163
+ trailing
164
+ ]
165
+ }
166
+ );
167
+ }
168
+ function EmptyState({
169
+ icon,
170
+ title,
171
+ description,
172
+ children,
173
+ className,
174
+ ...props
175
+ }) {
176
+ return /* @__PURE__ */ jsxRuntime.jsxs(
177
+ "div",
178
+ {
179
+ className: cn(
180
+ "flex w-[374px] max-w-full flex-col items-center gap-2 px-4 text-center",
181
+ className
182
+ ),
183
+ ...props,
184
+ children: [
185
+ icon && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex size-20 items-center justify-center [&_svg]:size-20", children: icon }),
186
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 pb-6 text-text", children: [
187
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-2xl font-bold leading-8", children: title }),
188
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-base leading-6 text-text", children: description })
189
+ ] }),
190
+ children && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-start justify-center gap-3", children })
191
+ ]
192
+ }
193
+ );
194
+ }
195
+ var avatar = classVarianceAuthority.cva(
196
+ "relative inline-flex shrink-0 items-center justify-center overflow-visible rounded-full bg-surface font-bold text-text select-none",
197
+ {
198
+ variants: {
199
+ size: {
200
+ xs: "size-6 text-2xs",
201
+ sm: "size-8 text-xs",
202
+ md: "size-10 text-sm",
203
+ lg: "size-12 text-md",
204
+ xl: "size-14 text-md",
205
+ "2xl": "size-16 text-xl"
206
+ }
207
+ },
208
+ defaultVariants: { size: "md" }
209
+ }
210
+ );
211
+ var badgeCorner = {
212
+ tr: "top-0 right-0",
213
+ tl: "top-0 left-0",
214
+ br: "bottom-0 right-0",
215
+ bl: "bottom-0 left-0"
216
+ };
217
+ var badgeSize = {
218
+ xs: "size-1 border-2",
219
+ sm: "size-2 border-2",
220
+ md: "size-2 border-2",
221
+ lg: "size-3 border-4",
222
+ xl: "size-3 border-4",
223
+ "2xl": "size-3 border-4"
224
+ };
225
+ function Avatar({
226
+ size = "md",
227
+ src,
228
+ alt = "",
229
+ children,
230
+ badge,
231
+ badgeColor = "bg-success",
232
+ className,
233
+ ...props
234
+ }) {
235
+ return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn(avatar({ size }), className), ...props, children: [
236
+ src ? /* @__PURE__ */ jsxRuntime.jsx(
237
+ "img",
238
+ {
239
+ src,
240
+ alt,
241
+ className: "absolute inset-0 size-full rounded-full object-cover"
242
+ }
243
+ ) : children,
244
+ badge && /* @__PURE__ */ jsxRuntime.jsx(
245
+ "span",
246
+ {
247
+ className: cn(
248
+ "absolute rounded-full border-background",
249
+ badgeCorner[badge],
250
+ badgeSize[size ?? "md"],
251
+ badgeColor
252
+ )
253
+ }
254
+ )
255
+ ] });
256
+ }
257
+ var cell = classVarianceAuthority.cva(
258
+ "size-14 w-12 rounded-[8px] border bg-surface text-center text-sm text-text outline-none transition-shadow focus:border-[1.5px] focus:border-primary focus:ring-2 focus:ring-primary-tint",
259
+ {
260
+ variants: {
261
+ error: {
262
+ true: "border-[1.5px] border-[var(--color-input-error)] text-[var(--color-input-error)] focus:border-[var(--color-input-error)] focus:ring-0",
263
+ false: "border-border"
264
+ }
265
+ },
266
+ defaultVariants: { error: false }
267
+ }
268
+ );
269
+ function splitCode(raw, length) {
270
+ const digits = raw.replace(/\D/g, "").slice(0, length).split("");
271
+ return Array.from({ length }, (_, i) => digits[i] ?? "");
272
+ }
273
+ function AuthCode({
274
+ value,
275
+ onChange,
276
+ length = 6,
277
+ error = false,
278
+ disabled,
279
+ className
280
+ }) {
281
+ const refs = react.useRef([]);
282
+ const cells = splitCode(value, length);
283
+ const hasError = Boolean(error);
284
+ const setCharAt = (index, char) => {
285
+ const next = cells.slice();
286
+ next[index] = char;
287
+ onChange(next.join(""));
288
+ };
289
+ const focusCell = (index) => {
290
+ const el = refs.current[Math.max(0, Math.min(index, length - 1))];
291
+ el?.focus();
292
+ el?.select();
293
+ };
294
+ const handleInput = (index, raw) => {
295
+ const char = raw.replace(/\D/g, "").slice(-1);
296
+ if (!char) return;
297
+ setCharAt(index, char);
298
+ if (index < length - 1) focusCell(index + 1);
299
+ };
300
+ const handleKeyDown = (index, e) => {
301
+ if (e.key === "Backspace") {
302
+ e.preventDefault();
303
+ if (cells[index]) {
304
+ setCharAt(index, "");
305
+ } else if (index > 0) {
306
+ setCharAt(index - 1, "");
307
+ focusCell(index - 1);
308
+ }
309
+ } else if (e.key === "ArrowLeft") {
310
+ focusCell(index - 1);
311
+ } else if (e.key === "ArrowRight") {
312
+ focusCell(index + 1);
313
+ }
314
+ };
315
+ const handlePaste = (index, e) => {
316
+ e.preventDefault();
317
+ const pasted = e.clipboardData.getData("text").replace(/\D/g, "");
318
+ if (!pasted) return;
319
+ const next = cells.slice();
320
+ for (let i = 0; i < pasted.length && index + i < length; i++) {
321
+ next[index + i] = pasted[i];
322
+ }
323
+ onChange(next.join(""));
324
+ focusCell(index + pasted.length);
325
+ };
326
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-2", className), children: [
327
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-2", children: cells.map((char, i) => /* @__PURE__ */ jsxRuntime.jsx(
328
+ "input",
329
+ {
330
+ ref: (el) => {
331
+ refs.current[i] = el;
332
+ },
333
+ value: char,
334
+ disabled,
335
+ inputMode: "numeric",
336
+ autoComplete: "one-time-code",
337
+ "aria-label": `Digit ${i + 1}`,
338
+ "aria-invalid": hasError,
339
+ className: cn(cell({ error: hasError }), "disabled:opacity-50"),
340
+ onChange: (e) => handleInput(i, e.target.value),
341
+ onKeyDown: (e) => handleKeyDown(i, e),
342
+ onPaste: (e) => handlePaste(i, e),
343
+ onFocus: (e) => e.target.select()
344
+ },
345
+ i
346
+ )) }),
347
+ typeof error === "string" && error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-2 text-center text-xs text-[var(--color-input-error)]", children: error })
348
+ ] });
349
+ }
350
+ function Popover({
351
+ trigger,
352
+ children,
353
+ open: controlledOpen,
354
+ onOpenChange,
355
+ align = "start",
356
+ className
357
+ }) {
358
+ const [uncontrolledOpen, setUncontrolledOpen] = react.useState(false);
359
+ const isControlled = controlledOpen !== void 0;
360
+ const open = isControlled ? controlledOpen : uncontrolledOpen;
361
+ const anchorRef = react.useRef(null);
362
+ const panelRef = react.useRef(null);
363
+ const id = react.useId();
364
+ const setOpen = (next) => {
365
+ if (!isControlled) setUncontrolledOpen(next);
366
+ onOpenChange?.(next);
367
+ };
368
+ react.useEffect(() => {
369
+ if (!open) return;
370
+ const onPointerDown = (e) => {
371
+ const target = e.target;
372
+ if (!anchorRef.current?.contains(target) && !panelRef.current?.contains(target)) {
373
+ setOpen(false);
374
+ }
375
+ };
376
+ const onKeyDown = (e) => {
377
+ if (e.key === "Escape") setOpen(false);
378
+ };
379
+ document.addEventListener("pointerdown", onPointerDown);
380
+ document.addEventListener("keydown", onKeyDown);
381
+ return () => {
382
+ document.removeEventListener("pointerdown", onPointerDown);
383
+ document.removeEventListener("keydown", onKeyDown);
384
+ };
385
+ });
386
+ const triggerEl = react.cloneElement(trigger, {
387
+ onClick: (e) => {
388
+ trigger.props.onClick?.(e);
389
+ setOpen(!open);
390
+ },
391
+ "aria-expanded": open,
392
+ "aria-haspopup": true
393
+ });
394
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: anchorRef, className: "relative inline-block w-full", children: [
395
+ triggerEl,
396
+ open && /* @__PURE__ */ jsxRuntime.jsx(
397
+ "div",
398
+ {
399
+ ref: panelRef,
400
+ id,
401
+ role: "listbox",
402
+ className: cn(
403
+ "absolute z-50 mt-1 min-w-full rounded-[12px] border border-border bg-surface p-1 shadow-lg",
404
+ align === "end" ? "right-0" : "left-0",
405
+ className
406
+ ),
407
+ children
408
+ }
409
+ )
410
+ ] });
411
+ }
412
+ var ELLIPSIS = /* @__PURE__ */ Symbol("ellipsis");
413
+ function collapseItems(items, maxItems) {
414
+ const indexed = items.map((item, index) => ({ item, index }));
415
+ if (!maxItems || items.length <= maxItems || items.length <= 2) {
416
+ return indexed;
417
+ }
418
+ const tail = Math.max(1, maxItems - 1);
419
+ return [indexed[0], ELLIPSIS, ...indexed.slice(items.length - tail)];
420
+ }
421
+ function ArrowSeparator() {
422
+ return /* @__PURE__ */ jsxRuntime.jsx(
423
+ "svg",
424
+ {
425
+ className: "size-4 shrink-0 text-text-muted",
426
+ viewBox: "0 0 16 16",
427
+ fill: "none",
428
+ stroke: "currentColor",
429
+ strokeWidth: "1.5",
430
+ strokeLinecap: "round",
431
+ strokeLinejoin: "round",
432
+ "aria-hidden": true,
433
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 8h9M9 5l3 3-3 3" })
434
+ }
435
+ );
436
+ }
437
+ function Breadcrumbs({
438
+ items,
439
+ separator,
440
+ maxItems,
441
+ className,
442
+ ...props
443
+ }) {
444
+ const sep = separator ?? /* @__PURE__ */ jsxRuntime.jsx(ArrowSeparator, {});
445
+ const slots = collapseItems(items, maxItems);
446
+ const hidden = slots.includes(ELLIPSIS) && maxItems ? items.slice(1, items.length - Math.max(1, maxItems - 1)) : [];
447
+ return /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Breadcrumb", className, ...props, children: /* @__PURE__ */ jsxRuntime.jsx("ol", { className: "flex items-center gap-2 text-sm", children: slots.map((slot, i) => {
448
+ const isLast = i === slots.length - 1;
449
+ return /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
450
+ /* @__PURE__ */ jsxRuntime.jsx("li", { className: "flex items-center", children: slot === ELLIPSIS ? /* @__PURE__ */ jsxRuntime.jsx(
451
+ Popover,
452
+ {
453
+ align: "start",
454
+ trigger: /* @__PURE__ */ jsxRuntime.jsx(
455
+ "button",
456
+ {
457
+ type: "button",
458
+ "aria-label": "Show more",
459
+ className: "rounded-[4px] px-1 text-text-muted hover:text-text focus-visible:outline-2 focus-visible:outline-text focus-visible:outline-offset-2",
460
+ children: "\u2026"
461
+ }
462
+ ),
463
+ children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "min-w-32", children: hidden.map((h, hi) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
464
+ "a",
465
+ {
466
+ href: h.href,
467
+ className: "block rounded-[8px] px-3 py-2 text-sm text-text hover:bg-hover",
468
+ children: h.label
469
+ }
470
+ ) }, hi)) })
471
+ }
472
+ ) : isLast || !slot.item.href ? /* @__PURE__ */ jsxRuntime.jsx(
473
+ "span",
474
+ {
475
+ "aria-current": isLast ? "page" : void 0,
476
+ className: cn(
477
+ isLast ? "font-bold text-text" : "text-text-muted"
478
+ ),
479
+ children: slot.item.label
480
+ }
481
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
482
+ "a",
483
+ {
484
+ href: slot.item.href,
485
+ className: "text-text-muted hover:text-text hover:underline",
486
+ children: slot.item.label
487
+ }
488
+ ) }),
489
+ !isLast && /* @__PURE__ */ jsxRuntime.jsx("li", { "aria-hidden": true, className: "flex items-center text-text-muted", children: sep })
490
+ ] }, i);
491
+ }) }) });
492
+ }
493
+ var buttonVariants = classVarianceAuthority.cva(
494
+ "inline-flex shrink-0 items-center justify-center gap-2 rounded-[8px] font-bold whitespace-nowrap transition-colors outline-none focus-visible:outline-2 focus-visible:outline-text focus-visible:outline-offset-2 disabled:pointer-events-none disabled:opacity-50 active:scale-95 hover:brightness-95",
495
+ {
496
+ variants: {
497
+ variant: {
498
+ fill: "",
499
+ outline: "border bg-transparent",
500
+ ghost: "bg-transparent",
501
+ text: "bg-transparent hover:underline hover:brightness-100"
502
+ },
503
+ color: {
504
+ primary: "",
505
+ success: "",
506
+ error: "",
507
+ warning: "",
508
+ info: ""
509
+ },
510
+ size: {
511
+ xs: "h-8 px-3 text-xs",
512
+ sm: "h-8 px-3 text-sm",
513
+ md: "h-10 px-4 text-sm",
514
+ lg: "h-12 px-5 text-md",
515
+ xl: "h-14 px-6 text-md"
516
+ },
517
+ iconOnly: {
518
+ true: "aspect-square p-0",
519
+ false: ""
520
+ },
521
+ fullWidth: {
522
+ true: "w-full",
523
+ false: ""
524
+ }
525
+ },
526
+ compoundVariants: [
527
+ { variant: "fill", color: "primary", class: "bg-primary text-white" },
528
+ { variant: "fill", color: "success", class: "bg-success text-white" },
529
+ { variant: "fill", color: "error", class: "bg-error text-white" },
530
+ { variant: "fill", color: "warning", class: "bg-warning text-text" },
531
+ { variant: "fill", color: "info", class: "bg-info text-white" },
532
+ {
533
+ variant: "outline",
534
+ color: "primary",
535
+ class: "border-primary text-primary hover:bg-primary-tint"
536
+ },
537
+ {
538
+ variant: "outline",
539
+ color: "success",
540
+ class: "border-success text-success hover:bg-success-tint"
541
+ },
542
+ {
543
+ variant: "outline",
544
+ color: "error",
545
+ class: "border-error text-error hover:bg-error-tint"
546
+ },
547
+ {
548
+ variant: "outline",
549
+ color: "warning",
550
+ class: "border-warning text-warning hover:bg-warning-tint"
551
+ },
552
+ {
553
+ variant: "outline",
554
+ color: "info",
555
+ class: "border-info text-info hover:bg-info-tint"
556
+ },
557
+ {
558
+ variant: "ghost",
559
+ color: "primary",
560
+ class: "text-primary hover:bg-primary-tint"
561
+ },
562
+ {
563
+ variant: "ghost",
564
+ color: "success",
565
+ class: "text-success hover:bg-success-tint"
566
+ },
567
+ {
568
+ variant: "ghost",
569
+ color: "error",
570
+ class: "text-error hover:bg-error-tint"
571
+ },
572
+ {
573
+ variant: "ghost",
574
+ color: "warning",
575
+ class: "text-warning hover:bg-warning-tint"
576
+ },
577
+ {
578
+ variant: "ghost",
579
+ color: "info",
580
+ class: "text-info hover:bg-info-tint"
581
+ },
582
+ { variant: "text", color: "primary", class: "text-primary" },
583
+ { variant: "text", color: "success", class: "text-success" },
584
+ { variant: "text", color: "error", class: "text-error" },
585
+ { variant: "text", color: "warning", class: "text-warning" },
586
+ { variant: "text", color: "info", class: "text-info" },
587
+ { iconOnly: true, size: "xs", class: "size-8" },
588
+ { iconOnly: true, size: "sm", class: "size-8" },
589
+ { iconOnly: true, size: "md", class: "size-10" },
590
+ { iconOnly: true, size: "lg", class: "size-12" },
591
+ { iconOnly: true, size: "xl", class: "size-14" }
592
+ ],
593
+ defaultVariants: {
594
+ variant: "fill",
595
+ color: "primary",
596
+ size: "md",
597
+ iconOnly: false,
598
+ fullWidth: false
599
+ }
600
+ }
601
+ );
602
+ function Button({
603
+ variant = "fill",
604
+ color = "primary",
605
+ size = "md",
606
+ fullWidth = false,
607
+ leftIcon,
608
+ rightIcon,
609
+ className,
610
+ children,
611
+ ...props
612
+ }) {
613
+ const iconOnly = !children && Boolean(leftIcon ?? rightIcon);
614
+ return /* @__PURE__ */ jsxRuntime.jsxs(
615
+ "button",
616
+ {
617
+ className: cn(
618
+ buttonVariants({ variant, color, size, fullWidth, iconOnly }),
619
+ fullWidth && (leftIcon || rightIcon) && "justify-between",
620
+ className
621
+ ),
622
+ ...props,
623
+ children: [
624
+ leftIcon,
625
+ children,
626
+ rightIcon
627
+ ]
628
+ }
629
+ );
630
+ }
631
+ function nextIndex(current, count, dir, loop) {
632
+ const n = current + dir;
633
+ if (n < 0) return loop ? count - 1 : 0;
634
+ if (n >= count) return loop ? 0 : count - 1;
635
+ return n;
636
+ }
637
+ function Carousel({
638
+ children,
639
+ title,
640
+ description,
641
+ seeAllHref,
642
+ arrows = true,
643
+ indicators = true,
644
+ autoSlide = false,
645
+ interval = 5e3,
646
+ loop = true,
647
+ gap = 16,
648
+ className,
649
+ ...props
650
+ }) {
651
+ const trackRef = react.useRef(null);
652
+ const items = react.Children.toArray(children);
653
+ const count = items.length;
654
+ const [active, setActive] = react.useState(0);
655
+ const [progress, setProgress] = react.useState(0);
656
+ const scrollToIndex = react.useCallback((index) => {
657
+ const track2 = trackRef.current;
658
+ if (!track2) return;
659
+ const child = track2.children[index];
660
+ child?.scrollIntoView({
661
+ behavior: "smooth",
662
+ inline: "start",
663
+ block: "nearest"
664
+ });
665
+ }, []);
666
+ const go = react.useCallback(
667
+ (dir) => {
668
+ setActive((cur) => {
669
+ const target = nextIndex(cur, count, dir, loop);
670
+ scrollToIndex(target);
671
+ return target;
672
+ });
673
+ },
674
+ [count, loop, scrollToIndex]
675
+ );
676
+ react.useEffect(() => {
677
+ const track2 = trackRef.current;
678
+ if (!track2) return;
679
+ const observer = new IntersectionObserver(
680
+ (entries) => {
681
+ for (const entry of entries) {
682
+ if (entry.isIntersecting) {
683
+ const idx = Array.prototype.indexOf.call(
684
+ track2.children,
685
+ entry.target
686
+ );
687
+ if (idx >= 0) setActive(idx);
688
+ }
689
+ }
690
+ },
691
+ { root: track2, threshold: 0.6 }
692
+ );
693
+ for (const child of Array.from(track2.children)) observer.observe(child);
694
+ return () => observer.disconnect();
695
+ }, [count]);
696
+ react.useEffect(() => {
697
+ if (!autoSlide || count <= 1) return;
698
+ const step = 50;
699
+ let elapsed = 0;
700
+ const id = setInterval(() => {
701
+ elapsed += step;
702
+ setProgress(Math.min(1, elapsed / interval));
703
+ if (elapsed >= interval) {
704
+ elapsed = 0;
705
+ go(1);
706
+ }
707
+ }, step);
708
+ return () => clearInterval(id);
709
+ }, [autoSlide, interval, count, active, go]);
710
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-4", className), ...props, children: [
711
+ (title || description || seeAllHref || arrows) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-end justify-between gap-4", children: [
712
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
713
+ title && /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-xl font-bold text-text", children: title }),
714
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-text-muted", children: description })
715
+ ] }),
716
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
717
+ seeAllHref && /* @__PURE__ */ jsxRuntime.jsx(
718
+ "a",
719
+ {
720
+ href: seeAllHref,
721
+ className: "text-sm font-bold text-primary hover:underline",
722
+ children: "See all"
723
+ }
724
+ ),
725
+ arrows && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
726
+ /* @__PURE__ */ jsxRuntime.jsx(ArrowButton, { dir: "prev", onClick: () => go(-1) }),
727
+ /* @__PURE__ */ jsxRuntime.jsx(ArrowButton, { dir: "next", onClick: () => go(1) })
728
+ ] })
729
+ ] })
730
+ ] }),
731
+ /* @__PURE__ */ jsxRuntime.jsx(
732
+ "div",
733
+ {
734
+ ref: trackRef,
735
+ className: "flex snap-x snap-mandatory overflow-x-auto scroll-smooth [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
736
+ style: { gap },
737
+ children: items.map((child, i) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0 snap-start", children: child }, i))
738
+ }
739
+ ),
740
+ indicators && count > 1 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center gap-2", children: items.map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(
741
+ "button",
742
+ {
743
+ "aria-label": `Go to slide ${i + 1}`,
744
+ "aria-current": i === active,
745
+ onClick: () => {
746
+ setActive(i);
747
+ scrollToIndex(i);
748
+ },
749
+ className: "relative size-2 overflow-hidden rounded-full bg-border",
750
+ children: /* @__PURE__ */ jsxRuntime.jsx(
751
+ "span",
752
+ {
753
+ className: cn(
754
+ "absolute inset-0 rounded-full bg-primary transition-transform",
755
+ i === active ? "scale-100" : "scale-0"
756
+ ),
757
+ style: autoSlide && i === active ? {
758
+ transform: `scaleX(${progress})`,
759
+ transformOrigin: "left"
760
+ } : void 0
761
+ }
762
+ )
763
+ },
764
+ i
765
+ )) })
766
+ ] });
767
+ }
768
+ function ArrowButton({
769
+ dir,
770
+ onClick
771
+ }) {
772
+ return /* @__PURE__ */ jsxRuntime.jsx(
773
+ "button",
774
+ {
775
+ type: "button",
776
+ "aria-label": dir === "prev" ? "Previous" : "Next",
777
+ onClick,
778
+ className: "flex size-8 items-center justify-center rounded-full border border-border text-text transition-colors hover:bg-hover",
779
+ children: /* @__PURE__ */ jsxRuntime.jsx(
780
+ "svg",
781
+ {
782
+ className: cn("size-4", dir === "prev" && "rotate-180"),
783
+ viewBox: "0 0 16 16",
784
+ fill: "none",
785
+ stroke: "currentColor",
786
+ strokeWidth: "1.5",
787
+ strokeLinecap: "round",
788
+ strokeLinejoin: "round",
789
+ "aria-hidden": true,
790
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m6 4 4 4-4 4" })
791
+ }
792
+ )
793
+ }
794
+ );
795
+ }
796
+ function Checkbox({
797
+ label,
798
+ indeterminate = false,
799
+ className,
800
+ disabled,
801
+ ...props
802
+ }) {
803
+ const ref = react.useRef(null);
804
+ react.useEffect(() => {
805
+ if (ref.current) ref.current.indeterminate = indeterminate;
806
+ }, [indeterminate]);
807
+ const input = /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "relative inline-flex size-6 shrink-0", children: [
808
+ /* @__PURE__ */ jsxRuntime.jsx(
809
+ "input",
810
+ {
811
+ ref,
812
+ type: "checkbox",
813
+ disabled,
814
+ className: cn(
815
+ "peer size-6 cursor-pointer appearance-none rounded-[4px] border-[1.5px] border-text-muted bg-transparent transition-colors",
816
+ "checked:border-primary checked:bg-primary indeterminate:border-primary indeterminate:bg-primary",
817
+ "focus-visible:outline-2 focus-visible:outline-text focus-visible:outline-offset-2",
818
+ "disabled:cursor-not-allowed disabled:opacity-50",
819
+ className
820
+ ),
821
+ ...props
822
+ }
823
+ ),
824
+ /* @__PURE__ */ jsxRuntime.jsx(
825
+ "svg",
826
+ {
827
+ className: "pointer-events-none absolute inset-0 m-auto hidden size-4 text-white peer-checked:block peer-indeterminate:hidden",
828
+ viewBox: "0 0 16 16",
829
+ fill: "none",
830
+ stroke: "currentColor",
831
+ strokeWidth: "2",
832
+ strokeLinecap: "round",
833
+ strokeLinejoin: "round",
834
+ "aria-hidden": true,
835
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m3 8 3.5 3.5L13 5" })
836
+ }
837
+ ),
838
+ /* @__PURE__ */ jsxRuntime.jsx(
839
+ "svg",
840
+ {
841
+ className: "pointer-events-none absolute inset-0 m-auto hidden size-4 text-white peer-indeterminate:block",
842
+ viewBox: "0 0 16 16",
843
+ fill: "none",
844
+ stroke: "currentColor",
845
+ strokeWidth: "2",
846
+ strokeLinecap: "round",
847
+ "aria-hidden": true,
848
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4 8h8" })
849
+ }
850
+ )
851
+ ] });
852
+ if (!label) return input;
853
+ return /* @__PURE__ */ jsxRuntime.jsxs(
854
+ "label",
855
+ {
856
+ className: cn(
857
+ "inline-flex items-center gap-2 text-sm text-text",
858
+ disabled && "cursor-not-allowed opacity-50"
859
+ ),
860
+ children: [
861
+ input,
862
+ label
863
+ ]
864
+ }
865
+ );
866
+ }
867
+ var chip = classVarianceAuthority.cva(
868
+ "inline-flex items-center gap-2 bg-surface text-text whitespace-nowrap",
869
+ {
870
+ variants: {
871
+ size: {
872
+ sm: "h-8 rounded-[4px] px-2 text-sm [&_svg]:size-4",
873
+ md: "h-10 rounded-[8px] px-3 text-sm [&_svg]:size-6"
874
+ }
875
+ },
876
+ defaultVariants: { size: "md" }
877
+ }
878
+ );
879
+ function Chip({
880
+ size = "md",
881
+ leading,
882
+ trailing,
883
+ onDismiss,
884
+ className,
885
+ children,
886
+ ...props
887
+ }) {
888
+ return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn(chip({ size }), className), ...props, children: [
889
+ leading,
890
+ children,
891
+ onDismiss ? /* @__PURE__ */ jsxRuntime.jsx(
892
+ "button",
893
+ {
894
+ type: "button",
895
+ "aria-label": "Remove",
896
+ onClick: onDismiss,
897
+ className: "-mr-1 inline-flex shrink-0 items-center justify-center rounded-full text-text-muted hover:text-text focus-visible:outline-2 focus-visible:outline-text focus-visible:outline-offset-2",
898
+ children: /* @__PURE__ */ jsxRuntime.jsx(
899
+ "svg",
900
+ {
901
+ viewBox: "0 0 24 24",
902
+ fill: "none",
903
+ stroke: "currentColor",
904
+ strokeWidth: "2",
905
+ strokeLinecap: "round",
906
+ "aria-hidden": true,
907
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 6l12 12M18 6L6 18" })
908
+ }
909
+ )
910
+ }
911
+ ) : trailing
912
+ ] });
913
+ }
914
+ var tag = classVarianceAuthority.cva(
915
+ "inline-flex items-center gap-1 rounded-[4px] bg-background font-bold text-text whitespace-nowrap",
916
+ {
917
+ variants: {
918
+ size: {
919
+ "2xs": "h-4 px-1 text-[10px] [&_svg]:size-3",
920
+ xs: "h-6 px-2 text-xs [&_svg]:size-4"
921
+ },
922
+ uppercase: {
923
+ true: "uppercase",
924
+ false: ""
925
+ }
926
+ },
927
+ defaultVariants: { size: "xs", uppercase: false }
928
+ }
929
+ );
930
+ function Tag({
931
+ size = "xs",
932
+ uppercase,
933
+ leading,
934
+ trailing,
935
+ className,
936
+ children,
937
+ ...props
938
+ }) {
939
+ return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn(tag({ size, uppercase }), className), ...props, children: [
940
+ leading,
941
+ children,
942
+ trailing
943
+ ] });
944
+ }
945
+ function Radio({ label, className, disabled, ...props }) {
946
+ const input = /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "relative inline-flex size-6 shrink-0", children: [
947
+ /* @__PURE__ */ jsxRuntime.jsx(
948
+ "input",
949
+ {
950
+ type: "radio",
951
+ disabled,
952
+ className: cn(
953
+ "peer size-6 cursor-pointer appearance-none rounded-full border-[1.5px] border-text-muted bg-transparent transition-colors",
954
+ "checked:border-primary",
955
+ "focus-visible:outline-2 focus-visible:outline-text focus-visible:outline-offset-2",
956
+ "disabled:cursor-not-allowed disabled:opacity-50",
957
+ className
958
+ ),
959
+ ...props
960
+ }
961
+ ),
962
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pointer-events-none absolute inset-0 m-auto size-3 scale-0 rounded-full bg-primary transition-transform peer-checked:scale-100" })
963
+ ] });
964
+ if (!label) return input;
965
+ return /* @__PURE__ */ jsxRuntime.jsxs(
966
+ "label",
967
+ {
968
+ className: cn(
969
+ "inline-flex items-center gap-2 text-sm text-text",
970
+ disabled && "cursor-not-allowed opacity-50"
971
+ ),
972
+ children: [
973
+ input,
974
+ label
975
+ ]
976
+ }
977
+ );
978
+ }
979
+ var loader = classVarianceAuthority.cva(
980
+ "inline-block animate-spin rounded-full border-current border-t-transparent text-primary",
981
+ {
982
+ variants: {
983
+ size: {
984
+ "2xs": "size-4 border-2",
985
+ xs: "size-6 border-2",
986
+ sm: "size-8 border-[3px]",
987
+ md: "size-10 border-4",
988
+ lg: "size-12 border-4"
989
+ }
990
+ },
991
+ defaultVariants: { size: "md" }
992
+ }
993
+ );
994
+ function Loader({
995
+ size = "md",
996
+ label = "Loading",
997
+ className,
998
+ ...props
999
+ }) {
1000
+ return /* @__PURE__ */ jsxRuntime.jsx(
1001
+ "span",
1002
+ {
1003
+ role: "status",
1004
+ "aria-label": label,
1005
+ className: cn(loader({ size }), className),
1006
+ ...props
1007
+ }
1008
+ );
1009
+ }
1010
+ function Search({
1011
+ value,
1012
+ onValueChange,
1013
+ results,
1014
+ loading = false,
1015
+ emptyState = "No results",
1016
+ resultsTitle = "Search results",
1017
+ shortcut = "\u2318K",
1018
+ mobile = false,
1019
+ open: controlledOpen,
1020
+ onOpenChange,
1021
+ placeholder = "Search\u2026",
1022
+ className,
1023
+ ...props
1024
+ }) {
1025
+ const [uncontrolledOpen, setUncontrolledOpen] = react.useState(false);
1026
+ const isControlled = controlledOpen !== void 0;
1027
+ const open = isControlled ? controlledOpen : uncontrolledOpen;
1028
+ const rootRef = react.useRef(null);
1029
+ const inputRef = react.useRef(null);
1030
+ const setOpen = (next) => {
1031
+ if (!isControlled) setUncontrolledOpen(next);
1032
+ onOpenChange?.(next);
1033
+ };
1034
+ react.useEffect(() => {
1035
+ if (!open || mobile) return;
1036
+ const onPointerDown = (e) => {
1037
+ if (!rootRef.current?.contains(e.target)) setOpen(false);
1038
+ };
1039
+ const onKey = (e) => {
1040
+ if (e.key === "Escape") setOpen(false);
1041
+ };
1042
+ document.addEventListener("pointerdown", onPointerDown);
1043
+ document.addEventListener("keydown", onKey);
1044
+ return () => {
1045
+ document.removeEventListener("pointerdown", onPointerDown);
1046
+ document.removeEventListener("keydown", onKey);
1047
+ };
1048
+ });
1049
+ const hasResults = Boolean(results);
1050
+ const inputRow = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-14 items-center gap-3 px-4", children: [
1051
+ loading ? /* @__PURE__ */ jsxRuntime.jsx(Loader, { size: "2xs", className: "text-text-muted" }) : /* @__PURE__ */ jsxRuntime.jsx(SearchIcon, { className: "size-6 shrink-0 text-text-muted" }),
1052
+ /* @__PURE__ */ jsxRuntime.jsx(
1053
+ "input",
1054
+ {
1055
+ ref: inputRef,
1056
+ type: "search",
1057
+ value,
1058
+ placeholder,
1059
+ role: "searchbox",
1060
+ className: "flex-1 bg-transparent text-sm text-text outline-none placeholder:text-text-muted [&::-webkit-search-cancel-button]:hidden",
1061
+ onChange: (e) => onValueChange(e.target.value),
1062
+ onFocus: () => setOpen(true),
1063
+ ...props
1064
+ }
1065
+ ),
1066
+ value ? /* @__PURE__ */ jsxRuntime.jsx(
1067
+ "button",
1068
+ {
1069
+ type: "button",
1070
+ "aria-label": "Clear search",
1071
+ onClick: () => {
1072
+ onValueChange("");
1073
+ inputRef.current?.focus();
1074
+ },
1075
+ className: "inline-flex size-6 shrink-0 items-center justify-center rounded-full text-text-muted hover:bg-hover hover:text-text",
1076
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1077
+ "svg",
1078
+ {
1079
+ viewBox: "0 0 24 24",
1080
+ className: "size-4",
1081
+ fill: "none",
1082
+ stroke: "currentColor",
1083
+ strokeWidth: "2",
1084
+ strokeLinecap: "round",
1085
+ "aria-hidden": true,
1086
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 6l12 12M18 6L6 18" })
1087
+ }
1088
+ )
1089
+ }
1090
+ ) : shortcut && /* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "shrink-0 text-xs text-text-muted", children: shortcut })
1091
+ ] });
1092
+ const panel = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1093
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-border" }),
1094
+ hasResults && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-3 text-sm font-bold text-text-muted", children: resultsTitle }),
1095
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-h-80 overflow-auto p-1", children: loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-8", children: /* @__PURE__ */ jsxRuntime.jsx(Loader, {}) }) : hasResults ? results : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-8 text-center text-sm text-text-muted", children: emptyState }) })
1096
+ ] });
1097
+ if (mobile && open) {
1098
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fixed inset-0 z-50 flex flex-col bg-surface", children: [
1099
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", children: [
1100
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: inputRow }),
1101
+ /* @__PURE__ */ jsxRuntime.jsx(
1102
+ "button",
1103
+ {
1104
+ type: "button",
1105
+ "aria-label": "Close search",
1106
+ onClick: () => setOpen(false),
1107
+ className: "px-4 text-sm font-bold text-primary",
1108
+ children: "Cancel"
1109
+ }
1110
+ )
1111
+ ] }),
1112
+ panel
1113
+ ] });
1114
+ }
1115
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: rootRef, className: cn("relative w-full", className), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-[12px] border border-border bg-surface", children: [
1116
+ inputRow,
1117
+ open && panel
1118
+ ] }) });
1119
+ }
1120
+ function SearchIcon({ className }) {
1121
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1122
+ "svg",
1123
+ {
1124
+ className,
1125
+ viewBox: "0 0 24 24",
1126
+ fill: "none",
1127
+ stroke: "currentColor",
1128
+ strokeWidth: "2",
1129
+ strokeLinecap: "round",
1130
+ strokeLinejoin: "round",
1131
+ "aria-hidden": true,
1132
+ children: [
1133
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "11", cy: "11", r: "7" }),
1134
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m21 21-4.3-4.3" })
1135
+ ]
1136
+ }
1137
+ );
1138
+ }
1139
+ var container = classVarianceAuthority.cva(
1140
+ "inline-flex items-center gap-1 rounded-[12px] bg-background p-1",
1141
+ {
1142
+ variants: {
1143
+ size: {
1144
+ sm: "h-10",
1145
+ md: "h-12"
1146
+ }
1147
+ },
1148
+ defaultVariants: { size: "md" }
1149
+ }
1150
+ );
1151
+ var segment = classVarianceAuthority.cva(
1152
+ "inline-flex h-full flex-1 items-center justify-center gap-2 rounded-[8px] px-3 text-sm font-bold whitespace-nowrap transition-colors focus-visible:outline-2 focus-visible:outline-text focus-visible:outline-offset-2 [&_svg]:size-5",
1153
+ {
1154
+ variants: {
1155
+ active: {
1156
+ true: "bg-surface text-text shadow-sm",
1157
+ false: "text-text-muted hover:text-text"
1158
+ }
1159
+ },
1160
+ defaultVariants: { active: false }
1161
+ }
1162
+ );
1163
+ function SegmentedControl({
1164
+ items,
1165
+ value,
1166
+ onChange,
1167
+ size = "md",
1168
+ className,
1169
+ ...props
1170
+ }) {
1171
+ return /* @__PURE__ */ jsxRuntime.jsx(
1172
+ "div",
1173
+ {
1174
+ role: "tablist",
1175
+ className: cn(container({ size }), className),
1176
+ ...props,
1177
+ children: items.map((item) => {
1178
+ const active = item.value === value;
1179
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1180
+ "button",
1181
+ {
1182
+ type: "button",
1183
+ role: "tab",
1184
+ "aria-selected": active,
1185
+ onClick: () => onChange(item.value),
1186
+ className: segment({ active }),
1187
+ children: [
1188
+ item.icon,
1189
+ item.label
1190
+ ]
1191
+ },
1192
+ item.value
1193
+ );
1194
+ })
1195
+ }
1196
+ );
1197
+ }
1198
+ var TabsContext = react.createContext(null);
1199
+ function useTabs() {
1200
+ const ctx = react.useContext(TabsContext);
1201
+ if (!ctx) throw new Error("Tabs components must be used within <Tabs>");
1202
+ return ctx;
1203
+ }
1204
+ function Tabs({
1205
+ value,
1206
+ onValueChange,
1207
+ type = "underline",
1208
+ size = "md",
1209
+ children,
1210
+ className
1211
+ }) {
1212
+ const baseId = react.useId();
1213
+ return /* @__PURE__ */ jsxRuntime.jsx(
1214
+ TabsContext.Provider,
1215
+ {
1216
+ value: { value, setValue: onValueChange, type, size, baseId },
1217
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className, children })
1218
+ }
1219
+ );
1220
+ }
1221
+ var list = classVarianceAuthority.cva("flex items-center", {
1222
+ variants: {
1223
+ type: {
1224
+ default: "gap-1",
1225
+ pill: "gap-1 rounded-[12px] bg-background p-1",
1226
+ underline: "gap-1 border-b border-border"
1227
+ }
1228
+ },
1229
+ defaultVariants: { type: "underline" }
1230
+ });
1231
+ function TabList({
1232
+ children,
1233
+ className
1234
+ }) {
1235
+ const { type } = useTabs();
1236
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { role: "tablist", className: cn(list({ type }), className), children });
1237
+ }
1238
+ var tab = classVarianceAuthority.cva(
1239
+ "inline-flex items-center justify-center gap-2 font-bold whitespace-nowrap transition-colors outline-none focus-visible:outline-2 focus-visible:outline-text focus-visible:outline-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:size-5",
1240
+ {
1241
+ variants: {
1242
+ type: {
1243
+ default: "rounded-[8px] px-3",
1244
+ pill: "rounded-[8px] px-3",
1245
+ underline: "-mb-px border-b-2 border-transparent px-3"
1246
+ },
1247
+ size: { sm: "h-8 text-sm", md: "h-10 text-sm" },
1248
+ active: { true: "", false: "text-text-muted hover:text-text" }
1249
+ },
1250
+ compoundVariants: [
1251
+ { type: "default", active: true, class: "text-primary" },
1252
+ { type: "pill", active: true, class: "bg-surface text-text shadow-sm" },
1253
+ { type: "underline", active: true, class: "border-primary text-primary" }
1254
+ ],
1255
+ defaultVariants: { type: "underline", size: "md", active: false }
1256
+ }
1257
+ );
1258
+ function Tab({
1259
+ value,
1260
+ leading,
1261
+ trailing,
1262
+ children,
1263
+ className,
1264
+ ...props
1265
+ }) {
1266
+ const ctx = useTabs();
1267
+ const active = ctx.value === value;
1268
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1269
+ "button",
1270
+ {
1271
+ type: "button",
1272
+ role: "tab",
1273
+ id: `${ctx.baseId}-tab-${value}`,
1274
+ "aria-selected": active,
1275
+ "aria-controls": `${ctx.baseId}-panel-${value}`,
1276
+ tabIndex: active ? 0 : -1,
1277
+ onClick: () => ctx.setValue(value),
1278
+ onKeyDown: (e) => {
1279
+ if (e.key !== "ArrowRight" && e.key !== "ArrowLeft") return;
1280
+ const tabs = Array.from(
1281
+ e.currentTarget.parentElement?.querySelectorAll(
1282
+ '[role="tab"]'
1283
+ ) ?? []
1284
+ );
1285
+ const i = tabs.indexOf(e.currentTarget);
1286
+ const next = e.key === "ArrowRight" ? tabs[i + 1] : tabs[i - 1];
1287
+ next?.focus();
1288
+ next?.click();
1289
+ },
1290
+ className: cn(tab({ type: ctx.type, size: ctx.size, active }), className),
1291
+ ...props,
1292
+ children: [
1293
+ leading,
1294
+ children,
1295
+ trailing
1296
+ ]
1297
+ }
1298
+ );
1299
+ }
1300
+ function TabPanel({
1301
+ value,
1302
+ children,
1303
+ className
1304
+ }) {
1305
+ const ctx = useTabs();
1306
+ if (ctx.value !== value) return null;
1307
+ return /* @__PURE__ */ jsxRuntime.jsx(
1308
+ "div",
1309
+ {
1310
+ role: "tabpanel",
1311
+ id: `${ctx.baseId}-panel-${value}`,
1312
+ "aria-labelledby": `${ctx.baseId}-tab-${value}`,
1313
+ className,
1314
+ children
1315
+ }
1316
+ );
1317
+ }
1318
+ var field = classVarianceAuthority.cva(
1319
+ "w-full appearance-none rounded-[8px] border bg-surface text-sm text-text outline-none transition-shadow disabled:cursor-not-allowed disabled:opacity-50",
1320
+ {
1321
+ variants: {
1322
+ size: {
1323
+ sm: "h-8 px-2",
1324
+ md: "h-10 px-3",
1325
+ lg: "h-12 px-3",
1326
+ xl: "h-14 px-4"
1327
+ },
1328
+ invalid: {
1329
+ true: "border-[2px] border-[var(--color-input-error)]",
1330
+ false: "border-border hover:border-text-muted focus:border-[1.5px] focus:border-primary focus:ring-2 focus:ring-primary-tint"
1331
+ }
1332
+ },
1333
+ defaultVariants: { size: "md", invalid: false }
1334
+ }
1335
+ );
1336
+ function Select({
1337
+ size = "md",
1338
+ invalid,
1339
+ label,
1340
+ leadingIcon,
1341
+ error,
1342
+ helperText,
1343
+ className,
1344
+ id,
1345
+ disabled,
1346
+ children,
1347
+ ...props
1348
+ }) {
1349
+ const isInvalid = invalid ?? Boolean(error);
1350
+ const hint = error ?? helperText;
1351
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex w-full flex-col gap-1", className), children: [
1352
+ label && /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: "text-sm font-bold text-text", children: label }),
1353
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
1354
+ leadingIcon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pointer-events-none absolute inset-y-0 left-3 flex items-center text-text-muted [&_svg]:size-5", children: leadingIcon }),
1355
+ /* @__PURE__ */ jsxRuntime.jsx(
1356
+ "select",
1357
+ {
1358
+ id,
1359
+ disabled,
1360
+ "aria-invalid": isInvalid || void 0,
1361
+ className: cn(
1362
+ field({ size, invalid: isInvalid }),
1363
+ leadingIcon && "pl-10",
1364
+ "pr-9"
1365
+ ),
1366
+ ...props,
1367
+ children
1368
+ }
1369
+ ),
1370
+ /* @__PURE__ */ jsxRuntime.jsx(ChevronDown2, { className: "pointer-events-none absolute inset-y-0 right-3 my-auto size-5 text-text-muted" })
1371
+ ] }),
1372
+ hint && /* @__PURE__ */ jsxRuntime.jsx(
1373
+ "span",
1374
+ {
1375
+ className: cn(
1376
+ "text-xs",
1377
+ error ? "text-[var(--color-input-error)]" : "text-text-muted"
1378
+ ),
1379
+ children: hint
1380
+ }
1381
+ )
1382
+ ] });
1383
+ }
1384
+ function ChevronDown2({ className }) {
1385
+ return /* @__PURE__ */ jsxRuntime.jsx(
1386
+ "svg",
1387
+ {
1388
+ className,
1389
+ viewBox: "0 0 24 24",
1390
+ fill: "none",
1391
+ stroke: "currentColor",
1392
+ strokeWidth: "2",
1393
+ strokeLinecap: "round",
1394
+ strokeLinejoin: "round",
1395
+ "aria-hidden": true,
1396
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m6 9 6 6 6-6" })
1397
+ }
1398
+ );
1399
+ }
1400
+ var field2 = classVarianceAuthority.cva(
1401
+ "w-full appearance-none rounded-[8px] border bg-surface text-sm text-text outline-none transition-shadow placeholder:text-text-muted disabled:cursor-not-allowed disabled:opacity-50",
1402
+ {
1403
+ variants: {
1404
+ size: {
1405
+ sm: "h-8 px-2",
1406
+ md: "h-10 px-3",
1407
+ lg: "h-12 px-3",
1408
+ xl: "h-14 px-4"
1409
+ },
1410
+ invalid: {
1411
+ true: "border-[2px] border-[var(--color-input-error)]",
1412
+ false: "border-border hover:border-text-muted focus:border-[1.5px] focus:border-primary focus:ring-2 focus:ring-primary-tint"
1413
+ }
1414
+ },
1415
+ defaultVariants: { size: "md", invalid: false }
1416
+ }
1417
+ );
1418
+ function TextInput({
1419
+ size = "md",
1420
+ invalid,
1421
+ label,
1422
+ leadingIcon,
1423
+ trailingIcon,
1424
+ error,
1425
+ helperText,
1426
+ floatingLabel = false,
1427
+ className,
1428
+ id,
1429
+ disabled,
1430
+ placeholder,
1431
+ ...props
1432
+ }) {
1433
+ const isInvalid = invalid ?? Boolean(error);
1434
+ const hint = error ?? helperText;
1435
+ const floating = floatingLabel && Boolean(label);
1436
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex w-full flex-col gap-1", className), children: [
1437
+ label && !floating && /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: "text-sm font-bold text-text", children: label }),
1438
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
1439
+ leadingIcon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pointer-events-none absolute inset-y-0 left-3 flex items-center text-text-muted [&_svg]:size-5", children: leadingIcon }),
1440
+ /* @__PURE__ */ jsxRuntime.jsx(
1441
+ "input",
1442
+ {
1443
+ id,
1444
+ disabled,
1445
+ placeholder: floating ? " " : placeholder,
1446
+ "aria-invalid": isInvalid || void 0,
1447
+ className: cn(
1448
+ field2({ size, invalid: isInvalid }),
1449
+ "peer",
1450
+ leadingIcon && "pl-10",
1451
+ trailingIcon && "pr-10",
1452
+ floating && "placeholder-shown:[&::placeholder]:opacity-0"
1453
+ ),
1454
+ ...props
1455
+ }
1456
+ ),
1457
+ floating && /* @__PURE__ */ jsxRuntime.jsx(
1458
+ "label",
1459
+ {
1460
+ htmlFor: id,
1461
+ className: cn(
1462
+ "pointer-events-none absolute left-3 top-0 flex h-full origin-left items-center text-sm text-text-muted transition-all peer-focus:top-0 peer-focus:h-auto peer-focus:-translate-y-1/2 peer-focus:text-xs peer-focus:text-primary peer-not-placeholder-shown:top-0 peer-not-placeholder-shown:h-auto peer-not-placeholder-shown:-translate-y-1/2 peer-not-placeholder-shown:text-xs",
1463
+ leadingIcon && "left-10 peer-focus:left-3 peer-not-placeholder-shown:left-3",
1464
+ isInvalid && "peer-focus:text-[var(--color-input-error)]"
1465
+ ),
1466
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bg-surface px-1", children: label })
1467
+ }
1468
+ ),
1469
+ trailingIcon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pointer-events-none absolute inset-y-0 right-3 flex items-center text-text-muted [&_svg]:size-5", children: trailingIcon })
1470
+ ] }),
1471
+ hint && /* @__PURE__ */ jsxRuntime.jsx(
1472
+ "span",
1473
+ {
1474
+ className: cn(
1475
+ "px-1 text-xs",
1476
+ error ? "text-[var(--color-input-error)]" : "text-text-muted"
1477
+ ),
1478
+ children: hint
1479
+ }
1480
+ )
1481
+ ] });
1482
+ }
1483
+ var cellBase = "relative flex w-full items-center rounded-[8px] border-[1.5px] border-transparent";
1484
+ var cellActive = "focus-within:z-10 focus-within:border-primary focus-within:ring-4 focus-within:ring-primary-tint";
1485
+ var cellError = "z-10 border-[var(--color-input-error)] focus-within:border-[var(--color-input-error)]";
1486
+ function GroupField({
1487
+ select,
1488
+ invalid,
1489
+ className,
1490
+ children,
1491
+ ...props
1492
+ }) {
1493
+ const cell3 = cn(cellBase, invalid ? cellError : cellActive, className);
1494
+ if (select) {
1495
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cell3, children: [
1496
+ /* @__PURE__ */ jsxRuntime.jsx(
1497
+ "select",
1498
+ {
1499
+ className: "w-full appearance-none bg-transparent px-4 py-4 pr-10 text-base text-text outline-none disabled:cursor-not-allowed disabled:opacity-50",
1500
+ ...props,
1501
+ children
1502
+ }
1503
+ ),
1504
+ /* @__PURE__ */ jsxRuntime.jsx(ChevronDown3, { className: "pointer-events-none absolute right-4 size-5 text-text-muted" })
1505
+ ] });
1506
+ }
1507
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cell3, children: [
1508
+ /* @__PURE__ */ jsxRuntime.jsx(
1509
+ "input",
1510
+ {
1511
+ className: "w-full bg-transparent px-4 py-4 text-base text-text outline-none placeholder:text-text-muted disabled:cursor-not-allowed disabled:opacity-50",
1512
+ ...props
1513
+ }
1514
+ ),
1515
+ children
1516
+ ] });
1517
+ }
1518
+ function TextInputGroup({
1519
+ direction = "vertical",
1520
+ errors,
1521
+ className,
1522
+ children,
1523
+ ...props
1524
+ }) {
1525
+ const fields = react.Children.toArray(children).filter(react.isValidElement);
1526
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex w-full flex-col gap-1", className), ...props, children: [
1527
+ /* @__PURE__ */ jsxRuntime.jsx(
1528
+ "div",
1529
+ {
1530
+ className: cn(
1531
+ "flex rounded-[8px] border border-border bg-surface",
1532
+ direction === "vertical" ? "flex-col divide-y divide-border" : "flex-row divide-x divide-border"
1533
+ ),
1534
+ children: fields.map(
1535
+ (child, i) => react.cloneElement(child, {
1536
+ key: i,
1537
+ className: cn(
1538
+ "-m-px",
1539
+ direction === "horizontal" && "flex-1",
1540
+ child.props.className
1541
+ )
1542
+ })
1543
+ )
1544
+ }
1545
+ ),
1546
+ errors?.filter(Boolean).map((msg, i) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-1 text-xs text-[var(--color-input-error)]", children: msg }, i))
1547
+ ] });
1548
+ }
1549
+ function ChevronDown3({ className }) {
1550
+ return /* @__PURE__ */ jsxRuntime.jsx(
1551
+ "svg",
1552
+ {
1553
+ className,
1554
+ viewBox: "0 0 24 24",
1555
+ fill: "none",
1556
+ stroke: "currentColor",
1557
+ strokeWidth: "2",
1558
+ strokeLinecap: "round",
1559
+ strokeLinejoin: "round",
1560
+ "aria-hidden": true,
1561
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m6 9 6 6 6-6" })
1562
+ }
1563
+ );
1564
+ }
1565
+ var field3 = classVarianceAuthority.cva(
1566
+ "w-full rounded-[8px] border bg-surface px-3 py-2 text-sm text-text outline-none transition-shadow placeholder:text-text-muted disabled:cursor-not-allowed disabled:opacity-50",
1567
+ {
1568
+ variants: {
1569
+ invalid: {
1570
+ true: "border-[2px] border-[var(--color-input-error)]",
1571
+ false: "border-border hover:border-text-muted focus:border-[1.5px] focus:border-primary focus:ring-2 focus:ring-primary-tint"
1572
+ }
1573
+ },
1574
+ defaultVariants: { invalid: false }
1575
+ }
1576
+ );
1577
+ function Textarea({
1578
+ invalid,
1579
+ label,
1580
+ error,
1581
+ helperText,
1582
+ autoResize = false,
1583
+ className,
1584
+ id,
1585
+ disabled,
1586
+ value,
1587
+ onChange,
1588
+ rows = 3,
1589
+ ...props
1590
+ }) {
1591
+ const ref = react.useRef(null);
1592
+ const isInvalid = invalid ?? Boolean(error);
1593
+ const hint = error ?? helperText;
1594
+ const resize = () => {
1595
+ const el = ref.current;
1596
+ if (!el || !autoResize) return;
1597
+ el.style.height = "auto";
1598
+ el.style.height = `${el.scrollHeight}px`;
1599
+ };
1600
+ react.useEffect(resize, [value, autoResize]);
1601
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex w-full flex-col gap-1", className), children: [
1602
+ label && /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: "text-sm font-bold text-text", children: label }),
1603
+ /* @__PURE__ */ jsxRuntime.jsx(
1604
+ "textarea",
1605
+ {
1606
+ ref,
1607
+ id,
1608
+ rows,
1609
+ disabled,
1610
+ value,
1611
+ "aria-invalid": isInvalid || void 0,
1612
+ className: cn(
1613
+ field3({ invalid: isInvalid }),
1614
+ autoResize && "resize-none overflow-hidden"
1615
+ ),
1616
+ onChange: (e) => {
1617
+ onChange?.(e);
1618
+ resize();
1619
+ },
1620
+ ...props
1621
+ }
1622
+ ),
1623
+ hint && /* @__PURE__ */ jsxRuntime.jsx(
1624
+ "span",
1625
+ {
1626
+ className: cn(
1627
+ "text-xs",
1628
+ error ? "text-[var(--color-input-error)]" : "text-text-muted"
1629
+ ),
1630
+ children: hint
1631
+ }
1632
+ )
1633
+ ] });
1634
+ }
1635
+ var track = classVarianceAuthority.cva(
1636
+ "peer relative inline-flex shrink-0 cursor-pointer appearance-none items-center rounded-full bg-border transition-colors checked:bg-primary focus-visible:outline-2 focus-visible:outline-text focus-visible:outline-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
1637
+ {
1638
+ variants: {
1639
+ size: {
1640
+ "2xs": "h-4 w-7",
1641
+ xs: "h-6 w-11",
1642
+ sm: "h-8 w-[60px]"
1643
+ }
1644
+ },
1645
+ defaultVariants: { size: "xs" }
1646
+ }
1647
+ );
1648
+ var thumb = classVarianceAuthority.cva(
1649
+ "pointer-events-none absolute left-0.5 rounded-full bg-surface transition-transform",
1650
+ {
1651
+ variants: {
1652
+ size: {
1653
+ "2xs": "size-3 peer-checked:translate-x-3",
1654
+ xs: "size-5 peer-checked:translate-x-5",
1655
+ sm: "size-7 peer-checked:translate-x-7"
1656
+ }
1657
+ },
1658
+ defaultVariants: { size: "xs" }
1659
+ }
1660
+ );
1661
+ function Switch({
1662
+ size = "xs",
1663
+ label,
1664
+ className,
1665
+ disabled,
1666
+ ...props
1667
+ }) {
1668
+ const control = /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "relative inline-flex", children: [
1669
+ /* @__PURE__ */ jsxRuntime.jsx(
1670
+ "input",
1671
+ {
1672
+ type: "checkbox",
1673
+ role: "switch",
1674
+ disabled,
1675
+ className: cn(track({ size }), className),
1676
+ ...props
1677
+ }
1678
+ ),
1679
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: thumb({ size }), "aria-hidden": true })
1680
+ ] });
1681
+ if (!label) return control;
1682
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1683
+ "label",
1684
+ {
1685
+ className: cn(
1686
+ "inline-flex items-center gap-2 text-sm text-text",
1687
+ disabled && "cursor-not-allowed opacity-50"
1688
+ ),
1689
+ children: [
1690
+ control,
1691
+ label
1692
+ ]
1693
+ }
1694
+ );
1695
+ }
1696
+ var cell2 = classVarianceAuthority.cva("px-3 text-left text-sm text-text", {
1697
+ variants: {
1698
+ size: {
1699
+ xs: "h-6",
1700
+ sm: "h-8",
1701
+ md: "h-10",
1702
+ lg: "h-12",
1703
+ xl: "h-14",
1704
+ "2xl": "h-16"
1705
+ }
1706
+ },
1707
+ defaultVariants: { size: "md" }
1708
+ });
1709
+ function Table({
1710
+ className,
1711
+ ...props
1712
+ }) {
1713
+ return /* @__PURE__ */ jsxRuntime.jsx(
1714
+ "table",
1715
+ {
1716
+ className: cn("w-full border-collapse text-text", className),
1717
+ ...props
1718
+ }
1719
+ );
1720
+ }
1721
+ function TableHead({
1722
+ className,
1723
+ ...props
1724
+ }) {
1725
+ return /* @__PURE__ */ jsxRuntime.jsx("thead", { className: cn("border-b border-border", className), ...props });
1726
+ }
1727
+ function TableBody(props) {
1728
+ return /* @__PURE__ */ jsxRuntime.jsx("tbody", { ...props });
1729
+ }
1730
+ function TableRow({
1731
+ zebra,
1732
+ hover = true,
1733
+ selected,
1734
+ className,
1735
+ ...props
1736
+ }) {
1737
+ return /* @__PURE__ */ jsxRuntime.jsx(
1738
+ "tr",
1739
+ {
1740
+ "aria-selected": selected || void 0,
1741
+ className: cn(
1742
+ "border-b border-border",
1743
+ zebra && "even:bg-background",
1744
+ hover && "hover:bg-hover",
1745
+ selected && "bg-primary-tint",
1746
+ className
1747
+ ),
1748
+ ...props
1749
+ }
1750
+ );
1751
+ }
1752
+ function TableCell({
1753
+ size = "md",
1754
+ header,
1755
+ className,
1756
+ ...props
1757
+ }) {
1758
+ const Tag2 = header ? "th" : "td";
1759
+ return /* @__PURE__ */ jsxRuntime.jsx(
1760
+ Tag2,
1761
+ {
1762
+ className: cn(
1763
+ cell2({ size }),
1764
+ header && "font-bold text-text-muted",
1765
+ className
1766
+ ),
1767
+ ...props
1768
+ }
1769
+ );
1770
+ }
1771
+ function selectionState(selectedCount, total) {
1772
+ return {
1773
+ checked: total > 0 && selectedCount === total,
1774
+ indeterminate: selectedCount > 0 && selectedCount < total
1775
+ };
1776
+ }
1777
+ function DataTable({
1778
+ columns,
1779
+ data,
1780
+ rowKey,
1781
+ size = "md",
1782
+ zebra,
1783
+ selectable,
1784
+ selected = [],
1785
+ onSelectedChange,
1786
+ className
1787
+ }) {
1788
+ const allKeys = data.map(rowKey);
1789
+ const { checked, indeterminate } = selectionState(
1790
+ selected.length,
1791
+ allKeys.length
1792
+ );
1793
+ const toggleAll = () => onSelectedChange?.(checked ? [] : allKeys);
1794
+ const toggleRow = (key) => onSelectedChange?.(
1795
+ selected.includes(key) ? selected.filter((k) => k !== key) : [...selected, key]
1796
+ );
1797
+ return /* @__PURE__ */ jsxRuntime.jsxs(Table, { className, children: [
1798
+ /* @__PURE__ */ jsxRuntime.jsx(TableHead, { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "border-b border-border", children: [
1799
+ selectable && /* @__PURE__ */ jsxRuntime.jsx(TableCell, { header: true, size, className: "w-px", children: /* @__PURE__ */ jsxRuntime.jsx(
1800
+ Checkbox,
1801
+ {
1802
+ checked,
1803
+ indeterminate,
1804
+ onChange: toggleAll,
1805
+ "aria-label": "Select all rows"
1806
+ }
1807
+ ) }),
1808
+ columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx(TableCell, { header: true, size, children: col.header }, col.key))
1809
+ ] }) }),
1810
+ /* @__PURE__ */ jsxRuntime.jsx(TableBody, { children: data.map((row) => {
1811
+ const key = rowKey(row);
1812
+ const isSelected = selected.includes(key);
1813
+ return /* @__PURE__ */ jsxRuntime.jsxs(TableRow, { zebra, selected: isSelected, children: [
1814
+ selectable && /* @__PURE__ */ jsxRuntime.jsx(TableCell, { size, className: "w-px", children: /* @__PURE__ */ jsxRuntime.jsx(
1815
+ Checkbox,
1816
+ {
1817
+ checked: isSelected,
1818
+ onChange: () => toggleRow(key),
1819
+ "aria-label": `Select row`
1820
+ }
1821
+ ) }),
1822
+ columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx(TableCell, { size, children: col.cell(row) }, col.key))
1823
+ ] }, key);
1824
+ }) })
1825
+ ] });
1826
+ }
1827
+ var ToastContext = react.createContext(null);
1828
+ function useToast() {
1829
+ const ctx = react.useContext(ToastContext);
1830
+ if (!ctx) throw new Error("useToast must be used within a ToastProvider");
1831
+ return ctx;
1832
+ }
1833
+ var POSITION_CLASS = {
1834
+ "top-left": "top-4 left-4 items-start",
1835
+ "top-center": "top-4 left-1/2 -translate-x-1/2 items-center",
1836
+ "top-right": "top-4 right-4 items-end",
1837
+ "bottom-left": "bottom-4 left-4 items-start",
1838
+ "bottom-center": "bottom-4 left-1/2 -translate-x-1/2 items-center",
1839
+ "bottom-right": "bottom-4 right-4 items-end"
1840
+ };
1841
+ function ToastProvider({
1842
+ children,
1843
+ position = "bottom-center",
1844
+ defaultDuration = 5e3
1845
+ }) {
1846
+ const [toasts, setToasts] = react.useState([]);
1847
+ const counter = react.useRef(0);
1848
+ const dismiss = react.useCallback((id) => {
1849
+ setToasts((list2) => list2.filter((t) => t.id !== id));
1850
+ }, []);
1851
+ const toast = react.useCallback(
1852
+ (options) => {
1853
+ const id = ++counter.current;
1854
+ setToasts((list2) => [...list2, { ...options, id }]);
1855
+ const duration = options.duration ?? defaultDuration;
1856
+ if (duration > 0 && !options.closable) {
1857
+ setTimeout(() => dismiss(id), duration);
1858
+ }
1859
+ return id;
1860
+ },
1861
+ [defaultDuration, dismiss]
1862
+ );
1863
+ return /* @__PURE__ */ jsxRuntime.jsxs(ToastContext.Provider, { value: { toast, dismiss }, children: [
1864
+ children,
1865
+ typeof document !== "undefined" && reactDom.createPortal(
1866
+ /* @__PURE__ */ jsxRuntime.jsx(
1867
+ "div",
1868
+ {
1869
+ className: cn(
1870
+ "pointer-events-none fixed z-[100] flex flex-col gap-2",
1871
+ POSITION_CLASS[position]
1872
+ ),
1873
+ children: toasts.map((t) => /* @__PURE__ */ jsxRuntime.jsx(
1874
+ Snackbar,
1875
+ {
1876
+ icon: t.icon,
1877
+ onClose: t.closable ? () => dismiss(t.id) : void 0,
1878
+ className: "pointer-events-auto",
1879
+ children: t.message
1880
+ },
1881
+ t.id
1882
+ ))
1883
+ }
1884
+ ),
1885
+ document.body
1886
+ )
1887
+ ] });
1888
+ }
1889
+ function Snackbar({
1890
+ icon,
1891
+ onClose,
1892
+ children,
1893
+ className,
1894
+ ...props
1895
+ }) {
1896
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1897
+ "div",
1898
+ {
1899
+ role: "status",
1900
+ "aria-live": "polite",
1901
+ className: cn(
1902
+ "flex min-w-48 max-w-sm items-center gap-3 rounded-[8px] bg-surface px-4 py-3 text-sm text-text shadow-lg",
1903
+ className
1904
+ ),
1905
+ ...props,
1906
+ children: [
1907
+ icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 [&_svg]:size-5", children: icon }),
1908
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children }),
1909
+ onClose && /* @__PURE__ */ jsxRuntime.jsx(
1910
+ "button",
1911
+ {
1912
+ type: "button",
1913
+ "aria-label": "Dismiss",
1914
+ onClick: onClose,
1915
+ className: "-mr-1 inline-flex size-6 shrink-0 items-center justify-center rounded-full text-text-muted hover:bg-hover hover:text-text",
1916
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1917
+ "svg",
1918
+ {
1919
+ viewBox: "0 0 24 24",
1920
+ className: "size-4",
1921
+ fill: "none",
1922
+ stroke: "currentColor",
1923
+ strokeWidth: "2",
1924
+ strokeLinecap: "round",
1925
+ "aria-hidden": true,
1926
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 6l12 12M18 6L6 18" })
1927
+ }
1928
+ )
1929
+ }
1930
+ )
1931
+ ]
1932
+ }
1933
+ );
1934
+ }
1935
+ var bubble = classVarianceAuthority.cva(
1936
+ "pointer-events-none absolute z-50 w-max max-w-xs rounded-[4px] bg-surface px-3 py-3 text-xs leading-4 text-text opacity-0 transition-opacity duration-150 group-hover:opacity-100 group-focus-within:opacity-100",
1937
+ {
1938
+ variants: {
1939
+ placement: {
1940
+ top: "bottom-full left-1/2 mb-2 -translate-x-1/2",
1941
+ "top-start": "bottom-full left-0 mb-2",
1942
+ "top-end": "bottom-full right-0 mb-2",
1943
+ bottom: "top-full left-1/2 mt-2 -translate-x-1/2",
1944
+ "bottom-start": "top-full left-0 mt-2",
1945
+ "bottom-end": "top-full right-0 mt-2",
1946
+ left: "right-full top-1/2 mr-2 -translate-y-1/2",
1947
+ right: "left-full top-1/2 ml-2 -translate-y-1/2"
1948
+ },
1949
+ shadow: {
1950
+ true: "shadow-[0_0_1px_rgba(0,0,0,0.4),0_6px_6px_-6px_rgba(0,0,0,0.16)]",
1951
+ false: ""
1952
+ }
1953
+ },
1954
+ defaultVariants: { placement: "top", shadow: true }
1955
+ }
1956
+ );
1957
+ var arrow = classVarianceAuthority.cva("absolute size-2 rotate-45 bg-surface", {
1958
+ variants: {
1959
+ placement: {
1960
+ top: "bottom-[-4px] left-1/2 -translate-x-1/2",
1961
+ "top-start": "bottom-[-4px] left-3",
1962
+ "top-end": "bottom-[-4px] right-3",
1963
+ bottom: "top-[-4px] left-1/2 -translate-x-1/2",
1964
+ "bottom-start": "top-[-4px] left-3",
1965
+ "bottom-end": "top-[-4px] right-3",
1966
+ left: "right-[-4px] top-1/2 -translate-y-1/2",
1967
+ right: "left-[-4px] top-1/2 -translate-y-1/2"
1968
+ }
1969
+ },
1970
+ defaultVariants: { placement: "top" }
1971
+ });
1972
+ function Tooltip({
1973
+ content,
1974
+ placement = "top",
1975
+ shadow = true,
1976
+ pointer = true,
1977
+ children,
1978
+ className
1979
+ }) {
1980
+ return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("group relative inline-flex", className), children: [
1981
+ children,
1982
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { role: "tooltip", className: bubble({ placement, shadow }), children: [
1983
+ content,
1984
+ pointer && /* @__PURE__ */ jsxRuntime.jsx("span", { className: arrow({ placement }), "aria-hidden": true })
1985
+ ] })
1986
+ ] });
1987
+ }
1988
+ var SidebarContext = react.createContext({
1989
+ collapsed: false
1990
+ });
1991
+ function Sidebar({
1992
+ collapsed = false,
1993
+ className,
1994
+ children,
1995
+ ...props
1996
+ }) {
1997
+ return /* @__PURE__ */ jsxRuntime.jsx(SidebarContext.Provider, { value: { collapsed }, children: /* @__PURE__ */ jsxRuntime.jsx(
1998
+ "nav",
1999
+ {
2000
+ "data-collapsed": collapsed || void 0,
2001
+ className: cn(
2002
+ "flex h-full flex-col gap-4 bg-surface text-text transition-[width] duration-200",
2003
+ collapsed ? "w-16 p-2" : "w-[280px] p-6",
2004
+ className
2005
+ ),
2006
+ ...props,
2007
+ children
2008
+ }
2009
+ ) });
2010
+ }
2011
+ function SidebarSection({
2012
+ title,
2013
+ divider,
2014
+ className,
2015
+ children,
2016
+ ...props
2017
+ }) {
2018
+ const { collapsed } = react.useContext(SidebarContext);
2019
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2020
+ divider && /* @__PURE__ */ jsxRuntime.jsx("hr", { className: "border-t border-border" }),
2021
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-1", className), ...props, children: [
2022
+ title && !collapsed && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-2 text-sm text-text-muted", children: title }),
2023
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-1", children })
2024
+ ] })
2025
+ ] });
2026
+ }
2027
+ function SidebarItem({
2028
+ icon,
2029
+ active,
2030
+ label,
2031
+ href,
2032
+ className,
2033
+ ...props
2034
+ }) {
2035
+ const { collapsed } = react.useContext(SidebarContext);
2036
+ const row = /* @__PURE__ */ jsxRuntime.jsxs(
2037
+ "a",
2038
+ {
2039
+ href,
2040
+ "aria-current": active ? "page" : void 0,
2041
+ className: cn(
2042
+ "flex items-center gap-3 rounded-[8px] px-2 py-2 text-sm transition-colors outline-none focus-visible:outline-2 focus-visible:outline-primary",
2043
+ collapsed && "justify-center",
2044
+ active ? "bg-primary-tint font-bold text-primary" : "text-text hover:bg-hover",
2045
+ className
2046
+ ),
2047
+ ...props,
2048
+ children: [
2049
+ icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex size-6 shrink-0 items-center justify-center [&_svg]:size-6", children: icon }),
2050
+ !collapsed && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate", children: label })
2051
+ ]
2052
+ }
2053
+ );
2054
+ if (collapsed) {
2055
+ return /* @__PURE__ */ jsxRuntime.jsx(
2056
+ Tooltip,
2057
+ {
2058
+ content: label,
2059
+ placement: "right",
2060
+ className: "w-full [&>a]:w-full",
2061
+ children: row
2062
+ }
2063
+ );
2064
+ }
2065
+ return row;
2066
+ }
2067
+ function Calendar({ className, classNames, ...props }) {
2068
+ return /* @__PURE__ */ jsxRuntime.jsx(
2069
+ reactDayPicker.DayPicker,
2070
+ {
2071
+ className: cn(
2072
+ "rounded-[12px] bg-surface p-4 text-text [--rdp-day-width:40px] [--rdp-day-height:40px]",
2073
+ className
2074
+ ),
2075
+ classNames: {
2076
+ months: "relative flex flex-col gap-4 sm:flex-row",
2077
+ month: "flex flex-col gap-2",
2078
+ month_caption: "relative flex h-10 items-center justify-center",
2079
+ caption_label: "text-sm font-semibold text-text",
2080
+ nav: "absolute inset-x-0 top-0 flex h-10 items-center justify-between px-1",
2081
+ button_previous: "inline-flex size-8 items-center justify-center rounded-[8px] text-text-muted transition-colors hover:bg-hover hover:text-text disabled:opacity-40",
2082
+ button_next: "inline-flex size-8 items-center justify-center rounded-[8px] text-text-muted transition-colors hover:bg-hover hover:text-text disabled:opacity-40",
2083
+ month_grid: "border-collapse",
2084
+ weekdays: "flex",
2085
+ weekday: "flex size-10 items-center justify-center text-xs font-semibold text-text-muted",
2086
+ week: "flex",
2087
+ day: "p-0 text-center text-sm",
2088
+ day_button: "inline-flex size-10 items-center justify-center rounded-full text-text transition-colors hover:bg-hover focus-visible:outline-2 focus-visible:outline-primary aria-selected:font-semibold",
2089
+ today: "font-semibold text-primary",
2090
+ selected: "[&_button]:bg-text [&_button]:text-background [&_button]:hover:bg-text",
2091
+ range_start: "rounded-l-full bg-primary-tint [&_button]:bg-text [&_button]:text-background",
2092
+ range_end: "rounded-r-full bg-primary-tint [&_button]:bg-text [&_button]:text-background",
2093
+ range_middle: "bg-primary-tint [&_button]:rounded-none [&_button]:bg-transparent [&_button]:text-text [&_button]:hover:bg-primary-tint",
2094
+ outside: "text-text-muted opacity-50",
2095
+ disabled: "text-text-muted opacity-40",
2096
+ hidden: "invisible",
2097
+ ...classNames
2098
+ },
2099
+ components: {
2100
+ Chevron: ({ orientation, className: cls }) => /* @__PURE__ */ jsxRuntime.jsx(ChevronIcon, { orientation, className: cls })
2101
+ },
2102
+ ...props
2103
+ }
2104
+ );
2105
+ }
2106
+ function ChevronIcon({
2107
+ orientation,
2108
+ className
2109
+ }) {
2110
+ const d = orientation === "left" ? "m15 18-6-6 6-6" : orientation === "right" ? "m9 18 6-6-6-6" : orientation === "up" ? "m18 15-6-6-6 6" : "m6 9 6 6 6-6";
2111
+ return /* @__PURE__ */ jsxRuntime.jsx(
2112
+ "svg",
2113
+ {
2114
+ className: cn("size-5", className),
2115
+ viewBox: "0 0 24 24",
2116
+ fill: "none",
2117
+ stroke: "currentColor",
2118
+ strokeWidth: "2",
2119
+ strokeLinecap: "round",
2120
+ strokeLinejoin: "round",
2121
+ "aria-hidden": true,
2122
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d })
2123
+ }
2124
+ );
2125
+ }
2126
+ var pad = (n) => String(n).padStart(2, "0");
2127
+ function TimePicker({
2128
+ value,
2129
+ onChange,
2130
+ minuteStep = 1,
2131
+ className
2132
+ }) {
2133
+ const hours = react.useMemo(() => Array.from({ length: 24 }, (_, i) => i), []);
2134
+ const minutes = react.useMemo(
2135
+ () => Array.from(
2136
+ { length: Math.ceil(60 / minuteStep) },
2137
+ (_, i) => i * minuteStep
2138
+ ),
2139
+ [minuteStep]
2140
+ );
2141
+ const set = (next) => onChange?.({
2142
+ hours: next.hours ?? value?.hours ?? 0,
2143
+ minutes: next.minutes ?? value?.minutes ?? 0
2144
+ });
2145
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2146
+ "div",
2147
+ {
2148
+ className: cn(
2149
+ "flex h-[280px] gap-px overflow-hidden rounded-[16px] bg-background p-1",
2150
+ className
2151
+ ),
2152
+ children: [
2153
+ /* @__PURE__ */ jsxRuntime.jsx(
2154
+ Column,
2155
+ {
2156
+ items: hours,
2157
+ selected: value?.hours,
2158
+ onSelect: (h) => set({ hours: h }),
2159
+ label: "Hours"
2160
+ }
2161
+ ),
2162
+ /* @__PURE__ */ jsxRuntime.jsx(
2163
+ Column,
2164
+ {
2165
+ items: minutes,
2166
+ selected: value?.minutes,
2167
+ onSelect: (m) => set({ minutes: m }),
2168
+ label: "Minutes"
2169
+ }
2170
+ )
2171
+ ]
2172
+ }
2173
+ );
2174
+ }
2175
+ function Column({
2176
+ items,
2177
+ selected,
2178
+ onSelect,
2179
+ label
2180
+ }) {
2181
+ return /* @__PURE__ */ jsxRuntime.jsx(
2182
+ "ul",
2183
+ {
2184
+ "aria-label": label,
2185
+ className: "flex w-12 flex-col gap-1 overflow-y-auto scroll-smooth py-1 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
2186
+ children: items.map((n) => {
2187
+ const active = selected === n;
2188
+ return /* @__PURE__ */ jsxRuntime.jsx("li", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
2189
+ "button",
2190
+ {
2191
+ type: "button",
2192
+ "aria-pressed": active,
2193
+ onClick: () => onSelect(n),
2194
+ className: cn(
2195
+ "flex size-9 items-center justify-center rounded-full text-xs font-semibold transition-colors",
2196
+ active ? "bg-text text-background" : "text-text hover:bg-hover"
2197
+ ),
2198
+ children: pad(n)
2199
+ }
2200
+ ) }, n);
2201
+ })
2202
+ }
2203
+ );
2204
+ }
2205
+ var startOfDay = (d) => new Date(d.getFullYear(), d.getMonth(), d.getDate());
2206
+ var addDays = (d, n) => {
2207
+ const r = startOfDay(d);
2208
+ r.setDate(r.getDate() + n);
2209
+ return r;
2210
+ };
2211
+ var startOfWeek = (d) => addDays(d, -((d.getDay() + 6) % 7));
2212
+ var startOfMonth = (d) => new Date(d.getFullYear(), d.getMonth(), 1);
2213
+ var endOfMonth = (d) => new Date(d.getFullYear(), d.getMonth() + 1, 0);
2214
+ function presetRanges(now) {
2215
+ const lastMonth = new Date(now.getFullYear(), now.getMonth() - 1, 1);
2216
+ return {
2217
+ today: { from: startOfDay(now), to: startOfDay(now) },
2218
+ yesterday: { from: addDays(now, -1), to: addDays(now, -1) },
2219
+ thisWeek: { from: startOfWeek(now), to: startOfDay(now) },
2220
+ lastWeek: {
2221
+ from: addDays(startOfWeek(now), -7),
2222
+ to: addDays(startOfWeek(now), -1)
2223
+ },
2224
+ thisMonth: { from: startOfMonth(now), to: startOfDay(now) },
2225
+ lastMonth: { from: startOfMonth(lastMonth), to: endOfMonth(lastMonth) }
2226
+ };
2227
+ }
2228
+ var defaultPresets = [
2229
+ { label: "Today", range: () => presetRanges(/* @__PURE__ */ new Date()).today },
2230
+ { label: "Yesterday", range: () => presetRanges(/* @__PURE__ */ new Date()).yesterday },
2231
+ { label: "This week", range: () => presetRanges(/* @__PURE__ */ new Date()).thisWeek },
2232
+ { label: "Last week", range: () => presetRanges(/* @__PURE__ */ new Date()).lastWeek },
2233
+ { label: "This month", range: () => presetRanges(/* @__PURE__ */ new Date()).thisMonth },
2234
+ { label: "Last month", range: () => presetRanges(/* @__PURE__ */ new Date()).lastMonth }
2235
+ ];
2236
+ function DateRangePicker({
2237
+ value,
2238
+ onApply,
2239
+ presets = defaultPresets,
2240
+ numberOfMonths = 2,
2241
+ className
2242
+ }) {
2243
+ const [range, setRange] = react.useState(value);
2244
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2245
+ "div",
2246
+ {
2247
+ className: cn(
2248
+ "inline-flex flex-col overflow-hidden rounded-[12px] bg-surface shadow-[0_0_1px_rgba(0,0,0,0.4),0_6px_6px_-6px_rgba(0,0,0,0.16)]",
2249
+ className
2250
+ ),
2251
+ children: [
2252
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex", children: [
2253
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex w-40 shrink-0 flex-col gap-1 border-r border-border p-2", children: presets.map((preset, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
2254
+ "button",
2255
+ {
2256
+ type: "button",
2257
+ onClick: () => setRange(preset.range()),
2258
+ className: "w-full rounded-[8px] px-3 py-2 text-left text-sm text-text transition-colors hover:bg-hover",
2259
+ children: preset.label
2260
+ }
2261
+ ) }, i)) }),
2262
+ /* @__PURE__ */ jsxRuntime.jsx(
2263
+ Calendar,
2264
+ {
2265
+ mode: "range",
2266
+ numberOfMonths,
2267
+ selected: range,
2268
+ onSelect: setRange,
2269
+ className: "p-3 shadow-none"
2270
+ }
2271
+ )
2272
+ ] }),
2273
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-end border-t border-border p-3", children: /* @__PURE__ */ jsxRuntime.jsx(Button, { size: "sm", onClick: () => onApply?.(range), children: "Apply" }) })
2274
+ ]
2275
+ }
2276
+ );
2277
+ }
2278
+ var quarters = [1, 2, 3, 4];
2279
+ var monthsOf = (q) => ["Jan\u2013Mar", "Apr\u2013Jun", "Jul\u2013Sep", "Oct\u2013Dec"][q - 1];
2280
+ function QuarterPicker({
2281
+ value,
2282
+ onChange,
2283
+ year = value?.year ?? (/* @__PURE__ */ new Date()).getFullYear(),
2284
+ onYearChange,
2285
+ className
2286
+ }) {
2287
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2288
+ "div",
2289
+ {
2290
+ className: cn(
2291
+ "w-[280px] rounded-[12px] bg-surface p-4 text-text",
2292
+ className
2293
+ ),
2294
+ children: [
2295
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-2 flex h-10 items-center justify-between", children: [
2296
+ /* @__PURE__ */ jsxRuntime.jsx(
2297
+ NavButton,
2298
+ {
2299
+ label: "Previous year",
2300
+ onClick: () => onYearChange?.(year - 1),
2301
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m15 18-6-6 6-6" })
2302
+ }
2303
+ ),
2304
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold", children: year }),
2305
+ /* @__PURE__ */ jsxRuntime.jsx(NavButton, { label: "Next year", onClick: () => onYearChange?.(year + 1), children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m9 18 6-6-6-6" }) })
2306
+ ] }),
2307
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-2", children: quarters.map((q) => {
2308
+ const active = value?.year === year && value?.quarter === q;
2309
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2310
+ "button",
2311
+ {
2312
+ type: "button",
2313
+ "aria-pressed": active,
2314
+ onClick: () => onChange?.({ year, quarter: q }),
2315
+ className: cn(
2316
+ "flex flex-col items-center justify-center rounded-[8px] py-4 transition-colors",
2317
+ active ? "bg-text text-background" : "hover:bg-hover"
2318
+ ),
2319
+ children: [
2320
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm font-semibold", children: [
2321
+ "Q",
2322
+ q
2323
+ ] }),
2324
+ /* @__PURE__ */ jsxRuntime.jsx(
2325
+ "span",
2326
+ {
2327
+ className: cn(
2328
+ "text-xs",
2329
+ active ? "text-background/70" : "text-text-muted"
2330
+ ),
2331
+ children: monthsOf(q)
2332
+ }
2333
+ )
2334
+ ]
2335
+ },
2336
+ q
2337
+ );
2338
+ }) })
2339
+ ]
2340
+ }
2341
+ );
2342
+ }
2343
+ function NavButton({
2344
+ label,
2345
+ onClick,
2346
+ children
2347
+ }) {
2348
+ return /* @__PURE__ */ jsxRuntime.jsx(
2349
+ "button",
2350
+ {
2351
+ type: "button",
2352
+ "aria-label": label,
2353
+ onClick,
2354
+ className: "inline-flex size-8 items-center justify-center rounded-[8px] text-text-muted transition-colors hover:bg-hover hover:text-text",
2355
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2356
+ "svg",
2357
+ {
2358
+ className: "size-5",
2359
+ viewBox: "0 0 24 24",
2360
+ fill: "none",
2361
+ stroke: "currentColor",
2362
+ strokeWidth: "2",
2363
+ strokeLinecap: "round",
2364
+ strokeLinejoin: "round",
2365
+ "aria-hidden": true,
2366
+ children
2367
+ }
2368
+ )
2369
+ }
2370
+ );
2371
+ }
2372
+ var drawer = classVarianceAuthority.cva(
2373
+ "fixed bg-surface p-1 shadow-lg backdrop:bg-overlay open:flex flex-col m-0",
2374
+ {
2375
+ variants: {
2376
+ side: {
2377
+ right: "inset-y-0 right-0 h-full w-[448px] max-w-full rounded-l-[8px]",
2378
+ left: "inset-y-0 left-0 h-full w-[448px] max-w-full rounded-r-[8px]",
2379
+ top: "inset-x-0 top-0 h-auto max-h-full w-full rounded-b-[8px]",
2380
+ bottom: "inset-x-0 bottom-0 h-auto max-h-full w-full rounded-t-[8px]"
2381
+ }
2382
+ },
2383
+ defaultVariants: { side: "right" }
2384
+ }
2385
+ );
2386
+ function Drawer({
2387
+ open,
2388
+ onClose,
2389
+ side = "right",
2390
+ className,
2391
+ children,
2392
+ ...props
2393
+ }) {
2394
+ const ref = react.useRef(null);
2395
+ react.useEffect(() => {
2396
+ const dialog = ref.current;
2397
+ if (!dialog) return;
2398
+ if (open && !dialog.open) dialog.showModal();
2399
+ else if (!open && dialog.open) dialog.close();
2400
+ }, [open]);
2401
+ return /* @__PURE__ */ jsxRuntime.jsx(
2402
+ "dialog",
2403
+ {
2404
+ ref,
2405
+ className: cn(drawer({ side }), className),
2406
+ onClose,
2407
+ onClick: (e) => {
2408
+ if (e.target === ref.current) onClose?.();
2409
+ },
2410
+ ...props,
2411
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2412
+ "div",
2413
+ {
2414
+ className: "flex size-full flex-col overflow-auto",
2415
+ onClick: (e) => e.stopPropagation(),
2416
+ children
2417
+ }
2418
+ )
2419
+ }
2420
+ );
2421
+ }
2422
+ var modal = classVarianceAuthority.cva(
2423
+ "m-auto w-full rounded-[12px] bg-surface p-0 shadow-lg backdrop:bg-overlay open:flex flex-col",
2424
+ {
2425
+ variants: {
2426
+ size: {
2427
+ sm: "max-w-sm",
2428
+ md: "max-w-md",
2429
+ lg: "max-w-4xl",
2430
+ xl: "max-w-7xl"
2431
+ }
2432
+ },
2433
+ defaultVariants: { size: "md" }
2434
+ }
2435
+ );
2436
+ function Modal({
2437
+ open,
2438
+ onClose,
2439
+ size = "md",
2440
+ title,
2441
+ className,
2442
+ children,
2443
+ ...props
2444
+ }) {
2445
+ const ref = react.useRef(null);
2446
+ react.useEffect(() => {
2447
+ const dialog = ref.current;
2448
+ if (!dialog) return;
2449
+ if (open && !dialog.open) dialog.showModal();
2450
+ else if (!open && dialog.open) dialog.close();
2451
+ }, [open]);
2452
+ return /* @__PURE__ */ jsxRuntime.jsx(
2453
+ "dialog",
2454
+ {
2455
+ ref,
2456
+ className: cn(modal({ size }), className),
2457
+ onClose,
2458
+ onClick: (e) => {
2459
+ if (e.target === ref.current) onClose?.();
2460
+ },
2461
+ ...props,
2462
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", onClick: (e) => e.stopPropagation(), children: [
2463
+ (title || onClose) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-4 border-b border-border px-6 py-4", children: [
2464
+ title ? /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-lg font-bold text-text", children: title }) : /* @__PURE__ */ jsxRuntime.jsx("span", {}),
2465
+ onClose && /* @__PURE__ */ jsxRuntime.jsx(
2466
+ "button",
2467
+ {
2468
+ type: "button",
2469
+ "aria-label": "Close",
2470
+ onClick: onClose,
2471
+ className: "-mr-2 inline-flex size-8 shrink-0 items-center justify-center rounded-full text-text-muted hover:bg-hover hover:text-text focus-visible:outline-2 focus-visible:outline-text focus-visible:outline-offset-2",
2472
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2473
+ "svg",
2474
+ {
2475
+ viewBox: "0 0 24 24",
2476
+ className: "size-5",
2477
+ fill: "none",
2478
+ stroke: "currentColor",
2479
+ strokeWidth: "2",
2480
+ strokeLinecap: "round",
2481
+ "aria-hidden": true,
2482
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 6l12 12M18 6L6 18" })
2483
+ }
2484
+ )
2485
+ }
2486
+ )
2487
+ ] }),
2488
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6", children })
2489
+ ] })
2490
+ }
2491
+ );
2492
+ }
2493
+ var DOTS = "\u2026";
2494
+ function paginationRange(current, total, siblings = 1) {
2495
+ const totalShown = siblings * 2 + 5;
2496
+ if (total <= totalShown) {
2497
+ return Array.from({ length: total }, (_, i) => i + 1);
2498
+ }
2499
+ const left = Math.max(current - siblings, 1);
2500
+ const right = Math.min(current + siblings, total);
2501
+ const showLeftDots = left > 2;
2502
+ const showRightDots = right < total - 1;
2503
+ if (!showLeftDots && showRightDots) {
2504
+ const len = siblings * 2 + 3;
2505
+ return [...Array.from({ length: len }, (_, i) => i + 1), DOTS, total];
2506
+ }
2507
+ if (showLeftDots && !showRightDots) {
2508
+ const len = siblings * 2 + 3;
2509
+ return [
2510
+ 1,
2511
+ DOTS,
2512
+ ...Array.from({ length: len }, (_, i) => total - len + 1 + i)
2513
+ ];
2514
+ }
2515
+ return [
2516
+ 1,
2517
+ DOTS,
2518
+ ...Array.from({ length: right - left + 1 }, (_, i) => left + i),
2519
+ DOTS,
2520
+ total
2521
+ ];
2522
+ }
2523
+ function Pagination({
2524
+ page,
2525
+ total,
2526
+ siblings = 1,
2527
+ onPageChange,
2528
+ className,
2529
+ ...props
2530
+ }) {
2531
+ const range = paginationRange(page, total, siblings);
2532
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2533
+ "nav",
2534
+ {
2535
+ "aria-label": "Pagination",
2536
+ className: cn("flex items-center gap-1", className),
2537
+ ...props,
2538
+ children: [
2539
+ /* @__PURE__ */ jsxRuntime.jsx(
2540
+ PageButton,
2541
+ {
2542
+ "aria-label": "Previous page",
2543
+ disabled: page <= 1,
2544
+ onClick: () => onPageChange(page - 1),
2545
+ children: /* @__PURE__ */ jsxRuntime.jsx(Chevron, { dir: "left" })
2546
+ }
2547
+ ),
2548
+ range.map(
2549
+ (item, i) => item === DOTS ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-2 text-sm text-text-muted", children: DOTS }, `dots-${i}`) : /* @__PURE__ */ jsxRuntime.jsx(
2550
+ PageButton,
2551
+ {
2552
+ "aria-label": `Page ${item}`,
2553
+ "aria-current": item === page ? "page" : void 0,
2554
+ selected: item === page,
2555
+ onClick: () => onPageChange(item),
2556
+ children: item
2557
+ },
2558
+ item
2559
+ )
2560
+ ),
2561
+ /* @__PURE__ */ jsxRuntime.jsx(
2562
+ PageButton,
2563
+ {
2564
+ "aria-label": "Next page",
2565
+ disabled: page >= total,
2566
+ onClick: () => onPageChange(page + 1),
2567
+ children: /* @__PURE__ */ jsxRuntime.jsx(Chevron, { dir: "right" })
2568
+ }
2569
+ )
2570
+ ]
2571
+ }
2572
+ );
2573
+ }
2574
+ function PageButton({
2575
+ selected,
2576
+ className,
2577
+ ...props
2578
+ }) {
2579
+ return /* @__PURE__ */ jsxRuntime.jsx(
2580
+ "button",
2581
+ {
2582
+ type: "button",
2583
+ className: cn(
2584
+ "inline-flex size-8 items-center justify-center rounded-[8px] text-sm transition-colors",
2585
+ "focus-visible:outline-2 focus-visible:outline-text focus-visible:outline-offset-2",
2586
+ "disabled:pointer-events-none disabled:opacity-50",
2587
+ selected ? "bg-primary font-bold text-white" : "text-text hover:bg-hover",
2588
+ className
2589
+ ),
2590
+ ...props
2591
+ }
2592
+ );
2593
+ }
2594
+ function Chevron({ dir }) {
2595
+ return /* @__PURE__ */ jsxRuntime.jsx(
2596
+ "svg",
2597
+ {
2598
+ className: cn("size-4", dir === "left" && "rotate-180"),
2599
+ viewBox: "0 0 16 16",
2600
+ fill: "none",
2601
+ stroke: "currentColor",
2602
+ strokeWidth: "1.5",
2603
+ strokeLinecap: "round",
2604
+ strokeLinejoin: "round",
2605
+ "aria-hidden": true,
2606
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m6 4 4 4-4 4" })
2607
+ }
2608
+ );
2609
+ }
2610
+ function clampPercent(value) {
2611
+ return Math.max(0, Math.min(100, value));
2612
+ }
2613
+ var LINEAR_THICKNESS = {
2614
+ "6xs": "h-0.5",
2615
+ "5xs": "h-1",
2616
+ "4xs": "h-2",
2617
+ "3xs": "h-3",
2618
+ "2xs": "h-4"
2619
+ };
2620
+ var CIRCULAR_SIZE = {
2621
+ "2xs": 16,
2622
+ xs: 24,
2623
+ sm: 32,
2624
+ md: 40,
2625
+ lg: 48
2626
+ };
2627
+ function Progress({
2628
+ value,
2629
+ className,
2630
+ label = "Progress",
2631
+ ...rest
2632
+ }) {
2633
+ const pct = clampPercent(value);
2634
+ const common = {
2635
+ role: "progressbar",
2636
+ "aria-label": label,
2637
+ "aria-valuenow": Math.round(pct),
2638
+ "aria-valuemin": 0,
2639
+ "aria-valuemax": 100
2640
+ };
2641
+ if (rest.variant === "circular") {
2642
+ const px = CIRCULAR_SIZE[rest.size ?? "md"];
2643
+ const stroke = Math.max(2, Math.round(px / 8));
2644
+ const r = (px - stroke) / 2;
2645
+ const circumference = 2 * Math.PI * r;
2646
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2647
+ "svg",
2648
+ {
2649
+ ...common,
2650
+ width: px,
2651
+ height: px,
2652
+ viewBox: `0 0 ${px} ${px}`,
2653
+ className: cn("-rotate-90", className),
2654
+ children: [
2655
+ /* @__PURE__ */ jsxRuntime.jsx(
2656
+ "circle",
2657
+ {
2658
+ cx: px / 2,
2659
+ cy: px / 2,
2660
+ r,
2661
+ fill: "none",
2662
+ strokeWidth: stroke,
2663
+ className: "stroke-background"
2664
+ }
2665
+ ),
2666
+ /* @__PURE__ */ jsxRuntime.jsx(
2667
+ "circle",
2668
+ {
2669
+ cx: px / 2,
2670
+ cy: px / 2,
2671
+ r,
2672
+ fill: "none",
2673
+ strokeWidth: stroke,
2674
+ strokeLinecap: "round",
2675
+ strokeDasharray: circumference,
2676
+ strokeDashoffset: circumference * (1 - pct / 100),
2677
+ className: "stroke-primary transition-[stroke-dashoffset]"
2678
+ }
2679
+ )
2680
+ ]
2681
+ }
2682
+ );
2683
+ }
2684
+ const thickness = LINEAR_THICKNESS[rest.size ?? "4xs"];
2685
+ return /* @__PURE__ */ jsxRuntime.jsx(
2686
+ "div",
2687
+ {
2688
+ ...common,
2689
+ className: cn(
2690
+ "w-full overflow-hidden rounded-full bg-background",
2691
+ thickness,
2692
+ className
2693
+ ),
2694
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2695
+ "div",
2696
+ {
2697
+ className: "h-full rounded-full bg-primary transition-[width]",
2698
+ style: { width: `${pct}%` }
2699
+ }
2700
+ )
2701
+ }
2702
+ );
2703
+ }
2704
+ var DropdownContext = react.createContext(null);
2705
+ function Dropdown({
2706
+ trigger,
2707
+ children,
2708
+ align = "start",
2709
+ className
2710
+ }) {
2711
+ const [open, setOpen] = react.useState(false);
2712
+ return /* @__PURE__ */ jsxRuntime.jsx(DropdownContext.Provider, { value: { close: () => setOpen(false) }, children: /* @__PURE__ */ jsxRuntime.jsx(
2713
+ Popover,
2714
+ {
2715
+ trigger,
2716
+ open,
2717
+ onOpenChange: setOpen,
2718
+ align,
2719
+ className: cn("min-w-40", className),
2720
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { role: "menu", className: "flex flex-col", children })
2721
+ }
2722
+ ) });
2723
+ }
2724
+ function DropdownItem({
2725
+ leading,
2726
+ trailing,
2727
+ description,
2728
+ selected,
2729
+ children,
2730
+ className,
2731
+ onClick,
2732
+ disabled,
2733
+ ...props
2734
+ }) {
2735
+ const ctx = react.useContext(DropdownContext);
2736
+ const end = trailing ?? (selected ? /* @__PURE__ */ jsxRuntime.jsx(CheckMark, {}) : null);
2737
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2738
+ "button",
2739
+ {
2740
+ type: "button",
2741
+ role: "menuitem",
2742
+ "aria-current": selected || void 0,
2743
+ disabled,
2744
+ onClick: (e) => {
2745
+ onClick?.(e);
2746
+ ctx?.close();
2747
+ },
2748
+ className: cn(
2749
+ "flex w-full gap-2 rounded-[8px] px-3 py-2 text-left text-sm text-text",
2750
+ description ? "items-start" : "items-center",
2751
+ "hover:bg-hover focus-visible:bg-hover focus-visible:outline-none",
2752
+ "disabled:pointer-events-none disabled:opacity-50",
2753
+ className
2754
+ ),
2755
+ ...props,
2756
+ children: [
2757
+ leading && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0", children: leading }),
2758
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex flex-1 flex-col", children: [
2759
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children }),
2760
+ description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-text-muted", children: description })
2761
+ ] }),
2762
+ end && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0", children: end })
2763
+ ]
2764
+ }
2765
+ );
2766
+ }
2767
+ function CheckMark() {
2768
+ return /* @__PURE__ */ jsxRuntime.jsx(
2769
+ "svg",
2770
+ {
2771
+ className: "size-4 text-primary",
2772
+ viewBox: "0 0 24 24",
2773
+ fill: "none",
2774
+ stroke: "currentColor",
2775
+ strokeWidth: "2",
2776
+ strokeLinecap: "round",
2777
+ strokeLinejoin: "round",
2778
+ "aria-hidden": true,
2779
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 6 9 17l-5-5" })
2780
+ }
2781
+ );
2782
+ }
2783
+ function filterOptions(options, query) {
2784
+ const q = query.trim().toLowerCase();
2785
+ if (!q) return options;
2786
+ return options.filter((o) => o.label.toLowerCase().includes(q));
2787
+ }
2788
+ function Combobox(props) {
2789
+ const {
2790
+ options,
2791
+ placeholder = "Select\u2026",
2792
+ disabled,
2793
+ className,
2794
+ emptyMessage = "No results"
2795
+ } = props;
2796
+ const [open, setOpen] = react.useState(false);
2797
+ const [query, setQuery] = react.useState("");
2798
+ const [activeIndex, setActiveIndex] = react.useState(0);
2799
+ const filtered = react.useMemo(
2800
+ () => filterOptions(options, query),
2801
+ [options, query]
2802
+ );
2803
+ const selectedValues = props.multiple ? props.value : props.value ? [props.value] : [];
2804
+ const labelFor = (v) => options.find((o) => o.value === v)?.label ?? v;
2805
+ const isSelected = (v) => selectedValues.includes(v);
2806
+ const commit = (v) => {
2807
+ if (props.multiple) {
2808
+ const set = new Set(props.value);
2809
+ if (set.has(v)) set.delete(v);
2810
+ else set.add(v);
2811
+ props.onChange([...set]);
2812
+ setQuery("");
2813
+ } else {
2814
+ props.onChange(v);
2815
+ setQuery("");
2816
+ setOpen(false);
2817
+ }
2818
+ };
2819
+ const onKeyDown = (e) => {
2820
+ if (e.key === "ArrowDown") {
2821
+ e.preventDefault();
2822
+ setOpen(true);
2823
+ setActiveIndex((i) => Math.min(i + 1, filtered.length - 1));
2824
+ } else if (e.key === "ArrowUp") {
2825
+ e.preventDefault();
2826
+ setActiveIndex((i) => Math.max(i - 1, 0));
2827
+ } else if (e.key === "Enter") {
2828
+ e.preventDefault();
2829
+ const opt = filtered[activeIndex];
2830
+ if (opt) commit(opt.value);
2831
+ } else if (e.key === "Escape") {
2832
+ setOpen(false);
2833
+ } else if (e.key === "Backspace" && !query && props.multiple && props.value.length) {
2834
+ props.onChange(props.value.slice(0, -1));
2835
+ }
2836
+ };
2837
+ const singleSelectedLabel = !props.multiple && props.value ? labelFor(props.value) : "";
2838
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative w-full", className), children: [
2839
+ /* @__PURE__ */ jsxRuntime.jsxs(
2840
+ "div",
2841
+ {
2842
+ className: cn(
2843
+ "flex min-h-10 w-full flex-wrap items-center gap-1 rounded-[8px] border border-border bg-surface px-2 py-1 text-sm",
2844
+ "focus-within:border-[1.5px] focus-within:border-primary",
2845
+ disabled && "pointer-events-none opacity-50"
2846
+ ),
2847
+ onClick: () => setOpen(true),
2848
+ children: [
2849
+ props.multiple && props.value.map((v) => /* @__PURE__ */ jsxRuntime.jsx(
2850
+ Chip,
2851
+ {
2852
+ size: "sm",
2853
+ onDismiss: () => props.onChange(props.value.filter((x) => x !== v)),
2854
+ children: labelFor(v)
2855
+ },
2856
+ v
2857
+ )),
2858
+ /* @__PURE__ */ jsxRuntime.jsx(
2859
+ "input",
2860
+ {
2861
+ className: "min-w-[60px] flex-1 bg-transparent text-text outline-none placeholder:text-text-muted",
2862
+ value: query || (!open ? singleSelectedLabel : ""),
2863
+ placeholder: selectedValues.length ? "" : placeholder,
2864
+ disabled,
2865
+ role: "combobox",
2866
+ "aria-expanded": open,
2867
+ "aria-autocomplete": "list",
2868
+ onChange: (e) => {
2869
+ setQuery(e.target.value);
2870
+ setOpen(true);
2871
+ setActiveIndex(0);
2872
+ },
2873
+ onFocus: () => setOpen(true),
2874
+ onBlur: () => setTimeout(() => setOpen(false), 120),
2875
+ onKeyDown
2876
+ }
2877
+ ),
2878
+ /* @__PURE__ */ jsxRuntime.jsx(
2879
+ ChevronDown4,
2880
+ {
2881
+ className: cn(
2882
+ "size-5 shrink-0 text-text-muted transition-transform",
2883
+ open && "rotate-180"
2884
+ )
2885
+ }
2886
+ )
2887
+ ]
2888
+ }
2889
+ ),
2890
+ open && /* @__PURE__ */ jsxRuntime.jsx(
2891
+ "ul",
2892
+ {
2893
+ role: "listbox",
2894
+ className: "absolute z-50 mt-1 max-h-60 w-full overflow-auto rounded-[12px] border border-border bg-surface p-1 shadow-lg",
2895
+ children: filtered.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("li", { className: "px-3 py-2 text-sm text-text-muted", children: emptyMessage }) : filtered.map((opt, i) => /* @__PURE__ */ jsxRuntime.jsxs(
2896
+ "li",
2897
+ {
2898
+ role: "option",
2899
+ "aria-selected": isSelected(opt.value),
2900
+ onMouseEnter: () => setActiveIndex(i),
2901
+ onMouseDown: (e) => {
2902
+ e.preventDefault();
2903
+ commit(opt.value);
2904
+ },
2905
+ className: cn(
2906
+ "flex cursor-pointer items-center justify-between rounded-[8px] px-3 py-2 text-sm text-text",
2907
+ i === activeIndex && "bg-hover"
2908
+ ),
2909
+ children: [
2910
+ opt.label,
2911
+ isSelected(opt.value) && /* @__PURE__ */ jsxRuntime.jsx(Check, { className: "size-4 text-primary" })
2912
+ ]
2913
+ },
2914
+ opt.value
2915
+ ))
2916
+ }
2917
+ )
2918
+ ] });
2919
+ }
2920
+ function ChevronDown4({ className }) {
2921
+ return /* @__PURE__ */ jsxRuntime.jsx(
2922
+ "svg",
2923
+ {
2924
+ className,
2925
+ viewBox: "0 0 24 24",
2926
+ fill: "none",
2927
+ stroke: "currentColor",
2928
+ strokeWidth: "2",
2929
+ strokeLinecap: "round",
2930
+ strokeLinejoin: "round",
2931
+ "aria-hidden": true,
2932
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m6 9 6 6 6-6" })
2933
+ }
2934
+ );
2935
+ }
2936
+ function Check({ className }) {
2937
+ return /* @__PURE__ */ jsxRuntime.jsx(
2938
+ "svg",
2939
+ {
2940
+ className,
2941
+ viewBox: "0 0 24 24",
2942
+ fill: "none",
2943
+ stroke: "currentColor",
2944
+ strokeWidth: "2",
2945
+ strokeLinecap: "round",
2946
+ strokeLinejoin: "round",
2947
+ "aria-hidden": true,
2948
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 6 9 17l-5-5" })
2949
+ }
2950
+ );
2951
+ }
2952
+
2953
+ exports.Accordion = Accordion;
2954
+ exports.Alert = Alert;
2955
+ exports.AuthCode = AuthCode;
2956
+ exports.Avatar = Avatar;
2957
+ exports.Breadcrumbs = Breadcrumbs;
2958
+ exports.Button = Button;
2959
+ exports.Calendar = Calendar;
2960
+ exports.Carousel = Carousel;
2961
+ exports.Checkbox = Checkbox;
2962
+ exports.Chip = Chip;
2963
+ exports.Combobox = Combobox;
2964
+ exports.Container = Container;
2965
+ exports.DataTable = DataTable;
2966
+ exports.DateRangePicker = DateRangePicker;
2967
+ exports.Drawer = Drawer;
2968
+ exports.Dropdown = Dropdown;
2969
+ exports.DropdownItem = DropdownItem;
2970
+ exports.EmptyState = EmptyState;
2971
+ exports.GroupField = GroupField;
2972
+ exports.Loader = Loader;
2973
+ exports.Modal = Modal;
2974
+ exports.Pagination = Pagination;
2975
+ exports.Popover = Popover;
2976
+ exports.Progress = Progress;
2977
+ exports.QuarterPicker = QuarterPicker;
2978
+ exports.Radio = Radio;
2979
+ exports.Search = Search;
2980
+ exports.SegmentedControl = SegmentedControl;
2981
+ exports.Select = Select;
2982
+ exports.Sidebar = Sidebar;
2983
+ exports.SidebarItem = SidebarItem;
2984
+ exports.SidebarSection = SidebarSection;
2985
+ exports.Snackbar = Snackbar;
2986
+ exports.Switch = Switch;
2987
+ exports.Tab = Tab;
2988
+ exports.TabList = TabList;
2989
+ exports.TabPanel = TabPanel;
2990
+ exports.Table = Table;
2991
+ exports.TableBody = TableBody;
2992
+ exports.TableCell = TableCell;
2993
+ exports.TableHead = TableHead;
2994
+ exports.TableRow = TableRow;
2995
+ exports.Tabs = Tabs;
2996
+ exports.Tag = Tag;
2997
+ exports.TextInput = TextInput;
2998
+ exports.TextInputGroup = TextInputGroup;
2999
+ exports.Textarea = Textarea;
3000
+ exports.TimePicker = TimePicker;
3001
+ exports.ToastProvider = ToastProvider;
3002
+ exports.Tooltip = Tooltip;
3003
+ exports.buttonVariants = buttonVariants;
3004
+ exports.clampPercent = clampPercent;
3005
+ exports.cn = cn;
3006
+ exports.defaultPresets = defaultPresets;
3007
+ exports.filterOptions = filterOptions;
3008
+ exports.paginationRange = paginationRange;
3009
+ exports.presetRanges = presetRanges;
3010
+ exports.selectionState = selectionState;
3011
+ exports.useToast = useToast;