@ambersecurityinc/ui 0.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.
@@ -0,0 +1,2337 @@
1
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
+ import { createContext, forwardRef, useId, useEffect, useCallback, useMemo, useState, useRef, useContext } from 'react';
3
+ import { createPortal } from 'react-dom';
4
+
5
+ // src/components/layout/AppShell.tsx
6
+ var rootStyle = {
7
+ display: "flex",
8
+ minHeight: "100vh",
9
+ background: "var(--bg)",
10
+ color: "var(--text)",
11
+ fontFamily: "var(--font-body, 'Manrope', sans-serif)"
12
+ };
13
+ var mainWrapperStyle = {
14
+ display: "flex",
15
+ flexDirection: "column",
16
+ flex: 1,
17
+ minWidth: 0
18
+ // prevent flex child overflow
19
+ };
20
+ var contentStyle = {
21
+ flex: 1,
22
+ padding: "24px",
23
+ overflowY: "auto"
24
+ };
25
+ function AppShell({
26
+ sidebar,
27
+ header,
28
+ children,
29
+ className,
30
+ style
31
+ }) {
32
+ return /* @__PURE__ */ jsxs(
33
+ "div",
34
+ {
35
+ className,
36
+ style: { ...rootStyle, ...style },
37
+ children: [
38
+ sidebar,
39
+ /* @__PURE__ */ jsxs("div", { style: mainWrapperStyle, children: [
40
+ header,
41
+ /* @__PURE__ */ jsx("main", { style: contentStyle, children })
42
+ ] })
43
+ ]
44
+ }
45
+ );
46
+ }
47
+ var SIDEBAR_WIDTH = 260;
48
+ var SIDEBAR_COLLAPSED_WIDTH = 64;
49
+ var MOBILE_BREAKPOINT = 768;
50
+ function Sidebar({
51
+ collapsed = false,
52
+ onToggle,
53
+ header,
54
+ children,
55
+ className,
56
+ style,
57
+ mobileOpen = false,
58
+ onMobileClose
59
+ }) {
60
+ useEffect(() => {
61
+ if (!mobileOpen) return;
62
+ const handleKeyDown = (e) => {
63
+ if (e.key === "Escape") onMobileClose?.();
64
+ };
65
+ document.addEventListener("keydown", handleKeyDown);
66
+ return () => document.removeEventListener("keydown", handleKeyDown);
67
+ }, [mobileOpen, onMobileClose]);
68
+ useEffect(() => {
69
+ if (!mobileOpen) return;
70
+ const prev = document.body.style.overflow;
71
+ document.body.style.overflow = "hidden";
72
+ return () => {
73
+ document.body.style.overflow = prev;
74
+ };
75
+ }, [mobileOpen]);
76
+ const handleToggleKeyDown = useCallback(
77
+ (e) => {
78
+ if (e.key === "Enter" || e.key === " ") {
79
+ e.preventDefault();
80
+ onToggle?.();
81
+ }
82
+ },
83
+ [onToggle]
84
+ );
85
+ const width = collapsed ? SIDEBAR_COLLAPSED_WIDTH : SIDEBAR_WIDTH;
86
+ const navStyle = {
87
+ width,
88
+ minWidth: width,
89
+ height: "100vh",
90
+ display: "flex",
91
+ flexDirection: "column",
92
+ background: "var(--sidebar)",
93
+ color: "var(--text-sidebar)",
94
+ borderRight: "1px solid var(--border-sidebar)",
95
+ transition: "width 200ms ease, min-width 200ms ease",
96
+ overflowX: "hidden",
97
+ overflowY: "auto",
98
+ position: "sticky",
99
+ top: 0
100
+ };
101
+ const mobileNavStyle = {
102
+ ...navStyle,
103
+ position: "fixed",
104
+ top: 0,
105
+ left: 0,
106
+ zIndex: 1100,
107
+ width: SIDEBAR_WIDTH,
108
+ minWidth: SIDEBAR_WIDTH,
109
+ transform: mobileOpen ? "translateX(0)" : `translateX(-100%)`,
110
+ transition: "transform 200ms ease"
111
+ };
112
+ const backdropStyle = {
113
+ position: "fixed",
114
+ inset: 0,
115
+ zIndex: 1099,
116
+ background: "rgba(0,0,0,0.5)",
117
+ opacity: mobileOpen ? 1 : 0,
118
+ pointerEvents: mobileOpen ? "auto" : "none",
119
+ transition: "opacity 200ms ease"
120
+ };
121
+ const headerSlotStyle = {
122
+ padding: collapsed ? "16px 8px" : "16px",
123
+ borderBottom: "1px solid var(--border-sidebar)",
124
+ display: "flex",
125
+ alignItems: "center",
126
+ justifyContent: collapsed ? "center" : "space-between",
127
+ gap: 8,
128
+ minHeight: 56
129
+ };
130
+ const toggleBtnStyle = {
131
+ background: "transparent",
132
+ border: "none",
133
+ color: "var(--text-sidebar-muted)",
134
+ cursor: "pointer",
135
+ padding: 4,
136
+ borderRadius: 4,
137
+ display: "flex",
138
+ alignItems: "center",
139
+ justifyContent: "center",
140
+ flexShrink: 0
141
+ };
142
+ const bodyStyle = {
143
+ flex: 1,
144
+ padding: collapsed ? "8px 4px" : "8px 12px",
145
+ overflowY: "auto",
146
+ overflowX: "hidden"
147
+ };
148
+ const toggleIcon = collapsed ? "\u25B6" : "\u25C0";
149
+ const sidebarContent = /* @__PURE__ */ jsxs(Fragment, { children: [
150
+ /* @__PURE__ */ jsxs("div", { style: headerSlotStyle, children: [
151
+ !collapsed && header,
152
+ onToggle && /* @__PURE__ */ jsx(
153
+ "button",
154
+ {
155
+ type: "button",
156
+ onClick: onToggle,
157
+ onKeyDown: handleToggleKeyDown,
158
+ "aria-label": collapsed ? "Expand sidebar" : "Collapse sidebar",
159
+ style: toggleBtnStyle,
160
+ children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: { fontSize: 12 }, children: toggleIcon })
161
+ }
162
+ )
163
+ ] }),
164
+ /* @__PURE__ */ jsx("div", { style: bodyStyle, role: "group", "aria-label": "Sidebar navigation", children })
165
+ ] });
166
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
167
+ /* @__PURE__ */ jsx(
168
+ "nav",
169
+ {
170
+ "aria-label": "Main navigation",
171
+ className,
172
+ style: { ...navStyle, ...style },
173
+ "data-sidebar-desktop": "",
174
+ children: sidebarContent
175
+ }
176
+ ),
177
+ /* @__PURE__ */ jsx(
178
+ "div",
179
+ {
180
+ "aria-hidden": !mobileOpen,
181
+ style: backdropStyle,
182
+ onClick: onMobileClose
183
+ }
184
+ ),
185
+ /* @__PURE__ */ jsx(
186
+ "nav",
187
+ {
188
+ "aria-label": "Main navigation",
189
+ "aria-modal": mobileOpen ? true : void 0,
190
+ role: mobileOpen ? "dialog" : void 0,
191
+ style: { ...mobileNavStyle, ...style },
192
+ "data-sidebar-mobile": "",
193
+ children: sidebarContent
194
+ }
195
+ ),
196
+ /* @__PURE__ */ jsx("style", { children: `
197
+ [data-sidebar-mobile] { display: none; }
198
+ @media (max-width: ${MOBILE_BREAKPOINT - 1}px) {
199
+ [data-sidebar-desktop] { display: none !important; }
200
+ [data-sidebar-mobile] { display: flex !important; }
201
+ }
202
+ ` })
203
+ ] });
204
+ }
205
+ var sectionStyle = {
206
+ marginBottom: 8
207
+ };
208
+ var sectionTitleStyle = {
209
+ fontSize: 11,
210
+ fontWeight: 600,
211
+ textTransform: "uppercase",
212
+ letterSpacing: "0.05em",
213
+ color: "var(--text-sidebar-muted)",
214
+ padding: "12px 8px 4px",
215
+ userSelect: "none"
216
+ };
217
+ function SidebarSection({
218
+ title,
219
+ children,
220
+ className,
221
+ style: customStyle
222
+ }) {
223
+ return /* @__PURE__ */ jsxs(
224
+ "div",
225
+ {
226
+ className,
227
+ style: { ...sectionStyle, ...customStyle },
228
+ role: "group",
229
+ "aria-label": title,
230
+ children: [
231
+ title && /* @__PURE__ */ jsx("div", { style: sectionTitleStyle, children: title }),
232
+ children
233
+ ]
234
+ }
235
+ );
236
+ }
237
+ var barStyle = {
238
+ display: "flex",
239
+ alignItems: "center",
240
+ justifyContent: "space-between",
241
+ gap: 16,
242
+ minHeight: 56,
243
+ padding: "0 24px",
244
+ background: "var(--surface)",
245
+ borderBottom: "1px solid var(--border)",
246
+ flexShrink: 0
247
+ };
248
+ var breadcrumbNavStyle = {
249
+ display: "flex",
250
+ alignItems: "center",
251
+ gap: 6,
252
+ flex: 1,
253
+ minWidth: 0,
254
+ overflow: "hidden"
255
+ };
256
+ var crumbStyle = {
257
+ fontSize: 14,
258
+ color: "var(--text-muted)",
259
+ whiteSpace: "nowrap",
260
+ textDecoration: "none",
261
+ transition: "color 150ms ease"
262
+ };
263
+ var crumbCurrentStyle = {
264
+ ...crumbStyle,
265
+ color: "var(--text)",
266
+ fontWeight: 600
267
+ };
268
+ var separatorStyle = {
269
+ fontSize: 12,
270
+ color: "var(--text-muted)",
271
+ userSelect: "none",
272
+ flexShrink: 0
273
+ };
274
+ var rightSlotStyle = {
275
+ display: "flex",
276
+ alignItems: "center",
277
+ gap: 12,
278
+ flexShrink: 0
279
+ };
280
+ function Header({
281
+ breadcrumbs = [],
282
+ actions,
283
+ avatar,
284
+ className,
285
+ style
286
+ }) {
287
+ const lastIdx = breadcrumbs.length - 1;
288
+ return /* @__PURE__ */ jsxs(
289
+ "header",
290
+ {
291
+ className,
292
+ style: { ...barStyle, ...style },
293
+ children: [
294
+ breadcrumbs.length > 0 && /* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", style: breadcrumbNavStyle, children: /* @__PURE__ */ jsx(
295
+ "ol",
296
+ {
297
+ style: {
298
+ display: "flex",
299
+ alignItems: "center",
300
+ gap: 6,
301
+ listStyle: "none",
302
+ margin: 0,
303
+ padding: 0
304
+ },
305
+ children: breadcrumbs.map((crumb, i) => {
306
+ const isCurrent = i === lastIdx;
307
+ return /* @__PURE__ */ jsxs(
308
+ "li",
309
+ {
310
+ style: { display: "flex", alignItems: "center", gap: 6 },
311
+ children: [
312
+ i > 0 && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: separatorStyle, children: "/" }),
313
+ crumb.href && !isCurrent ? /* @__PURE__ */ jsx(
314
+ "a",
315
+ {
316
+ href: crumb.href,
317
+ style: crumbStyle,
318
+ children: crumb.label
319
+ }
320
+ ) : /* @__PURE__ */ jsx(
321
+ "span",
322
+ {
323
+ style: isCurrent ? crumbCurrentStyle : crumbStyle,
324
+ "aria-current": isCurrent ? "page" : void 0,
325
+ children: crumb.label
326
+ }
327
+ )
328
+ ]
329
+ },
330
+ `${crumb.label}-${i}`
331
+ );
332
+ })
333
+ }
334
+ ) }),
335
+ /* @__PURE__ */ jsxs("div", { style: rightSlotStyle, children: [
336
+ actions,
337
+ avatar
338
+ ] })
339
+ ]
340
+ }
341
+ );
342
+ }
343
+ var variantStyles = {
344
+ success: { background: "var(--success-soft)", color: "var(--success)" },
345
+ warning: { background: "var(--warning-soft)", color: "var(--warning)" },
346
+ error: { background: "var(--error-soft)", color: "var(--error)" },
347
+ info: { background: "var(--info-soft)", color: "var(--info)" },
348
+ accent: { background: "var(--accent-soft)", color: "var(--accent)" },
349
+ neutral: { background: "var(--surface-alt)", color: "var(--text-secondary)" }
350
+ };
351
+ var sizeStyles = {
352
+ sm: { fontSize: 11, padding: "1px 6px", borderRadius: "var(--radius-sm, 6px)" },
353
+ md: { fontSize: 12, padding: "2px 8px", borderRadius: "var(--radius-sm, 6px)" }
354
+ };
355
+ function Badge({
356
+ variant,
357
+ size = "md",
358
+ children,
359
+ className,
360
+ style,
361
+ ...rest
362
+ }) {
363
+ return /* @__PURE__ */ jsx(
364
+ "span",
365
+ {
366
+ className,
367
+ style: {
368
+ display: "inline-flex",
369
+ alignItems: "center",
370
+ fontFamily: "var(--font-body)",
371
+ fontWeight: 600,
372
+ lineHeight: 1.5,
373
+ whiteSpace: "nowrap",
374
+ ...variantStyles[variant],
375
+ ...sizeStyles[size],
376
+ ...style
377
+ },
378
+ ...rest,
379
+ children
380
+ }
381
+ );
382
+ }
383
+ var shimmerKeyframes = `
384
+ @keyframes amber-skeleton-shimmer {
385
+ 0% { background-position: -400px 0; }
386
+ 100% { background-position: 400px 0; }
387
+ }
388
+ `;
389
+ var styleInjected = false;
390
+ function injectKeyframes() {
391
+ if (styleInjected || typeof document === "undefined") return;
392
+ const sheet = document.createElement("style");
393
+ sheet.textContent = shimmerKeyframes;
394
+ document.head.appendChild(sheet);
395
+ styleInjected = true;
396
+ }
397
+ function baseStyle(extra) {
398
+ return {
399
+ background: `linear-gradient(90deg, var(--surface-alt, #eee) 25%, var(--surface-hover, #ddd) 50%, var(--surface-alt, #eee) 75%)`,
400
+ backgroundSize: "800px 100%",
401
+ animation: "amber-skeleton-shimmer 1.6s ease-in-out infinite",
402
+ borderRadius: "var(--radius-sm, 6px)",
403
+ ...extra
404
+ };
405
+ }
406
+ function Skeleton({
407
+ variant,
408
+ width,
409
+ height,
410
+ lines = 3,
411
+ className,
412
+ style,
413
+ ...rest
414
+ }) {
415
+ injectKeyframes();
416
+ if (variant === "text") {
417
+ return /* @__PURE__ */ jsxs(
418
+ "div",
419
+ {
420
+ role: "status",
421
+ "aria-label": "Loading",
422
+ className,
423
+ style: { display: "flex", flexDirection: "column", gap: 8, ...style },
424
+ ...rest,
425
+ children: [
426
+ Array.from({ length: lines }, (_, i) => /* @__PURE__ */ jsx(
427
+ "div",
428
+ {
429
+ style: baseStyle({
430
+ width: i === lines - 1 ? "60%" : width ?? "100%",
431
+ height: typeof height === "number" ? height : height ?? 14,
432
+ borderRadius: "var(--radius-sm, 6px)"
433
+ })
434
+ },
435
+ i
436
+ )),
437
+ /* @__PURE__ */ jsx("span", { style: { position: "absolute", width: 1, height: 1, overflow: "hidden", clip: "rect(0,0,0,0)" }, children: "Loading..." })
438
+ ]
439
+ }
440
+ );
441
+ }
442
+ const isCircle = variant === "circle";
443
+ const resolvedWidth = width ?? (isCircle ? 40 : "100%");
444
+ const resolvedHeight = height ?? (isCircle ? 40 : 20);
445
+ return /* @__PURE__ */ jsx(
446
+ "div",
447
+ {
448
+ role: "status",
449
+ "aria-label": "Loading",
450
+ className,
451
+ style: baseStyle({
452
+ width: resolvedWidth,
453
+ height: resolvedHeight,
454
+ borderRadius: isCircle ? "50%" : "var(--radius-sm, 6px)",
455
+ ...style
456
+ }),
457
+ ...rest,
458
+ children: /* @__PURE__ */ jsx("span", { style: { position: "absolute", width: 1, height: 1, overflow: "hidden", clip: "rect(0,0,0,0)" }, children: "Loading..." })
459
+ }
460
+ );
461
+ }
462
+ function EmptyState({
463
+ icon,
464
+ title,
465
+ description,
466
+ action,
467
+ className,
468
+ style,
469
+ ...rest
470
+ }) {
471
+ return /* @__PURE__ */ jsxs(
472
+ "div",
473
+ {
474
+ role: "status",
475
+ className,
476
+ style: {
477
+ display: "flex",
478
+ flexDirection: "column",
479
+ alignItems: "center",
480
+ justifyContent: "center",
481
+ padding: 48,
482
+ textAlign: "center",
483
+ fontFamily: "var(--font-body)",
484
+ ...style
485
+ },
486
+ ...rest,
487
+ children: [
488
+ icon && /* @__PURE__ */ jsx(
489
+ "div",
490
+ {
491
+ style: {
492
+ marginBottom: 16,
493
+ color: "var(--text-muted)",
494
+ fontSize: 40,
495
+ lineHeight: 1
496
+ },
497
+ children: icon
498
+ }
499
+ ),
500
+ /* @__PURE__ */ jsx(
501
+ "h3",
502
+ {
503
+ style: {
504
+ margin: 0,
505
+ fontSize: 16,
506
+ fontWeight: 600,
507
+ color: "var(--text)",
508
+ fontFamily: "var(--font-display)"
509
+ },
510
+ children: title
511
+ }
512
+ ),
513
+ description && /* @__PURE__ */ jsx(
514
+ "p",
515
+ {
516
+ style: {
517
+ margin: "8px 0 0",
518
+ fontSize: 14,
519
+ color: "var(--text-secondary)",
520
+ maxWidth: 360,
521
+ lineHeight: 1.5
522
+ },
523
+ children: description
524
+ }
525
+ ),
526
+ action && /* @__PURE__ */ jsx("div", { style: { marginTop: 20 }, children: action })
527
+ ]
528
+ }
529
+ );
530
+ }
531
+ function SortIcon({ direction, active }) {
532
+ return /* @__PURE__ */ jsxs(
533
+ "svg",
534
+ {
535
+ width: 14,
536
+ height: 14,
537
+ viewBox: "0 0 14 14",
538
+ fill: "none",
539
+ "aria-hidden": "true",
540
+ style: {
541
+ marginLeft: 4,
542
+ flexShrink: 0,
543
+ opacity: active ? 1 : 0.35,
544
+ transition: "opacity 0.15s"
545
+ },
546
+ children: [
547
+ /* @__PURE__ */ jsx(
548
+ "path",
549
+ {
550
+ d: "M7 3L10 6.5H4L7 3Z",
551
+ fill: active && direction === "asc" ? "currentColor" : "var(--text-muted)"
552
+ }
553
+ ),
554
+ /* @__PURE__ */ jsx(
555
+ "path",
556
+ {
557
+ d: "M7 11L4 7.5H10L7 11Z",
558
+ fill: active && direction === "desc" ? "currentColor" : "var(--text-muted)"
559
+ }
560
+ )
561
+ ]
562
+ }
563
+ );
564
+ }
565
+ var tableWrapperStyle = {
566
+ width: "100%",
567
+ overflowX: "auto",
568
+ border: "1px solid var(--border)",
569
+ borderRadius: "var(--radius-md, 10px)",
570
+ background: "var(--surface)",
571
+ fontFamily: "var(--font-body)"
572
+ };
573
+ var tableStyle = {
574
+ width: "100%",
575
+ borderCollapse: "collapse",
576
+ fontSize: 14
577
+ };
578
+ var thStyle = {
579
+ textAlign: "left",
580
+ padding: "10px 14px",
581
+ fontWeight: 600,
582
+ fontSize: 12,
583
+ color: "var(--text-secondary)",
584
+ textTransform: "uppercase",
585
+ letterSpacing: "0.04em",
586
+ borderBottom: "1px solid var(--border)",
587
+ background: "var(--surface-alt)",
588
+ whiteSpace: "nowrap",
589
+ userSelect: "none"
590
+ };
591
+ var tdStyle = {
592
+ padding: "10px 14px",
593
+ color: "var(--text)",
594
+ borderBottom: "1px solid var(--border)",
595
+ verticalAlign: "middle"
596
+ };
597
+ var checkboxCellStyle = {
598
+ width: 36,
599
+ textAlign: "center"
600
+ };
601
+ function DataTable({
602
+ columns,
603
+ data,
604
+ loading = false,
605
+ emptyState,
606
+ selectable = false,
607
+ selectedRows,
608
+ onSelectionChange,
609
+ sortKey,
610
+ sortDirection,
611
+ onSort,
612
+ cursor = null,
613
+ onPageChange,
614
+ pageSize = 10,
615
+ className,
616
+ style,
617
+ ...rest
618
+ }) {
619
+ const selected = selectedRows ?? /* @__PURE__ */ new Set();
620
+ const allSelected = useMemo(
621
+ () => data.length > 0 && data.every((_, i) => selected.has(i)),
622
+ [data, selected]
623
+ );
624
+ const someSelected = useMemo(
625
+ () => !allSelected && data.some((_, i) => selected.has(i)),
626
+ [data, selected, allSelected]
627
+ );
628
+ const toggleAll = useCallback(() => {
629
+ if (!onSelectionChange) return;
630
+ if (allSelected) {
631
+ onSelectionChange(/* @__PURE__ */ new Set());
632
+ } else {
633
+ onSelectionChange(new Set(data.map((_, i) => i)));
634
+ }
635
+ }, [allSelected, data, onSelectionChange]);
636
+ const toggleRow = useCallback(
637
+ (index) => {
638
+ if (!onSelectionChange) return;
639
+ const next = new Set(selected);
640
+ if (next.has(index)) {
641
+ next.delete(index);
642
+ } else {
643
+ next.add(index);
644
+ }
645
+ onSelectionChange(next);
646
+ },
647
+ [selected, onSelectionChange]
648
+ );
649
+ const handleSort = useCallback(
650
+ (key) => {
651
+ if (!onSort) return;
652
+ const nextDir = sortKey === key && sortDirection === "asc" ? "desc" : "asc";
653
+ onSort(key, nextDir);
654
+ },
655
+ [onSort, sortKey, sortDirection]
656
+ );
657
+ const getCellValue = (row, key) => {
658
+ const val = row[key];
659
+ if (val == null) return "";
660
+ return String(val);
661
+ };
662
+ if (loading) {
663
+ return /* @__PURE__ */ jsx("div", { className, style: { ...tableWrapperStyle, ...style }, ...rest, children: /* @__PURE__ */ jsxs("table", { style: tableStyle, role: "table", "aria-busy": "true", children: [
664
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
665
+ selectable && /* @__PURE__ */ jsx("th", { style: { ...thStyle, ...checkboxCellStyle } }),
666
+ columns.map((col) => /* @__PURE__ */ jsx("th", { style: thStyle, children: col.header }, col.key))
667
+ ] }) }),
668
+ /* @__PURE__ */ jsx("tbody", { children: Array.from({ length: pageSize }, (_, rowIdx) => /* @__PURE__ */ jsxs("tr", { children: [
669
+ selectable && /* @__PURE__ */ jsx("td", { style: { ...tdStyle, ...checkboxCellStyle }, children: /* @__PURE__ */ jsx(Skeleton, { variant: "rect", width: 16, height: 16 }) }),
670
+ columns.map((col) => /* @__PURE__ */ jsx("td", { style: tdStyle, children: /* @__PURE__ */ jsx(Skeleton, { variant: "rect", width: "80%", height: 14 }) }, col.key))
671
+ ] }, rowIdx)) })
672
+ ] }) });
673
+ }
674
+ if (data.length === 0) {
675
+ return /* @__PURE__ */ jsx("div", { className, style: { ...tableWrapperStyle, ...style }, ...rest, children: emptyState ?? /* @__PURE__ */ jsx(
676
+ EmptyState,
677
+ {
678
+ title: "No data",
679
+ description: "There are no items to display."
680
+ }
681
+ ) });
682
+ }
683
+ return /* @__PURE__ */ jsxs("div", { className, style: { ...tableWrapperStyle, ...style }, ...rest, children: [
684
+ /* @__PURE__ */ jsxs("table", { style: tableStyle, role: "table", children: [
685
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
686
+ selectable && /* @__PURE__ */ jsx("th", { style: { ...thStyle, ...checkboxCellStyle }, children: /* @__PURE__ */ jsx(
687
+ "input",
688
+ {
689
+ type: "checkbox",
690
+ checked: allSelected,
691
+ ref: (el) => {
692
+ if (el) el.indeterminate = someSelected;
693
+ },
694
+ onChange: toggleAll,
695
+ "aria-label": "Select all rows",
696
+ style: { cursor: "pointer" }
697
+ }
698
+ ) }),
699
+ columns.map((col) => {
700
+ const isSortable = col.sortable && onSort;
701
+ const isActive = sortKey === col.key;
702
+ return /* @__PURE__ */ jsx(
703
+ "th",
704
+ {
705
+ style: {
706
+ ...thStyle,
707
+ cursor: isSortable ? "pointer" : "default"
708
+ },
709
+ onClick: isSortable ? () => handleSort(col.key) : void 0,
710
+ "aria-sort": isActive ? sortDirection === "asc" ? "ascending" : "descending" : void 0,
711
+ children: /* @__PURE__ */ jsxs("span", { style: { display: "inline-flex", alignItems: "center" }, children: [
712
+ col.header,
713
+ isSortable && /* @__PURE__ */ jsx(
714
+ SortIcon,
715
+ {
716
+ direction: isActive ? sortDirection : void 0,
717
+ active: isActive
718
+ }
719
+ )
720
+ ] })
721
+ },
722
+ col.key
723
+ );
724
+ })
725
+ ] }) }),
726
+ /* @__PURE__ */ jsx("tbody", { children: data.map((row, rowIndex) => {
727
+ const isSelected = selected.has(rowIndex);
728
+ return /* @__PURE__ */ jsxs(
729
+ "tr",
730
+ {
731
+ style: {
732
+ background: isSelected ? "var(--accent-soft)" : void 0,
733
+ transition: "background 0.12s"
734
+ },
735
+ children: [
736
+ selectable && /* @__PURE__ */ jsx("td", { style: { ...tdStyle, ...checkboxCellStyle }, children: /* @__PURE__ */ jsx(
737
+ "input",
738
+ {
739
+ type: "checkbox",
740
+ checked: isSelected,
741
+ onChange: () => toggleRow(rowIndex),
742
+ "aria-label": `Select row ${rowIndex + 1}`,
743
+ style: { cursor: "pointer" }
744
+ }
745
+ ) }),
746
+ columns.map((col) => /* @__PURE__ */ jsx("td", { style: tdStyle, children: col.render ? col.render(row, rowIndex) : getCellValue(row, col.key) }, col.key))
747
+ ]
748
+ },
749
+ rowIndex
750
+ );
751
+ }) })
752
+ ] }),
753
+ onPageChange && /* @__PURE__ */ jsxs(
754
+ "div",
755
+ {
756
+ style: {
757
+ display: "flex",
758
+ alignItems: "center",
759
+ justifyContent: "flex-end",
760
+ gap: 8,
761
+ padding: "10px 14px",
762
+ borderTop: "1px solid var(--border)"
763
+ },
764
+ children: [
765
+ /* @__PURE__ */ jsx(
766
+ PaginationButton,
767
+ {
768
+ label: "Previous",
769
+ onClick: () => onPageChange("prev", cursor)
770
+ }
771
+ ),
772
+ /* @__PURE__ */ jsx(
773
+ PaginationButton,
774
+ {
775
+ label: "Next",
776
+ onClick: () => onPageChange("next", cursor)
777
+ }
778
+ )
779
+ ]
780
+ }
781
+ )
782
+ ] });
783
+ }
784
+ function PaginationButton({ label, onClick }) {
785
+ return /* @__PURE__ */ jsx(
786
+ "button",
787
+ {
788
+ type: "button",
789
+ onClick,
790
+ style: {
791
+ display: "inline-flex",
792
+ alignItems: "center",
793
+ padding: "6px 14px",
794
+ fontSize: 13,
795
+ fontWeight: 500,
796
+ fontFamily: "var(--font-body)",
797
+ color: "var(--text)",
798
+ background: "var(--surface-alt)",
799
+ border: "1px solid var(--border)",
800
+ borderRadius: "var(--radius-sm, 6px)",
801
+ cursor: "pointer",
802
+ transition: "background 0.15s"
803
+ },
804
+ onMouseEnter: (e) => {
805
+ e.currentTarget.style.background = "var(--surface-hover)";
806
+ },
807
+ onMouseLeave: (e) => {
808
+ e.currentTarget.style.background = "var(--surface-alt)";
809
+ },
810
+ children: label
811
+ }
812
+ );
813
+ }
814
+ function DeltaArrow({ direction }) {
815
+ return /* @__PURE__ */ jsx(
816
+ "svg",
817
+ {
818
+ width: 12,
819
+ height: 12,
820
+ viewBox: "0 0 12 12",
821
+ fill: "none",
822
+ "aria-hidden": "true",
823
+ style: {
824
+ transform: direction === "down" ? "rotate(180deg)" : void 0,
825
+ flexShrink: 0
826
+ },
827
+ children: /* @__PURE__ */ jsx("path", { d: "M6 2.5L10 8.5H2L6 2.5Z", fill: "currentColor" })
828
+ }
829
+ );
830
+ }
831
+ function StatCard({
832
+ label,
833
+ value,
834
+ delta,
835
+ deltaLabel,
836
+ icon,
837
+ className,
838
+ style,
839
+ ...rest
840
+ }) {
841
+ const [hovered, setHovered] = useState(false);
842
+ const deltaDirection = delta != null && delta >= 0 ? "up" : "down";
843
+ const deltaColor = delta != null ? delta >= 0 ? "var(--success)" : "var(--error)" : void 0;
844
+ return /* @__PURE__ */ jsxs(
845
+ "div",
846
+ {
847
+ className,
848
+ onMouseEnter: () => setHovered(true),
849
+ onMouseLeave: () => setHovered(false),
850
+ style: {
851
+ position: "relative",
852
+ background: "var(--surface)",
853
+ border: "1px solid var(--border)",
854
+ borderRadius: "var(--radius-md, 10px)",
855
+ padding: 20,
856
+ fontFamily: "var(--font-body)",
857
+ boxShadow: hovered ? "var(--shadow-md)" : "var(--shadow)",
858
+ transition: "box-shadow 0.2s ease, transform 0.2s ease",
859
+ transform: hovered ? "translateY(-1px)" : "none",
860
+ cursor: "default",
861
+ ...style
862
+ },
863
+ ...rest,
864
+ children: [
865
+ /* @__PURE__ */ jsxs(
866
+ "div",
867
+ {
868
+ style: {
869
+ display: "flex",
870
+ alignItems: "flex-start",
871
+ justifyContent: "space-between"
872
+ },
873
+ children: [
874
+ /* @__PURE__ */ jsx(
875
+ "span",
876
+ {
877
+ style: {
878
+ fontSize: 13,
879
+ fontWeight: 500,
880
+ color: "var(--text-secondary)",
881
+ lineHeight: 1.4
882
+ },
883
+ children: label
884
+ }
885
+ ),
886
+ icon && /* @__PURE__ */ jsx(
887
+ "span",
888
+ {
889
+ style: {
890
+ color: "var(--text-muted)",
891
+ fontSize: 20,
892
+ lineHeight: 1,
893
+ flexShrink: 0,
894
+ marginLeft: 8
895
+ },
896
+ children: icon
897
+ }
898
+ )
899
+ ]
900
+ }
901
+ ),
902
+ /* @__PURE__ */ jsx(
903
+ "div",
904
+ {
905
+ style: {
906
+ marginTop: 8,
907
+ fontSize: 28,
908
+ fontWeight: 700,
909
+ color: "var(--text)",
910
+ fontFamily: "var(--font-display)",
911
+ lineHeight: 1.2
912
+ },
913
+ children: value
914
+ }
915
+ ),
916
+ delta != null && /* @__PURE__ */ jsxs(
917
+ "div",
918
+ {
919
+ style: {
920
+ display: "flex",
921
+ alignItems: "center",
922
+ gap: 4,
923
+ marginTop: 8,
924
+ fontSize: 13,
925
+ fontWeight: 500,
926
+ color: deltaColor
927
+ },
928
+ children: [
929
+ /* @__PURE__ */ jsx(DeltaArrow, { direction: deltaDirection }),
930
+ /* @__PURE__ */ jsxs("span", { children: [
931
+ delta > 0 ? "+" : "",
932
+ delta,
933
+ "%"
934
+ ] }),
935
+ deltaLabel && /* @__PURE__ */ jsx("span", { style: { color: "var(--text-muted)", marginLeft: 2 }, children: deltaLabel })
936
+ ]
937
+ }
938
+ )
939
+ ]
940
+ }
941
+ );
942
+ }
943
+ var VARIANT_COLORS = {
944
+ success: {
945
+ bg: "var(--successSoft)",
946
+ border: "var(--success)",
947
+ icon: "\u2713"
948
+ },
949
+ error: {
950
+ bg: "var(--errorSoft)",
951
+ border: "var(--error)",
952
+ icon: "\u2717"
953
+ },
954
+ warning: {
955
+ bg: "var(--warningSoft)",
956
+ border: "var(--warning)",
957
+ icon: "\u26A0"
958
+ },
959
+ info: {
960
+ bg: "var(--infoSoft)",
961
+ border: "var(--info)",
962
+ icon: "\u2139"
963
+ }
964
+ };
965
+ function Toast({
966
+ variant = "info",
967
+ message,
968
+ onDismiss,
969
+ className,
970
+ style
971
+ }) {
972
+ const colors = VARIANT_COLORS[variant];
973
+ const toastRef = useRef(null);
974
+ useEffect(() => {
975
+ const el = toastRef.current;
976
+ if (!el) return;
977
+ requestAnimationFrame(() => {
978
+ el.style.transform = "translateX(0)";
979
+ el.style.opacity = "1";
980
+ });
981
+ }, []);
982
+ const baseStyle2 = {
983
+ display: "flex",
984
+ alignItems: "flex-start",
985
+ gap: 10,
986
+ padding: "12px 16px",
987
+ borderRadius: 10,
988
+ border: `1px solid ${colors.border}`,
989
+ backgroundColor: colors.bg,
990
+ color: "var(--text)",
991
+ fontFamily: "var(--font-body, inherit)",
992
+ fontSize: 14,
993
+ lineHeight: 1.5,
994
+ boxShadow: "var(--shadowMd)",
995
+ pointerEvents: "auto",
996
+ transform: "translateX(120%)",
997
+ opacity: 0,
998
+ transition: "transform 0.3s ease, opacity 0.3s ease",
999
+ maxWidth: 400,
1000
+ minWidth: 280,
1001
+ ...style
1002
+ };
1003
+ return /* @__PURE__ */ jsxs(
1004
+ "div",
1005
+ {
1006
+ ref: toastRef,
1007
+ role: "alert",
1008
+ "aria-live": "assertive",
1009
+ className,
1010
+ style: baseStyle2,
1011
+ children: [
1012
+ /* @__PURE__ */ jsx(
1013
+ "span",
1014
+ {
1015
+ "aria-hidden": "true",
1016
+ style: {
1017
+ flexShrink: 0,
1018
+ fontSize: 16,
1019
+ lineHeight: "20px",
1020
+ color: colors.border
1021
+ },
1022
+ children: colors.icon
1023
+ }
1024
+ ),
1025
+ /* @__PURE__ */ jsx("span", { style: { flex: 1, wordBreak: "break-word" }, children: message }),
1026
+ /* @__PURE__ */ jsx(
1027
+ "button",
1028
+ {
1029
+ type: "button",
1030
+ onClick: onDismiss,
1031
+ "aria-label": "Dismiss notification",
1032
+ style: {
1033
+ flexShrink: 0,
1034
+ background: "none",
1035
+ border: "none",
1036
+ cursor: "pointer",
1037
+ padding: 0,
1038
+ color: "var(--textMuted)",
1039
+ fontSize: 18,
1040
+ lineHeight: "20px"
1041
+ },
1042
+ children: "\\u00D7"
1043
+ }
1044
+ )
1045
+ ]
1046
+ }
1047
+ );
1048
+ }
1049
+ var ToastContext = createContext(null);
1050
+ var nextId = 0;
1051
+ function ToastProvider({ children }) {
1052
+ const [toasts, setToasts] = useState([]);
1053
+ const timersRef = useRef(/* @__PURE__ */ new Map());
1054
+ const dismiss = useCallback((id) => {
1055
+ const timer = timersRef.current.get(id);
1056
+ if (timer) {
1057
+ clearTimeout(timer);
1058
+ timersRef.current.delete(id);
1059
+ }
1060
+ setToasts((prev) => prev.filter((t) => t.id !== id));
1061
+ }, []);
1062
+ const toast = useCallback(
1063
+ (message, options) => {
1064
+ const id = nextId++;
1065
+ const variant = options?.variant ?? "info";
1066
+ const duration = options?.duration ?? 5e3;
1067
+ setToasts((prev) => [...prev, { id, message, variant, duration }]);
1068
+ if (duration > 0) {
1069
+ const timer = setTimeout(() => {
1070
+ dismiss(id);
1071
+ }, duration);
1072
+ timersRef.current.set(id, timer);
1073
+ }
1074
+ },
1075
+ [dismiss]
1076
+ );
1077
+ useEffect(() => {
1078
+ const timers = timersRef.current;
1079
+ return () => {
1080
+ timers.forEach((timer) => clearTimeout(timer));
1081
+ timers.clear();
1082
+ };
1083
+ }, []);
1084
+ const containerStyle = {
1085
+ position: "fixed",
1086
+ bottom: 20,
1087
+ right: 20,
1088
+ display: "flex",
1089
+ flexDirection: "column",
1090
+ gap: 8,
1091
+ zIndex: 9999,
1092
+ pointerEvents: "none"
1093
+ };
1094
+ return /* @__PURE__ */ jsxs(ToastContext.Provider, { value: { toast }, children: [
1095
+ children,
1096
+ typeof document !== "undefined" && toasts.length > 0 && createPortal(
1097
+ /* @__PURE__ */ jsx(
1098
+ "div",
1099
+ {
1100
+ "aria-label": "Notifications",
1101
+ style: containerStyle,
1102
+ children: toasts.map((t) => /* @__PURE__ */ jsx(
1103
+ Toast,
1104
+ {
1105
+ variant: t.variant,
1106
+ message: t.message,
1107
+ onDismiss: () => dismiss(t.id)
1108
+ },
1109
+ t.id
1110
+ ))
1111
+ }
1112
+ ),
1113
+ document.body
1114
+ )
1115
+ ] });
1116
+ }
1117
+ function useToast() {
1118
+ const ctx = useContext(ToastContext);
1119
+ if (!ctx) {
1120
+ throw new Error("useToast must be used within a <ToastProvider>");
1121
+ }
1122
+ return ctx;
1123
+ }
1124
+ var FOCUSABLE_SELECTOR = 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';
1125
+ function Modal({
1126
+ open,
1127
+ onClose,
1128
+ title,
1129
+ children,
1130
+ footer,
1131
+ className,
1132
+ style
1133
+ }) {
1134
+ const panelRef = useRef(null);
1135
+ const previousFocusRef = useRef(null);
1136
+ useEffect(() => {
1137
+ if (open) {
1138
+ previousFocusRef.current = document.activeElement;
1139
+ const raf = requestAnimationFrame(() => {
1140
+ const panel = panelRef.current;
1141
+ if (!panel) return;
1142
+ const first = panel.querySelector(FOCUSABLE_SELECTOR);
1143
+ if (first) {
1144
+ first.focus();
1145
+ } else {
1146
+ panel.focus();
1147
+ }
1148
+ });
1149
+ return () => cancelAnimationFrame(raf);
1150
+ } else {
1151
+ previousFocusRef.current?.focus();
1152
+ }
1153
+ }, [open]);
1154
+ const handleKeyDown = useCallback(
1155
+ (e) => {
1156
+ if (e.key === "Escape") {
1157
+ e.stopPropagation();
1158
+ onClose();
1159
+ }
1160
+ },
1161
+ [onClose]
1162
+ );
1163
+ const handleBackdropClick = useCallback(
1164
+ (e) => {
1165
+ if (e.target === e.currentTarget) {
1166
+ onClose();
1167
+ }
1168
+ },
1169
+ [onClose]
1170
+ );
1171
+ if (!open || typeof document === "undefined") return null;
1172
+ const backdropStyle = {
1173
+ position: "fixed",
1174
+ inset: 0,
1175
+ display: "flex",
1176
+ alignItems: "center",
1177
+ justifyContent: "center",
1178
+ backgroundColor: "rgba(0, 0, 0, 0.5)",
1179
+ zIndex: 9998,
1180
+ padding: 20
1181
+ };
1182
+ const panelStyle = {
1183
+ position: "relative",
1184
+ backgroundColor: "var(--surface)",
1185
+ color: "var(--text)",
1186
+ borderRadius: 14,
1187
+ border: "1px solid var(--border)",
1188
+ boxShadow: "var(--shadowLg)",
1189
+ fontFamily: "var(--font-body, inherit)",
1190
+ maxWidth: 560,
1191
+ width: "100%",
1192
+ maxHeight: "calc(100vh - 40px)",
1193
+ display: "flex",
1194
+ flexDirection: "column",
1195
+ overflow: "hidden",
1196
+ outline: "none",
1197
+ ...style
1198
+ };
1199
+ const headerStyle = {
1200
+ display: "flex",
1201
+ alignItems: "center",
1202
+ justifyContent: "space-between",
1203
+ padding: "16px 20px",
1204
+ borderBottom: "1px solid var(--border)",
1205
+ flexShrink: 0
1206
+ };
1207
+ const titleStyle = {
1208
+ margin: 0,
1209
+ fontSize: 18,
1210
+ fontWeight: 600,
1211
+ fontFamily: "var(--font-display, inherit)",
1212
+ color: "var(--text)",
1213
+ lineHeight: 1.3
1214
+ };
1215
+ const closeButtonStyle = {
1216
+ background: "none",
1217
+ border: "none",
1218
+ cursor: "pointer",
1219
+ padding: 4,
1220
+ color: "var(--textMuted)",
1221
+ fontSize: 20,
1222
+ lineHeight: 1,
1223
+ borderRadius: 6
1224
+ };
1225
+ const bodyStyle = {
1226
+ padding: 20,
1227
+ flex: 1,
1228
+ overflowY: "auto",
1229
+ fontSize: 14,
1230
+ lineHeight: 1.6,
1231
+ color: "var(--textSecondary)"
1232
+ };
1233
+ const footerStyle = {
1234
+ padding: "12px 20px",
1235
+ borderTop: "1px solid var(--border)",
1236
+ display: "flex",
1237
+ justifyContent: "flex-end",
1238
+ gap: 8,
1239
+ flexShrink: 0
1240
+ };
1241
+ return createPortal(
1242
+ /* @__PURE__ */ jsx(
1243
+ "div",
1244
+ {
1245
+ role: "presentation",
1246
+ style: backdropStyle,
1247
+ onClick: handleBackdropClick,
1248
+ onKeyDown: handleKeyDown,
1249
+ children: /* @__PURE__ */ jsxs(
1250
+ "div",
1251
+ {
1252
+ ref: panelRef,
1253
+ role: "dialog",
1254
+ "aria-modal": "true",
1255
+ "aria-label": title ?? "Dialog",
1256
+ tabIndex: -1,
1257
+ className,
1258
+ style: panelStyle,
1259
+ children: [
1260
+ title != null && /* @__PURE__ */ jsxs("div", { style: headerStyle, children: [
1261
+ /* @__PURE__ */ jsx("h2", { style: titleStyle, children: title }),
1262
+ /* @__PURE__ */ jsx(
1263
+ "button",
1264
+ {
1265
+ type: "button",
1266
+ onClick: onClose,
1267
+ "aria-label": "Close dialog",
1268
+ style: closeButtonStyle,
1269
+ children: "\xD7"
1270
+ }
1271
+ )
1272
+ ] }),
1273
+ /* @__PURE__ */ jsx("div", { style: bodyStyle, children }),
1274
+ footer != null && /* @__PURE__ */ jsx("div", { style: footerStyle, children: footer })
1275
+ ]
1276
+ }
1277
+ )
1278
+ }
1279
+ ),
1280
+ document.body
1281
+ );
1282
+ }
1283
+ function ConfirmDialog({
1284
+ open,
1285
+ onClose,
1286
+ onConfirm,
1287
+ title,
1288
+ description,
1289
+ confirmLabel = "Confirm",
1290
+ cancelLabel = "Cancel",
1291
+ destructive = false,
1292
+ loading = false,
1293
+ className,
1294
+ style
1295
+ }) {
1296
+ const buttonBase = {
1297
+ padding: "8px 16px",
1298
+ borderRadius: 8,
1299
+ fontSize: 14,
1300
+ fontWeight: 500,
1301
+ fontFamily: "var(--font-body, inherit)",
1302
+ cursor: loading ? "not-allowed" : "pointer",
1303
+ border: "1px solid var(--border)",
1304
+ lineHeight: 1.4,
1305
+ transition: "background-color 0.15s ease"
1306
+ };
1307
+ const cancelStyle = {
1308
+ ...buttonBase,
1309
+ backgroundColor: "var(--surface)",
1310
+ color: "var(--text)"
1311
+ };
1312
+ const confirmStyle = {
1313
+ ...buttonBase,
1314
+ backgroundColor: destructive ? "var(--error)" : "var(--accent)",
1315
+ color: destructive ? "#fff" : "var(--accentText)",
1316
+ border: "1px solid transparent",
1317
+ opacity: loading ? 0.7 : 1
1318
+ };
1319
+ const footer = /* @__PURE__ */ jsxs(Fragment, { children: [
1320
+ /* @__PURE__ */ jsx(
1321
+ "button",
1322
+ {
1323
+ type: "button",
1324
+ onClick: onClose,
1325
+ disabled: loading,
1326
+ style: cancelStyle,
1327
+ children: cancelLabel
1328
+ }
1329
+ ),
1330
+ /* @__PURE__ */ jsx(
1331
+ "button",
1332
+ {
1333
+ type: "button",
1334
+ onClick: onConfirm,
1335
+ disabled: loading,
1336
+ "aria-busy": loading || void 0,
1337
+ style: confirmStyle,
1338
+ children: loading ? "Loading\u2026" : confirmLabel
1339
+ }
1340
+ )
1341
+ ] });
1342
+ return /* @__PURE__ */ jsx(
1343
+ Modal,
1344
+ {
1345
+ open,
1346
+ onClose,
1347
+ title,
1348
+ footer,
1349
+ className,
1350
+ style,
1351
+ children: description != null && /* @__PURE__ */ jsx("p", { style: { margin: 0, color: "var(--textSecondary)", lineHeight: 1.6 }, children: description })
1352
+ }
1353
+ );
1354
+ }
1355
+ var Input = forwardRef(
1356
+ ({
1357
+ type = "text",
1358
+ label,
1359
+ helperText,
1360
+ error,
1361
+ iconLeft,
1362
+ iconRight,
1363
+ className,
1364
+ style,
1365
+ disabled,
1366
+ id: idProp,
1367
+ ...rest
1368
+ }, ref) => {
1369
+ const autoId = useId();
1370
+ const id = idProp ?? autoId;
1371
+ const helperId = `${id}-helper`;
1372
+ const errorId = `${id}-error`;
1373
+ const hasError = Boolean(error);
1374
+ const errorMessage = typeof error === "string" ? error : void 0;
1375
+ return /* @__PURE__ */ jsxs(
1376
+ "div",
1377
+ {
1378
+ className,
1379
+ style: {
1380
+ display: "flex",
1381
+ flexDirection: "column",
1382
+ gap: "6px",
1383
+ ...style
1384
+ },
1385
+ children: [
1386
+ label && /* @__PURE__ */ jsx(
1387
+ "label",
1388
+ {
1389
+ htmlFor: id,
1390
+ style: {
1391
+ fontSize: "14px",
1392
+ fontWeight: 500,
1393
+ color: "var(--text)"
1394
+ },
1395
+ children: label
1396
+ }
1397
+ ),
1398
+ /* @__PURE__ */ jsxs("div", { style: { position: "relative", display: "flex", alignItems: "center" }, children: [
1399
+ iconLeft && /* @__PURE__ */ jsx(
1400
+ "span",
1401
+ {
1402
+ "aria-hidden": "true",
1403
+ style: {
1404
+ position: "absolute",
1405
+ left: "10px",
1406
+ display: "flex",
1407
+ alignItems: "center",
1408
+ color: "var(--text-muted, var(--text))",
1409
+ pointerEvents: "none"
1410
+ },
1411
+ children: iconLeft
1412
+ }
1413
+ ),
1414
+ /* @__PURE__ */ jsx(
1415
+ "input",
1416
+ {
1417
+ ref,
1418
+ id,
1419
+ type,
1420
+ disabled,
1421
+ "aria-invalid": hasError || void 0,
1422
+ "aria-describedby": [hasError && errorId, helperText && helperId].filter(Boolean).join(" ") || void 0,
1423
+ style: {
1424
+ width: "100%",
1425
+ padding: "8px 12px",
1426
+ paddingLeft: iconLeft ? "36px" : "12px",
1427
+ paddingRight: iconRight ? "36px" : "12px",
1428
+ fontSize: "14px",
1429
+ lineHeight: "20px",
1430
+ color: "var(--text)",
1431
+ backgroundColor: "var(--surface)",
1432
+ border: `1px solid ${hasError ? "var(--error)" : "var(--border)"}`,
1433
+ borderRadius: "6px",
1434
+ outline: "none",
1435
+ transition: "border-color 0.15s, box-shadow 0.15s",
1436
+ opacity: disabled ? 0.5 : 1,
1437
+ cursor: disabled ? "not-allowed" : void 0,
1438
+ boxSizing: "border-box"
1439
+ },
1440
+ onFocus: (e) => {
1441
+ e.currentTarget.style.borderColor = hasError ? "var(--error)" : "var(--accent)";
1442
+ e.currentTarget.style.boxShadow = `0 0 0 2px ${hasError ? "var(--error)" : "var(--accent)"}33`;
1443
+ rest.onFocus?.(e);
1444
+ },
1445
+ onBlur: (e) => {
1446
+ e.currentTarget.style.borderColor = hasError ? "var(--error)" : "var(--border)";
1447
+ e.currentTarget.style.boxShadow = "none";
1448
+ rest.onBlur?.(e);
1449
+ },
1450
+ ...rest
1451
+ }
1452
+ ),
1453
+ iconRight && /* @__PURE__ */ jsx(
1454
+ "span",
1455
+ {
1456
+ "aria-hidden": "true",
1457
+ style: {
1458
+ position: "absolute",
1459
+ right: "10px",
1460
+ display: "flex",
1461
+ alignItems: "center",
1462
+ color: "var(--text-muted, var(--text))",
1463
+ pointerEvents: "none"
1464
+ },
1465
+ children: iconRight
1466
+ }
1467
+ )
1468
+ ] }),
1469
+ errorMessage && /* @__PURE__ */ jsx(
1470
+ "span",
1471
+ {
1472
+ id: errorId,
1473
+ role: "alert",
1474
+ style: { fontSize: "12px", color: "var(--error)" },
1475
+ children: errorMessage
1476
+ }
1477
+ ),
1478
+ helperText && !errorMessage && /* @__PURE__ */ jsx(
1479
+ "span",
1480
+ {
1481
+ id: helperId,
1482
+ style: {
1483
+ fontSize: "12px",
1484
+ color: "var(--text-muted, var(--text))"
1485
+ },
1486
+ children: helperText
1487
+ }
1488
+ )
1489
+ ]
1490
+ }
1491
+ );
1492
+ }
1493
+ );
1494
+ Input.displayName = "Input";
1495
+ var Select = forwardRef(
1496
+ ({
1497
+ label,
1498
+ error,
1499
+ helperText,
1500
+ options,
1501
+ placeholder,
1502
+ className,
1503
+ style,
1504
+ disabled,
1505
+ id: idProp,
1506
+ ...rest
1507
+ }, ref) => {
1508
+ const autoId = useId();
1509
+ const id = idProp ?? autoId;
1510
+ const helperId = `${id}-helper`;
1511
+ const errorId = `${id}-error`;
1512
+ const hasError = Boolean(error);
1513
+ const errorMessage = typeof error === "string" ? error : void 0;
1514
+ return /* @__PURE__ */ jsxs(
1515
+ "div",
1516
+ {
1517
+ className,
1518
+ style: {
1519
+ display: "flex",
1520
+ flexDirection: "column",
1521
+ gap: "6px",
1522
+ ...style
1523
+ },
1524
+ children: [
1525
+ label && /* @__PURE__ */ jsx(
1526
+ "label",
1527
+ {
1528
+ htmlFor: id,
1529
+ style: {
1530
+ fontSize: "14px",
1531
+ fontWeight: 500,
1532
+ color: "var(--text)"
1533
+ },
1534
+ children: label
1535
+ }
1536
+ ),
1537
+ /* @__PURE__ */ jsxs("div", { style: { position: "relative", display: "flex", alignItems: "center" }, children: [
1538
+ /* @__PURE__ */ jsxs(
1539
+ "select",
1540
+ {
1541
+ ref,
1542
+ id,
1543
+ disabled,
1544
+ "aria-invalid": hasError || void 0,
1545
+ "aria-describedby": [hasError && errorId, helperText && helperId].filter(Boolean).join(" ") || void 0,
1546
+ style: {
1547
+ width: "100%",
1548
+ padding: "8px 32px 8px 12px",
1549
+ fontSize: "14px",
1550
+ lineHeight: "20px",
1551
+ color: "var(--text)",
1552
+ backgroundColor: "var(--surface)",
1553
+ border: `1px solid ${hasError ? "var(--error)" : "var(--border)"}`,
1554
+ borderRadius: "6px",
1555
+ outline: "none",
1556
+ appearance: "none",
1557
+ cursor: disabled ? "not-allowed" : "pointer",
1558
+ opacity: disabled ? 0.5 : 1,
1559
+ transition: "border-color 0.15s, box-shadow 0.15s",
1560
+ boxSizing: "border-box"
1561
+ },
1562
+ onFocus: (e) => {
1563
+ e.currentTarget.style.borderColor = hasError ? "var(--error)" : "var(--accent)";
1564
+ e.currentTarget.style.boxShadow = `0 0 0 2px ${hasError ? "var(--error)" : "var(--accent)"}33`;
1565
+ rest.onFocus?.(e);
1566
+ },
1567
+ onBlur: (e) => {
1568
+ e.currentTarget.style.borderColor = hasError ? "var(--error)" : "var(--border)";
1569
+ e.currentTarget.style.boxShadow = "none";
1570
+ rest.onBlur?.(e);
1571
+ },
1572
+ ...rest,
1573
+ children: [
1574
+ placeholder && /* @__PURE__ */ jsx("option", { value: "", disabled: true, children: placeholder }),
1575
+ options.map((opt) => /* @__PURE__ */ jsx("option", { value: opt.value, children: opt.label }, opt.value))
1576
+ ]
1577
+ }
1578
+ ),
1579
+ /* @__PURE__ */ jsx(
1580
+ "svg",
1581
+ {
1582
+ "aria-hidden": "true",
1583
+ width: "16",
1584
+ height: "16",
1585
+ viewBox: "0 0 16 16",
1586
+ fill: "none",
1587
+ style: {
1588
+ position: "absolute",
1589
+ right: "10px",
1590
+ pointerEvents: "none",
1591
+ color: "var(--text-muted, var(--text))"
1592
+ },
1593
+ children: /* @__PURE__ */ jsx(
1594
+ "path",
1595
+ {
1596
+ d: "M4 6l4 4 4-4",
1597
+ stroke: "currentColor",
1598
+ strokeWidth: "1.5",
1599
+ strokeLinecap: "round",
1600
+ strokeLinejoin: "round"
1601
+ }
1602
+ )
1603
+ }
1604
+ )
1605
+ ] }),
1606
+ errorMessage && /* @__PURE__ */ jsx(
1607
+ "span",
1608
+ {
1609
+ id: errorId,
1610
+ role: "alert",
1611
+ style: { fontSize: "12px", color: "var(--error)" },
1612
+ children: errorMessage
1613
+ }
1614
+ ),
1615
+ helperText && !errorMessage && /* @__PURE__ */ jsx(
1616
+ "span",
1617
+ {
1618
+ id: helperId,
1619
+ style: {
1620
+ fontSize: "12px",
1621
+ color: "var(--text-muted, var(--text))"
1622
+ },
1623
+ children: helperText
1624
+ }
1625
+ )
1626
+ ]
1627
+ }
1628
+ );
1629
+ }
1630
+ );
1631
+ Select.displayName = "Select";
1632
+ var variantStyles2 = {
1633
+ primary: {
1634
+ backgroundColor: "var(--accent)",
1635
+ color: "var(--accent-text, #fff)",
1636
+ border: "1px solid transparent"
1637
+ },
1638
+ secondary: {
1639
+ backgroundColor: "var(--surface)",
1640
+ color: "var(--text)",
1641
+ border: "1px solid var(--border)"
1642
+ },
1643
+ ghost: {
1644
+ backgroundColor: "transparent",
1645
+ color: "var(--text)",
1646
+ border: "1px solid transparent"
1647
+ },
1648
+ danger: {
1649
+ backgroundColor: "var(--error)",
1650
+ color: "var(--error-text, #fff)",
1651
+ border: "1px solid transparent"
1652
+ }
1653
+ };
1654
+ var Spinner = () => /* @__PURE__ */ jsxs(
1655
+ "svg",
1656
+ {
1657
+ "aria-hidden": "true",
1658
+ width: "16",
1659
+ height: "16",
1660
+ viewBox: "0 0 16 16",
1661
+ fill: "none",
1662
+ style: {
1663
+ animation: "amber-spin 0.6s linear infinite",
1664
+ flexShrink: 0
1665
+ },
1666
+ children: [
1667
+ /* @__PURE__ */ jsx(
1668
+ "circle",
1669
+ {
1670
+ cx: "8",
1671
+ cy: "8",
1672
+ r: "6",
1673
+ stroke: "currentColor",
1674
+ strokeOpacity: "0.25",
1675
+ strokeWidth: "2"
1676
+ }
1677
+ ),
1678
+ /* @__PURE__ */ jsx(
1679
+ "path",
1680
+ {
1681
+ d: "M14 8a6 6 0 0 0-6-6",
1682
+ stroke: "currentColor",
1683
+ strokeWidth: "2",
1684
+ strokeLinecap: "round"
1685
+ }
1686
+ )
1687
+ ]
1688
+ }
1689
+ );
1690
+ if (typeof document !== "undefined") {
1691
+ const styleId = "amber-spin-keyframes";
1692
+ if (!document.getElementById(styleId)) {
1693
+ const sheet = document.createElement("style");
1694
+ sheet.id = styleId;
1695
+ sheet.textContent = `@keyframes amber-spin { to { transform: rotate(360deg); } }`;
1696
+ document.head.appendChild(sheet);
1697
+ }
1698
+ }
1699
+ var Button = forwardRef(
1700
+ ({
1701
+ variant = "primary",
1702
+ icon,
1703
+ loading = false,
1704
+ disabled,
1705
+ children,
1706
+ className,
1707
+ style,
1708
+ type = "button",
1709
+ ...rest
1710
+ }, ref) => {
1711
+ const isDisabled = disabled || loading;
1712
+ return /* @__PURE__ */ jsxs(
1713
+ "button",
1714
+ {
1715
+ ref,
1716
+ type,
1717
+ disabled: isDisabled,
1718
+ className,
1719
+ "aria-busy": loading || void 0,
1720
+ style: {
1721
+ display: "inline-flex",
1722
+ alignItems: "center",
1723
+ justifyContent: "center",
1724
+ gap: "8px",
1725
+ padding: "8px 16px",
1726
+ fontSize: "14px",
1727
+ fontWeight: 500,
1728
+ lineHeight: "20px",
1729
+ borderRadius: "6px",
1730
+ cursor: isDisabled ? "not-allowed" : "pointer",
1731
+ opacity: isDisabled ? 0.5 : 1,
1732
+ transition: "background-color 0.15s, opacity 0.15s",
1733
+ outline: "none",
1734
+ textDecoration: "none",
1735
+ whiteSpace: "nowrap",
1736
+ boxSizing: "border-box",
1737
+ ...variantStyles2[variant],
1738
+ ...style
1739
+ },
1740
+ onFocus: (e) => {
1741
+ e.currentTarget.style.boxShadow = "0 0 0 2px var(--accent)33";
1742
+ rest.onFocus?.(e);
1743
+ },
1744
+ onBlur: (e) => {
1745
+ e.currentTarget.style.boxShadow = "none";
1746
+ rest.onBlur?.(e);
1747
+ },
1748
+ ...rest,
1749
+ children: [
1750
+ loading ? /* @__PURE__ */ jsx(Spinner, {}) : icon ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: { display: "flex", alignItems: "center", flexShrink: 0 }, children: icon }) : null,
1751
+ children
1752
+ ]
1753
+ }
1754
+ );
1755
+ }
1756
+ );
1757
+ Button.displayName = "Button";
1758
+ var TRACK_W = 40;
1759
+ var TRACK_H = 22;
1760
+ var THUMB_SIZE = 16;
1761
+ var THUMB_OFFSET = 3;
1762
+ var Toggle = ({
1763
+ checked,
1764
+ onChange,
1765
+ label,
1766
+ disabled = false,
1767
+ className,
1768
+ style
1769
+ }) => {
1770
+ const autoId = useId();
1771
+ return /* @__PURE__ */ jsxs(
1772
+ "div",
1773
+ {
1774
+ className,
1775
+ style: {
1776
+ display: "inline-flex",
1777
+ alignItems: "center",
1778
+ gap: "8px",
1779
+ opacity: disabled ? 0.5 : 1,
1780
+ cursor: disabled ? "not-allowed" : "pointer",
1781
+ ...style
1782
+ },
1783
+ children: [
1784
+ /* @__PURE__ */ jsx(
1785
+ "button",
1786
+ {
1787
+ id: autoId,
1788
+ type: "button",
1789
+ role: "switch",
1790
+ "aria-checked": checked,
1791
+ "aria-label": label ?? void 0,
1792
+ disabled,
1793
+ onClick: () => onChange(!checked),
1794
+ style: {
1795
+ position: "relative",
1796
+ width: TRACK_W,
1797
+ height: TRACK_H,
1798
+ borderRadius: TRACK_H / 2,
1799
+ backgroundColor: checked ? "var(--accent)" : "var(--border)",
1800
+ border: "none",
1801
+ padding: 0,
1802
+ cursor: disabled ? "not-allowed" : "pointer",
1803
+ transition: "background-color 0.2s",
1804
+ outline: "none",
1805
+ flexShrink: 0
1806
+ },
1807
+ onFocus: (e) => {
1808
+ e.currentTarget.style.boxShadow = "0 0 0 2px var(--accent)33";
1809
+ },
1810
+ onBlur: (e) => {
1811
+ e.currentTarget.style.boxShadow = "none";
1812
+ },
1813
+ children: /* @__PURE__ */ jsx(
1814
+ "span",
1815
+ {
1816
+ "aria-hidden": "true",
1817
+ style: {
1818
+ position: "absolute",
1819
+ top: THUMB_OFFSET,
1820
+ left: checked ? TRACK_W - THUMB_SIZE - THUMB_OFFSET : THUMB_OFFSET,
1821
+ width: THUMB_SIZE,
1822
+ height: THUMB_SIZE,
1823
+ borderRadius: "50%",
1824
+ backgroundColor: "#fff",
1825
+ transition: "left 0.2s",
1826
+ boxShadow: "0 1px 3px rgba(0,0,0,0.2)"
1827
+ }
1828
+ }
1829
+ )
1830
+ }
1831
+ ),
1832
+ label && /* @__PURE__ */ jsx(
1833
+ "label",
1834
+ {
1835
+ htmlFor: autoId,
1836
+ style: {
1837
+ fontSize: "14px",
1838
+ color: "var(--text)",
1839
+ cursor: disabled ? "not-allowed" : "pointer",
1840
+ userSelect: "none"
1841
+ },
1842
+ children: label
1843
+ }
1844
+ )
1845
+ ]
1846
+ }
1847
+ );
1848
+ };
1849
+ Toggle.displayName = "Toggle";
1850
+ var SIZE = 18;
1851
+ var Checkbox = ({
1852
+ checked,
1853
+ onChange,
1854
+ label,
1855
+ disabled = false,
1856
+ indeterminate = false,
1857
+ className,
1858
+ style
1859
+ }) => {
1860
+ const autoId = useId();
1861
+ const inputRef = useRef(null);
1862
+ useEffect(() => {
1863
+ if (inputRef.current) {
1864
+ inputRef.current.indeterminate = indeterminate;
1865
+ }
1866
+ }, [indeterminate]);
1867
+ const isActive = checked || indeterminate;
1868
+ return /* @__PURE__ */ jsxs(
1869
+ "div",
1870
+ {
1871
+ className,
1872
+ style: {
1873
+ display: "inline-flex",
1874
+ alignItems: "center",
1875
+ gap: "8px",
1876
+ opacity: disabled ? 0.5 : 1,
1877
+ cursor: disabled ? "not-allowed" : "pointer",
1878
+ ...style
1879
+ },
1880
+ children: [
1881
+ /* @__PURE__ */ jsxs(
1882
+ "span",
1883
+ {
1884
+ style: {
1885
+ position: "relative",
1886
+ display: "inline-flex",
1887
+ alignItems: "center",
1888
+ justifyContent: "center",
1889
+ width: SIZE,
1890
+ height: SIZE,
1891
+ flexShrink: 0
1892
+ },
1893
+ children: [
1894
+ /* @__PURE__ */ jsx(
1895
+ "input",
1896
+ {
1897
+ ref: inputRef,
1898
+ id: autoId,
1899
+ type: "checkbox",
1900
+ checked,
1901
+ disabled,
1902
+ onChange: (e) => onChange(e.target.checked),
1903
+ style: {
1904
+ position: "absolute",
1905
+ width: SIZE,
1906
+ height: SIZE,
1907
+ margin: 0,
1908
+ opacity: 0,
1909
+ cursor: disabled ? "not-allowed" : "pointer"
1910
+ }
1911
+ }
1912
+ ),
1913
+ /* @__PURE__ */ jsxs(
1914
+ "span",
1915
+ {
1916
+ "aria-hidden": "true",
1917
+ style: {
1918
+ width: SIZE,
1919
+ height: SIZE,
1920
+ borderRadius: "4px",
1921
+ border: `1.5px solid ${isActive ? "var(--accent)" : "var(--border)"}`,
1922
+ backgroundColor: isActive ? "var(--accent)" : "var(--surface)",
1923
+ display: "flex",
1924
+ alignItems: "center",
1925
+ justifyContent: "center",
1926
+ transition: "background-color 0.15s, border-color 0.15s",
1927
+ pointerEvents: "none"
1928
+ },
1929
+ children: [
1930
+ checked && !indeterminate && /* @__PURE__ */ jsx("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", children: /* @__PURE__ */ jsx(
1931
+ "path",
1932
+ {
1933
+ d: "M2.5 6l2.5 2.5 4.5-5",
1934
+ stroke: "var(--accent-text, #fff)",
1935
+ strokeWidth: "1.5",
1936
+ strokeLinecap: "round",
1937
+ strokeLinejoin: "round"
1938
+ }
1939
+ ) }),
1940
+ indeterminate && /* @__PURE__ */ jsx("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", children: /* @__PURE__ */ jsx(
1941
+ "path",
1942
+ {
1943
+ d: "M3 6h6",
1944
+ stroke: "var(--accent-text, #fff)",
1945
+ strokeWidth: "1.5",
1946
+ strokeLinecap: "round"
1947
+ }
1948
+ ) })
1949
+ ]
1950
+ }
1951
+ )
1952
+ ]
1953
+ }
1954
+ ),
1955
+ label && /* @__PURE__ */ jsx(
1956
+ "label",
1957
+ {
1958
+ htmlFor: autoId,
1959
+ style: {
1960
+ fontSize: "14px",
1961
+ color: "var(--text)",
1962
+ cursor: disabled ? "not-allowed" : "pointer",
1963
+ userSelect: "none"
1964
+ },
1965
+ children: label
1966
+ }
1967
+ )
1968
+ ]
1969
+ }
1970
+ );
1971
+ };
1972
+ Checkbox.displayName = "Checkbox";
1973
+ var barStyle2 = {
1974
+ display: "flex",
1975
+ gap: 4,
1976
+ borderBottom: "1px solid var(--border)",
1977
+ background: "var(--surface)",
1978
+ position: "relative",
1979
+ overflowX: "auto"
1980
+ };
1981
+ var baseTabStyle = {
1982
+ position: "relative",
1983
+ padding: "10px 16px",
1984
+ fontSize: 14,
1985
+ fontWeight: 500,
1986
+ fontFamily: "inherit",
1987
+ lineHeight: "20px",
1988
+ color: "var(--text-secondary)",
1989
+ background: "none",
1990
+ border: "none",
1991
+ borderBottom: "2px solid transparent",
1992
+ cursor: "pointer",
1993
+ whiteSpace: "nowrap",
1994
+ transition: "color 150ms, border-color 150ms",
1995
+ outline: "none"
1996
+ };
1997
+ var activeTabStyle = {
1998
+ color: "var(--accent)",
1999
+ borderBottomColor: "var(--accent)"
2000
+ };
2001
+ var disabledTabStyle = {
2002
+ color: "var(--text-muted)",
2003
+ cursor: "not-allowed",
2004
+ opacity: 0.6
2005
+ };
2006
+ var focusVisibleOutline = {
2007
+ outline: "2px solid var(--accent)",
2008
+ outlineOffset: -2,
2009
+ borderRadius: 4
2010
+ };
2011
+ function Tabs({ tabs, activeKey, onChange, className, style }) {
2012
+ const tabRefs = useRef([]);
2013
+ const enabledIndices = tabs.reduce((acc, tab, i) => {
2014
+ if (!tab.disabled) acc.push(i);
2015
+ return acc;
2016
+ }, []);
2017
+ function focusTab(index) {
2018
+ tabRefs.current[index]?.focus();
2019
+ }
2020
+ function handleKeyDown(e) {
2021
+ const target = e.target;
2022
+ const currentIndex = tabRefs.current.indexOf(target);
2023
+ if (currentIndex === -1) return;
2024
+ const pos = enabledIndices.indexOf(currentIndex);
2025
+ let nextIndex;
2026
+ switch (e.key) {
2027
+ case "ArrowRight": {
2028
+ const next = pos < enabledIndices.length - 1 ? pos + 1 : 0;
2029
+ nextIndex = enabledIndices[next];
2030
+ break;
2031
+ }
2032
+ case "ArrowLeft": {
2033
+ const prev = pos > 0 ? pos - 1 : enabledIndices.length - 1;
2034
+ nextIndex = enabledIndices[prev];
2035
+ break;
2036
+ }
2037
+ case "Home":
2038
+ nextIndex = enabledIndices[0];
2039
+ break;
2040
+ case "End":
2041
+ nextIndex = enabledIndices[enabledIndices.length - 1];
2042
+ break;
2043
+ default:
2044
+ return;
2045
+ }
2046
+ if (nextIndex !== void 0) {
2047
+ e.preventDefault();
2048
+ focusTab(nextIndex);
2049
+ }
2050
+ }
2051
+ return /* @__PURE__ */ jsx(
2052
+ "div",
2053
+ {
2054
+ role: "tablist",
2055
+ className,
2056
+ style: { ...barStyle2, ...style },
2057
+ onKeyDown: handleKeyDown,
2058
+ children: tabs.map((tab, i) => {
2059
+ const isActive = tab.key === activeKey;
2060
+ const isDisabled = !!tab.disabled;
2061
+ return /* @__PURE__ */ jsx(
2062
+ "button",
2063
+ {
2064
+ ref: (el) => {
2065
+ tabRefs.current[i] = el;
2066
+ },
2067
+ role: "tab",
2068
+ id: `tab-${tab.key}`,
2069
+ "aria-selected": isActive,
2070
+ "aria-disabled": isDisabled || void 0,
2071
+ "aria-controls": `tabpanel-${tab.key}`,
2072
+ tabIndex: isActive ? 0 : -1,
2073
+ disabled: isDisabled,
2074
+ onClick: () => {
2075
+ if (!isDisabled) onChange(tab.key);
2076
+ },
2077
+ onFocus: (e) => {
2078
+ Object.assign(e.currentTarget.style, focusVisibleOutline);
2079
+ },
2080
+ onBlur: (e) => {
2081
+ e.currentTarget.style.outline = "none";
2082
+ e.currentTarget.style.outlineOffset = "";
2083
+ e.currentTarget.style.borderRadius = "";
2084
+ },
2085
+ style: {
2086
+ ...baseTabStyle,
2087
+ ...isActive ? activeTabStyle : void 0,
2088
+ ...isDisabled ? disabledTabStyle : void 0
2089
+ },
2090
+ children: tab.label
2091
+ },
2092
+ tab.key
2093
+ );
2094
+ })
2095
+ }
2096
+ );
2097
+ }
2098
+ var wrapperStyle = {
2099
+ position: "relative",
2100
+ display: "inline-block"
2101
+ };
2102
+ var triggerBtnStyle = {
2103
+ background: "none",
2104
+ border: "none",
2105
+ padding: 0,
2106
+ cursor: "pointer",
2107
+ font: "inherit",
2108
+ color: "inherit",
2109
+ display: "inline-flex",
2110
+ alignItems: "center"
2111
+ };
2112
+ var menuBase = {
2113
+ position: "absolute",
2114
+ top: "calc(100% + 4px)",
2115
+ zIndex: 1e3,
2116
+ minWidth: 180,
2117
+ padding: "4px 0",
2118
+ background: "var(--surface)",
2119
+ border: "1px solid var(--border)",
2120
+ borderRadius: 10,
2121
+ boxShadow: "var(--shadow-md)",
2122
+ listStyle: "none",
2123
+ margin: 0,
2124
+ outline: "none"
2125
+ };
2126
+ var itemBase = {
2127
+ display: "flex",
2128
+ alignItems: "center",
2129
+ gap: 8,
2130
+ width: "100%",
2131
+ padding: "8px 12px",
2132
+ fontSize: 14,
2133
+ lineHeight: "20px",
2134
+ fontFamily: "inherit",
2135
+ color: "var(--text)",
2136
+ background: "none",
2137
+ border: "none",
2138
+ cursor: "pointer",
2139
+ textAlign: "left",
2140
+ whiteSpace: "nowrap",
2141
+ outline: "none"
2142
+ };
2143
+ var itemDisabled = {
2144
+ color: "var(--text-muted)",
2145
+ cursor: "not-allowed",
2146
+ opacity: 0.5
2147
+ };
2148
+ var itemDanger = {
2149
+ color: "var(--error)"
2150
+ };
2151
+ var itemHighlighted = {
2152
+ background: "var(--surface-hover)"
2153
+ };
2154
+ var itemIconStyle = {
2155
+ display: "inline-flex",
2156
+ flexShrink: 0,
2157
+ width: 16,
2158
+ height: 16,
2159
+ alignItems: "center",
2160
+ justifyContent: "center"
2161
+ };
2162
+ function Dropdown({
2163
+ trigger,
2164
+ items,
2165
+ onSelect,
2166
+ align = "left",
2167
+ className,
2168
+ style
2169
+ }) {
2170
+ const [open, setOpen] = useState(false);
2171
+ const [highlightIndex, setHighlightIndex] = useState(-1);
2172
+ const wrapperRef = useRef(null);
2173
+ const menuRef = useRef(null);
2174
+ const itemRefs = useRef([]);
2175
+ const enabledIndices = items.reduce((acc, item, i) => {
2176
+ if (!item.disabled) acc.push(i);
2177
+ return acc;
2178
+ }, []);
2179
+ const openMenu = useCallback(() => {
2180
+ setOpen(true);
2181
+ setHighlightIndex(enabledIndices[0] ?? -1);
2182
+ }, [enabledIndices]);
2183
+ const closeMenu = useCallback(() => {
2184
+ setOpen(false);
2185
+ setHighlightIndex(-1);
2186
+ }, []);
2187
+ useEffect(() => {
2188
+ if (!open) return;
2189
+ function handleClick(e) {
2190
+ if (wrapperRef.current && !wrapperRef.current.contains(e.target)) {
2191
+ closeMenu();
2192
+ }
2193
+ }
2194
+ document.addEventListener("mousedown", handleClick);
2195
+ return () => document.removeEventListener("mousedown", handleClick);
2196
+ }, [open, closeMenu]);
2197
+ useEffect(() => {
2198
+ if (open) {
2199
+ menuRef.current?.focus();
2200
+ }
2201
+ }, [open]);
2202
+ useEffect(() => {
2203
+ if (highlightIndex >= 0) {
2204
+ itemRefs.current[highlightIndex]?.scrollIntoView({ block: "nearest" });
2205
+ }
2206
+ }, [highlightIndex]);
2207
+ function handleMenuKeyDown(e) {
2208
+ switch (e.key) {
2209
+ case "ArrowDown": {
2210
+ e.preventDefault();
2211
+ const pos = enabledIndices.indexOf(highlightIndex);
2212
+ const next = pos < enabledIndices.length - 1 ? pos + 1 : 0;
2213
+ setHighlightIndex(enabledIndices[next]);
2214
+ break;
2215
+ }
2216
+ case "ArrowUp": {
2217
+ e.preventDefault();
2218
+ const pos = enabledIndices.indexOf(highlightIndex);
2219
+ const prev = pos > 0 ? pos - 1 : enabledIndices.length - 1;
2220
+ setHighlightIndex(enabledIndices[prev]);
2221
+ break;
2222
+ }
2223
+ case "Home":
2224
+ e.preventDefault();
2225
+ setHighlightIndex(enabledIndices[0]);
2226
+ break;
2227
+ case "End":
2228
+ e.preventDefault();
2229
+ setHighlightIndex(enabledIndices[enabledIndices.length - 1]);
2230
+ break;
2231
+ case "Enter":
2232
+ case " ": {
2233
+ e.preventDefault();
2234
+ const item = items[highlightIndex];
2235
+ if (item && !item.disabled) {
2236
+ onSelect(item.key);
2237
+ closeMenu();
2238
+ }
2239
+ break;
2240
+ }
2241
+ case "Escape":
2242
+ e.preventDefault();
2243
+ closeMenu();
2244
+ break;
2245
+ case "Tab":
2246
+ closeMenu();
2247
+ break;
2248
+ default: {
2249
+ if (e.key.length === 1) {
2250
+ const char = e.key.toLowerCase();
2251
+ const match = enabledIndices.find(
2252
+ (i) => items[i].label.toLowerCase().startsWith(char)
2253
+ );
2254
+ if (match !== void 0) setHighlightIndex(match);
2255
+ }
2256
+ }
2257
+ }
2258
+ }
2259
+ function handleTriggerKeyDown(e) {
2260
+ if (e.key === "ArrowDown" || e.key === "Enter" || e.key === " ") {
2261
+ e.preventDefault();
2262
+ if (!open) openMenu();
2263
+ }
2264
+ }
2265
+ const menuAlignStyle = align === "right" ? { right: 0 } : { left: 0 };
2266
+ return /* @__PURE__ */ jsxs(
2267
+ "div",
2268
+ {
2269
+ ref: wrapperRef,
2270
+ className,
2271
+ style: { ...wrapperStyle, ...style },
2272
+ children: [
2273
+ /* @__PURE__ */ jsx(
2274
+ "button",
2275
+ {
2276
+ type: "button",
2277
+ "aria-haspopup": "true",
2278
+ "aria-expanded": open,
2279
+ onClick: () => open ? closeMenu() : openMenu(),
2280
+ onKeyDown: handleTriggerKeyDown,
2281
+ style: triggerBtnStyle,
2282
+ children: trigger
2283
+ }
2284
+ ),
2285
+ open && /* @__PURE__ */ jsx(
2286
+ "ul",
2287
+ {
2288
+ ref: menuRef,
2289
+ role: "menu",
2290
+ tabIndex: -1,
2291
+ onKeyDown: handleMenuKeyDown,
2292
+ style: { ...menuBase, ...menuAlignStyle },
2293
+ children: items.map((item, i) => {
2294
+ const isHighlighted = i === highlightIndex;
2295
+ const isDisabled = !!item.disabled;
2296
+ return /* @__PURE__ */ jsxs(
2297
+ "li",
2298
+ {
2299
+ ref: (el) => {
2300
+ itemRefs.current[i] = el;
2301
+ },
2302
+ role: "menuitem",
2303
+ "aria-disabled": isDisabled || void 0,
2304
+ onMouseEnter: () => {
2305
+ if (!isDisabled) setHighlightIndex(i);
2306
+ },
2307
+ onMouseLeave: () => setHighlightIndex(-1),
2308
+ onClick: () => {
2309
+ if (!isDisabled) {
2310
+ onSelect(item.key);
2311
+ closeMenu();
2312
+ }
2313
+ },
2314
+ style: {
2315
+ ...itemBase,
2316
+ ...item.danger ? itemDanger : void 0,
2317
+ ...isDisabled ? itemDisabled : void 0,
2318
+ ...isHighlighted && !isDisabled ? itemHighlighted : void 0
2319
+ },
2320
+ children: [
2321
+ item.icon && /* @__PURE__ */ jsx("span", { style: itemIconStyle, children: item.icon }),
2322
+ item.label
2323
+ ]
2324
+ },
2325
+ item.key
2326
+ );
2327
+ })
2328
+ }
2329
+ )
2330
+ ]
2331
+ }
2332
+ );
2333
+ }
2334
+
2335
+ export { AppShell, Badge, Button, Checkbox, ConfirmDialog, DataTable, Dropdown, EmptyState, Header, Input, Modal, Select, Sidebar, SidebarSection, Skeleton, StatCard, Tabs, Toast, ToastProvider, Toggle, useToast };
2336
+ //# sourceMappingURL=chunk-ADYBFXWS.mjs.map
2337
+ //# sourceMappingURL=chunk-ADYBFXWS.mjs.map