@annondeveloper/ui-kit 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.
Files changed (69) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +215 -0
  3. package/dist/chunk-5OKSXPWK.js +270 -0
  4. package/dist/chunk-5OKSXPWK.js.map +1 -0
  5. package/dist/cli/index.js +430 -0
  6. package/dist/form.d.ts +65 -0
  7. package/dist/form.js +148 -0
  8. package/dist/form.js.map +1 -0
  9. package/dist/index.d.ts +942 -0
  10. package/dist/index.js +2812 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/select-nnBJUO8U.d.ts +26 -0
  13. package/package.json +114 -0
  14. package/src/components/animated-counter.stories.tsx +68 -0
  15. package/src/components/animated-counter.tsx +85 -0
  16. package/src/components/avatar.tsx +106 -0
  17. package/src/components/badge.stories.tsx +70 -0
  18. package/src/components/badge.tsx +97 -0
  19. package/src/components/button.stories.tsx +101 -0
  20. package/src/components/button.tsx +67 -0
  21. package/src/components/card.tsx +128 -0
  22. package/src/components/checkbox.stories.tsx +64 -0
  23. package/src/components/checkbox.tsx +58 -0
  24. package/src/components/confirm-dialog.stories.tsx +96 -0
  25. package/src/components/confirm-dialog.tsx +145 -0
  26. package/src/components/data-table.stories.tsx +125 -0
  27. package/src/components/data-table.tsx +791 -0
  28. package/src/components/dropdown-menu.tsx +111 -0
  29. package/src/components/empty-state.stories.tsx +42 -0
  30. package/src/components/empty-state.tsx +43 -0
  31. package/src/components/filter-pill.stories.tsx +71 -0
  32. package/src/components/filter-pill.tsx +45 -0
  33. package/src/components/form-input.stories.tsx +91 -0
  34. package/src/components/form-input.tsx +77 -0
  35. package/src/components/log-viewer.tsx +212 -0
  36. package/src/components/metric-card.tsx +141 -0
  37. package/src/components/pipeline-stage.tsx +134 -0
  38. package/src/components/popover.tsx +72 -0
  39. package/src/components/port-status-grid.tsx +102 -0
  40. package/src/components/progress.tsx +128 -0
  41. package/src/components/radio-group.tsx +162 -0
  42. package/src/components/select.stories.tsx +52 -0
  43. package/src/components/select.tsx +92 -0
  44. package/src/components/severity-timeline.tsx +125 -0
  45. package/src/components/sheet.tsx +164 -0
  46. package/src/components/skeleton.stories.tsx +64 -0
  47. package/src/components/skeleton.tsx +62 -0
  48. package/src/components/slider.tsx +208 -0
  49. package/src/components/sparkline.tsx +104 -0
  50. package/src/components/status-badge.stories.tsx +84 -0
  51. package/src/components/status-badge.tsx +71 -0
  52. package/src/components/status-pulse.stories.tsx +56 -0
  53. package/src/components/status-pulse.tsx +78 -0
  54. package/src/components/success-checkmark.stories.tsx +67 -0
  55. package/src/components/success-checkmark.tsx +53 -0
  56. package/src/components/tabs.tsx +177 -0
  57. package/src/components/threshold-gauge.tsx +149 -0
  58. package/src/components/time-range-selector.tsx +86 -0
  59. package/src/components/toast.stories.tsx +70 -0
  60. package/src/components/toast.tsx +48 -0
  61. package/src/components/toggle-switch.stories.tsx +66 -0
  62. package/src/components/toggle-switch.tsx +51 -0
  63. package/src/components/tooltip.tsx +62 -0
  64. package/src/components/truncated-text.stories.tsx +56 -0
  65. package/src/components/truncated-text.tsx +80 -0
  66. package/src/components/uptime-tracker.tsx +138 -0
  67. package/src/components/utilization-bar.tsx +103 -0
  68. package/src/theme.css +178 -0
  69. package/src/utils.ts +123 -0
package/dist/index.js ADDED
@@ -0,0 +1,2812 @@
1
+ import { cn, clamp } from './chunk-5OKSXPWK.js';
2
+ export { Checkbox, FormInput, INPUT_CLS, LABEL_CLS, Select, TEXTAREA_CLS, ToggleSwitch, clamp, cn, defaultUtilColorMap, fmtBps, fmtBytes, fmtCompact, fmtDuration, fmtPct, fmtRelative, fmtSpeed, fmtUptime, fmtUtil, stripCidr, utilColor } from './chunk-5OKSXPWK.js';
3
+ import { forwardRef, useRef, useState, useEffect, useCallback, useMemo } from 'react';
4
+ import { Loader2, Check, Copy, AlertTriangle, Search, X, Filter, List, AlignJustify, LayoutList, Columns3, Download, ChevronUp, ChevronDown, ChevronsUpDown, TrendingUp, TrendingDown, ArrowDown, ChevronRight, GripVertical, Eye, EyeOff } from 'lucide-react';
5
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
6
+ import * as Tooltip from '@radix-ui/react-tooltip';
7
+ import * as AlertDialog from '@radix-ui/react-alert-dialog';
8
+ import { AnimatePresence, motion, useReducedMotion } from 'framer-motion';
9
+ import { Toaster as Toaster$1 } from 'sonner';
10
+ export { toast } from 'sonner';
11
+ import { useReactTable, getPaginationRowModel, getFilteredRowModel, getSortedRowModel, getCoreRowModel, flexRender } from '@tanstack/react-table';
12
+ import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
13
+ import * as PopoverPrimitive from '@radix-ui/react-popover';
14
+
15
+ var variantClasses = {
16
+ primary: "bg-[hsl(var(--brand-primary))] text-[hsl(var(--text-on-brand))] hover:bg-[hsl(var(--brand-primary)/0.85)] active:bg-[hsl(var(--brand-primary)/0.75)]",
17
+ secondary: "bg-[hsl(var(--bg-elevated))] text-[hsl(var(--text-primary))] border border-[hsl(var(--border-default))] hover:bg-[hsl(var(--bg-overlay))] active:bg-[hsl(var(--border-subtle))]",
18
+ danger: "bg-[hsl(var(--status-critical))] text-[hsl(var(--text-on-brand))] hover:bg-[hsl(var(--status-critical)/0.85)] active:bg-[hsl(var(--status-critical)/0.75)]",
19
+ outline: "bg-transparent text-[hsl(var(--text-primary))] border border-[hsl(var(--border-default))] hover:bg-[hsl(var(--bg-elevated))] active:bg-[hsl(var(--bg-overlay))]",
20
+ ghost: "bg-transparent text-[hsl(var(--text-secondary))] hover:bg-[hsl(var(--bg-elevated))] hover:text-[hsl(var(--text-primary))] active:bg-[hsl(var(--bg-overlay))]"
21
+ };
22
+ var sizeClasses = {
23
+ sm: "h-8 px-3 text-xs gap-1.5 rounded-lg",
24
+ md: "h-9 px-4 text-sm gap-2 rounded-lg",
25
+ lg: "h-11 px-6 text-sm gap-2 rounded-xl",
26
+ icon: "h-9 w-9 rounded-lg"
27
+ };
28
+ var Button = forwardRef(
29
+ ({ variant = "primary", size = "md", loading, disabled, className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
30
+ "button",
31
+ {
32
+ ref,
33
+ disabled: disabled || loading,
34
+ className: cn(
35
+ "inline-flex items-center justify-center font-medium transition-colors duration-150",
36
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[hsl(var(--brand-primary))] focus-visible:ring-offset-2 focus-visible:ring-offset-[hsl(var(--bg-base))]",
37
+ "disabled:pointer-events-none disabled:opacity-50",
38
+ "cursor-pointer select-none",
39
+ variantClasses[variant],
40
+ sizeClasses[size],
41
+ className
42
+ ),
43
+ ...props,
44
+ children: [
45
+ loading && /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }),
46
+ children
47
+ ]
48
+ }
49
+ )
50
+ );
51
+ Button.displayName = "Button";
52
+ var COLOR_MAP = {
53
+ brand: "bg-[hsl(var(--brand-primary))]/10 text-[hsl(var(--brand-primary))]",
54
+ blue: "bg-[hsl(var(--brand-secondary))]/10 text-[hsl(var(--brand-secondary))]",
55
+ green: "bg-[hsl(var(--status-ok))]/10 text-[hsl(var(--status-ok))]",
56
+ yellow: "bg-[hsl(var(--status-warning))]/10 text-[hsl(var(--status-warning))]",
57
+ red: "bg-[hsl(var(--status-critical))]/10 text-[hsl(var(--status-critical))]",
58
+ orange: "bg-[hsl(var(--status-warning))]/15 text-[hsl(var(--status-warning))]",
59
+ purple: "bg-[hsl(270,60%,60%)]/10 text-[hsl(270,60%,65%)]",
60
+ pink: "bg-[hsl(330,60%,60%)]/10 text-[hsl(330,60%,65%)]",
61
+ teal: "bg-[hsl(180,60%,40%)]/10 text-[hsl(180,60%,55%)]",
62
+ gray: "bg-[hsl(var(--bg-overlay))] text-[hsl(var(--text-secondary))]"
63
+ };
64
+ function Badge({
65
+ children,
66
+ color = "gray",
67
+ icon: Icon,
68
+ size = "sm",
69
+ className
70
+ }) {
71
+ return /* @__PURE__ */ jsxs("span", { className: cn(
72
+ "inline-flex items-center gap-1 rounded-full font-medium whitespace-nowrap",
73
+ size === "xs" && "px-1.5 py-0.5 text-[10px]",
74
+ size === "sm" && "px-2 py-0.5 text-xs",
75
+ size === "md" && "px-2.5 py-1 text-xs",
76
+ COLOR_MAP[color],
77
+ className
78
+ ), children: [
79
+ Icon && /* @__PURE__ */ jsx(Icon, { className: cn(size === "xs" ? "size-2.5" : "size-3") }),
80
+ children
81
+ ] });
82
+ }
83
+ function createBadgeVariant(config) {
84
+ const { colorMap, labelMap, defaultColor = "gray", defaultSize = "xs" } = config;
85
+ return function VariantBadge({ value, className }) {
86
+ const color = colorMap[value] ?? defaultColor;
87
+ const label = labelMap?.[value] ?? value.replace(/_/g, " ");
88
+ return /* @__PURE__ */ jsx(Badge, { color, size: defaultSize, className, children: label });
89
+ };
90
+ }
91
+ function FilterPill({ label, count, active, onClick, className }) {
92
+ return /* @__PURE__ */ jsxs(
93
+ "button",
94
+ {
95
+ type: "button",
96
+ onClick,
97
+ className: cn(
98
+ "rounded-full px-3 py-1 text-xs transition-colors whitespace-nowrap",
99
+ active ? "bg-[hsl(var(--brand-primary))]/10 text-[hsl(var(--brand-primary))] font-medium" : "bg-[hsl(var(--bg-elevated))] text-[hsl(var(--text-secondary))] hover:bg-[hsl(var(--bg-overlay))]",
100
+ className
101
+ ),
102
+ children: [
103
+ label,
104
+ count != null && /* @__PURE__ */ jsx("span", { className: cn(
105
+ "ml-1.5 tabular-nums",
106
+ active ? "text-[hsl(var(--brand-primary))]/70" : "text-[hsl(var(--text-tertiary))]"
107
+ ), children: count })
108
+ ]
109
+ }
110
+ );
111
+ }
112
+ function EmptyState({ icon: Icon, title, description, actions, className }) {
113
+ return /* @__PURE__ */ jsxs(
114
+ "div",
115
+ {
116
+ className: cn(
117
+ "relative overflow-hidden flex flex-col items-center justify-center rounded-2xl border border-dashed border-[hsl(var(--border-default))]",
118
+ "bg-[hsl(var(--bg-surface)/0.6)] backdrop-blur-xl px-6 py-12 text-center",
119
+ className
120
+ ),
121
+ children: [
122
+ /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-0 bg-gradient-to-b from-[hsl(var(--brand-primary)/0.04)] to-transparent" }),
123
+ /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-0 bg-[radial-gradient(ellipse_at_50%_0%,hsl(var(--brand-primary)/0.06),transparent_70%)]" }),
124
+ /* @__PURE__ */ jsx("div", { className: "relative mb-4 flex size-14 items-center justify-center rounded-2xl bg-[hsl(var(--bg-elevated))] border border-[hsl(var(--border-subtle)/0.6)] shadow-[0_1px_3px_hsl(0_0%_0%/0.12)]", children: /* @__PURE__ */ jsx(Icon, { className: "size-6 text-[hsl(var(--text-disabled))]" }) }),
125
+ /* @__PURE__ */ jsx("h3", { className: "relative text-heading-3 text-[hsl(var(--text-primary))] mb-1", children: title }),
126
+ /* @__PURE__ */ jsx("p", { className: "relative text-body text-[hsl(var(--text-secondary))] max-w-sm", children: description }),
127
+ actions && /* @__PURE__ */ jsx("div", { className: "relative mt-6 flex gap-3", children: actions })
128
+ ]
129
+ }
130
+ );
131
+ }
132
+ function Skeleton({ className, ...props }) {
133
+ return /* @__PURE__ */ jsx(
134
+ "div",
135
+ {
136
+ className: cn("skeleton-shimmer rounded-md", className),
137
+ ...props
138
+ }
139
+ );
140
+ }
141
+ function SkeletonText({ lines = 1, className }) {
142
+ return /* @__PURE__ */ jsx("div", { className: cn("space-y-2", className), children: Array.from({ length: lines }).map((_, i) => /* @__PURE__ */ jsx(
143
+ Skeleton,
144
+ {
145
+ className: cn("h-3", i === lines - 1 && lines > 1 ? "w-4/5" : "w-full")
146
+ },
147
+ i
148
+ )) });
149
+ }
150
+ function SkeletonCard({ className }) {
151
+ return /* @__PURE__ */ jsxs("div", { className: cn("rounded-lg border border-[hsl(var(--border-subtle))] bg-[hsl(var(--bg-surface))] p-4 space-y-3", className), children: [
152
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
153
+ /* @__PURE__ */ jsx(Skeleton, { className: "size-8 rounded-md" }),
154
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 space-y-1.5", children: [
155
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-3.5 w-32" }),
156
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-2.5 w-20" })
157
+ ] }),
158
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-5 w-14 rounded-full" })
159
+ ] }),
160
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-3", children: [
161
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-2.5 flex-1" }),
162
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-2.5 flex-1" }),
163
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-2.5 flex-1" })
164
+ ] })
165
+ ] });
166
+ }
167
+ function TruncatedText({ text, maxWidth = "100%", className = "" }) {
168
+ const ref = useRef(null);
169
+ const [isTruncated, setIsTruncated] = useState(false);
170
+ const [copied, setCopied] = useState(false);
171
+ useEffect(() => {
172
+ const el = ref.current;
173
+ if (el) setIsTruncated(el.scrollWidth > el.clientWidth);
174
+ }, [text]);
175
+ const handleCopy = async (e) => {
176
+ e.stopPropagation();
177
+ await navigator.clipboard.writeText(text);
178
+ setCopied(true);
179
+ setTimeout(() => setCopied(false), 1500);
180
+ };
181
+ const inner = /* @__PURE__ */ jsx(
182
+ "span",
183
+ {
184
+ ref,
185
+ className: `block truncate ${className}`,
186
+ style: { maxWidth },
187
+ children: text
188
+ }
189
+ );
190
+ if (!isTruncated) return inner;
191
+ return /* @__PURE__ */ jsx(Tooltip.Provider, { delayDuration: 300, children: /* @__PURE__ */ jsxs(Tooltip.Root, { children: [
192
+ /* @__PURE__ */ jsx(Tooltip.Trigger, { asChild: true, children: inner }),
193
+ /* @__PURE__ */ jsx(Tooltip.Portal, { children: /* @__PURE__ */ jsxs(
194
+ Tooltip.Content,
195
+ {
196
+ side: "top",
197
+ align: "start",
198
+ sideOffset: 6,
199
+ className: "z-50 max-w-[400px] rounded-lg border border-[hsl(var(--border-default))]\n bg-[hsl(var(--bg-elevated))] px-3 py-2 shadow-lg\n animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out\n data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
200
+ children: [
201
+ /* @__PURE__ */ jsx("p", { className: "text-small text-[hsl(var(--text-primary))] break-all", children: text }),
202
+ /* @__PURE__ */ jsx("div", { className: "mt-1.5 flex justify-end", children: /* @__PURE__ */ jsxs(
203
+ "button",
204
+ {
205
+ onClick: handleCopy,
206
+ className: "flex items-center gap-1 rounded px-2 py-0.5\n text-[11px] text-[hsl(var(--brand-primary))]\n hover:bg-[hsl(var(--bg-surface))] transition-colors",
207
+ children: [
208
+ copied ? /* @__PURE__ */ jsx(Check, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx(Copy, { className: "h-3 w-3" }),
209
+ copied ? "Copied" : "Copy"
210
+ ]
211
+ }
212
+ ) }),
213
+ /* @__PURE__ */ jsx(Tooltip.Arrow, { className: "fill-[hsl(var(--bg-elevated))]" })
214
+ ]
215
+ }
216
+ ) })
217
+ ] }) });
218
+ }
219
+ var variantStyles = {
220
+ danger: {
221
+ icon: "text-[hsl(var(--status-critical))] bg-[hsl(var(--status-critical))]/10",
222
+ button: "bg-[hsl(var(--status-critical))] hover:bg-[hsl(var(--status-critical))]/90 text-[hsl(var(--text-on-brand))]"
223
+ },
224
+ warning: {
225
+ icon: "text-[hsl(var(--status-warning))] bg-[hsl(var(--status-warning))]/10",
226
+ button: "bg-[hsl(var(--status-warning))] hover:bg-[hsl(var(--status-warning))]/90 text-[hsl(var(--text-on-brand))]"
227
+ },
228
+ default: {
229
+ icon: "text-[hsl(var(--brand-primary))] bg-[hsl(var(--brand-primary))]/10",
230
+ button: "bg-[hsl(var(--brand-primary))] hover:bg-[hsl(var(--brand-primary))]/90 text-[hsl(var(--text-on-brand))]"
231
+ }
232
+ };
233
+ function ConfirmDialog({
234
+ open,
235
+ onOpenChange,
236
+ title,
237
+ description,
238
+ confirmLabel = "Confirm",
239
+ cancelLabel = "Cancel",
240
+ variant = "danger",
241
+ loading = false,
242
+ onConfirm
243
+ }) {
244
+ const styles = variantStyles[variant];
245
+ return /* @__PURE__ */ jsx(AlertDialog.Root, { open, onOpenChange, children: /* @__PURE__ */ jsx(AnimatePresence, { children: open && /* @__PURE__ */ jsxs(AlertDialog.Portal, { forceMount: true, children: [
246
+ /* @__PURE__ */ jsx(AlertDialog.Overlay, { asChild: true, children: /* @__PURE__ */ jsx(
247
+ motion.div,
248
+ {
249
+ initial: { opacity: 0 },
250
+ animate: { opacity: 1 },
251
+ exit: { opacity: 0 },
252
+ transition: { duration: 0.15 },
253
+ className: "fixed inset-0 z-50 bg-[hsl(var(--bg-base)/0.7)] backdrop-blur-sm"
254
+ }
255
+ ) }),
256
+ /* @__PURE__ */ jsx(AlertDialog.Content, { asChild: true, children: /* @__PURE__ */ jsxs(
257
+ motion.div,
258
+ {
259
+ initial: { opacity: 0, scale: 0.95, y: 8 },
260
+ animate: { opacity: 1, scale: 1, y: 0 },
261
+ exit: { opacity: 0, scale: 0.95, y: 8 },
262
+ transition: { duration: 0.2, ease: [0.16, 1, 0.3, 1] },
263
+ className: cn(
264
+ "fixed left-1/2 top-1/2 z-50 -translate-x-1/2 -translate-y-1/2",
265
+ "w-full max-w-md p-6 rounded-2xl",
266
+ "border border-[hsl(var(--border-default))]",
267
+ "bg-[hsl(var(--bg-elevated))] shadow-2xl",
268
+ "focus:outline-none"
269
+ ),
270
+ children: [
271
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-4", children: [
272
+ /* @__PURE__ */ jsx("div", { className: cn("flex-shrink-0 p-2.5 rounded-xl h-fit", styles.icon), children: /* @__PURE__ */ jsx(AlertTriangle, { className: "w-5 h-5" }) }),
273
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
274
+ /* @__PURE__ */ jsx(AlertDialog.Title, { className: "text-base font-semibold text-[hsl(var(--text-primary))]", children: title }),
275
+ /* @__PURE__ */ jsx(AlertDialog.Description, { className: "mt-2 text-sm text-[hsl(var(--text-secondary))] leading-relaxed", children: description })
276
+ ] })
277
+ ] }),
278
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-3 mt-6", children: [
279
+ /* @__PURE__ */ jsx(
280
+ AlertDialog.Cancel,
281
+ {
282
+ className: cn(
283
+ "px-4 py-2 text-sm font-medium rounded-lg",
284
+ "border border-[hsl(var(--border-default))]",
285
+ "text-[hsl(var(--text-primary))]",
286
+ "hover:bg-[hsl(var(--bg-overlay))] transition-colors",
287
+ "focus:outline-none focus:ring-2 focus:ring-[hsl(var(--brand-primary))]"
288
+ ),
289
+ children: cancelLabel
290
+ }
291
+ ),
292
+ /* @__PURE__ */ jsx(
293
+ AlertDialog.Action,
294
+ {
295
+ onClick: (e) => {
296
+ e.preventDefault();
297
+ onConfirm();
298
+ },
299
+ disabled: loading,
300
+ className: cn(
301
+ "px-4 py-2 text-sm font-medium rounded-lg transition-all",
302
+ "focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-[hsl(var(--bg-elevated))]",
303
+ styles.button,
304
+ loading && "opacity-70 cursor-not-allowed"
305
+ ),
306
+ children: loading ? /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
307
+ /* @__PURE__ */ jsx(Loader2, { className: "w-4 h-4 animate-spin" }),
308
+ confirmLabel
309
+ ] }) : confirmLabel
310
+ }
311
+ )
312
+ ] })
313
+ ]
314
+ }
315
+ ) })
316
+ ] }) }) });
317
+ }
318
+ function easeOutCubic(t) {
319
+ return 1 - Math.pow(1 - t, 3);
320
+ }
321
+ function AnimatedCounter({
322
+ value,
323
+ duration = 400,
324
+ className,
325
+ format
326
+ }) {
327
+ const reduced = useReducedMotion();
328
+ const prevRef = useRef(value);
329
+ const rafRef = useRef(null);
330
+ const [displayed, setDisplayed] = useState(value);
331
+ useEffect(() => {
332
+ const from = prevRef.current;
333
+ const to = value;
334
+ prevRef.current = value;
335
+ if (reduced || from === to) {
336
+ setDisplayed(to);
337
+ return;
338
+ }
339
+ const start = performance.now();
340
+ function tick(now) {
341
+ const elapsed = now - start;
342
+ const progress = Math.min(elapsed / duration, 1);
343
+ const eased = easeOutCubic(progress);
344
+ const current = from + (to - from) * eased;
345
+ setDisplayed(current);
346
+ if (progress < 1) {
347
+ rafRef.current = requestAnimationFrame(tick);
348
+ } else {
349
+ setDisplayed(to);
350
+ }
351
+ }
352
+ rafRef.current = requestAnimationFrame(tick);
353
+ return () => {
354
+ if (rafRef.current !== null) {
355
+ cancelAnimationFrame(rafRef.current);
356
+ }
357
+ };
358
+ }, [value, duration, reduced]);
359
+ const formatted = format ? format(displayed) : Number.isInteger(value) ? Math.round(displayed).toString() : displayed.toFixed(
360
+ value.toString().split(".")[1]?.length ?? 1
361
+ );
362
+ return /* @__PURE__ */ jsx("span", { className: cn("tabular-nums", className), children: formatted });
363
+ }
364
+ function SuccessCheckmark({ size = 20, className }) {
365
+ const reduced = useReducedMotion();
366
+ return /* @__PURE__ */ jsxs(
367
+ motion.svg,
368
+ {
369
+ width: size,
370
+ height: size,
371
+ viewBox: "0 0 20 20",
372
+ fill: "none",
373
+ className,
374
+ initial: reduced ? false : { scale: 0, opacity: 0 },
375
+ animate: { scale: 1, opacity: 1 },
376
+ transition: { type: "spring", stiffness: 300, damping: 20 },
377
+ children: [
378
+ /* @__PURE__ */ jsx(
379
+ motion.circle,
380
+ {
381
+ cx: "10",
382
+ cy: "10",
383
+ r: "9",
384
+ stroke: "hsl(var(--status-ok))",
385
+ strokeWidth: "1.5",
386
+ fill: "none",
387
+ initial: reduced ? false : { pathLength: 0 },
388
+ animate: { pathLength: 1 },
389
+ transition: { duration: 0.4, ease: "easeOut" }
390
+ }
391
+ ),
392
+ /* @__PURE__ */ jsx(
393
+ motion.path,
394
+ {
395
+ d: "M6 10l2.5 2.5L14 7.5",
396
+ stroke: "hsl(var(--status-ok))",
397
+ strokeWidth: "1.5",
398
+ strokeLinecap: "round",
399
+ strokeLinejoin: "round",
400
+ fill: "none",
401
+ initial: reduced ? false : { pathLength: 0 },
402
+ animate: { pathLength: 1 },
403
+ transition: { duration: 0.3, delay: 0.2, ease: "easeOut" }
404
+ }
405
+ )
406
+ ]
407
+ }
408
+ );
409
+ }
410
+ var defaultStatusMap = {
411
+ ok: { label: "OK", dot: "bg-[hsl(var(--status-ok))]", text: "text-[hsl(var(--status-ok))]", bg: "bg-[hsl(var(--status-ok))]/10" },
412
+ active: { label: "Active", dot: "bg-[hsl(var(--status-ok))]", text: "text-[hsl(var(--status-ok))]", bg: "bg-[hsl(var(--status-ok))]/10" },
413
+ warning: { label: "Warning", dot: "bg-[hsl(var(--status-warning))]", text: "text-[hsl(var(--status-warning))]", bg: "bg-[hsl(var(--status-warning))]/10" },
414
+ critical: { label: "Critical", dot: "bg-[hsl(var(--status-critical))]", text: "text-[hsl(var(--status-critical))]", bg: "bg-[hsl(var(--status-critical))]/10" },
415
+ unknown: { label: "Unknown", dot: "bg-[hsl(var(--status-unknown))]", text: "text-[hsl(var(--status-unknown))]", bg: "bg-[hsl(var(--status-unknown))]/10" },
416
+ maintenance: { label: "Maintenance", dot: "bg-[hsl(var(--status-maintenance))]", text: "text-[hsl(var(--status-maintenance))]", bg: "bg-[hsl(var(--status-maintenance))]/10" },
417
+ stale: { label: "Stale", dot: "bg-[hsl(var(--status-warning))]", text: "text-[hsl(var(--status-warning))]", bg: "bg-[hsl(var(--status-warning))]/10" },
418
+ inactive: { label: "Inactive", dot: "bg-[hsl(var(--text-tertiary))]", text: "text-[hsl(var(--text-tertiary))]", bg: "bg-[hsl(var(--text-tertiary))]/10" },
419
+ decommissioned: { label: "Decommissioned", dot: "bg-[hsl(var(--text-disabled))]", text: "text-[hsl(var(--text-disabled))]", bg: "bg-[hsl(var(--text-disabled))]/10" },
420
+ pending: { label: "Pending", dot: "bg-[hsl(var(--status-warning))]", text: "text-[hsl(var(--status-warning))]", bg: "bg-[hsl(var(--status-warning))]/10" }
421
+ };
422
+ function StatusBadge({
423
+ status,
424
+ label,
425
+ size = "md",
426
+ pulse = false,
427
+ statusMap,
428
+ className
429
+ }) {
430
+ const map = statusMap ?? defaultStatusMap;
431
+ const fallback = map["unknown"] ?? defaultStatusMap["unknown"];
432
+ const config = map[status] ?? fallback;
433
+ return /* @__PURE__ */ jsxs(
434
+ "span",
435
+ {
436
+ className: cn(
437
+ "inline-flex items-center gap-1.5 rounded-full font-medium",
438
+ size === "sm" ? "px-1.5 py-0.5 text-[0.6875rem]" : "px-2 py-1 text-[0.75rem]",
439
+ config.text,
440
+ config.bg,
441
+ className
442
+ ),
443
+ children: [
444
+ /* @__PURE__ */ jsx("span", { className: cn("rounded-full shrink-0", size === "sm" ? "size-1.5" : "size-2", config.dot, pulse && "animate-pulse") }),
445
+ label ?? config.label
446
+ ]
447
+ }
448
+ );
449
+ }
450
+ var defaultPulseConfigMap = {
451
+ online: { dot: "bg-[hsl(var(--status-ok))]", ring: "bg-[hsl(var(--status-ok))]", pulse: true, fast: false },
452
+ degraded: { dot: "bg-[hsl(var(--status-warning))]", ring: "bg-[hsl(var(--status-warning))]", pulse: true, fast: true },
453
+ offline: { dot: "bg-[hsl(var(--status-critical))]", ring: "bg-[hsl(var(--status-critical))]", pulse: false, fast: false },
454
+ unknown: { dot: "bg-[hsl(var(--text-tertiary))]", ring: "bg-[hsl(var(--text-tertiary))]", pulse: false, fast: false }
455
+ };
456
+ function StatusPulse({ status, label = true, configMap, className }) {
457
+ const reduced = useReducedMotion();
458
+ const map = configMap ?? defaultPulseConfigMap;
459
+ const cfg = map[status] ?? map["unknown"] ?? defaultPulseConfigMap["unknown"];
460
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2", className), children: [
461
+ /* @__PURE__ */ jsxs("div", { className: "relative flex size-2.5 shrink-0", children: [
462
+ cfg.pulse && !reduced && /* @__PURE__ */ jsx(
463
+ "span",
464
+ {
465
+ className: cn(
466
+ "absolute inline-flex size-full rounded-full opacity-75 animate-pulse-ring",
467
+ cfg.ring,
468
+ cfg.fast && "[animation-duration:1s]"
469
+ )
470
+ }
471
+ ),
472
+ /* @__PURE__ */ jsx(
473
+ motion.span,
474
+ {
475
+ className: cn("relative inline-flex size-2.5 rounded-full", cfg.dot),
476
+ animate: { scale: 1 },
477
+ whileHover: { scale: reduced ? 1 : 1.3 },
478
+ transition: { type: "spring", stiffness: 400, damping: 15 }
479
+ }
480
+ )
481
+ ] }),
482
+ label && /* @__PURE__ */ jsx(
483
+ motion.span,
484
+ {
485
+ initial: reduced ? {} : { opacity: 0 },
486
+ animate: { opacity: 1 },
487
+ className: "text-xs font-medium capitalize text-[hsl(var(--text-secondary))]",
488
+ children: status
489
+ },
490
+ status
491
+ )
492
+ ] });
493
+ }
494
+ function Toaster({ theme = "dark", position = "bottom-right", duration = 4e3 }) {
495
+ return /* @__PURE__ */ jsx(
496
+ Toaster$1,
497
+ {
498
+ theme,
499
+ position,
500
+ richColors: true,
501
+ duration,
502
+ gap: 8,
503
+ toastOptions: {
504
+ style: {
505
+ background: "hsl(var(--bg-elevated))",
506
+ color: "hsl(var(--text-primary))",
507
+ border: "1px solid hsl(var(--border-default))",
508
+ borderRadius: "0.75rem",
509
+ boxShadow: "0 8px 32px hsl(0 0% 0% / 0.25)",
510
+ fontSize: "0.875rem"
511
+ },
512
+ classNames: {
513
+ success: "toast-success",
514
+ error: "toast-error",
515
+ warning: "toast-warning",
516
+ info: "toast-info"
517
+ }
518
+ }
519
+ }
520
+ );
521
+ }
522
+ var DENSITY_CLASSES = {
523
+ compact: "py-1.5 px-3",
524
+ comfortable: "py-3 px-4",
525
+ spacious: "py-4 px-5"
526
+ };
527
+ var DENSITY_ICONS = [
528
+ { key: "compact", icon: List, label: "Compact" },
529
+ { key: "comfortable", icon: AlignJustify, label: "Comfortable" },
530
+ { key: "spacious", icon: LayoutList, label: "Spacious" }
531
+ ];
532
+ var PAGE_SIZES = [10, 25, 50, 100];
533
+ var STORAGE_KEY = "ui-kit-table-density";
534
+ var globalFilterFn = (row, _columnId, filterValue) => {
535
+ const search = String(filterValue).toLowerCase();
536
+ return row.getAllCells().some(
537
+ (cell) => String(cell.getValue() ?? "").toLowerCase().includes(search)
538
+ );
539
+ };
540
+ function exportToCsv(table, filename) {
541
+ const headers = table.getAllColumns().filter((c) => c.getIsVisible()).map((c) => c.id);
542
+ const rows = table.getFilteredRowModel().rows.map(
543
+ (row) => headers.map((h) => {
544
+ const val = row.getValue(h);
545
+ const str = String(val ?? "");
546
+ return str.includes(",") || str.includes('"') ? `"${str.replace(/"/g, '""')}"` : str;
547
+ }).join(",")
548
+ );
549
+ const csv = [headers.join(","), ...rows].join("\n");
550
+ const blob = new Blob([csv], { type: "text/csv" });
551
+ const url = URL.createObjectURL(blob);
552
+ const a = document.createElement("a");
553
+ a.href = url;
554
+ a.download = `${filename}.csv`;
555
+ a.click();
556
+ URL.revokeObjectURL(url);
557
+ }
558
+ function ColumnFilterPopover({ column, table }) {
559
+ const [open, setOpen] = useState(false);
560
+ const ref = useRef(null);
561
+ const currentFilter = column.getFilterValue();
562
+ const isActive = currentFilter !== void 0 && currentFilter !== "" && !(Array.isArray(currentFilter) && currentFilter.length === 0);
563
+ useEffect(() => {
564
+ if (!open) return;
565
+ const handler = (e) => {
566
+ if (ref.current && !ref.current.contains(e.target)) setOpen(false);
567
+ };
568
+ document.addEventListener("mousedown", handler);
569
+ return () => document.removeEventListener("mousedown", handler);
570
+ }, [open]);
571
+ const { kind, uniqueValues } = useMemo(() => {
572
+ const rows = table.getPreFilteredRowModel().rows.slice(0, 100);
573
+ const vals = rows.map((r) => r.getValue(column.id)).filter((v) => v != null);
574
+ const nums = vals.filter((v) => typeof v === "number" || typeof v === "string" && v !== "" && !isNaN(Number(v)));
575
+ if (nums.length > vals.length * 0.7 && vals.length > 0) return { kind: "number", uniqueValues: [] };
576
+ const uniques = [...new Set(vals.map((v) => String(v)))];
577
+ if (uniques.length > 0 && uniques.length < 20) return { kind: "enum", uniqueValues: uniques.sort() };
578
+ return { kind: "text", uniqueValues: [] };
579
+ }, [table, column.id]);
580
+ return /* @__PURE__ */ jsxs("div", { ref, className: "relative inline-flex", children: [
581
+ /* @__PURE__ */ jsxs(
582
+ "button",
583
+ {
584
+ onClick: (e) => {
585
+ e.stopPropagation();
586
+ setOpen((o) => !o);
587
+ },
588
+ className: "relative p-0.5 rounded hover:bg-[hsl(var(--bg-elevated)/0.5)] transition-colors",
589
+ "aria-label": `Filter ${column.id}`,
590
+ children: [
591
+ /* @__PURE__ */ jsx(Filter, { className: "h-3 w-3 text-[hsl(var(--text-tertiary))]" }),
592
+ isActive && /* @__PURE__ */ jsx("span", { className: "absolute -top-0.5 -right-0.5 w-1.5 h-1.5 rounded-full bg-[hsl(var(--brand-primary))]" })
593
+ ]
594
+ }
595
+ ),
596
+ open && /* @__PURE__ */ jsxs(
597
+ "div",
598
+ {
599
+ className: "absolute top-full left-0 z-50 mt-1 min-w-[200px]\n bg-[hsl(var(--bg-elevated))] border border-[hsl(var(--border-default))] rounded-lg shadow-lg p-3",
600
+ onClick: (e) => e.stopPropagation(),
601
+ children: [
602
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-2", children: [
603
+ /* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium text-[hsl(var(--text-secondary))] uppercase tracking-wider", children: "Filter" }),
604
+ isActive && /* @__PURE__ */ jsx(
605
+ "button",
606
+ {
607
+ onClick: () => {
608
+ column.setFilterValue(void 0);
609
+ setOpen(false);
610
+ },
611
+ className: "text-[11px] text-[hsl(var(--brand-primary))] hover:underline",
612
+ children: "Clear"
613
+ }
614
+ )
615
+ ] }),
616
+ kind === "text" && /* @__PURE__ */ jsx(
617
+ "input",
618
+ {
619
+ type: "text",
620
+ value: currentFilter ?? "",
621
+ onChange: (e) => column.setFilterValue(e.target.value || void 0),
622
+ placeholder: "Search\\u2026",
623
+ className: "w-full rounded-md border border-[hsl(var(--border-subtle))]\n bg-[hsl(var(--bg-surface))] px-2.5 py-1.5 text-small text-[hsl(var(--text-primary))]\n placeholder:text-[hsl(var(--text-tertiary))] outline-none\n focus:border-[hsl(var(--brand-primary))] transition-colors",
624
+ autoFocus: true
625
+ }
626
+ ),
627
+ kind === "number" && /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
628
+ /* @__PURE__ */ jsx(
629
+ "input",
630
+ {
631
+ type: "number",
632
+ value: currentFilter?.[0] ?? "",
633
+ onChange: (e) => {
634
+ const val = e.target.value === "" ? void 0 : Number(e.target.value);
635
+ column.setFilterValue((old) => [val, old?.[1]]);
636
+ },
637
+ placeholder: "Min",
638
+ className: "w-full rounded-md border border-[hsl(var(--border-subtle))]\n bg-[hsl(var(--bg-surface))] px-2.5 py-1.5 text-small text-[hsl(var(--text-primary))]\n placeholder:text-[hsl(var(--text-tertiary))] outline-none\n focus:border-[hsl(var(--brand-primary))] transition-colors"
639
+ }
640
+ ),
641
+ /* @__PURE__ */ jsx(
642
+ "input",
643
+ {
644
+ type: "number",
645
+ value: currentFilter?.[1] ?? "",
646
+ onChange: (e) => {
647
+ const val = e.target.value === "" ? void 0 : Number(e.target.value);
648
+ column.setFilterValue((old) => [old?.[0], val]);
649
+ },
650
+ placeholder: "Max",
651
+ className: "w-full rounded-md border border-[hsl(var(--border-subtle))]\n bg-[hsl(var(--bg-surface))] px-2.5 py-1.5 text-small text-[hsl(var(--text-primary))]\n placeholder:text-[hsl(var(--text-tertiary))] outline-none\n focus:border-[hsl(var(--brand-primary))] transition-colors"
652
+ }
653
+ )
654
+ ] }),
655
+ kind === "enum" && /* @__PURE__ */ jsx("div", { className: "max-h-[200px] overflow-y-auto space-y-1", children: uniqueValues.map((val) => {
656
+ const selected = Array.isArray(currentFilter) ? currentFilter.includes(val) : false;
657
+ return /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 rounded px-1.5 py-1\n hover:bg-[hsl(var(--bg-surface)/0.5)] cursor-pointer transition-colors", children: [
658
+ /* @__PURE__ */ jsx(
659
+ "input",
660
+ {
661
+ type: "checkbox",
662
+ checked: selected,
663
+ onChange: () => {
664
+ const prev = Array.isArray(currentFilter) ? currentFilter : [];
665
+ const next = selected ? prev.filter((v) => v !== val) : [...prev, val];
666
+ column.setFilterValue(next.length > 0 ? next : void 0);
667
+ },
668
+ className: "rounded border-[hsl(var(--border-default))] accent-[hsl(var(--brand-primary))]"
669
+ }
670
+ ),
671
+ /* @__PURE__ */ jsx("span", { className: "text-small text-[hsl(var(--text-primary))] truncate", children: val })
672
+ ] }, val);
673
+ }) })
674
+ ]
675
+ }
676
+ )
677
+ ] });
678
+ }
679
+ function ColumnPicker({ table, onClose }) {
680
+ const ref = useRef(null);
681
+ const [dragIdx, setDragIdx] = useState(null);
682
+ useEffect(() => {
683
+ const handler = (e) => {
684
+ if (ref.current && !ref.current.contains(e.target)) onClose();
685
+ };
686
+ document.addEventListener("mousedown", handler);
687
+ return () => document.removeEventListener("mousedown", handler);
688
+ }, [onClose]);
689
+ const allColumns = table.getAllLeafColumns();
690
+ const handleDragStart = (idx) => setDragIdx(idx);
691
+ const handleDragOver = (e, idx) => {
692
+ e.preventDefault();
693
+ if (dragIdx === null || dragIdx === idx) return;
694
+ const order = table.getState().columnOrder.length > 0 ? [...table.getState().columnOrder] : allColumns.map((c) => c.id);
695
+ const [moved] = order.splice(dragIdx, 1);
696
+ if (moved !== void 0) order.splice(idx, 0, moved);
697
+ table.setColumnOrder(order);
698
+ setDragIdx(idx);
699
+ };
700
+ return /* @__PURE__ */ jsxs(
701
+ motion.div,
702
+ {
703
+ ref,
704
+ initial: { opacity: 0, y: -4 },
705
+ animate: { opacity: 1, y: 0 },
706
+ exit: { opacity: 0, y: -4 },
707
+ transition: { duration: 0.12 },
708
+ className: cn(
709
+ "absolute right-0 top-full z-50 mt-1 w-56 rounded-xl overflow-hidden",
710
+ "border border-[hsl(var(--border-subtle))] bg-[hsl(var(--bg-elevated))] shadow-xl"
711
+ ),
712
+ children: [
713
+ /* @__PURE__ */ jsx("div", { className: "px-3 py-2 border-b border-[hsl(var(--border-subtle)/0.5)]", children: /* @__PURE__ */ jsx("span", { className: "text-[10px] font-semibold uppercase tracking-wider text-[hsl(var(--text-tertiary))]", children: "Columns" }) }),
714
+ /* @__PURE__ */ jsx("div", { className: "max-h-72 overflow-y-auto p-1", children: allColumns.map((col, idx) => {
715
+ if (!col.getCanHide()) return null;
716
+ const visible = col.getIsVisible();
717
+ const header = typeof col.columnDef.header === "string" ? col.columnDef.header : col.id;
718
+ return /* @__PURE__ */ jsxs(
719
+ "div",
720
+ {
721
+ draggable: true,
722
+ onDragStart: () => handleDragStart(idx),
723
+ onDragOver: (e) => handleDragOver(e, idx),
724
+ onDragEnd: () => setDragIdx(null),
725
+ className: cn(
726
+ "flex items-center gap-2 rounded-lg px-2 py-1.5 text-small cursor-grab",
727
+ "hover:bg-[hsl(var(--bg-surface)/0.7)] transition-colors",
728
+ dragIdx === idx && "bg-[hsl(var(--brand-primary)/0.1)]"
729
+ ),
730
+ children: [
731
+ /* @__PURE__ */ jsx(GripVertical, { className: "h-3 w-3 text-[hsl(var(--text-disabled))] shrink-0" }),
732
+ /* @__PURE__ */ jsxs(
733
+ "button",
734
+ {
735
+ onClick: () => col.toggleVisibility(),
736
+ className: "flex items-center gap-2 flex-1 text-left",
737
+ children: [
738
+ visible ? /* @__PURE__ */ jsx(Eye, { className: "h-3.5 w-3.5 text-[hsl(var(--brand-primary))]" }) : /* @__PURE__ */ jsx(EyeOff, { className: "h-3.5 w-3.5 text-[hsl(var(--text-disabled))]" }),
739
+ /* @__PURE__ */ jsx("span", { className: cn(
740
+ "truncate",
741
+ visible ? "text-[hsl(var(--text-primary))]" : "text-[hsl(var(--text-disabled))]"
742
+ ), children: header })
743
+ ]
744
+ }
745
+ )
746
+ ]
747
+ },
748
+ col.id
749
+ );
750
+ }) }),
751
+ /* @__PURE__ */ jsx("div", { className: "px-3 py-2 border-t border-[hsl(var(--border-subtle)/0.5)]", children: /* @__PURE__ */ jsx(
752
+ "button",
753
+ {
754
+ onClick: () => {
755
+ table.toggleAllColumnsVisible(true);
756
+ table.setColumnOrder([]);
757
+ },
758
+ className: "text-[10px] text-[hsl(var(--brand-primary))] hover:text-[hsl(var(--text-primary))] transition-colors",
759
+ children: "Reset to defaults"
760
+ }
761
+ ) })
762
+ ]
763
+ }
764
+ );
765
+ }
766
+ function DataTable({
767
+ columns,
768
+ data,
769
+ isLoading = false,
770
+ emptyState: emptyStateProps,
771
+ searchPlaceholder = "Search...",
772
+ onRowClick,
773
+ defaultSort,
774
+ defaultPageSize = 25,
775
+ exportFilename,
776
+ stickyFirstColumn = false,
777
+ density: densityProp
778
+ }) {
779
+ const prefersReducedMotion = useReducedMotion();
780
+ const [density, setDensity] = useState(() => {
781
+ if (densityProp) return densityProp;
782
+ if (typeof window !== "undefined") {
783
+ const stored = localStorage.getItem(STORAGE_KEY);
784
+ if (stored && stored in DENSITY_CLASSES) return stored;
785
+ }
786
+ return "comfortable";
787
+ });
788
+ const handleDensity = useCallback((d) => {
789
+ setDensity(d);
790
+ localStorage.setItem(STORAGE_KEY, d);
791
+ }, []);
792
+ const [sorting, setSorting] = useState(
793
+ defaultSort ? [{ id: defaultSort.id, desc: defaultSort.desc }] : []
794
+ );
795
+ const [columnFilters, setColumnFilters] = useState([]);
796
+ const [globalFilter, setGlobalFilter] = useState("");
797
+ const [columnVisibility, setColumnVisibility] = useState({});
798
+ const [columnOrder, setColumnOrder] = useState([]);
799
+ const [columnPickerOpen, setColumnPickerOpen] = useState(false);
800
+ const table = useReactTable({
801
+ data,
802
+ columns,
803
+ state: { sorting, columnFilters, globalFilter, columnVisibility, columnOrder },
804
+ onSortingChange: setSorting,
805
+ onColumnFiltersChange: setColumnFilters,
806
+ onGlobalFilterChange: setGlobalFilter,
807
+ onColumnVisibilityChange: setColumnVisibility,
808
+ onColumnOrderChange: setColumnOrder,
809
+ globalFilterFn,
810
+ getCoreRowModel: getCoreRowModel(),
811
+ getSortedRowModel: getSortedRowModel(),
812
+ getFilteredRowModel: getFilteredRowModel(),
813
+ getPaginationRowModel: getPaginationRowModel(),
814
+ initialState: { pagination: { pageSize: defaultPageSize } }
815
+ });
816
+ const activeFilterCount = columnFilters.length;
817
+ const { pageIndex, pageSize } = table.getState().pagination;
818
+ const totalRows = table.getFilteredRowModel().rows.length;
819
+ const startRow = totalRows === 0 ? 0 : pageIndex * pageSize + 1;
820
+ const endRow = Math.min((pageIndex + 1) * pageSize, totalRows);
821
+ const pageCount = table.getPageCount();
822
+ const rowVariants = useMemo(() => ({
823
+ hidden: { opacity: 0, y: 4 },
824
+ visible: (i) => ({
825
+ opacity: 1,
826
+ y: 0,
827
+ transition: {
828
+ delay: Math.min(i, 20) * 0.02,
829
+ duration: 0.15
830
+ }
831
+ })
832
+ }), []);
833
+ if (isLoading) {
834
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-[hsl(var(--border-subtle)/0.5)]\n bg-[hsl(var(--bg-surface)/0.6)] backdrop-blur-xl overflow-hidden", children: [
835
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 p-4 border-b border-[hsl(var(--border-subtle)/0.3)]", children: [
836
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-9 w-64 rounded-lg" }),
837
+ /* @__PURE__ */ jsx("div", { className: "flex-1" }),
838
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-24 rounded-lg" })
839
+ ] }),
840
+ /* @__PURE__ */ jsx("div", { className: "divide-y divide-[hsl(var(--border-subtle)/0.3)]", children: Array.from({ length: 8 }).map((_, i) => /* @__PURE__ */ jsxs("div", { className: cn("flex gap-4", DENSITY_CLASSES.comfortable), children: [
841
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-32" }),
842
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-48" }),
843
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-24" }),
844
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 flex-1" })
845
+ ] }, i)) })
846
+ ] });
847
+ }
848
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-[hsl(var(--border-subtle)/0.5)]\n bg-[hsl(var(--bg-surface)/0.6)] backdrop-blur-xl overflow-hidden", children: [
849
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-3 px-4 py-3\n border-b border-[hsl(var(--border-subtle)/0.3)]", children: [
850
+ /* @__PURE__ */ jsxs("div", { className: "relative flex-1 min-w-[200px] max-w-sm", children: [
851
+ /* @__PURE__ */ jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4\n text-[hsl(var(--text-tertiary))]" }),
852
+ /* @__PURE__ */ jsx(
853
+ "input",
854
+ {
855
+ type: "text",
856
+ value: globalFilter,
857
+ onChange: (e) => setGlobalFilter(e.target.value),
858
+ placeholder: searchPlaceholder,
859
+ className: "w-full rounded-lg border border-[hsl(var(--border-subtle))]\n bg-[hsl(var(--bg-surface))] pl-9 pr-3 py-2 text-small\n text-[hsl(var(--text-primary))] placeholder:text-[hsl(var(--text-tertiary))]\n outline-none focus:border-[hsl(var(--brand-primary))] transition-colors"
860
+ }
861
+ ),
862
+ globalFilter && /* @__PURE__ */ jsx(
863
+ "button",
864
+ {
865
+ onClick: () => setGlobalFilter(""),
866
+ className: "absolute right-2.5 top-1/2 -translate-y-1/2 p-0.5 rounded\n hover:bg-[hsl(var(--bg-elevated)/0.5)] transition-colors",
867
+ children: /* @__PURE__ */ jsx(X, { className: "h-3.5 w-3.5 text-[hsl(var(--text-tertiary))]" })
868
+ }
869
+ )
870
+ ] }),
871
+ activeFilterCount > 0 && /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 rounded-full\n bg-[hsl(var(--brand-primary)/0.15)] px-2.5 py-1 text-[11px] font-medium\n text-[hsl(var(--brand-primary))]", children: [
872
+ /* @__PURE__ */ jsx(Filter, { className: "h-3 w-3" }),
873
+ activeFilterCount,
874
+ " filter",
875
+ activeFilterCount > 1 ? "s" : ""
876
+ ] }),
877
+ /* @__PURE__ */ jsx("div", { className: "flex-1" }),
878
+ /* @__PURE__ */ jsx("div", { className: "flex items-center rounded-lg border border-[hsl(var(--border-subtle))]\n bg-[hsl(var(--bg-surface))] p-0.5", children: DENSITY_ICONS.map(({ key, icon: Icon, label }) => /* @__PURE__ */ jsx(
879
+ "button",
880
+ {
881
+ onClick: () => handleDensity(key),
882
+ title: label,
883
+ className: cn(
884
+ "p-1.5 rounded-md transition-colors",
885
+ density === key ? "bg-[hsl(var(--brand-primary)/0.2)] text-[hsl(var(--brand-primary))]" : "text-[hsl(var(--text-tertiary))] hover:text-[hsl(var(--text-secondary))]"
886
+ ),
887
+ children: /* @__PURE__ */ jsx(Icon, { className: "h-3.5 w-3.5" })
888
+ },
889
+ key
890
+ )) }),
891
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
892
+ /* @__PURE__ */ jsxs(
893
+ "button",
894
+ {
895
+ onClick: () => setColumnPickerOpen((o) => !o),
896
+ className: cn(
897
+ "flex items-center gap-1.5 rounded-lg border border-[hsl(var(--border-subtle))]",
898
+ "bg-[hsl(var(--bg-surface))] px-3 py-1.5 text-small text-[hsl(var(--text-secondary))]",
899
+ "hover:bg-[hsl(var(--bg-elevated)/0.5)] hover:text-[hsl(var(--text-primary))] transition-colors"
900
+ ),
901
+ children: [
902
+ /* @__PURE__ */ jsx(Columns3, { className: "h-3.5 w-3.5" }),
903
+ "Columns"
904
+ ]
905
+ }
906
+ ),
907
+ /* @__PURE__ */ jsx(AnimatePresence, { children: columnPickerOpen && /* @__PURE__ */ jsx(ColumnPicker, { table, onClose: () => setColumnPickerOpen(false) }) })
908
+ ] }),
909
+ exportFilename && /* @__PURE__ */ jsxs(
910
+ "button",
911
+ {
912
+ onClick: () => exportToCsv(table, exportFilename),
913
+ className: "flex items-center gap-1.5 rounded-lg border border-[hsl(var(--border-subtle))]\n bg-[hsl(var(--bg-surface))] px-3 py-1.5 text-small text-[hsl(var(--text-secondary))]\n hover:bg-[hsl(var(--bg-elevated)/0.5)] hover:text-[hsl(var(--text-primary))]\n transition-colors",
914
+ children: [
915
+ /* @__PURE__ */ jsx(Download, { className: "h-3.5 w-3.5" }),
916
+ "Export"
917
+ ]
918
+ }
919
+ ),
920
+ /* @__PURE__ */ jsxs("span", { className: "text-[11px] text-[hsl(var(--text-tertiary))] tabular-nums", children: [
921
+ totalRows,
922
+ " row",
923
+ totalRows !== 1 ? "s" : ""
924
+ ] })
925
+ ] }),
926
+ /* @__PURE__ */ jsx("div", { className: cn("overflow-x-auto", stickyFirstColumn && "relative"), children: /* @__PURE__ */ jsxs("table", { className: "w-full border-collapse text-small", children: [
927
+ /* @__PURE__ */ jsx("thead", { children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx("tr", { className: "bg-[hsl(var(--bg-elevated)/0.3)]", children: headerGroup.headers.map((header, colIdx) => {
928
+ const canSort = header.column.getCanSort();
929
+ const sorted = header.column.getIsSorted();
930
+ return /* @__PURE__ */ jsx(
931
+ "th",
932
+ {
933
+ className: cn(
934
+ DENSITY_CLASSES[density],
935
+ "text-left text-[11px] font-semibold uppercase tracking-wider",
936
+ "text-[hsl(var(--text-tertiary))] select-none whitespace-nowrap",
937
+ "border-b border-[hsl(var(--border-subtle)/0.3)]",
938
+ stickyFirstColumn && colIdx === 0 && "sticky left-0 z-10 bg-[hsl(var(--bg-elevated)/0.8)] backdrop-blur-sm"
939
+ ),
940
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
941
+ canSort ? /* @__PURE__ */ jsxs(
942
+ "button",
943
+ {
944
+ onClick: header.column.getToggleSortingHandler(),
945
+ className: "flex items-center gap-1 hover:text-[hsl(var(--text-secondary))] transition-colors",
946
+ children: [
947
+ header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext()),
948
+ sorted === "asc" ? /* @__PURE__ */ jsx(ChevronUp, { className: "h-3.5 w-3.5 text-[hsl(var(--brand-primary))]" }) : sorted === "desc" ? /* @__PURE__ */ jsx(ChevronDown, { className: "h-3.5 w-3.5 text-[hsl(var(--brand-primary))]" }) : /* @__PURE__ */ jsx(ChevronsUpDown, { className: "h-3 w-3 opacity-40" })
949
+ ]
950
+ }
951
+ ) : header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext()),
952
+ header.column.getCanFilter() && /* @__PURE__ */ jsx(ColumnFilterPopover, { column: header.column, table })
953
+ ] })
954
+ },
955
+ header.id
956
+ );
957
+ }) }, headerGroup.id)) }),
958
+ /* @__PURE__ */ jsx("tbody", { children: /* @__PURE__ */ jsx(AnimatePresence, { mode: "popLayout", children: table.getRowModel().rows.length === 0 ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan: columns.length, className: "p-0", children: emptyStateProps ? /* @__PURE__ */ jsx(
959
+ EmptyState,
960
+ {
961
+ icon: emptyStateProps.icon,
962
+ title: emptyStateProps.title,
963
+ description: emptyStateProps.description,
964
+ className: "border-0 rounded-none"
965
+ }
966
+ ) : /* @__PURE__ */ jsx(
967
+ EmptyState,
968
+ {
969
+ icon: Search,
970
+ title: "No results",
971
+ description: "No rows match your search or filter criteria.",
972
+ className: "border-0 rounded-none"
973
+ }
974
+ ) }) }) : table.getRowModel().rows.map((row, i) => /* @__PURE__ */ jsx(
975
+ motion.tr,
976
+ {
977
+ custom: i,
978
+ variants: prefersReducedMotion ? void 0 : rowVariants,
979
+ initial: prefersReducedMotion ? void 0 : "hidden",
980
+ animate: prefersReducedMotion ? void 0 : "visible",
981
+ exit: prefersReducedMotion ? void 0 : { opacity: 0 },
982
+ onClick: onRowClick ? () => onRowClick(row.original) : void 0,
983
+ className: cn(
984
+ "border-b border-[hsl(var(--border-subtle)/0.3)]",
985
+ "transition-colors",
986
+ onRowClick && "cursor-pointer hover:bg-[hsl(var(--bg-elevated)/0.5)]"
987
+ ),
988
+ children: row.getVisibleCells().map((cell, colIdx) => /* @__PURE__ */ jsx(
989
+ "td",
990
+ {
991
+ className: cn(
992
+ DENSITY_CLASSES[density],
993
+ "text-[hsl(var(--text-primary))]",
994
+ stickyFirstColumn && colIdx === 0 && "sticky left-0 z-10 bg-[hsl(var(--bg-surface)/0.9)] backdrop-blur-sm"
995
+ ),
996
+ children: flexRender(cell.column.columnDef.cell, cell.getContext())
997
+ },
998
+ cell.id
999
+ ))
1000
+ },
1001
+ row.id
1002
+ )) }) })
1003
+ ] }) }),
1004
+ totalRows > 0 && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3 px-4 py-3\n border-t border-[hsl(var(--border-subtle)/0.3)]", children: [
1005
+ /* @__PURE__ */ jsxs("span", { className: "text-[12px] text-[hsl(var(--text-tertiary))] tabular-nums", children: [
1006
+ "Showing ",
1007
+ startRow,
1008
+ "\u2013",
1009
+ endRow,
1010
+ " of ",
1011
+ totalRows
1012
+ ] }),
1013
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1014
+ /* @__PURE__ */ jsx(
1015
+ "select",
1016
+ {
1017
+ value: pageSize,
1018
+ onChange: (e) => table.setPageSize(Number(e.target.value)),
1019
+ className: "rounded-md border border-[hsl(var(--border-subtle))]\n bg-[hsl(var(--bg-surface))] px-2 py-1 text-[12px]\n text-[hsl(var(--text-secondary))] outline-none\n focus:border-[hsl(var(--brand-primary))] transition-colors",
1020
+ children: PAGE_SIZES.map((size) => /* @__PURE__ */ jsxs("option", { value: size, children: [
1021
+ size,
1022
+ " / page"
1023
+ ] }, size))
1024
+ }
1025
+ ),
1026
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
1027
+ /* @__PURE__ */ jsx(
1028
+ PaginationButton,
1029
+ {
1030
+ onClick: () => table.setPageIndex(0),
1031
+ disabled: !table.getCanPreviousPage(),
1032
+ children: "First"
1033
+ }
1034
+ ),
1035
+ /* @__PURE__ */ jsx(
1036
+ PaginationButton,
1037
+ {
1038
+ onClick: () => table.previousPage(),
1039
+ disabled: !table.getCanPreviousPage(),
1040
+ children: "Prev"
1041
+ }
1042
+ ),
1043
+ generatePageNumbers(pageIndex, pageCount).map(
1044
+ (p, idx) => p === -1 ? /* @__PURE__ */ jsx("span", { className: "px-1 text-[hsl(var(--text-tertiary))]", children: "..." }, `ellipsis-${idx}`) : /* @__PURE__ */ jsx(
1045
+ PaginationButton,
1046
+ {
1047
+ onClick: () => table.setPageIndex(p),
1048
+ active: p === pageIndex,
1049
+ children: p + 1
1050
+ },
1051
+ p
1052
+ )
1053
+ ),
1054
+ /* @__PURE__ */ jsx(
1055
+ PaginationButton,
1056
+ {
1057
+ onClick: () => table.nextPage(),
1058
+ disabled: !table.getCanNextPage(),
1059
+ children: "Next"
1060
+ }
1061
+ ),
1062
+ /* @__PURE__ */ jsx(
1063
+ PaginationButton,
1064
+ {
1065
+ onClick: () => table.setPageIndex(pageCount - 1),
1066
+ disabled: !table.getCanNextPage(),
1067
+ children: "Last"
1068
+ }
1069
+ )
1070
+ ] })
1071
+ ] })
1072
+ ] })
1073
+ ] });
1074
+ }
1075
+ function PaginationButton({ children, onClick, disabled, active }) {
1076
+ return /* @__PURE__ */ jsx(
1077
+ "button",
1078
+ {
1079
+ onClick,
1080
+ disabled,
1081
+ className: cn(
1082
+ "rounded-md px-2 py-1 text-[12px] font-medium transition-colors tabular-nums",
1083
+ active ? "bg-[hsl(var(--brand-primary)/0.2)] text-[hsl(var(--brand-primary))]" : "text-[hsl(var(--text-secondary))] hover:bg-[hsl(var(--bg-elevated)/0.5)] hover:text-[hsl(var(--text-primary))]",
1084
+ disabled && "opacity-40 pointer-events-none"
1085
+ ),
1086
+ children
1087
+ }
1088
+ );
1089
+ }
1090
+ function generatePageNumbers(current, total) {
1091
+ if (total <= 7) return Array.from({ length: total }, (_, i) => i);
1092
+ const pages = [];
1093
+ const addPage = (p) => {
1094
+ if (!pages.includes(p)) pages.push(p);
1095
+ };
1096
+ addPage(0);
1097
+ for (let i = Math.max(1, current - 1); i <= Math.min(total - 2, current + 1); i++) addPage(i);
1098
+ addPage(total - 1);
1099
+ const result = [];
1100
+ for (let i = 0; i < pages.length; i++) {
1101
+ if (i > 0 && pages[i] - pages[i - 1] > 1) result.push(-1);
1102
+ result.push(pages[i]);
1103
+ }
1104
+ return result;
1105
+ }
1106
+ var sizeClasses2 = {
1107
+ sm: "text-xs px-3 py-1.5 gap-1.5",
1108
+ md: "text-sm px-4 py-2 gap-2"
1109
+ };
1110
+ function Tabs({
1111
+ tabs,
1112
+ value,
1113
+ onChange,
1114
+ variant = "underline",
1115
+ size = "md",
1116
+ className
1117
+ }) {
1118
+ const prefersReducedMotion = useReducedMotion();
1119
+ const tabListRef = useRef(null);
1120
+ const enabledTabs = tabs.filter((t) => !t.disabled);
1121
+ const handleKeyDown = useCallback(
1122
+ (e) => {
1123
+ const currentIdx = enabledTabs.findIndex((t) => t.value === value);
1124
+ if (currentIdx === -1) return;
1125
+ let nextIdx = null;
1126
+ if (e.key === "ArrowRight" || e.key === "ArrowDown") {
1127
+ e.preventDefault();
1128
+ nextIdx = (currentIdx + 1) % enabledTabs.length;
1129
+ } else if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
1130
+ e.preventDefault();
1131
+ nextIdx = (currentIdx - 1 + enabledTabs.length) % enabledTabs.length;
1132
+ } else if (e.key === "Home") {
1133
+ e.preventDefault();
1134
+ nextIdx = 0;
1135
+ } else if (e.key === "End") {
1136
+ e.preventDefault();
1137
+ nextIdx = enabledTabs.length - 1;
1138
+ }
1139
+ if (nextIdx !== null) {
1140
+ onChange(enabledTabs[nextIdx].value);
1141
+ const buttons = tabListRef.current?.querySelectorAll('[role="tab"]:not([disabled])');
1142
+ buttons?.[nextIdx]?.focus();
1143
+ }
1144
+ },
1145
+ [enabledTabs, value, onChange]
1146
+ );
1147
+ const listCls = cn(
1148
+ "inline-flex items-center",
1149
+ variant === "underline" && "border-b border-[hsl(var(--border-subtle))] gap-0",
1150
+ variant === "pills" && "gap-1 p-1 rounded-xl bg-[hsl(var(--bg-surface))]",
1151
+ variant === "enclosed" && "gap-0 border-b border-[hsl(var(--border-subtle))]",
1152
+ className
1153
+ );
1154
+ const layoutId = `tabs-indicator-${variant}`;
1155
+ return /* @__PURE__ */ jsx(
1156
+ "div",
1157
+ {
1158
+ ref: tabListRef,
1159
+ role: "tablist",
1160
+ "aria-orientation": "horizontal",
1161
+ onKeyDown: handleKeyDown,
1162
+ className: listCls,
1163
+ children: tabs.map((tab) => {
1164
+ const isActive = tab.value === value;
1165
+ const Icon = tab.icon;
1166
+ const buttonCls = cn(
1167
+ "relative inline-flex items-center justify-center font-medium transition-colors duration-150",
1168
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[hsl(var(--brand-primary))] focus-visible:ring-offset-1 focus-visible:ring-offset-[hsl(var(--bg-base))]",
1169
+ "disabled:pointer-events-none disabled:opacity-40",
1170
+ "cursor-pointer select-none whitespace-nowrap",
1171
+ sizeClasses2[size],
1172
+ // variant-specific active/inactive
1173
+ variant === "underline" && [
1174
+ isActive ? "text-[hsl(var(--text-primary))]" : "text-[hsl(var(--text-tertiary))] hover:text-[hsl(var(--text-secondary))]"
1175
+ ],
1176
+ variant === "pills" && [
1177
+ isActive ? "text-[hsl(var(--text-primary))]" : "text-[hsl(var(--text-tertiary))] hover:text-[hsl(var(--text-secondary))] hover:bg-[hsl(var(--bg-elevated)/0.5)]",
1178
+ "rounded-lg"
1179
+ ],
1180
+ variant === "enclosed" && [
1181
+ isActive ? "text-[hsl(var(--text-primary))] bg-[hsl(var(--bg-elevated))]" : "text-[hsl(var(--text-tertiary))] hover:text-[hsl(var(--text-secondary))]",
1182
+ "rounded-t-lg"
1183
+ ]
1184
+ );
1185
+ return /* @__PURE__ */ jsxs(
1186
+ "button",
1187
+ {
1188
+ role: "tab",
1189
+ "aria-selected": isActive,
1190
+ "aria-controls": `tabpanel-${tab.value}`,
1191
+ tabIndex: isActive ? 0 : -1,
1192
+ disabled: tab.disabled,
1193
+ onClick: () => onChange(tab.value),
1194
+ className: buttonCls,
1195
+ children: [
1196
+ Icon && /* @__PURE__ */ jsx(Icon, { className: size === "sm" ? "h-3.5 w-3.5" : "h-4 w-4" }),
1197
+ tab.label,
1198
+ isActive && variant === "underline" && /* @__PURE__ */ jsx(
1199
+ motion.div,
1200
+ {
1201
+ layoutId,
1202
+ className: "absolute bottom-0 left-0 right-0 h-0.5 bg-[hsl(var(--brand-primary))] rounded-full",
1203
+ transition: prefersReducedMotion ? { duration: 0 } : { type: "spring", stiffness: 500, damping: 35 }
1204
+ }
1205
+ ),
1206
+ isActive && variant === "pills" && /* @__PURE__ */ jsx(
1207
+ motion.div,
1208
+ {
1209
+ layoutId,
1210
+ className: "absolute inset-0 rounded-lg bg-[hsl(var(--bg-elevated))] -z-10",
1211
+ transition: prefersReducedMotion ? { duration: 0 } : { type: "spring", stiffness: 500, damping: 35 }
1212
+ }
1213
+ ),
1214
+ isActive && variant === "enclosed" && /* @__PURE__ */ jsx(
1215
+ motion.div,
1216
+ {
1217
+ layoutId,
1218
+ className: "absolute bottom-0 left-0 right-0 h-0.5 bg-[hsl(var(--brand-primary))] rounded-full",
1219
+ transition: prefersReducedMotion ? { duration: 0 } : { type: "spring", stiffness: 500, damping: 35 }
1220
+ }
1221
+ )
1222
+ ]
1223
+ },
1224
+ tab.value
1225
+ );
1226
+ })
1227
+ }
1228
+ );
1229
+ }
1230
+ var contentVariants = {
1231
+ hidden: { opacity: 0, scale: 0.95, y: -4 },
1232
+ visible: { opacity: 1, scale: 1, y: 0 },
1233
+ exit: { opacity: 0, scale: 0.95, y: -4 }
1234
+ };
1235
+ function DropdownMenu({ trigger, items, align = "end", className }) {
1236
+ const prefersReducedMotion = useReducedMotion();
1237
+ return /* @__PURE__ */ jsxs(DropdownMenuPrimitive.Root, { children: [
1238
+ /* @__PURE__ */ jsx(DropdownMenuPrimitive.Trigger, { asChild: true, children: trigger }),
1239
+ /* @__PURE__ */ jsx(AnimatePresence, { children: /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(
1240
+ DropdownMenuPrimitive.Content,
1241
+ {
1242
+ align,
1243
+ sideOffset: 6,
1244
+ asChild: true,
1245
+ children: /* @__PURE__ */ jsx(
1246
+ motion.div,
1247
+ {
1248
+ initial: "hidden",
1249
+ animate: "visible",
1250
+ exit: "exit",
1251
+ variants: contentVariants,
1252
+ transition: prefersReducedMotion ? { duration: 0 } : { duration: 0.15, ease: [0.16, 1, 0.3, 1] },
1253
+ className: cn(
1254
+ "z-50 min-w-[160px] overflow-hidden rounded-xl p-1",
1255
+ "border border-[hsl(var(--border-default))]",
1256
+ "bg-[hsl(var(--bg-elevated))] shadow-xl",
1257
+ "focus:outline-none",
1258
+ className
1259
+ ),
1260
+ children: items.map((item, i) => {
1261
+ const Icon = item.icon;
1262
+ const isDanger = item.variant === "danger";
1263
+ return /* @__PURE__ */ jsxs(
1264
+ DropdownMenuPrimitive.Item,
1265
+ {
1266
+ disabled: item.disabled,
1267
+ onSelect: item.onClick,
1268
+ className: cn(
1269
+ "relative flex items-center gap-2.5 px-3 py-2 text-sm rounded-lg",
1270
+ "outline-none cursor-pointer select-none transition-colors duration-100",
1271
+ "data-[disabled]:pointer-events-none data-[disabled]:opacity-40",
1272
+ isDanger ? "text-[hsl(var(--status-critical))] data-[highlighted]:bg-[hsl(var(--status-critical)/0.1)]" : "text-[hsl(var(--text-primary))] data-[highlighted]:bg-[hsl(var(--bg-overlay))]"
1273
+ ),
1274
+ children: [
1275
+ Icon && /* @__PURE__ */ jsx(
1276
+ Icon,
1277
+ {
1278
+ className: cn(
1279
+ "h-4 w-4 shrink-0",
1280
+ isDanger ? "text-[hsl(var(--status-critical))]" : "text-[hsl(var(--text-secondary))]"
1281
+ )
1282
+ }
1283
+ ),
1284
+ item.label
1285
+ ]
1286
+ },
1287
+ i
1288
+ );
1289
+ })
1290
+ }
1291
+ )
1292
+ }
1293
+ ) }) })
1294
+ ] });
1295
+ }
1296
+ var slideVariants = {
1297
+ right: { initial: { x: "100%" }, animate: { x: 0 }, exit: { x: "100%" } },
1298
+ left: { initial: { x: "-100%" }, animate: { x: 0 }, exit: { x: "-100%" } },
1299
+ top: { initial: { y: "-100%" }, animate: { y: 0 }, exit: { y: "-100%" } },
1300
+ bottom: { initial: { y: "100%" }, animate: { y: 0 }, exit: { y: "100%" } }
1301
+ };
1302
+ var positionClasses = {
1303
+ right: "inset-y-0 right-0",
1304
+ left: "inset-y-0 left-0",
1305
+ top: "inset-x-0 top-0",
1306
+ bottom: "inset-x-0 bottom-0"
1307
+ };
1308
+ function Sheet({
1309
+ open,
1310
+ onClose,
1311
+ side = "right",
1312
+ title,
1313
+ description,
1314
+ width = "max-w-md",
1315
+ children,
1316
+ className
1317
+ }) {
1318
+ const prefersReducedMotion = useReducedMotion();
1319
+ const panelRef = useRef(null);
1320
+ const handleKeyDown = useCallback(
1321
+ (e) => {
1322
+ if (e.key === "Escape") onClose();
1323
+ },
1324
+ [onClose]
1325
+ );
1326
+ useEffect(() => {
1327
+ if (open) {
1328
+ document.addEventListener("keydown", handleKeyDown);
1329
+ const prevOverflow = document.body.style.overflow;
1330
+ document.body.style.overflow = "hidden";
1331
+ return () => {
1332
+ document.removeEventListener("keydown", handleKeyDown);
1333
+ document.body.style.overflow = prevOverflow;
1334
+ };
1335
+ }
1336
+ }, [open, handleKeyDown]);
1337
+ useEffect(() => {
1338
+ if (open) {
1339
+ requestAnimationFrame(() => {
1340
+ panelRef.current?.focus();
1341
+ });
1342
+ }
1343
+ }, [open]);
1344
+ const isHorizontal = side === "left" || side === "right";
1345
+ const variants = slideVariants[side];
1346
+ return /* @__PURE__ */ jsx(AnimatePresence, { children: open && /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-50", children: [
1347
+ /* @__PURE__ */ jsx(
1348
+ motion.div,
1349
+ {
1350
+ initial: { opacity: 0 },
1351
+ animate: { opacity: 1 },
1352
+ exit: { opacity: 0 },
1353
+ transition: prefersReducedMotion ? { duration: 0 } : { duration: 0.2 },
1354
+ className: "absolute inset-0 bg-[hsl(var(--bg-base)/0.6)] backdrop-blur-sm",
1355
+ onClick: onClose
1356
+ }
1357
+ ),
1358
+ /* @__PURE__ */ jsxs(
1359
+ motion.div,
1360
+ {
1361
+ ref: panelRef,
1362
+ tabIndex: -1,
1363
+ role: "dialog",
1364
+ "aria-modal": "true",
1365
+ "aria-label": title,
1366
+ initial: variants.initial,
1367
+ animate: variants.animate,
1368
+ exit: variants.exit,
1369
+ transition: prefersReducedMotion ? { duration: 0 } : { type: "spring", stiffness: 400, damping: 35 },
1370
+ className: cn(
1371
+ "absolute flex flex-col",
1372
+ "bg-[hsl(var(--bg-surface))] border-[hsl(var(--border-default))]",
1373
+ "shadow-2xl focus:outline-none",
1374
+ positionClasses[side],
1375
+ isHorizontal ? cn("w-full h-full", width, side === "right" ? "border-l" : "border-r") : cn("h-auto w-full", side === "top" ? "border-b" : "border-t"),
1376
+ className
1377
+ ),
1378
+ children: [
1379
+ (title || description) && /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-4 px-6 pt-6 pb-4 border-b border-[hsl(var(--border-subtle))]", children: [
1380
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
1381
+ title && /* @__PURE__ */ jsx("h2", { className: "text-base font-semibold text-[hsl(var(--text-primary))]", children: title }),
1382
+ description && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-[hsl(var(--text-secondary))]", children: description })
1383
+ ] }),
1384
+ /* @__PURE__ */ jsx(
1385
+ "button",
1386
+ {
1387
+ onClick: onClose,
1388
+ className: cn(
1389
+ "shrink-0 p-1.5 rounded-lg transition-colors",
1390
+ "text-[hsl(var(--text-tertiary))] hover:text-[hsl(var(--text-primary))]",
1391
+ "hover:bg-[hsl(var(--bg-elevated))]",
1392
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[hsl(var(--brand-primary))]"
1393
+ ),
1394
+ children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
1395
+ }
1396
+ )
1397
+ ] }),
1398
+ /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto px-6 py-4", children })
1399
+ ]
1400
+ }
1401
+ )
1402
+ ] }) });
1403
+ }
1404
+ var variantColors = {
1405
+ default: "bg-[hsl(var(--brand-primary))]",
1406
+ success: "bg-[hsl(var(--status-ok))]",
1407
+ warning: "bg-[hsl(var(--status-warning))]",
1408
+ danger: "bg-[hsl(var(--status-critical))]"
1409
+ };
1410
+ var sizeClasses3 = {
1411
+ sm: "h-1.5",
1412
+ md: "h-2.5",
1413
+ lg: "h-4"
1414
+ };
1415
+ function Progress({
1416
+ value,
1417
+ max = 100,
1418
+ label,
1419
+ showValue = false,
1420
+ variant = "default",
1421
+ size = "md",
1422
+ animated = true,
1423
+ indeterminate = false,
1424
+ className
1425
+ }) {
1426
+ const prefersReducedMotion = useReducedMotion();
1427
+ const pct = Math.min(100, Math.max(0, value / max * 100));
1428
+ return /* @__PURE__ */ jsxs("div", { className: cn("w-full", className), children: [
1429
+ (label || showValue) && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-1.5", children: [
1430
+ label && /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-[hsl(var(--text-secondary))]", children: label }),
1431
+ showValue && !indeterminate && /* @__PURE__ */ jsxs("span", { className: "text-xs font-medium tabular-nums text-[hsl(var(--text-secondary))]", children: [
1432
+ Math.round(pct),
1433
+ "%"
1434
+ ] })
1435
+ ] }),
1436
+ /* @__PURE__ */ jsx(
1437
+ "div",
1438
+ {
1439
+ role: "progressbar",
1440
+ "aria-valuenow": indeterminate ? void 0 : pct,
1441
+ "aria-valuemin": 0,
1442
+ "aria-valuemax": 100,
1443
+ "aria-label": label,
1444
+ className: cn(
1445
+ "w-full overflow-hidden rounded-full bg-[hsl(var(--bg-overlay))]",
1446
+ sizeClasses3[size]
1447
+ ),
1448
+ children: indeterminate ? /* @__PURE__ */ jsx(
1449
+ "div",
1450
+ {
1451
+ className: cn(
1452
+ "h-full w-1/3 rounded-full",
1453
+ variantColors[variant],
1454
+ prefersReducedMotion ? "" : "animate-shimmer"
1455
+ ),
1456
+ style: prefersReducedMotion ? { width: "33%" } : {
1457
+ animation: "indeterminate-slide 1.5s ease-in-out infinite"
1458
+ }
1459
+ }
1460
+ ) : animated && !prefersReducedMotion ? /* @__PURE__ */ jsx(
1461
+ motion.div,
1462
+ {
1463
+ className: cn("h-full rounded-full", variantColors[variant]),
1464
+ initial: { width: 0 },
1465
+ animate: { width: `${pct}%` },
1466
+ transition: { type: "spring", stiffness: 100, damping: 20 }
1467
+ }
1468
+ ) : /* @__PURE__ */ jsx(
1469
+ "div",
1470
+ {
1471
+ className: cn("h-full rounded-full transition-[width] duration-300", variantColors[variant]),
1472
+ style: { width: `${pct}%` }
1473
+ }
1474
+ )
1475
+ }
1476
+ ),
1477
+ indeterminate && !prefersReducedMotion && /* @__PURE__ */ jsx("style", { children: `
1478
+ @keyframes indeterminate-slide {
1479
+ 0% { transform: translateX(-100%); }
1480
+ 50% { transform: translateX(200%); }
1481
+ 100% { transform: translateX(-100%); }
1482
+ }
1483
+ ` })
1484
+ ] });
1485
+ }
1486
+ var sizeClasses4 = {
1487
+ xs: { root: "h-6 w-6", text: "text-[10px]", dot: "h-2 w-2 -bottom-0 -right-0 ring-1" },
1488
+ sm: { root: "h-8 w-8", text: "text-xs", dot: "h-2.5 w-2.5 -bottom-0.5 -right-0.5 ring-[1.5px]" },
1489
+ md: { root: "h-10 w-10", text: "text-sm", dot: "h-3 w-3 -bottom-0.5 -right-0.5 ring-2" },
1490
+ lg: { root: "h-12 w-12", text: "text-base", dot: "h-3.5 w-3.5 -bottom-0.5 -right-0.5 ring-2" },
1491
+ xl: { root: "h-16 w-16", text: "text-lg", dot: "h-4 w-4 -bottom-0.5 -right-0.5 ring-2" }
1492
+ };
1493
+ var statusColors = {
1494
+ online: "bg-[hsl(var(--status-ok))]",
1495
+ offline: "bg-[hsl(var(--text-disabled))]",
1496
+ busy: "bg-[hsl(var(--status-critical))]",
1497
+ away: "bg-[hsl(var(--status-warning))]"
1498
+ };
1499
+ function deriveInitials(name) {
1500
+ const parts = name.trim().split(/\s+/);
1501
+ if (parts.length >= 2) {
1502
+ return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
1503
+ }
1504
+ return name.slice(0, 2).toUpperCase();
1505
+ }
1506
+ function Avatar({
1507
+ src,
1508
+ alt,
1509
+ fallback,
1510
+ size = "md",
1511
+ status,
1512
+ className
1513
+ }) {
1514
+ const [imgError, setImgError] = useState(false);
1515
+ const s = sizeClasses4[size];
1516
+ const initials = fallback ?? deriveInitials(alt);
1517
+ const showImage = src && !imgError;
1518
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative inline-flex shrink-0", className), children: [
1519
+ /* @__PURE__ */ jsx(
1520
+ "div",
1521
+ {
1522
+ className: cn(
1523
+ s.root,
1524
+ "rounded-full overflow-hidden",
1525
+ "flex items-center justify-center",
1526
+ !showImage && "bg-[hsl(var(--bg-overlay))]"
1527
+ ),
1528
+ children: showImage ? /* @__PURE__ */ jsx(
1529
+ "img",
1530
+ {
1531
+ src,
1532
+ alt,
1533
+ onError: () => setImgError(true),
1534
+ className: "h-full w-full object-cover"
1535
+ }
1536
+ ) : /* @__PURE__ */ jsx(
1537
+ "span",
1538
+ {
1539
+ className: cn(
1540
+ s.text,
1541
+ "font-semibold text-[hsl(var(--text-secondary))] select-none"
1542
+ ),
1543
+ children: initials
1544
+ }
1545
+ )
1546
+ }
1547
+ ),
1548
+ status && /* @__PURE__ */ jsx(
1549
+ "span",
1550
+ {
1551
+ className: cn(
1552
+ "absolute rounded-full ring-[hsl(var(--bg-surface))]",
1553
+ s.dot,
1554
+ statusColors[status]
1555
+ ),
1556
+ "aria-label": status
1557
+ }
1558
+ )
1559
+ ] });
1560
+ }
1561
+ var contentVariants2 = {
1562
+ hidden: { opacity: 0, scale: 0.96, y: -2 },
1563
+ visible: { opacity: 1, scale: 1, y: 0 },
1564
+ exit: { opacity: 0, scale: 0.96, y: -2 }
1565
+ };
1566
+ function Popover({ trigger, children, side = "bottom", align = "center", className }) {
1567
+ const prefersReducedMotion = useReducedMotion();
1568
+ return /* @__PURE__ */ jsxs(PopoverPrimitive.Root, { children: [
1569
+ /* @__PURE__ */ jsx(PopoverPrimitive.Trigger, { asChild: true, children: trigger }),
1570
+ /* @__PURE__ */ jsx(AnimatePresence, { children: /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
1571
+ PopoverPrimitive.Content,
1572
+ {
1573
+ side,
1574
+ align,
1575
+ sideOffset: 8,
1576
+ asChild: true,
1577
+ children: /* @__PURE__ */ jsxs(
1578
+ motion.div,
1579
+ {
1580
+ initial: "hidden",
1581
+ animate: "visible",
1582
+ exit: "exit",
1583
+ variants: contentVariants2,
1584
+ transition: prefersReducedMotion ? { duration: 0 } : { duration: 0.15, ease: [0.16, 1, 0.3, 1] },
1585
+ className: cn(
1586
+ "z-50 rounded-xl p-4",
1587
+ "border border-[hsl(var(--border-default))]",
1588
+ "bg-[hsl(var(--bg-elevated))] shadow-xl",
1589
+ "focus:outline-none",
1590
+ className
1591
+ ),
1592
+ children: [
1593
+ children,
1594
+ /* @__PURE__ */ jsx(
1595
+ PopoverPrimitive.Arrow,
1596
+ {
1597
+ className: "fill-[hsl(var(--bg-elevated))]",
1598
+ width: 12,
1599
+ height: 6
1600
+ }
1601
+ )
1602
+ ]
1603
+ }
1604
+ )
1605
+ }
1606
+ ) }) })
1607
+ ] });
1608
+ }
1609
+ function Slider({
1610
+ value,
1611
+ onChange,
1612
+ min = 0,
1613
+ max = 100,
1614
+ step = 1,
1615
+ label,
1616
+ showValue = false,
1617
+ className
1618
+ }) {
1619
+ const trackRef = useRef(null);
1620
+ const [isDragging, setIsDragging] = useState(false);
1621
+ const [isHovering, setIsHovering] = useState(false);
1622
+ const pct = max === min ? 0 : (value - min) / (max - min) * 100;
1623
+ const clampToStep = useCallback(
1624
+ (raw) => {
1625
+ const clamped = Math.min(max, Math.max(min, raw));
1626
+ const stepped = Math.round((clamped - min) / step) * step + min;
1627
+ return Math.min(max, Math.max(min, parseFloat(stepped.toPrecision(10))));
1628
+ },
1629
+ [min, max, step]
1630
+ );
1631
+ const getValueFromPosition = useCallback(
1632
+ (clientX) => {
1633
+ const track = trackRef.current;
1634
+ if (!track) return value;
1635
+ const rect = track.getBoundingClientRect();
1636
+ const ratio = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));
1637
+ return clampToStep(min + ratio * (max - min));
1638
+ },
1639
+ [min, max, value, clampToStep]
1640
+ );
1641
+ const handleMouseDown = useCallback(
1642
+ (e) => {
1643
+ e.preventDefault();
1644
+ setIsDragging(true);
1645
+ onChange(getValueFromPosition(e.clientX));
1646
+ const handleMouseMove = (ev) => {
1647
+ onChange(getValueFromPosition(ev.clientX));
1648
+ };
1649
+ const handleMouseUp = () => {
1650
+ setIsDragging(false);
1651
+ document.removeEventListener("mousemove", handleMouseMove);
1652
+ document.removeEventListener("mouseup", handleMouseUp);
1653
+ };
1654
+ document.addEventListener("mousemove", handleMouseMove);
1655
+ document.addEventListener("mouseup", handleMouseUp);
1656
+ },
1657
+ [getValueFromPosition, onChange]
1658
+ );
1659
+ const handleTouchStart = useCallback(
1660
+ (e) => {
1661
+ setIsDragging(true);
1662
+ if (e.touches[0]) {
1663
+ onChange(getValueFromPosition(e.touches[0].clientX));
1664
+ }
1665
+ const handleTouchMove = (ev) => {
1666
+ if (ev.touches[0]) {
1667
+ onChange(getValueFromPosition(ev.touches[0].clientX));
1668
+ }
1669
+ };
1670
+ const handleTouchEnd = () => {
1671
+ setIsDragging(false);
1672
+ document.removeEventListener("touchmove", handleTouchMove);
1673
+ document.removeEventListener("touchend", handleTouchEnd);
1674
+ };
1675
+ document.addEventListener("touchmove", handleTouchMove);
1676
+ document.addEventListener("touchend", handleTouchEnd);
1677
+ },
1678
+ [getValueFromPosition, onChange]
1679
+ );
1680
+ const handleKeyDown = useCallback(
1681
+ (e) => {
1682
+ let newValue = value;
1683
+ if (e.key === "ArrowRight" || e.key === "ArrowUp") {
1684
+ e.preventDefault();
1685
+ newValue = clampToStep(value + step);
1686
+ } else if (e.key === "ArrowLeft" || e.key === "ArrowDown") {
1687
+ e.preventDefault();
1688
+ newValue = clampToStep(value - step);
1689
+ } else if (e.key === "Home") {
1690
+ e.preventDefault();
1691
+ newValue = min;
1692
+ } else if (e.key === "End") {
1693
+ e.preventDefault();
1694
+ newValue = max;
1695
+ }
1696
+ if (newValue !== value) onChange(newValue);
1697
+ },
1698
+ [value, min, max, step, clampToStep, onChange]
1699
+ );
1700
+ const showTooltip = isDragging || isHovering;
1701
+ return /* @__PURE__ */ jsxs("div", { className: cn("w-full", className), children: [
1702
+ (label || showValue) && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-2", children: [
1703
+ label && /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-[hsl(var(--text-secondary))]", children: label }),
1704
+ showValue && /* @__PURE__ */ jsx("span", { className: "text-xs font-medium tabular-nums text-[hsl(var(--text-secondary))]", children: value })
1705
+ ] }),
1706
+ /* @__PURE__ */ jsxs(
1707
+ "div",
1708
+ {
1709
+ ref: trackRef,
1710
+ role: "slider",
1711
+ "aria-valuenow": value,
1712
+ "aria-valuemin": min,
1713
+ "aria-valuemax": max,
1714
+ "aria-label": label,
1715
+ tabIndex: 0,
1716
+ onMouseDown: handleMouseDown,
1717
+ onTouchStart: handleTouchStart,
1718
+ onKeyDown: handleKeyDown,
1719
+ onMouseEnter: () => setIsHovering(true),
1720
+ onMouseLeave: () => setIsHovering(false),
1721
+ className: cn(
1722
+ "relative h-6 w-full cursor-pointer select-none",
1723
+ "focus-visible:outline-none",
1724
+ "group"
1725
+ ),
1726
+ children: [
1727
+ /* @__PURE__ */ jsx("div", { className: "absolute top-1/2 -translate-y-1/2 w-full h-2 rounded-full bg-[hsl(var(--bg-overlay))]", children: /* @__PURE__ */ jsx(
1728
+ "div",
1729
+ {
1730
+ className: "absolute inset-y-0 left-0 rounded-full bg-[hsl(var(--brand-primary))]",
1731
+ style: { width: `${pct}%` }
1732
+ }
1733
+ ) }),
1734
+ /* @__PURE__ */ jsx(
1735
+ "div",
1736
+ {
1737
+ className: cn(
1738
+ "absolute top-1/2 -translate-y-1/2 -translate-x-1/2",
1739
+ "h-5 w-5 rounded-full",
1740
+ "bg-[hsl(var(--text-on-brand))] border-2 border-[hsl(var(--brand-primary))]",
1741
+ "shadow-md transition-transform duration-100",
1742
+ isDragging && "scale-110",
1743
+ "group-focus-visible:ring-2 group-focus-visible:ring-[hsl(var(--brand-primary))] group-focus-visible:ring-offset-2 group-focus-visible:ring-offset-[hsl(var(--bg-base))]"
1744
+ ),
1745
+ style: { left: `${pct}%` },
1746
+ children: showTooltip && /* @__PURE__ */ jsx(
1747
+ "div",
1748
+ {
1749
+ className: cn(
1750
+ "absolute -top-8 left-1/2 -translate-x-1/2",
1751
+ "px-2 py-0.5 rounded-md text-xs font-medium tabular-nums",
1752
+ "bg-[hsl(var(--bg-elevated))] text-[hsl(var(--text-primary))]",
1753
+ "border border-[hsl(var(--border-subtle))] shadow-sm",
1754
+ "pointer-events-none whitespace-nowrap"
1755
+ ),
1756
+ children: value
1757
+ }
1758
+ )
1759
+ }
1760
+ )
1761
+ ]
1762
+ }
1763
+ )
1764
+ ] });
1765
+ }
1766
+ var variantClasses2 = {
1767
+ default: "bg-[hsl(var(--bg-surface))] border border-[hsl(var(--border-subtle))] shadow-sm",
1768
+ elevated: "bg-[hsl(var(--bg-elevated))] border border-[hsl(var(--border-default))] shadow-lg",
1769
+ outlined: "bg-transparent border border-[hsl(var(--border-default))]",
1770
+ interactive: "bg-[hsl(var(--bg-surface))] border border-[hsl(var(--border-subtle))] shadow-sm hover:bg-[hsl(var(--bg-elevated))] hover:border-[hsl(var(--border-default))] hover:shadow-md transition-all duration-150 cursor-pointer"
1771
+ };
1772
+ var paddingClasses = {
1773
+ none: "",
1774
+ sm: "p-3",
1775
+ md: "p-5",
1776
+ lg: "p-6"
1777
+ };
1778
+ var Card = forwardRef(
1779
+ ({ variant = "default", padding = "md", className, children, ...props }, ref) => /* @__PURE__ */ jsx(
1780
+ "div",
1781
+ {
1782
+ ref,
1783
+ className: cn("rounded-2xl", variantClasses2[variant], paddingClasses[padding], className),
1784
+ ...props,
1785
+ children
1786
+ }
1787
+ )
1788
+ );
1789
+ Card.displayName = "Card";
1790
+ var CardHeader = forwardRef(
1791
+ ({ className, children, ...props }, ref) => /* @__PURE__ */ jsx(
1792
+ "div",
1793
+ {
1794
+ ref,
1795
+ className: cn("flex items-start justify-between gap-4", className),
1796
+ ...props,
1797
+ children
1798
+ }
1799
+ )
1800
+ );
1801
+ CardHeader.displayName = "CardHeader";
1802
+ var CardTitle = forwardRef(
1803
+ ({ className, children, ...props }, ref) => /* @__PURE__ */ jsx(
1804
+ "h3",
1805
+ {
1806
+ ref,
1807
+ className: cn("text-base font-semibold text-[hsl(var(--text-primary))]", className),
1808
+ ...props,
1809
+ children
1810
+ }
1811
+ )
1812
+ );
1813
+ CardTitle.displayName = "CardTitle";
1814
+ var CardDescription = forwardRef(
1815
+ ({ className, children, ...props }, ref) => /* @__PURE__ */ jsx(
1816
+ "p",
1817
+ {
1818
+ ref,
1819
+ className: cn("text-sm text-[hsl(var(--text-secondary))]", className),
1820
+ ...props,
1821
+ children
1822
+ }
1823
+ )
1824
+ );
1825
+ CardDescription.displayName = "CardDescription";
1826
+ var CardContent = forwardRef(
1827
+ ({ className, children, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("mt-4", className), ...props, children })
1828
+ );
1829
+ CardContent.displayName = "CardContent";
1830
+ var CardFooter = forwardRef(
1831
+ ({ className, children, ...props }, ref) => /* @__PURE__ */ jsx(
1832
+ "div",
1833
+ {
1834
+ ref,
1835
+ className: cn(
1836
+ "mt-4 pt-4 flex items-center gap-3 border-t border-[hsl(var(--border-subtle))]",
1837
+ className
1838
+ ),
1839
+ ...props,
1840
+ children
1841
+ }
1842
+ )
1843
+ );
1844
+ CardFooter.displayName = "CardFooter";
1845
+ function RadioGroup({
1846
+ options,
1847
+ value,
1848
+ onChange,
1849
+ orientation = "vertical",
1850
+ className
1851
+ }) {
1852
+ const prefersReducedMotion = useReducedMotion();
1853
+ const groupRef = useRef(null);
1854
+ const enabledOptions = options.filter((o) => !o.disabled);
1855
+ const handleKeyDown = useCallback(
1856
+ (e) => {
1857
+ const currentIdx = enabledOptions.findIndex((o) => o.value === value);
1858
+ if (currentIdx === -1) return;
1859
+ const isVertical = orientation === "vertical";
1860
+ const nextKey = isVertical ? "ArrowDown" : "ArrowRight";
1861
+ const prevKey = isVertical ? "ArrowUp" : "ArrowLeft";
1862
+ let nextIdx = null;
1863
+ if (e.key === nextKey) {
1864
+ e.preventDefault();
1865
+ nextIdx = (currentIdx + 1) % enabledOptions.length;
1866
+ } else if (e.key === prevKey) {
1867
+ e.preventDefault();
1868
+ nextIdx = (currentIdx - 1 + enabledOptions.length) % enabledOptions.length;
1869
+ } else if (e.key === "Home") {
1870
+ e.preventDefault();
1871
+ nextIdx = 0;
1872
+ } else if (e.key === "End") {
1873
+ e.preventDefault();
1874
+ nextIdx = enabledOptions.length - 1;
1875
+ }
1876
+ if (nextIdx !== null) {
1877
+ onChange(enabledOptions[nextIdx].value);
1878
+ const radios = groupRef.current?.querySelectorAll('[role="radio"]:not([aria-disabled="true"])');
1879
+ radios?.[nextIdx]?.focus();
1880
+ }
1881
+ },
1882
+ [enabledOptions, value, onChange, orientation]
1883
+ );
1884
+ return /* @__PURE__ */ jsx(
1885
+ "div",
1886
+ {
1887
+ ref: groupRef,
1888
+ role: "radiogroup",
1889
+ "aria-orientation": orientation,
1890
+ onKeyDown: handleKeyDown,
1891
+ className: cn(
1892
+ "flex",
1893
+ orientation === "vertical" ? "flex-col gap-2" : "flex-row flex-wrap gap-4",
1894
+ className
1895
+ ),
1896
+ children: options.map((option) => {
1897
+ const isSelected = option.value === value;
1898
+ return /* @__PURE__ */ jsxs(
1899
+ "div",
1900
+ {
1901
+ role: "radio",
1902
+ "aria-checked": isSelected,
1903
+ "aria-disabled": option.disabled,
1904
+ tabIndex: isSelected ? 0 : -1,
1905
+ onClick: () => {
1906
+ if (!option.disabled) onChange(option.value);
1907
+ },
1908
+ className: cn(
1909
+ "flex items-start gap-3 cursor-pointer select-none group",
1910
+ "focus-visible:outline-none",
1911
+ option.disabled && "opacity-40 pointer-events-none"
1912
+ ),
1913
+ children: [
1914
+ /* @__PURE__ */ jsx(
1915
+ "div",
1916
+ {
1917
+ className: cn(
1918
+ "relative mt-0.5 h-[18px] w-[18px] shrink-0 rounded-full border-2 transition-colors duration-150",
1919
+ "flex items-center justify-center",
1920
+ isSelected ? "border-[hsl(var(--brand-primary))]" : "border-[hsl(var(--border-strong))] group-hover:border-[hsl(var(--brand-primary))]",
1921
+ "group-focus-visible:ring-2 group-focus-visible:ring-[hsl(var(--brand-primary))] group-focus-visible:ring-offset-2 group-focus-visible:ring-offset-[hsl(var(--bg-base))]"
1922
+ ),
1923
+ children: isSelected && /* @__PURE__ */ jsx(
1924
+ motion.div,
1925
+ {
1926
+ layoutId: "radio-indicator",
1927
+ initial: prefersReducedMotion ? false : { scale: 0 },
1928
+ animate: { scale: 1 },
1929
+ transition: prefersReducedMotion ? { duration: 0 } : { type: "spring", stiffness: 500, damping: 30 },
1930
+ className: "h-2.5 w-2.5 rounded-full bg-[hsl(var(--brand-primary))]"
1931
+ }
1932
+ )
1933
+ }
1934
+ ),
1935
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
1936
+ /* @__PURE__ */ jsx(
1937
+ "span",
1938
+ {
1939
+ className: cn(
1940
+ "text-sm font-medium",
1941
+ isSelected ? "text-[hsl(var(--text-primary))]" : "text-[hsl(var(--text-secondary))]"
1942
+ ),
1943
+ children: option.label
1944
+ }
1945
+ ),
1946
+ option.description && /* @__PURE__ */ jsx("p", { className: "mt-0.5 text-xs text-[hsl(var(--text-tertiary))]", children: option.description })
1947
+ ] })
1948
+ ]
1949
+ },
1950
+ option.value
1951
+ );
1952
+ })
1953
+ }
1954
+ );
1955
+ }
1956
+ function Tooltip2({
1957
+ content,
1958
+ children,
1959
+ side = "top",
1960
+ delay = 200,
1961
+ className
1962
+ }) {
1963
+ return /* @__PURE__ */ jsx(Tooltip.Provider, { delayDuration: delay, children: /* @__PURE__ */ jsxs(Tooltip.Root, { children: [
1964
+ /* @__PURE__ */ jsx(Tooltip.Trigger, { asChild: true, children }),
1965
+ /* @__PURE__ */ jsx(Tooltip.Portal, { children: /* @__PURE__ */ jsxs(
1966
+ Tooltip.Content,
1967
+ {
1968
+ side,
1969
+ sideOffset: 6,
1970
+ className: cn(
1971
+ "z-50 px-3 py-1.5 rounded-lg text-xs font-medium",
1972
+ "bg-[hsl(var(--bg-elevated))] text-[hsl(var(--text-primary))]",
1973
+ "border border-[hsl(var(--border-default))] shadow-lg",
1974
+ "animate-in fade-in-0 zoom-in-95",
1975
+ "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
1976
+ "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2",
1977
+ "data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
1978
+ className
1979
+ ),
1980
+ children: [
1981
+ content,
1982
+ /* @__PURE__ */ jsx(
1983
+ Tooltip.Arrow,
1984
+ {
1985
+ className: "fill-[hsl(var(--bg-elevated))]",
1986
+ width: 10,
1987
+ height: 5
1988
+ }
1989
+ )
1990
+ ]
1991
+ }
1992
+ ) })
1993
+ ] }) });
1994
+ }
1995
+ function buildPoints(data, w, h, pad) {
1996
+ if (data.length < 2) return "";
1997
+ const min = Math.min(...data);
1998
+ const max = Math.max(...data);
1999
+ const range = max - min || 1;
2000
+ const stepX = (w - pad * 2) / (data.length - 1);
2001
+ return data.map((v, i) => {
2002
+ const x = pad + i * stepX;
2003
+ const y = pad + (1 - (v - min) / range) * (h - pad * 2);
2004
+ return `${x},${y}`;
2005
+ }).join(" ");
2006
+ }
2007
+ function Sparkline({
2008
+ data,
2009
+ width = 80,
2010
+ height = 24,
2011
+ color = "hsl(var(--brand-primary))",
2012
+ fillOpacity = 0.1,
2013
+ showDots = false,
2014
+ className
2015
+ }) {
2016
+ if (data.length < 2) return null;
2017
+ const pad = showDots ? 3 : 1;
2018
+ const points = buildPoints(data, width, height, pad);
2019
+ const gradId = `sp-grad-${Math.random().toString(36).slice(2, 8)}`;
2020
+ const min = Math.min(...data);
2021
+ const max = Math.max(...data);
2022
+ const range = max - min || 1;
2023
+ const stepX = (width - pad * 2) / (data.length - 1);
2024
+ const firstX = pad;
2025
+ const firstY = pad + (1 - (data[0] - min) / range) * (height - pad * 2);
2026
+ const lastX = pad + (data.length - 1) * stepX;
2027
+ const lastY = pad + (1 - (data[data.length - 1] - min) / range) * (height - pad * 2);
2028
+ const fillPath = fillOpacity > 0 ? `M ${firstX},${height} L ${points.split(" ").join(" L ")} L ${lastX},${height} Z` : void 0;
2029
+ return /* @__PURE__ */ jsxs(
2030
+ "svg",
2031
+ {
2032
+ width,
2033
+ height,
2034
+ viewBox: `0 0 ${width} ${height}`,
2035
+ className: cn("shrink-0", className),
2036
+ "aria-hidden": "true",
2037
+ children: [
2038
+ fillOpacity > 0 && /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("linearGradient", { id: gradId, x1: "0", y1: "0", x2: "0", y2: "1", children: [
2039
+ /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: color, stopOpacity: fillOpacity }),
2040
+ /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: color, stopOpacity: 0 })
2041
+ ] }) }),
2042
+ fillPath && /* @__PURE__ */ jsx("path", { d: fillPath, fill: `url(#${gradId})` }),
2043
+ /* @__PURE__ */ jsx(
2044
+ "polyline",
2045
+ {
2046
+ points,
2047
+ fill: "none",
2048
+ stroke: color,
2049
+ strokeWidth: 1.5,
2050
+ strokeLinecap: "round",
2051
+ strokeLinejoin: "round"
2052
+ }
2053
+ ),
2054
+ showDots && /* @__PURE__ */ jsxs(Fragment, { children: [
2055
+ /* @__PURE__ */ jsx("circle", { cx: firstX, cy: firstY, r: 2, fill: color }),
2056
+ /* @__PURE__ */ jsx("circle", { cx: lastX, cy: lastY, r: 2, fill: color })
2057
+ ] })
2058
+ ]
2059
+ }
2060
+ );
2061
+ }
2062
+ var statusBorder = {
2063
+ ok: "border-l-[hsl(var(--status-ok))]",
2064
+ warning: "border-l-[hsl(var(--status-warning))]",
2065
+ critical: "border-l-[hsl(var(--status-critical))]"
2066
+ };
2067
+ var trendColors = {
2068
+ good: "text-[hsl(var(--status-ok))]",
2069
+ bad: "text-[hsl(var(--status-critical))]"
2070
+ };
2071
+ function MetricCard({
2072
+ label,
2073
+ value,
2074
+ format,
2075
+ previousValue,
2076
+ trendDirection,
2077
+ icon: Icon,
2078
+ status,
2079
+ sparklineData,
2080
+ className
2081
+ }) {
2082
+ const reduced = useReducedMotion();
2083
+ let trendPct = null;
2084
+ let trendUp = false;
2085
+ let trendColorKey = null;
2086
+ if (previousValue != null && previousValue !== 0) {
2087
+ trendPct = (value - previousValue) / Math.abs(previousValue) * 100;
2088
+ trendUp = trendPct >= 0;
2089
+ if (trendDirection) {
2090
+ const isUp = trendPct >= 0;
2091
+ if (trendDirection === "up-good") trendColorKey = isUp ? "good" : "bad";
2092
+ else if (trendDirection === "up-bad") trendColorKey = isUp ? "bad" : "good";
2093
+ else if (trendDirection === "down-good") trendColorKey = isUp ? "bad" : "good";
2094
+ else if (trendDirection === "down-bad") trendColorKey = isUp ? "good" : "bad";
2095
+ }
2096
+ }
2097
+ return /* @__PURE__ */ jsx(
2098
+ motion.div,
2099
+ {
2100
+ initial: reduced ? false : { opacity: 0, y: 8 },
2101
+ animate: { opacity: 1, y: 0 },
2102
+ transition: { duration: 0.2, ease: "easeOut" },
2103
+ className: cn(
2104
+ "relative rounded-2xl border border-[hsl(var(--border-subtle))] bg-[hsl(var(--bg-surface))]",
2105
+ "p-5 shadow-sm border-l-[3px]",
2106
+ status ? statusBorder[status] : "border-l-[hsl(var(--border-subtle))]",
2107
+ className
2108
+ ),
2109
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
2110
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
2111
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-1", children: [
2112
+ Icon && /* @__PURE__ */ jsx(Icon, { className: "size-4 shrink-0 text-[hsl(var(--text-tertiary))]" }),
2113
+ /* @__PURE__ */ jsx("span", { className: "text-[0.75rem] font-medium text-[hsl(var(--text-secondary))] truncate", children: label })
2114
+ ] }),
2115
+ /* @__PURE__ */ jsxs("div", { className: "flex items-baseline gap-2", children: [
2116
+ /* @__PURE__ */ jsx("span", { className: "text-2xl font-semibold text-[hsl(var(--text-primary))] tabular-nums", children: /* @__PURE__ */ jsx(AnimatedCounter, { value, format }) }),
2117
+ trendPct != null && /* @__PURE__ */ jsxs(
2118
+ "span",
2119
+ {
2120
+ className: cn(
2121
+ "inline-flex items-center gap-0.5 text-[0.6875rem] font-medium tabular-nums",
2122
+ trendColorKey ? trendColors[trendColorKey] : "text-[hsl(var(--text-tertiary))]"
2123
+ ),
2124
+ children: [
2125
+ trendUp ? /* @__PURE__ */ jsx(TrendingUp, { className: "size-3" }) : /* @__PURE__ */ jsx(TrendingDown, { className: "size-3" }),
2126
+ Math.abs(trendPct).toFixed(1),
2127
+ "%"
2128
+ ]
2129
+ }
2130
+ )
2131
+ ] })
2132
+ ] }),
2133
+ sparklineData && sparklineData.length >= 2 && /* @__PURE__ */ jsx(
2134
+ Sparkline,
2135
+ {
2136
+ data: sparklineData,
2137
+ width: 72,
2138
+ height: 28,
2139
+ color: status === "critical" ? "hsl(var(--status-critical))" : status === "warning" ? "hsl(var(--status-warning))" : "hsl(var(--brand-primary))",
2140
+ fillOpacity: 0.15
2141
+ }
2142
+ )
2143
+ ] })
2144
+ }
2145
+ );
2146
+ }
2147
+ var sizeMap = {
2148
+ sm: "h-1.5",
2149
+ md: "h-2.5",
2150
+ lg: "h-4"
2151
+ };
2152
+ function getBarColor(value, warning, critical) {
2153
+ if (value >= critical) return "hsl(var(--util-high))";
2154
+ if (value >= warning) return "hsl(var(--util-medium))";
2155
+ return "hsl(var(--util-low))";
2156
+ }
2157
+ function getTextClass(value, warning, critical) {
2158
+ if (value >= critical) return "text-[hsl(var(--status-critical))]";
2159
+ if (value >= warning) return "text-[hsl(var(--status-warning))]";
2160
+ return "text-[hsl(var(--text-secondary))]";
2161
+ }
2162
+ function UtilizationBar({
2163
+ value: rawValue,
2164
+ thresholds,
2165
+ label,
2166
+ showValue = true,
2167
+ size = "md",
2168
+ animated = true,
2169
+ className
2170
+ }) {
2171
+ const reduced = useReducedMotion();
2172
+ const value = clamp(rawValue, 0, 100);
2173
+ const warning = thresholds?.warning ?? 70;
2174
+ const critical = thresholds?.critical ?? 90;
2175
+ const [displayWidth, setDisplayWidth] = useState(animated && !reduced ? 0 : value);
2176
+ useEffect(() => {
2177
+ if (!animated || reduced) {
2178
+ setDisplayWidth(value);
2179
+ return;
2180
+ }
2181
+ const raf = requestAnimationFrame(() => setDisplayWidth(value));
2182
+ return () => cancelAnimationFrame(raf);
2183
+ }, [value, animated, reduced]);
2184
+ const barColor = getBarColor(value, warning, critical);
2185
+ const textClass = getTextClass(value, warning, critical);
2186
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2", className), title: `${value.toFixed(1)}%`, children: [
2187
+ label && /* @__PURE__ */ jsx("span", { className: "text-[0.75rem] font-medium text-[hsl(var(--text-secondary))] shrink-0 min-w-[3rem]", children: label }),
2188
+ /* @__PURE__ */ jsx(
2189
+ "div",
2190
+ {
2191
+ className: cn(
2192
+ "flex-1 rounded-full bg-[hsl(var(--bg-elevated))] overflow-hidden",
2193
+ sizeMap[size]
2194
+ ),
2195
+ children: /* @__PURE__ */ jsx(
2196
+ "div",
2197
+ {
2198
+ className: "h-full rounded-full",
2199
+ style: {
2200
+ width: `${displayWidth}%`,
2201
+ backgroundColor: barColor,
2202
+ transition: animated && !reduced ? "width 600ms cubic-bezier(0.4, 0, 0.2, 1)" : "none"
2203
+ }
2204
+ }
2205
+ )
2206
+ }
2207
+ ),
2208
+ showValue && /* @__PURE__ */ jsxs("span", { className: cn("text-[0.75rem] font-medium tabular-nums shrink-0 min-w-[2.5rem] text-right", textClass), children: [
2209
+ value.toFixed(0),
2210
+ "%"
2211
+ ] })
2212
+ ] });
2213
+ }
2214
+ var ARC_START = 135;
2215
+ var ARC_SWEEP = 270;
2216
+ function polarToCartesian(cx, cy, r, angleDeg) {
2217
+ const rad = (angleDeg - 90) * Math.PI / 180;
2218
+ return { x: cx + r * Math.cos(rad), y: cy + r * Math.sin(rad) };
2219
+ }
2220
+ function describeArc(cx, cy, r, startAngle, endAngle) {
2221
+ const start = polarToCartesian(cx, cy, r, endAngle);
2222
+ const end = polarToCartesian(cx, cy, r, startAngle);
2223
+ const largeArc = endAngle - startAngle > 180 ? 1 : 0;
2224
+ return `M ${start.x} ${start.y} A ${r} ${r} 0 ${largeArc} 0 ${end.x} ${end.y}`;
2225
+ }
2226
+ function getArcColor(pct, warning, critical) {
2227
+ if (pct >= critical) return "hsl(var(--util-high))";
2228
+ if (pct >= warning) return "hsl(var(--util-medium))";
2229
+ return "hsl(var(--util-low))";
2230
+ }
2231
+ function ThresholdGauge({
2232
+ value: rawValue,
2233
+ label,
2234
+ thresholds,
2235
+ size = 120,
2236
+ showValue = true,
2237
+ format,
2238
+ className
2239
+ }) {
2240
+ const reduced = useReducedMotion();
2241
+ const value = clamp(rawValue, 0, 100);
2242
+ const warning = thresholds?.warning ?? 70;
2243
+ const critical = thresholds?.critical ?? 90;
2244
+ const [animatedValue, setAnimatedValue] = useState(reduced ? value : 0);
2245
+ useEffect(() => {
2246
+ if (reduced) {
2247
+ setAnimatedValue(value);
2248
+ return;
2249
+ }
2250
+ const start = performance.now();
2251
+ const from = 0;
2252
+ const dur = 600;
2253
+ let raf;
2254
+ function tick(now) {
2255
+ const progress = Math.min((now - start) / dur, 1);
2256
+ const eased = 1 - Math.pow(1 - progress, 3);
2257
+ setAnimatedValue(from + (value - from) * eased);
2258
+ if (progress < 1) raf = requestAnimationFrame(tick);
2259
+ }
2260
+ raf = requestAnimationFrame(tick);
2261
+ return () => cancelAnimationFrame(raf);
2262
+ }, [value, reduced]);
2263
+ const cx = size / 2;
2264
+ const cy = size / 2;
2265
+ const r = (size - 16) / 2;
2266
+ const strokeWidth = Math.max(6, size * 0.08);
2267
+ const warnAngle = ARC_START + warning / 100 * ARC_SWEEP;
2268
+ const critAngle = ARC_START + critical / 100 * ARC_SWEEP;
2269
+ const endAngle = ARC_START + ARC_SWEEP;
2270
+ const greenArc = describeArc(cx, cy, r, ARC_START, warnAngle);
2271
+ const yellowArc = describeArc(cx, cy, r, warnAngle, critAngle);
2272
+ const redArc = describeArc(cx, cy, r, critAngle, endAngle);
2273
+ const valueAngle = ARC_START + animatedValue / 100 * ARC_SWEEP;
2274
+ const valueArc = animatedValue > 0.5 ? describeArc(cx, cy, r, ARC_START, valueAngle) : "";
2275
+ const displayText = format ? format(value) : `${Math.round(value)}%`;
2276
+ return /* @__PURE__ */ jsxs("div", { className: cn("inline-flex flex-col items-center", className), children: [
2277
+ /* @__PURE__ */ jsxs("svg", { width: size, height: size * 0.75, viewBox: `0 0 ${size} ${size * 0.75}`, "aria-hidden": "true", children: [
2278
+ /* @__PURE__ */ jsx("path", { d: greenArc, fill: "none", stroke: "hsl(var(--util-low))", strokeWidth, strokeLinecap: "round", opacity: 0.2 }),
2279
+ /* @__PURE__ */ jsx("path", { d: yellowArc, fill: "none", stroke: "hsl(var(--util-medium))", strokeWidth, strokeLinecap: "round", opacity: 0.2 }),
2280
+ /* @__PURE__ */ jsx("path", { d: redArc, fill: "none", stroke: "hsl(var(--util-high))", strokeWidth, strokeLinecap: "round", opacity: 0.2 }),
2281
+ valueArc && /* @__PURE__ */ jsx(
2282
+ "path",
2283
+ {
2284
+ d: valueArc,
2285
+ fill: "none",
2286
+ stroke: getArcColor(animatedValue, warning, critical),
2287
+ strokeWidth,
2288
+ strokeLinecap: "round"
2289
+ }
2290
+ ),
2291
+ showValue && /* @__PURE__ */ jsx(
2292
+ "text",
2293
+ {
2294
+ x: cx,
2295
+ y: cy - 2,
2296
+ textAnchor: "middle",
2297
+ dominantBaseline: "central",
2298
+ fill: "hsl(var(--text-primary))",
2299
+ fontSize: size * 0.2,
2300
+ fontWeight: 600,
2301
+ fontFamily: "inherit",
2302
+ className: "tabular-nums",
2303
+ children: displayText
2304
+ }
2305
+ )
2306
+ ] }),
2307
+ label && /* @__PURE__ */ jsx("span", { className: "text-[0.75rem] font-medium text-[hsl(var(--text-secondary))] mt-1", children: label })
2308
+ ] });
2309
+ }
2310
+ var severityDot = {
2311
+ critical: "bg-[hsl(var(--status-critical))]",
2312
+ warning: "bg-[hsl(var(--status-warning))]",
2313
+ info: "bg-[hsl(var(--brand-primary))]",
2314
+ ok: "bg-[hsl(var(--status-ok))]"
2315
+ };
2316
+ var severityRing = {
2317
+ critical: "ring-[hsl(var(--status-critical))]/30",
2318
+ warning: "ring-[hsl(var(--status-warning))]/30",
2319
+ info: "ring-[hsl(var(--brand-primary))]/30",
2320
+ ok: "ring-[hsl(var(--status-ok))]/30"
2321
+ };
2322
+ function formatTime(iso) {
2323
+ try {
2324
+ const d = new Date(iso);
2325
+ return d.toLocaleTimeString(void 0, { hour: "2-digit", minute: "2-digit" });
2326
+ } catch {
2327
+ return iso;
2328
+ }
2329
+ }
2330
+ function SeverityTimeline({
2331
+ events,
2332
+ maxVisible = 20,
2333
+ onEventClick,
2334
+ className
2335
+ }) {
2336
+ const reduced = useReducedMotion();
2337
+ const scrollRef = useRef(null);
2338
+ const visible = events.slice(0, maxVisible);
2339
+ if (visible.length === 0) return null;
2340
+ return /* @__PURE__ */ jsx(
2341
+ "div",
2342
+ {
2343
+ ref: scrollRef,
2344
+ className: cn(
2345
+ "relative overflow-x-auto scrollbar-thin py-2",
2346
+ className
2347
+ ),
2348
+ children: /* @__PURE__ */ jsx("div", { className: "flex items-start gap-0 min-w-max", children: /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: visible.map((ev, i) => /* @__PURE__ */ jsxs(
2349
+ motion.div,
2350
+ {
2351
+ initial: reduced ? false : { opacity: 0, scale: 0.8 },
2352
+ animate: { opacity: 1, scale: 1 },
2353
+ exit: { opacity: 0, scale: 0.8 },
2354
+ transition: { duration: 0.15, delay: reduced ? 0 : i * 0.03 },
2355
+ className: "flex flex-col items-center relative",
2356
+ style: { minWidth: 64 },
2357
+ children: [
2358
+ i < visible.length - 1 && /* @__PURE__ */ jsx(
2359
+ "div",
2360
+ {
2361
+ className: "absolute top-[11px] left-1/2 h-px bg-[hsl(var(--border-default))]",
2362
+ style: { width: 64 }
2363
+ }
2364
+ ),
2365
+ /* @__PURE__ */ jsx(
2366
+ "button",
2367
+ {
2368
+ type: "button",
2369
+ onClick: () => onEventClick?.(ev),
2370
+ className: cn(
2371
+ "relative z-10 size-[10px] rounded-full ring-4 shrink-0",
2372
+ "transition-transform hover:scale-125 cursor-pointer",
2373
+ severityDot[ev.severity] ?? severityDot.info,
2374
+ severityRing[ev.severity] ?? severityRing.info
2375
+ ),
2376
+ title: ev.detail ?? ev.label,
2377
+ "aria-label": `${ev.label} \u2014 ${ev.severity}`
2378
+ }
2379
+ ),
2380
+ /* @__PURE__ */ jsx("span", { className: "mt-1.5 text-[0.6875rem] font-medium text-[hsl(var(--text-primary))] text-center max-w-[56px] truncate", children: ev.label }),
2381
+ /* @__PURE__ */ jsx("span", { className: "text-[0.625rem] text-[hsl(var(--text-tertiary))] tabular-nums", children: formatTime(ev.time) })
2382
+ ]
2383
+ },
2384
+ `${ev.time}-${i}`
2385
+ )) }) })
2386
+ }
2387
+ );
2388
+ }
2389
+ var levelBorder = {
2390
+ error: "border-l-[hsl(var(--status-critical))]",
2391
+ warn: "border-l-[hsl(var(--status-warning))]",
2392
+ info: "border-l-[hsl(var(--brand-primary))]",
2393
+ debug: "border-l-[hsl(var(--text-tertiary))]",
2394
+ trace: "border-l-[hsl(var(--text-disabled))]"
2395
+ };
2396
+ var levelText = {
2397
+ error: "text-[hsl(var(--status-critical))]",
2398
+ warn: "text-[hsl(var(--status-warning))]",
2399
+ info: "text-[hsl(var(--brand-primary))]",
2400
+ debug: "text-[hsl(var(--text-tertiary))]",
2401
+ trace: "text-[hsl(var(--text-disabled))]"
2402
+ };
2403
+ var levelLabel = {
2404
+ error: "ERR",
2405
+ warn: "WRN",
2406
+ info: "INF",
2407
+ debug: "DBG",
2408
+ trace: "TRC"
2409
+ };
2410
+ function formatTs(iso) {
2411
+ try {
2412
+ const d = new Date(iso);
2413
+ return d.toLocaleTimeString(void 0, { hour: "2-digit", minute: "2-digit", second: "2-digit" });
2414
+ } catch {
2415
+ return iso;
2416
+ }
2417
+ }
2418
+ function LogViewer({
2419
+ entries,
2420
+ maxHeight = 400,
2421
+ autoScroll = true,
2422
+ showTimestamps = true,
2423
+ showLevel = true,
2424
+ onEntryClick,
2425
+ className
2426
+ }) {
2427
+ const reduced = useReducedMotion();
2428
+ const containerRef = useRef(null);
2429
+ const [isAtBottom, setIsAtBottom] = useState(true);
2430
+ const [filter, setFilter] = useState("");
2431
+ const [newCount, setNewCount] = useState(0);
2432
+ const prevLenRef = useRef(entries.length);
2433
+ const checkAtBottom = useCallback(() => {
2434
+ const el = containerRef.current;
2435
+ if (!el) return;
2436
+ const atBottom = el.scrollHeight - el.scrollTop - el.clientHeight < 32;
2437
+ setIsAtBottom(atBottom);
2438
+ if (atBottom) setNewCount(0);
2439
+ }, []);
2440
+ useEffect(() => {
2441
+ const added = entries.length - prevLenRef.current;
2442
+ prevLenRef.current = entries.length;
2443
+ if (added > 0 && !isAtBottom) {
2444
+ setNewCount((prev) => prev + added);
2445
+ }
2446
+ if (autoScroll && isAtBottom && containerRef.current) {
2447
+ containerRef.current.scrollTop = containerRef.current.scrollHeight;
2448
+ }
2449
+ }, [entries.length, autoScroll, isAtBottom]);
2450
+ const scrollToBottom = useCallback(() => {
2451
+ if (containerRef.current) {
2452
+ containerRef.current.scrollTop = containerRef.current.scrollHeight;
2453
+ setNewCount(0);
2454
+ setIsAtBottom(true);
2455
+ }
2456
+ }, []);
2457
+ const lowerFilter = filter.toLowerCase();
2458
+ const filtered = filter ? entries.filter(
2459
+ (e) => e.message.toLowerCase().includes(lowerFilter) || e.source?.toLowerCase().includes(lowerFilter) || e.level.includes(lowerFilter)
2460
+ ) : entries;
2461
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative rounded-xl border border-[hsl(var(--border-subtle))] bg-[hsl(var(--bg-surface))] overflow-hidden", className), children: [
2462
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-3 py-2 border-b border-[hsl(var(--border-subtle))] bg-[hsl(var(--bg-elevated))]", children: [
2463
+ /* @__PURE__ */ jsx(Search, { className: "size-3.5 text-[hsl(var(--text-tertiary))] shrink-0" }),
2464
+ /* @__PURE__ */ jsx(
2465
+ "input",
2466
+ {
2467
+ type: "text",
2468
+ value: filter,
2469
+ onChange: (e) => setFilter(e.target.value),
2470
+ placeholder: "Filter logs...",
2471
+ className: "flex-1 bg-transparent text-[0.75rem] text-[hsl(var(--text-primary))] placeholder:text-[hsl(var(--text-disabled))] outline-none font-mono"
2472
+ }
2473
+ ),
2474
+ filter && /* @__PURE__ */ jsxs("span", { className: "text-[0.6875rem] text-[hsl(var(--text-tertiary))] tabular-nums shrink-0", children: [
2475
+ filtered.length,
2476
+ " / ",
2477
+ entries.length
2478
+ ] })
2479
+ ] }),
2480
+ /* @__PURE__ */ jsx(
2481
+ "div",
2482
+ {
2483
+ ref: containerRef,
2484
+ onScroll: checkAtBottom,
2485
+ className: "overflow-y-auto",
2486
+ style: { maxHeight },
2487
+ children: filtered.map((entry, i) => /* @__PURE__ */ jsxs(
2488
+ "div",
2489
+ {
2490
+ onClick: () => onEntryClick?.(entry),
2491
+ className: cn(
2492
+ "flex items-start gap-2 px-3 py-1 border-l-2 font-mono text-[0.75rem] leading-5",
2493
+ "hover:bg-[hsl(var(--bg-elevated))] transition-colors",
2494
+ onEntryClick && "cursor-pointer",
2495
+ levelBorder[entry.level] ?? levelBorder.info
2496
+ ),
2497
+ children: [
2498
+ showTimestamps && /* @__PURE__ */ jsx("span", { className: "text-[hsl(var(--text-tertiary))] tabular-nums shrink-0 select-all", children: formatTs(entry.time) }),
2499
+ showLevel && /* @__PURE__ */ jsx("span", { className: cn("font-semibold shrink-0 w-[2.5ch]", levelText[entry.level] ?? levelText.info), children: levelLabel[entry.level] ?? entry.level.toUpperCase().slice(0, 3) }),
2500
+ entry.source && /* @__PURE__ */ jsxs("span", { className: "text-[hsl(var(--text-secondary))] shrink-0", children: [
2501
+ "[",
2502
+ entry.source,
2503
+ "]"
2504
+ ] }),
2505
+ /* @__PURE__ */ jsx("span", { className: "text-[hsl(var(--text-primary))] break-all min-w-0", children: entry.message })
2506
+ ]
2507
+ },
2508
+ `${entry.time}-${i}`
2509
+ ))
2510
+ }
2511
+ ),
2512
+ /* @__PURE__ */ jsx(AnimatePresence, { children: newCount > 0 && !isAtBottom && /* @__PURE__ */ jsxs(
2513
+ motion.button,
2514
+ {
2515
+ type: "button",
2516
+ initial: reduced ? false : { opacity: 0, y: 8 },
2517
+ animate: { opacity: 1, y: 0 },
2518
+ exit: { opacity: 0, y: 8 },
2519
+ transition: { duration: 0.15 },
2520
+ onClick: scrollToBottom,
2521
+ className: cn(
2522
+ "absolute bottom-3 left-1/2 -translate-x-1/2 z-10",
2523
+ "inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full",
2524
+ "bg-[hsl(var(--brand-primary))] text-[hsl(var(--text-on-brand))]",
2525
+ "text-[0.6875rem] font-medium shadow-lg cursor-pointer",
2526
+ "hover:opacity-90 transition-opacity"
2527
+ ),
2528
+ children: [
2529
+ /* @__PURE__ */ jsx(ArrowDown, { className: "size-3" }),
2530
+ newCount,
2531
+ " new ",
2532
+ newCount === 1 ? "entry" : "entries"
2533
+ ]
2534
+ }
2535
+ ) })
2536
+ ] });
2537
+ }
2538
+ var statusColor = {
2539
+ up: "bg-[hsl(var(--status-ok))]",
2540
+ down: "bg-[hsl(var(--status-critical))]",
2541
+ disabled: "bg-[hsl(var(--text-disabled))]",
2542
+ error: "bg-[hsl(var(--status-warning))]"
2543
+ };
2544
+ var statusHover = {
2545
+ up: "hover:ring-[hsl(var(--status-ok))]/40",
2546
+ down: "hover:ring-[hsl(var(--status-critical))]/40",
2547
+ disabled: "hover:ring-[hsl(var(--text-disabled))]/40",
2548
+ error: "hover:ring-[hsl(var(--status-warning))]/40"
2549
+ };
2550
+ var sizeClasses5 = {
2551
+ sm: "size-3 rounded-[2px]",
2552
+ md: "size-5 rounded-[3px]"
2553
+ };
2554
+ function PortStatusGrid({
2555
+ ports,
2556
+ columns,
2557
+ size = "sm",
2558
+ onPortClick,
2559
+ className
2560
+ }) {
2561
+ const reduced = useReducedMotion();
2562
+ const gridStyle = columns ? { gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))` } : { gridTemplateColumns: `repeat(auto-fill, minmax(${size === "sm" ? "12px" : "20px"}, 1fr))` };
2563
+ return /* @__PURE__ */ jsx(
2564
+ "div",
2565
+ {
2566
+ className: cn("grid gap-1", className),
2567
+ style: gridStyle,
2568
+ role: "grid",
2569
+ "aria-label": "Port status grid",
2570
+ children: ports.map((port, i) => {
2571
+ const tooltipParts = [port.label];
2572
+ if (port.speed) tooltipParts.push(port.speed);
2573
+ if (port.utilization != null) tooltipParts.push(`${port.utilization.toFixed(0)}%`);
2574
+ tooltipParts.push(port.status);
2575
+ return /* @__PURE__ */ jsx(
2576
+ motion.button,
2577
+ {
2578
+ type: "button",
2579
+ initial: reduced ? false : { opacity: 0, scale: 0.5 },
2580
+ animate: { opacity: 1, scale: 1 },
2581
+ transition: { duration: 0.1, delay: reduced ? 0 : Math.min(i * 8e-3, 0.4) },
2582
+ onClick: () => onPortClick?.(port),
2583
+ title: tooltipParts.join(" \xB7 "),
2584
+ "aria-label": `${port.label}: ${port.status}`,
2585
+ className: cn(
2586
+ "transition-all cursor-pointer ring-0 hover:ring-2",
2587
+ sizeClasses5[size],
2588
+ statusColor[port.status] ?? statusColor.disabled,
2589
+ statusHover[port.status] ?? statusHover.disabled
2590
+ )
2591
+ },
2592
+ port.id
2593
+ );
2594
+ })
2595
+ }
2596
+ );
2597
+ }
2598
+ var defaultRanges = [
2599
+ { label: "1h", value: "1h", seconds: 3600 },
2600
+ { label: "6h", value: "6h", seconds: 21600 },
2601
+ { label: "24h", value: "24h", seconds: 86400 },
2602
+ { label: "7d", value: "7d", seconds: 604800 },
2603
+ { label: "30d", value: "30d", seconds: 2592e3 }
2604
+ ];
2605
+ function TimeRangeSelector({
2606
+ value,
2607
+ onChange,
2608
+ ranges = defaultRanges,
2609
+ className
2610
+ }) {
2611
+ const reduced = useReducedMotion();
2612
+ return /* @__PURE__ */ jsx(
2613
+ "div",
2614
+ {
2615
+ className: cn(
2616
+ "inline-flex items-center rounded-lg bg-[hsl(var(--bg-elevated))] p-0.5",
2617
+ "border border-[hsl(var(--border-subtle))]",
2618
+ className
2619
+ ),
2620
+ role: "radiogroup",
2621
+ "aria-label": "Time range",
2622
+ children: ranges.map((range) => {
2623
+ const isActive = range.value === value;
2624
+ return /* @__PURE__ */ jsxs(
2625
+ "button",
2626
+ {
2627
+ type: "button",
2628
+ role: "radio",
2629
+ "aria-checked": isActive,
2630
+ onClick: () => onChange(range.value, range),
2631
+ className: cn(
2632
+ "relative px-3 py-1 text-[0.75rem] font-medium rounded-md cursor-pointer",
2633
+ "transition-colors duration-150",
2634
+ isActive ? "text-[hsl(var(--text-on-brand))]" : "text-[hsl(var(--text-secondary))] hover:text-[hsl(var(--text-primary))]"
2635
+ ),
2636
+ children: [
2637
+ isActive && /* @__PURE__ */ jsx(
2638
+ motion.span,
2639
+ {
2640
+ layoutId: "time-range-active",
2641
+ className: "absolute inset-0 rounded-md bg-[hsl(var(--brand-primary))]",
2642
+ transition: reduced ? { duration: 0 } : { type: "spring", stiffness: 400, damping: 30 }
2643
+ }
2644
+ ),
2645
+ /* @__PURE__ */ jsx("span", { className: "relative z-10", children: range.label })
2646
+ ]
2647
+ },
2648
+ range.value
2649
+ );
2650
+ })
2651
+ }
2652
+ );
2653
+ }
2654
+ var statusDot = {
2655
+ active: "bg-[hsl(var(--status-ok))]",
2656
+ idle: "bg-[hsl(var(--text-tertiary))]",
2657
+ error: "bg-[hsl(var(--status-critical))]",
2658
+ disabled: "bg-[hsl(var(--text-disabled))]"
2659
+ };
2660
+ var statusBorder2 = {
2661
+ active: "border-[hsl(var(--status-ok))]/30",
2662
+ idle: "border-[hsl(var(--border-default))]",
2663
+ error: "border-[hsl(var(--status-critical))]/30",
2664
+ disabled: "border-[hsl(var(--border-subtle))]"
2665
+ };
2666
+ var statusBg = {
2667
+ active: "bg-[hsl(var(--bg-surface))]",
2668
+ idle: "bg-[hsl(var(--bg-surface))]",
2669
+ error: "bg-[hsl(var(--status-critical))]/5",
2670
+ disabled: "bg-[hsl(var(--bg-elevated))]"
2671
+ };
2672
+ function PipelineStage({
2673
+ stages,
2674
+ onStageClick,
2675
+ className
2676
+ }) {
2677
+ const reduced = useReducedMotion();
2678
+ return /* @__PURE__ */ jsx("div", { className: cn("flex items-center gap-0 overflow-x-auto", className), children: stages.map((stage, i) => {
2679
+ const Icon = stage.icon;
2680
+ const isDisabled = stage.status === "disabled";
2681
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center shrink-0", children: [
2682
+ i > 0 && /* @__PURE__ */ jsx(
2683
+ motion.div,
2684
+ {
2685
+ initial: reduced ? false : { opacity: 0, x: -4 },
2686
+ animate: { opacity: 1, x: 0 },
2687
+ transition: { duration: 0.15, delay: reduced ? 0 : i * 0.05 },
2688
+ className: "px-1",
2689
+ children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-4 text-[hsl(var(--text-tertiary))]" })
2690
+ }
2691
+ ),
2692
+ /* @__PURE__ */ jsxs(
2693
+ motion.button,
2694
+ {
2695
+ type: "button",
2696
+ initial: reduced ? false : { opacity: 0, y: 6 },
2697
+ animate: { opacity: 1, y: 0 },
2698
+ transition: { duration: 0.2, delay: reduced ? 0 : i * 0.06 },
2699
+ onClick: () => onStageClick?.(stage, i),
2700
+ disabled: isDisabled && !onStageClick,
2701
+ className: cn(
2702
+ "flex flex-col items-start gap-1.5 px-4 py-3 rounded-xl border",
2703
+ "transition-all min-w-[120px]",
2704
+ statusBorder2[stage.status],
2705
+ statusBg[stage.status],
2706
+ onStageClick && !isDisabled && "cursor-pointer hover:bg-[hsl(var(--bg-elevated))]",
2707
+ isDisabled && "opacity-50"
2708
+ ),
2709
+ children: [
2710
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 w-full", children: [
2711
+ Icon && /* @__PURE__ */ jsx(Icon, { className: cn("size-3.5 shrink-0", isDisabled ? "text-[hsl(var(--text-disabled))]" : "text-[hsl(var(--text-secondary))]") }),
2712
+ /* @__PURE__ */ jsx("span", { className: cn(
2713
+ "text-[0.8125rem] font-medium truncate",
2714
+ isDisabled ? "text-[hsl(var(--text-disabled))]" : "text-[hsl(var(--text-primary))]"
2715
+ ), children: stage.name }),
2716
+ /* @__PURE__ */ jsx(
2717
+ "span",
2718
+ {
2719
+ className: cn(
2720
+ "size-2 rounded-full shrink-0 ml-auto",
2721
+ statusDot[stage.status],
2722
+ stage.status === "active" && "animate-pulse"
2723
+ )
2724
+ }
2725
+ )
2726
+ ] }),
2727
+ stage.metric && /* @__PURE__ */ jsxs("div", { className: "flex items-baseline gap-1", children: [
2728
+ /* @__PURE__ */ jsx("span", { className: "text-[0.875rem] font-semibold text-[hsl(var(--text-primary))] tabular-nums", children: stage.metric.value }),
2729
+ /* @__PURE__ */ jsx("span", { className: "text-[0.625rem] text-[hsl(var(--text-tertiary))]", children: stage.metric.label })
2730
+ ] })
2731
+ ]
2732
+ }
2733
+ )
2734
+ ] }, `${stage.name}-${i}`);
2735
+ }) });
2736
+ }
2737
+ var dayColor = {
2738
+ ok: "bg-[hsl(var(--status-ok))]",
2739
+ degraded: "bg-[hsl(var(--status-warning))]",
2740
+ outage: "bg-[hsl(var(--status-critical))]",
2741
+ "no-data": "bg-[hsl(var(--text-disabled))]"
2742
+ };
2743
+ var dayHover = {
2744
+ ok: "hover:bg-[hsl(var(--status-ok))]/80",
2745
+ degraded: "hover:bg-[hsl(var(--status-warning))]/80",
2746
+ outage: "hover:bg-[hsl(var(--status-critical))]/80",
2747
+ "no-data": "hover:bg-[hsl(var(--text-disabled))]/80"
2748
+ };
2749
+ function formatDate(dateStr) {
2750
+ try {
2751
+ const d = /* @__PURE__ */ new Date(dateStr + "T00:00:00");
2752
+ return d.toLocaleDateString(void 0, { month: "short", day: "numeric" });
2753
+ } catch {
2754
+ return dateStr;
2755
+ }
2756
+ }
2757
+ function UptimeTracker({
2758
+ days,
2759
+ showPercentage = true,
2760
+ label,
2761
+ onDayClick,
2762
+ className
2763
+ }) {
2764
+ const reduced = useReducedMotion();
2765
+ const daysWithUptime = days.filter((d) => d.uptime != null);
2766
+ const overallUptime = daysWithUptime.length > 0 ? daysWithUptime.reduce((sum, d) => sum + (d.uptime ?? 0), 0) / daysWithUptime.length : null;
2767
+ return /* @__PURE__ */ jsxs("div", { className: cn("space-y-2", className), children: [
2768
+ (label || showPercentage) && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
2769
+ label && /* @__PURE__ */ jsx("span", { className: "text-[0.8125rem] font-medium text-[hsl(var(--text-primary))]", children: label }),
2770
+ showPercentage && overallUptime != null && /* @__PURE__ */ jsxs("span", { className: cn(
2771
+ "text-[0.8125rem] font-semibold tabular-nums",
2772
+ overallUptime >= 99.9 ? "text-[hsl(var(--status-ok))]" : overallUptime >= 99 ? "text-[hsl(var(--status-warning))]" : "text-[hsl(var(--status-critical))]"
2773
+ ), children: [
2774
+ overallUptime.toFixed(2),
2775
+ "% uptime"
2776
+ ] })
2777
+ ] }),
2778
+ /* @__PURE__ */ jsx("div", { className: "flex items-end gap-px h-8", children: days.map((day, i) => {
2779
+ const tooltip = [
2780
+ formatDate(day.date),
2781
+ day.uptime != null ? `${day.uptime.toFixed(1)}%` : day.status
2782
+ ].join(" \u2014 ");
2783
+ return /* @__PURE__ */ jsx(
2784
+ motion.button,
2785
+ {
2786
+ type: "button",
2787
+ initial: reduced ? false : { scaleY: 0 },
2788
+ animate: { scaleY: 1 },
2789
+ transition: { duration: 0.15, delay: reduced ? 0 : Math.min(i * 5e-3, 0.3) },
2790
+ style: { originY: "100%" },
2791
+ onClick: () => onDayClick?.(day),
2792
+ title: tooltip,
2793
+ "aria-label": tooltip,
2794
+ className: cn(
2795
+ "flex-1 min-w-[2px] h-full rounded-[1px] transition-opacity cursor-pointer",
2796
+ dayColor[day.status] ?? dayColor["no-data"],
2797
+ dayHover[day.status] ?? dayHover["no-data"]
2798
+ )
2799
+ },
2800
+ day.date
2801
+ );
2802
+ }) }),
2803
+ days.length > 0 && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
2804
+ /* @__PURE__ */ jsx("span", { className: "text-[0.625rem] text-[hsl(var(--text-tertiary))]", children: formatDate(days[0].date) }),
2805
+ /* @__PURE__ */ jsx("span", { className: "text-[0.625rem] text-[hsl(var(--text-tertiary))]", children: formatDate(days[days.length - 1].date) })
2806
+ ] })
2807
+ ] });
2808
+ }
2809
+
2810
+ export { AnimatedCounter, Avatar, Badge, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ConfirmDialog, DataTable, DropdownMenu, EmptyState, FilterPill, LogViewer, MetricCard, PipelineStage, Popover, PortStatusGrid, Progress, RadioGroup, SeverityTimeline, Sheet, Skeleton, SkeletonCard, SkeletonText, Slider, Sparkline, StatusBadge, StatusPulse, SuccessCheckmark, Tabs, ThresholdGauge, TimeRangeSelector, Toaster, Tooltip2 as Tooltip, TruncatedText, UptimeTracker, UtilizationBar, createBadgeVariant, defaultPulseConfigMap, defaultStatusMap };
2811
+ //# sourceMappingURL=index.js.map
2812
+ //# sourceMappingURL=index.js.map