@tollerud/ui 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,2750 @@
1
+ 'use strict';
2
+
3
+ var clsx = require('clsx');
4
+ var tailwindMerge = require('tailwind-merge');
5
+ var React2 = require('react');
6
+ var jsxRuntime = require('react/jsx-runtime');
7
+ var framerMotion = require('framer-motion');
8
+ var DialogPrimitive = require('@radix-ui/react-dialog');
9
+ var lucideReact = require('lucide-react');
10
+ var TooltipPrimitive = require('@radix-ui/react-tooltip');
11
+ var TabsPrimitive = require('@radix-ui/react-tabs');
12
+ var ProgressPrimitive = require('@radix-ui/react-progress');
13
+ var sonner = require('sonner');
14
+ var DropdownMenuPrimitive = require('@radix-ui/react-dropdown-menu');
15
+
16
+ function _interopNamespace(e) {
17
+ if (e && e.__esModule) return e;
18
+ var n = Object.create(null);
19
+ if (e) {
20
+ Object.keys(e).forEach(function (k) {
21
+ if (k !== 'default') {
22
+ var d = Object.getOwnPropertyDescriptor(e, k);
23
+ Object.defineProperty(n, k, d.get ? d : {
24
+ enumerable: true,
25
+ get: function () { return e[k]; }
26
+ });
27
+ }
28
+ });
29
+ }
30
+ n.default = e;
31
+ return Object.freeze(n);
32
+ }
33
+
34
+ var React2__namespace = /*#__PURE__*/_interopNamespace(React2);
35
+ var DialogPrimitive__namespace = /*#__PURE__*/_interopNamespace(DialogPrimitive);
36
+ var TooltipPrimitive__namespace = /*#__PURE__*/_interopNamespace(TooltipPrimitive);
37
+ var TabsPrimitive__namespace = /*#__PURE__*/_interopNamespace(TabsPrimitive);
38
+ var ProgressPrimitive__namespace = /*#__PURE__*/_interopNamespace(ProgressPrimitive);
39
+ var DropdownMenuPrimitive__namespace = /*#__PURE__*/_interopNamespace(DropdownMenuPrimitive);
40
+
41
+ // lib/utils.ts
42
+ function cn(...inputs) {
43
+ return tailwindMerge.twMerge(clsx.clsx(inputs));
44
+ }
45
+ var variants = {
46
+ primary: "bg-tollerud-yellow text-tollerud-black border-tollerud-yellow hover:bg-tollerud-yellow-bright hover:shadow-tollerud-glow",
47
+ secondary: "bg-transparent text-tollerud-text-primary border-tollerud-border hover:border-tollerud-text-secondary hover:bg-tollerud-surface-hover",
48
+ ghost: "bg-transparent text-tollerud-text-secondary border-transparent hover:text-tollerud-text-primary hover:bg-tollerud-surface-hover",
49
+ destructive: "bg-tollerud-error text-white border-tollerud-error hover:shadow-[0_0_12px_rgba(239,68,68,0.3)]",
50
+ terminal: 'font-mono text-tollerud-yellow border-[rgba(232,213,0,0.25)] bg-transparent before:content-["\u276F_"] before:opacity-70 hover:border-tollerud-yellow hover:shadow-tollerud-glow hover:bg-[rgba(232,213,0,0.05)]'
51
+ };
52
+ var sizes = {
53
+ sm: "px-3 py-1 text-sm",
54
+ md: "px-4 py-2 text-base",
55
+ lg: "px-6 py-3 text-lg"
56
+ };
57
+ var Button = React2.forwardRef(
58
+ ({ className, variant = "secondary", size = "md", ...props }, ref) => {
59
+ return /* @__PURE__ */ jsxRuntime.jsx(
60
+ "button",
61
+ {
62
+ ref,
63
+ className: cn(
64
+ "inline-flex items-center justify-center gap-2 font-semibold rounded transition-all duration-[150ms] focus-visible:outline-2 focus-visible:outline-tollerud-yellow focus-visible:outline-offset-2",
65
+ "border cursor-pointer",
66
+ "disabled:opacity-50 disabled:pointer-events-none",
67
+ variants[variant],
68
+ sizes[size],
69
+ className
70
+ ),
71
+ ...props
72
+ }
73
+ );
74
+ }
75
+ );
76
+ Button.displayName = "Button";
77
+ var toneStyles = {
78
+ default: { wrapper: "border-tollerud-border bg-tollerud-surface-raised", icon: "text-tollerud-text-muted" },
79
+ accent: { wrapper: "border-tollerud-yellow/30 bg-tollerud-yellow/5", icon: "text-tollerud-yellow" },
80
+ info: { wrapper: "border-blue-500/30 bg-blue-500/5", icon: "text-blue-400" },
81
+ success: { wrapper: "border-green-500/30 bg-green-500/5", icon: "text-green-400" },
82
+ error: { wrapper: "border-red-500/30 bg-red-500/5", icon: "text-red-400" }
83
+ };
84
+ var Alert = React2.forwardRef(
85
+ ({ className, tone = "default", title, icon, children, ...props }, ref) => {
86
+ const styles = toneStyles[tone];
87
+ return /* @__PURE__ */ jsxRuntime.jsxs(
88
+ "div",
89
+ {
90
+ ref,
91
+ role: "alert",
92
+ className: cn(
93
+ "flex gap-3 rounded-md border p-4",
94
+ styles.wrapper,
95
+ className
96
+ ),
97
+ ...props,
98
+ children: [
99
+ icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("mt-0.5 flex-shrink-0 w-[18px] h-[18px]", styles.icon), children: icon }),
100
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
101
+ title && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-tollerud-text-primary leading-snug", children: title }),
102
+ children && /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("text-sm text-tollerud-text-secondary leading-relaxed", title && "mt-1"), children })
103
+ ] })
104
+ ]
105
+ }
106
+ );
107
+ }
108
+ );
109
+ Alert.displayName = "Alert";
110
+ var Card = React2.forwardRef(
111
+ ({ className, accent, density, ...props }, ref) => {
112
+ return /* @__PURE__ */ jsxRuntime.jsx(
113
+ "div",
114
+ {
115
+ ref,
116
+ "data-density": density ?? void 0,
117
+ className: cn(
118
+ "rounded-lg border bg-tollerud-surface-raised p-6 transition-[border-color] duration-[150ms]",
119
+ accent ? "border-tollerud-yellow/25" : "border-tollerud-border",
120
+ "hover:border-tollerud-noir-500",
121
+ className
122
+ ),
123
+ ...props
124
+ }
125
+ );
126
+ }
127
+ );
128
+ Card.displayName = "Card";
129
+ var badgeVariants = {
130
+ default: "bg-tollerud-noir-700 text-tollerud-text-secondary",
131
+ accent: "bg-tollerud-yellow/15 text-tollerud-yellow",
132
+ success: "bg-tollerud-success/15 text-tollerud-success",
133
+ error: "bg-tollerud-error/15 text-tollerud-error",
134
+ info: "bg-tollerud-info/15 text-tollerud-info",
135
+ warning: "bg-tollerud-yellow/15 text-tollerud-warning"
136
+ };
137
+ var Badge = React2.forwardRef(
138
+ ({ className, variant = "default", ...props }, ref) => {
139
+ return /* @__PURE__ */ jsxRuntime.jsx(
140
+ "span",
141
+ {
142
+ ref,
143
+ className: cn(
144
+ "inline-flex items-center px-2 py-0.5 text-xs font-medium rounded",
145
+ "tracking-wide",
146
+ badgeVariants[variant],
147
+ className
148
+ ),
149
+ ...props
150
+ }
151
+ );
152
+ }
153
+ );
154
+ Badge.displayName = "Badge";
155
+ var statusColors = {
156
+ online: "bg-tollerud-success",
157
+ offline: "bg-tollerud-error",
158
+ warning: "bg-tollerud-yellow",
159
+ idle: "bg-tollerud-noir-400"
160
+ };
161
+ var pulseColors = {
162
+ online: "rgba(34,197,94,0.5)",
163
+ warning: "rgba(232,213,0,0.45)",
164
+ offline: "rgba(239,68,68,0.5)"
165
+ };
166
+ var animationKeyframes = `
167
+ @keyframes tollerud-dot-pulse {
168
+ 0%, 100% { box-shadow: 0 0 0 0 var(--pulse-color, rgba(34,197,94,0.5)); }
169
+ 50% { box-shadow: 0 0 0 5px var(--pulse-color, rgba(34,197,94,0)); }
170
+ }
171
+ `;
172
+ var StatusDot = React2.forwardRef(
173
+ ({ className, status = "idle", label, noPulse, ...props }, ref) => {
174
+ const shouldPulse = !noPulse && (status === "online" || status === "warning" || status === "offline");
175
+ const pulseColor = pulseColors[status];
176
+ return /* @__PURE__ */ jsxRuntime.jsxs(
177
+ "span",
178
+ {
179
+ ref,
180
+ className: cn("inline-flex items-center gap-1.5 text-xs font-medium", className),
181
+ ...props,
182
+ children: [
183
+ /* @__PURE__ */ jsxRuntime.jsx("style", { children: animationKeyframes }),
184
+ /* @__PURE__ */ jsxRuntime.jsx(
185
+ framerMotion.motion.span,
186
+ {
187
+ layout: true,
188
+ animate: {
189
+ scaleX: [1, 1.6, 1],
190
+ scaleY: [1, 0.6, 1]
191
+ },
192
+ transition: {
193
+ duration: 0.4,
194
+ ease: "easeOut",
195
+ times: [0, 0.3, 1]
196
+ },
197
+ className: cn(
198
+ "inline-block w-2 h-2 rounded-full",
199
+ statusColors[status],
200
+ shouldPulse && "animate-tollerud-dot-pulse"
201
+ ),
202
+ style: {
203
+ ...shouldPulse && pulseColor ? { "--pulse-color": pulseColor } : {},
204
+ animation: shouldPulse ? "tollerud-dot-pulse 2s ease-in-out infinite" : void 0
205
+ }
206
+ },
207
+ status
208
+ ),
209
+ label && /* @__PURE__ */ jsxRuntime.jsx("span", { children: label })
210
+ ]
211
+ }
212
+ );
213
+ }
214
+ );
215
+ StatusDot.displayName = "StatusDot";
216
+ var Input = React2.forwardRef(
217
+ ({ className, label, error, id, ...props }, ref) => {
218
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
219
+ label && /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: "text-xs font-medium text-tollerud-text-muted", children: label }),
220
+ /* @__PURE__ */ jsxRuntime.jsx(
221
+ "input",
222
+ {
223
+ ref,
224
+ id,
225
+ className: cn(
226
+ "font-sans text-base px-3 py-2 rounded",
227
+ "bg-tollerud-surface-raised border",
228
+ "text-tollerud-text-primary",
229
+ "placeholder:text-tollerud-text-muted",
230
+ "transition-[border-color] duration-[150ms]",
231
+ "focus:outline-none focus:border-tollerud-yellow focus:shadow-[0_0_0_1px_#E8D500]",
232
+ error ? "border-tollerud-error" : "border-tollerud-border",
233
+ className
234
+ ),
235
+ ...props
236
+ }
237
+ ),
238
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-tollerud-error mt-0.5", children: error })
239
+ ] });
240
+ }
241
+ );
242
+ Input.displayName = "Input";
243
+ var CodeBlock = React2.forwardRef(
244
+ ({ className, children, code, promptPrefix, showCopy = true, ...props }, ref) => {
245
+ const [copied, setCopied] = React2.useState(false);
246
+ const content = code ? /* @__PURE__ */ jsxRuntime.jsx("code", { className: "text-tollerud-noir-200", children: code }) : children;
247
+ const handleCopy = React2.useCallback(async () => {
248
+ const text = code ?? (typeof children === "string" ? children : "");
249
+ if (!text) return;
250
+ try {
251
+ await navigator.clipboard.writeText(text);
252
+ } catch {
253
+ const textarea = document.createElement("textarea");
254
+ textarea.value = text;
255
+ textarea.style.position = "fixed";
256
+ textarea.style.opacity = "0";
257
+ document.body.appendChild(textarea);
258
+ textarea.select();
259
+ document.execCommand("copy");
260
+ document.body.removeChild(textarea);
261
+ }
262
+ setCopied(true);
263
+ setTimeout(() => setCopied(false), 1500);
264
+ }, [code, children]);
265
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative group", children: [
266
+ /* @__PURE__ */ jsxRuntime.jsx(
267
+ "pre",
268
+ {
269
+ ref,
270
+ className: cn(
271
+ "font-mono text-sm leading-relaxed overflow-x-auto rounded border p-4",
272
+ "bg-tollerud-noir-900 border-tollerud-border text-tollerud-noir-200",
273
+ className
274
+ ),
275
+ ...props,
276
+ children: content
277
+ }
278
+ ),
279
+ showCopy && /* @__PURE__ */ jsxRuntime.jsx(
280
+ "button",
281
+ {
282
+ onClick: handleCopy,
283
+ className: cn(
284
+ "absolute top-2 right-2 px-2 py-1 rounded text-xs font-medium",
285
+ "opacity-0 group-hover:opacity-100 transition-all",
286
+ "bg-tollerud-noir-800 border border-tollerud-border/30 text-tollerud-text-muted",
287
+ "hover:bg-tollerud-surface-raised hover:text-tollerud-text-primary",
288
+ copied && "opacity-100 bg-tollerud-success/15 text-tollerud-success border-tollerud-success/40"
289
+ ),
290
+ "aria-label": copied ? "Copied" : "Copy code",
291
+ children: copied ? "\u2713 Copied" : "Copy"
292
+ }
293
+ )
294
+ ] });
295
+ }
296
+ );
297
+ CodeBlock.displayName = "CodeBlock";
298
+ var StatCard = React2.forwardRef(
299
+ ({ className, label, value, change, accent, ...props }, ref) => {
300
+ return /* @__PURE__ */ jsxRuntime.jsxs(
301
+ "div",
302
+ {
303
+ ref,
304
+ className: cn(
305
+ "group relative rounded-lg border p-4",
306
+ "bg-tollerud-surface-raised",
307
+ "transition-all duration-200 ease-out",
308
+ "hover:translate-y-[-1px]",
309
+ accent ? "border-tollerud-yellow/20 hover:border-tollerud-yellow/40 hover:shadow-[0_0_20px_rgba(232,213,0,0.08)]" : "border-tollerud-border hover:border-tollerud-noir-500 hover:shadow-[0_4px_12px_rgba(0,0,0,0.3)]",
310
+ className
311
+ ),
312
+ ...props,
313
+ children: [
314
+ accent && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute top-0 left-4 right-4 h-px bg-gradient-to-r from-transparent via-tollerud-yellow/60 to-transparent" }),
315
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-2", children: [
316
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-medium uppercase tracking-wider text-tollerud-text-muted", children: label }),
317
+ change && /* @__PURE__ */ jsxRuntime.jsxs(
318
+ "span",
319
+ {
320
+ className: cn(
321
+ "inline-flex items-center gap-0.5 text-[11px] font-semibold whitespace-nowrap",
322
+ change.direction === "up" ? "text-tollerud-success" : "text-tollerud-error"
323
+ ),
324
+ children: [
325
+ /* @__PURE__ */ jsxRuntime.jsx(
326
+ "svg",
327
+ {
328
+ className: cn(
329
+ "w-3 h-3",
330
+ change.direction === "down" && "rotate-180"
331
+ ),
332
+ viewBox: "0 0 24 24",
333
+ fill: "none",
334
+ stroke: "currentColor",
335
+ strokeWidth: 2.5,
336
+ strokeLinecap: "round",
337
+ strokeLinejoin: "round",
338
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 5v14M5 12l7 7 7-7" })
339
+ }
340
+ ),
341
+ change.value
342
+ ]
343
+ }
344
+ )
345
+ ] }),
346
+ /* @__PURE__ */ jsxRuntime.jsx(
347
+ "p",
348
+ {
349
+ className: cn(
350
+ "text-2xl font-bold tracking-tight mt-1",
351
+ accent ? "text-tollerud-yellow" : "text-tollerud-text-primary"
352
+ ),
353
+ children: value
354
+ }
355
+ )
356
+ ]
357
+ }
358
+ );
359
+ }
360
+ );
361
+ StatCard.displayName = "StatCard";
362
+ var Container = React2.forwardRef(
363
+ ({ className, as: Tag = "div", ...props }, ref) => {
364
+ return /* @__PURE__ */ jsxRuntime.jsx(
365
+ Tag,
366
+ {
367
+ ref,
368
+ className: cn("mx-auto w-full max-w-[1100px] px-6", className),
369
+ ...props
370
+ }
371
+ );
372
+ }
373
+ );
374
+ Container.displayName = "Container";
375
+ var GrainGradient = React2.lazy(
376
+ () => import('@paper-design/shaders-react').then((module) => ({
377
+ default: module.GrainGradient
378
+ }))
379
+ );
380
+ var intensityMap = {
381
+ subtle: 0.24,
382
+ medium: 0.45,
383
+ loud: 0.68
384
+ };
385
+ var speedMap = {
386
+ still: 0,
387
+ slow: 0.45,
388
+ medium: 1,
389
+ fast: 1.8
390
+ };
391
+ var grainMap = {
392
+ none: 0,
393
+ soft: 0.12,
394
+ high: 0.28
395
+ };
396
+ function cx(...classes) {
397
+ return classes.filter(Boolean).join(" ");
398
+ }
399
+ function CssFallback({ preserveCenter = true, noiseOverlay = true }) {
400
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
401
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "tollerud-noir-glow-bg", "aria-hidden": "true" }),
402
+ preserveCenter && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "tollerud-noir-glow-vignette", "aria-hidden": "true" }),
403
+ noiseOverlay && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "tollerud-noir-noise", "aria-hidden": "true" })
404
+ ] });
405
+ }
406
+ function NoirGlowBackground({
407
+ className,
408
+ style,
409
+ shape = "corners",
410
+ intensity = "medium",
411
+ speed = "medium",
412
+ grain = "none",
413
+ softness = 0.76,
414
+ colorBack = "hsl(0, 0%, 0%)",
415
+ colors = ["hsl(54, 85%, 66%)", "hsl(56, 100%, 80%)", "hsl(56, 100%, 50%)"],
416
+ preserveCenter = false,
417
+ noiseOverlay = false,
418
+ forceCssFallback = false,
419
+ inert = true
420
+ }) {
421
+ const wrapperClassName = cx(
422
+ "tollerud-noir-glow-root absolute inset-0 z-0 overflow-hidden",
423
+ inert && "pointer-events-none",
424
+ className
425
+ );
426
+ if (forceCssFallback) {
427
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: wrapperClassName, style, "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(CssFallback, { preserveCenter, noiseOverlay }) });
428
+ }
429
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: wrapperClassName, style, "aria-hidden": "true", children: [
430
+ /* @__PURE__ */ jsxRuntime.jsx(React2.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(CssFallback, { preserveCenter, noiseOverlay }), children: /* @__PURE__ */ jsxRuntime.jsx(
431
+ GrainGradient,
432
+ {
433
+ style: { height: "100%", width: "100%" },
434
+ colorBack,
435
+ softness,
436
+ intensity: intensityMap[intensity],
437
+ noise: grainMap[grain],
438
+ shape,
439
+ offsetX: 0,
440
+ offsetY: 0,
441
+ scale: 1,
442
+ rotation: 0,
443
+ speed: speedMap[speed],
444
+ colors
445
+ }
446
+ ) }),
447
+ preserveCenter && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "tollerud-noir-glow-vignette", "aria-hidden": "true" }),
448
+ noiseOverlay && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "tollerud-noir-noise", "aria-hidden": "true" })
449
+ ] });
450
+ }
451
+ var Kbd = React2.forwardRef(
452
+ ({ className, keys, size = "md", ...props }, ref) => {
453
+ const keyArray = typeof keys === "string" ? [keys] : keys;
454
+ return /* @__PURE__ */ jsxRuntime.jsx(
455
+ "span",
456
+ {
457
+ ref,
458
+ className: cn(
459
+ "tollerud-kbd",
460
+ size === "sm" && "tollerud-kbd--sm",
461
+ className
462
+ ),
463
+ ...props,
464
+ children: keyArray.map((key, i) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tollerud-kbd__key", children: key }, i))
465
+ }
466
+ );
467
+ }
468
+ );
469
+ Kbd.displayName = "Kbd";
470
+ var ActionRow = React2.forwardRef(
471
+ ({
472
+ action,
473
+ highlighted = false,
474
+ showShortcut = true,
475
+ className,
476
+ disabled,
477
+ onClick,
478
+ ...props
479
+ }, ref) => {
480
+ return /* @__PURE__ */ jsxRuntime.jsxs(
481
+ "button",
482
+ {
483
+ ref,
484
+ type: "button",
485
+ disabled: disabled ?? action.disabled,
486
+ onClick: (e) => {
487
+ onClick?.(e);
488
+ action.onSelect?.();
489
+ },
490
+ className: cn(
491
+ "tollerud-action-row",
492
+ highlighted && "tollerud-action-row--highlighted",
493
+ (disabled ?? action.disabled) && "tollerud-action-row--disabled",
494
+ className
495
+ ),
496
+ role: "option",
497
+ "aria-selected": highlighted,
498
+ "aria-disabled": disabled ?? action.disabled,
499
+ ...props,
500
+ children: [
501
+ action.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tollerud-action-row__icon", children: action.icon }),
502
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "tollerud-action-row__content", children: [
503
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tollerud-action-row__label", children: action.label }),
504
+ action.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tollerud-action-row__description", children: action.description })
505
+ ] }),
506
+ showShortcut && action.shortcut && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tollerud-action-row__shortcut", children: /* @__PURE__ */ jsxRuntime.jsx(Kbd, { keys: action.shortcut, size: "sm" }) })
507
+ ]
508
+ }
509
+ );
510
+ }
511
+ );
512
+ ActionRow.displayName = "ActionRow";
513
+ var CommandMenu = React2.forwardRef(
514
+ ({
515
+ open,
516
+ onOpenChange,
517
+ groups,
518
+ placeholder = "Type a command\u2026",
519
+ emptyMessage = "No matching commands",
520
+ className,
521
+ filter: customFilter,
522
+ onAction
523
+ }, ref) => {
524
+ const [query, setQuery] = React2.useState("");
525
+ const [selectedIndex, setSelectedIndex] = React2.useState(0);
526
+ const inputRef = React2.useRef(null);
527
+ const listRef = React2.useRef(null);
528
+ const flatItems = groups.flatMap((g) => g.items);
529
+ const handleKeyDown = React2.useCallback(
530
+ (e) => {
531
+ if (e.key === "Escape") {
532
+ e.preventDefault();
533
+ onOpenChange(false);
534
+ return;
535
+ }
536
+ if (e.key === "ArrowDown") {
537
+ e.preventDefault();
538
+ setSelectedIndex(
539
+ (prev) => prev < flatItems.length - 1 ? prev + 1 : 0
540
+ );
541
+ return;
542
+ }
543
+ if (e.key === "ArrowUp") {
544
+ e.preventDefault();
545
+ setSelectedIndex(
546
+ (prev) => prev > 0 ? prev - 1 : flatItems.length - 1
547
+ );
548
+ return;
549
+ }
550
+ if (e.key === "Enter") {
551
+ e.preventDefault();
552
+ const item = flatItems[selectedIndex];
553
+ if (item && !item.disabled) {
554
+ item.onSelect?.();
555
+ onAction?.(item);
556
+ onOpenChange(false);
557
+ }
558
+ return;
559
+ }
560
+ },
561
+ [flatItems, selectedIndex, onOpenChange, onAction]
562
+ );
563
+ React2.useEffect(() => {
564
+ function handleGlobalKey(e) {
565
+ if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") {
566
+ e.preventDefault();
567
+ onOpenChange(!open);
568
+ }
569
+ }
570
+ document.addEventListener("keydown", handleGlobalKey);
571
+ return () => document.removeEventListener("keydown", handleGlobalKey);
572
+ }, [open, onOpenChange]);
573
+ React2.useEffect(() => {
574
+ if (open) {
575
+ setQuery("");
576
+ setSelectedIndex(0);
577
+ const timer = setTimeout(() => inputRef.current?.focus(), 50);
578
+ return () => clearTimeout(timer);
579
+ }
580
+ }, [open]);
581
+ React2.useEffect(() => {
582
+ if (open) {
583
+ document.body.style.overflow = "hidden";
584
+ } else {
585
+ document.body.style.overflow = "";
586
+ }
587
+ return () => {
588
+ document.body.style.overflow = "";
589
+ };
590
+ }, [open]);
591
+ const filteredGroups = customFilter ? customFilter(query, groups) : query.trim() ? groups.map((g) => ({
592
+ ...g,
593
+ items: g.items.filter(
594
+ (item) => item.label.toLowerCase().includes(query.toLowerCase()) || item.description?.toLowerCase().includes(query.toLowerCase()) || item.group?.toLowerCase().includes(query.toLowerCase())
595
+ )
596
+ })).filter((g) => g.items.length > 0) : groups;
597
+ const currentFlat = filteredGroups.flatMap((g) => g.items);
598
+ React2.useEffect(() => {
599
+ if (selectedIndex >= currentFlat.length) {
600
+ setSelectedIndex(0);
601
+ }
602
+ }, [currentFlat.length, selectedIndex]);
603
+ if (!open) return null;
604
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
605
+ /* @__PURE__ */ jsxRuntime.jsx(
606
+ "div",
607
+ {
608
+ className: "tollerud-cmd-overlay",
609
+ onClick: () => onOpenChange(false),
610
+ "aria-hidden": "true"
611
+ }
612
+ ),
613
+ /* @__PURE__ */ jsxRuntime.jsxs(
614
+ "div",
615
+ {
616
+ className: cn("tollerud-cmd", className),
617
+ role: "listbox",
618
+ "aria-label": "Command palette",
619
+ onKeyDown: handleKeyDown,
620
+ children: [
621
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "tollerud-cmd__header", children: [
622
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tollerud-cmd__search-icon", children: /* @__PURE__ */ jsxRuntime.jsxs(
623
+ "svg",
624
+ {
625
+ width: "18",
626
+ height: "18",
627
+ viewBox: "0 0 24 24",
628
+ fill: "none",
629
+ stroke: "currentColor",
630
+ strokeWidth: "2",
631
+ strokeLinecap: "round",
632
+ strokeLinejoin: "round",
633
+ children: [
634
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "11", cy: "11", r: "8" }),
635
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m21 21-4.35-4.35" })
636
+ ]
637
+ }
638
+ ) }),
639
+ /* @__PURE__ */ jsxRuntime.jsx(
640
+ "input",
641
+ {
642
+ ref: inputRef,
643
+ type: "text",
644
+ className: "tollerud-cmd__input",
645
+ placeholder,
646
+ value: query,
647
+ onChange: (e) => {
648
+ setQuery(e.target.value);
649
+ setSelectedIndex(0);
650
+ },
651
+ autoComplete: "off",
652
+ spellCheck: false
653
+ }
654
+ )
655
+ ] }),
656
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: listRef, className: "tollerud-cmd__list", children: [
657
+ filteredGroups.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "tollerud-cmd__empty", children: emptyMessage }),
658
+ filteredGroups.map((group, gi) => {
659
+ const flatOffset = filteredGroups.slice(0, gi).reduce((acc, g) => acc + g.items.length, 0);
660
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "tollerud-cmd__group", children: [
661
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "tollerud-cmd__group-label", children: group.label }),
662
+ group.items.map((item, ii) => {
663
+ const flatIndex = flatOffset + ii;
664
+ return /* @__PURE__ */ jsxRuntime.jsx(
665
+ ActionRow,
666
+ {
667
+ action: item,
668
+ highlighted: selectedIndex === flatIndex,
669
+ onClick: () => {
670
+ item.onSelect?.();
671
+ onAction?.(item);
672
+ onOpenChange(false);
673
+ },
674
+ onMouseEnter: () => setSelectedIndex(flatIndex)
675
+ },
676
+ item.id
677
+ );
678
+ })
679
+ ] }, group.label);
680
+ })
681
+ ] }),
682
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "tollerud-cmd__footer", children: [
683
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "tollerud-cmd__hint", children: [
684
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tollerud-kbd tollerud-kbd--sm", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tollerud-kbd__key", children: "\u2191" }) }),
685
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tollerud-kbd tollerud-kbd--sm", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tollerud-kbd__key", children: "\u2193" }) }),
686
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tollerud-cmd__hint-text", children: "navigate" })
687
+ ] }),
688
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "tollerud-cmd__hint", children: [
689
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tollerud-kbd tollerud-kbd--sm", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tollerud-kbd__key", children: "\u21B5" }) }),
690
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tollerud-cmd__hint-text", children: "select" })
691
+ ] }),
692
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "tollerud-cmd__hint", children: [
693
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tollerud-kbd tollerud-kbd--sm", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tollerud-kbd__key", children: "Esc" }) }),
694
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tollerud-cmd__hint-text", children: "close" })
695
+ ] })
696
+ ] })
697
+ ]
698
+ }
699
+ )
700
+ ] });
701
+ }
702
+ );
703
+ CommandMenu.displayName = "CommandMenu";
704
+ var ServiceHealthCard = React2.forwardRef(
705
+ ({ className, service, status = "online", uptime, responseTime, version, loading, ...props }, ref) => {
706
+ return /* @__PURE__ */ jsxRuntime.jsxs(
707
+ "div",
708
+ {
709
+ ref,
710
+ className: cn(
711
+ "rounded-lg border bg-tollerud-surface-raised p-4",
712
+ "transition-[border-color] duration-[150ms]",
713
+ status === "offline" && "border-tollerud-error/40",
714
+ status === "warning" && "border-tollerud-yellow/30",
715
+ status === "online" && "border-tollerud-border hover:border-tollerud-noir-500",
716
+ status === "idle" && "border-tollerud-border opacity-60",
717
+ loading && "animate-pulse",
718
+ className
719
+ ),
720
+ ...props,
721
+ children: [
722
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-2", children: [
723
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold text-tollerud-foreground truncate", children: service }),
724
+ /* @__PURE__ */ jsxRuntime.jsx(StatusDot, { status })
725
+ ] }),
726
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-x-4 gap-y-1 text-xs text-tollerud-text-muted", children: [
727
+ uptime && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
728
+ "Uptime: ",
729
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-tollerud-text-secondary", children: uptime })
730
+ ] }),
731
+ responseTime && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
732
+ "Response: ",
733
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-tollerud-text-secondary", children: responseTime })
734
+ ] }),
735
+ version && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
736
+ "Version: ",
737
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-tollerud-text-secondary", children: version })
738
+ ] })
739
+ ] })
740
+ ]
741
+ }
742
+ );
743
+ }
744
+ );
745
+ ServiceHealthCard.displayName = "ServiceHealthCard";
746
+ var HostCard = React2.forwardRef(
747
+ ({ className, hostname, ip, status = "online", cpu, memory, disk, uptime, containers, loading, ...props }, ref) => {
748
+ return /* @__PURE__ */ jsxRuntime.jsxs(
749
+ "div",
750
+ {
751
+ ref,
752
+ className: cn(
753
+ "rounded-lg border bg-tollerud-surface-raised p-4",
754
+ "transition-[border-color] duration-[150ms]",
755
+ status === "offline" && "border-tollerud-error/40",
756
+ status === "warning" && "border-tollerud-yellow/30",
757
+ status === "online" && "border-tollerud-border hover:border-tollerud-noir-500",
758
+ loading && "animate-pulse",
759
+ className
760
+ ),
761
+ ...props,
762
+ children: [
763
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-2", children: [
764
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [
765
+ /* @__PURE__ */ jsxRuntime.jsx(StatusDot, { status }),
766
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-sm text-tollerud-foreground truncate", children: hostname })
767
+ ] }),
768
+ containers !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[11px] text-tollerud-text-muted whitespace-nowrap ml-2", children: [
769
+ containers,
770
+ " container",
771
+ containers !== 1 ? "s" : ""
772
+ ] })
773
+ ] }),
774
+ ip && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-tollerud-text-muted mb-2 font-mono", children: ip }),
775
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-x-4 gap-y-1 text-xs text-tollerud-text-muted", children: [
776
+ cpu && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
777
+ "CPU: ",
778
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-tollerud-text-secondary", children: cpu })
779
+ ] }),
780
+ memory && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
781
+ "RAM: ",
782
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-tollerud-text-secondary", children: memory })
783
+ ] }),
784
+ disk && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
785
+ "Disk: ",
786
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-tollerud-text-secondary", children: disk })
787
+ ] }),
788
+ uptime && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
789
+ "Up: ",
790
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-tollerud-text-secondary", children: uptime })
791
+ ] })
792
+ ] })
793
+ ]
794
+ }
795
+ );
796
+ }
797
+ );
798
+ HostCard.displayName = "HostCard";
799
+ var DockerStackCard = React2.forwardRef(
800
+ ({ className, name, services, composePath, loading, ...props }, ref) => {
801
+ const onlineCount = services.filter((s) => s.status === "online").length;
802
+ const degraded = services.some((s) => s.status === "offline" || s.status === "warning");
803
+ const status = services.every((s) => s.status === "online") ? "online" : degraded ? "warning" : "offline";
804
+ return /* @__PURE__ */ jsxRuntime.jsxs(
805
+ "div",
806
+ {
807
+ ref,
808
+ className: cn(
809
+ "rounded-lg border bg-tollerud-surface-raised p-4",
810
+ "transition-[border-color] duration-[150ms]",
811
+ status === "offline" && "border-tollerud-error/40",
812
+ status === "warning" && "border-tollerud-yellow/30",
813
+ status === "online" && "border-tollerud-border hover:border-tollerud-noir-500",
814
+ loading && "animate-pulse",
815
+ className
816
+ ),
817
+ ...props,
818
+ children: [
819
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-3", children: [
820
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [
821
+ /* @__PURE__ */ jsxRuntime.jsx(StatusDot, { status }),
822
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-sm text-tollerud-foreground truncate", children: name })
823
+ ] }),
824
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-tollerud-text-muted whitespace-nowrap ml-2", children: [
825
+ onlineCount,
826
+ "/",
827
+ services.length,
828
+ " healthy"
829
+ ] })
830
+ ] }),
831
+ composePath && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[11px] text-tollerud-text-muted font-mono mb-2 truncate", children: composePath }),
832
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-1", children: services.map((svc) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-xs", children: [
833
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-tollerud-text-secondary truncate", children: svc.name }),
834
+ /* @__PURE__ */ jsxRuntime.jsx(StatusDot, { status: svc.status })
835
+ ] }, svc.name)) })
836
+ ]
837
+ }
838
+ );
839
+ }
840
+ );
841
+ DockerStackCard.displayName = "DockerStackCard";
842
+ var severityStyles = {
843
+ critical: { border: "border-tollerud-error/50", dot: "bg-tollerud-error shadow-[0_0_8px_rgba(239,68,68,0.6)]", label: "text-tollerud-error" },
844
+ high: { border: "border-tollerud-yellow/50", dot: "bg-tollerud-yellow shadow-[0_0_8px_rgba(232,213,0,0.5)]", label: "text-tollerud-yellow" },
845
+ medium: { border: "border-tollerud-amber/40", dot: "bg-tollerud-amber", label: "text-tollerud-amber" },
846
+ low: { border: "border-tollerud-noir-500", dot: "bg-tollerud-noir-400", label: "text-tollerud-text-muted" },
847
+ info: { border: "border-tollerud-info/30", dot: "bg-tollerud-info", label: "text-tollerud-info" }
848
+ };
849
+ var IncidentCard = React2.forwardRef(
850
+ ({ className, title, severity, timestamp, description, service, acknowledged, loading, ...props }, ref) => {
851
+ const style = severityStyles[severity];
852
+ return /* @__PURE__ */ jsxRuntime.jsx(
853
+ "div",
854
+ {
855
+ ref,
856
+ className: cn(
857
+ "rounded-lg border bg-tollerud-surface-raised p-4",
858
+ "transition-[border-color] duration-[150ms]",
859
+ style.border,
860
+ acknowledged && "opacity-50",
861
+ loading && "animate-pulse",
862
+ className
863
+ ),
864
+ ...props,
865
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3", children: [
866
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("w-2 h-2 rounded-full mt-1.5 flex-shrink-0", style.dot) }),
867
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
868
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
869
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold text-tollerud-foreground truncate", children: title }),
870
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-[11px] font-medium uppercase whitespace-nowrap", style.label), children: severity })
871
+ ] }),
872
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mt-0.5 text-xs text-tollerud-text-muted", children: [
873
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: timestamp }),
874
+ service && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
875
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-tollerud-noir-500", children: "\xB7" }),
876
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: service })
877
+ ] })
878
+ ] }),
879
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1.5 text-xs text-tollerud-text-secondary leading-relaxed", children: description })
880
+ ] })
881
+ ] })
882
+ }
883
+ );
884
+ }
885
+ );
886
+ IncidentCard.displayName = "IncidentCard";
887
+ var stateStyles = {
888
+ pending: "border-tollerud-yellow/30 hover:border-tollerud-yellow/50",
889
+ approved: "border-tollerud-success/40 opacity-70",
890
+ rejected: "border-tollerud-error/40 opacity-70"
891
+ };
892
+ var stateLabels = {
893
+ pending: { text: "Awaiting approval", cls: "text-tollerud-yellow" },
894
+ approved: { text: "Approved", cls: "text-tollerud-success" },
895
+ rejected: { text: "Rejected", cls: "text-tollerud-error" }
896
+ };
897
+ var ApprovalCard = React2.forwardRef(
898
+ ({ className, action, description, source, state = "pending", timestamp, onApprove, onReject, disabled, loading, ...props }, ref) => {
899
+ const label = stateLabels[state];
900
+ return /* @__PURE__ */ jsxRuntime.jsxs(
901
+ "div",
902
+ {
903
+ ref,
904
+ className: cn(
905
+ "rounded-lg border bg-tollerud-surface-raised p-4",
906
+ "transition-all duration-[150ms]",
907
+ stateStyles[state],
908
+ loading && "animate-pulse",
909
+ className
910
+ ),
911
+ ...props,
912
+ children: [
913
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-1.5", children: [
914
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold text-tollerud-foreground truncate", children: action }),
915
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-[11px] font-medium whitespace-nowrap ml-2", label.cls), children: label.text })
916
+ ] }),
917
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-tollerud-text-secondary mb-1.5 leading-relaxed", children: description }),
918
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-x-4 gap-y-0.5 text-[11px] text-tollerud-text-muted mb-3", children: [
919
+ source && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono", children: source }),
920
+ timestamp && /* @__PURE__ */ jsxRuntime.jsx("span", { children: timestamp })
921
+ ] }),
922
+ state === "pending" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
923
+ /* @__PURE__ */ jsxRuntime.jsx(
924
+ "button",
925
+ {
926
+ type: "button",
927
+ disabled,
928
+ onClick: onApprove,
929
+ className: cn(
930
+ "flex-1 rounded-md px-3 py-1.5 text-xs font-semibold transition-all",
931
+ "bg-tollerud-success text-tollerud-text-inverse",
932
+ "hover:brightness-110 disabled:opacity-40 disabled:cursor-not-allowed"
933
+ ),
934
+ children: "Approve"
935
+ }
936
+ ),
937
+ /* @__PURE__ */ jsxRuntime.jsx(
938
+ "button",
939
+ {
940
+ type: "button",
941
+ disabled,
942
+ onClick: onReject,
943
+ className: cn(
944
+ "flex-1 rounded-md px-3 py-1.5 text-xs font-semibold transition-all",
945
+ "bg-tollerud-error text-white",
946
+ "hover:brightness-110 disabled:opacity-40 disabled:cursor-not-allowed"
947
+ ),
948
+ children: "Reject"
949
+ }
950
+ )
951
+ ] })
952
+ ]
953
+ }
954
+ );
955
+ }
956
+ );
957
+ ApprovalCard.displayName = "ApprovalCard";
958
+ var BackupStatusPanel = React2.forwardRef(
959
+ ({ className, jobs, totalSize, lastFullBackup, loading, ...props }, ref) => {
960
+ const failed = jobs.filter((j) => j.status === "offline").length;
961
+ return /* @__PURE__ */ jsxRuntime.jsxs(
962
+ "div",
963
+ {
964
+ ref,
965
+ className: cn(
966
+ "rounded-lg border border-tollerud-border bg-tollerud-surface-raised",
967
+ loading && "animate-pulse",
968
+ className
969
+ ),
970
+ ...props,
971
+ children: [
972
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-4 py-3 border-b border-tollerud-border", children: [
973
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold text-tollerud-foreground", children: "Backups" }),
974
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 text-[11px] text-tollerud-text-muted", children: [
975
+ totalSize && /* @__PURE__ */ jsxRuntime.jsx("span", { children: totalSize }),
976
+ lastFullBackup && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
977
+ "Last full: ",
978
+ lastFullBackup
979
+ ] })
980
+ ] })
981
+ ] }),
982
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-1", children: [
983
+ jobs.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-6 text-xs text-center text-tollerud-text-muted", children: "No backup jobs configured" }),
984
+ jobs.map((job) => /* @__PURE__ */ jsxRuntime.jsxs(
985
+ "div",
986
+ {
987
+ className: "flex items-center justify-between px-3 py-2 rounded-md hover:bg-tollerud-noir-800/50 transition-colors",
988
+ children: [
989
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 min-w-0 flex-1", children: [
990
+ /* @__PURE__ */ jsxRuntime.jsx(StatusDot, { status: job.status }),
991
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-tollerud-foreground truncate", children: job.name })
992
+ ] }),
993
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 text-[11px] text-tollerud-text-muted flex-shrink-0 ml-2", children: [
994
+ job.size && /* @__PURE__ */ jsxRuntime.jsx("span", { children: job.size }),
995
+ job.target && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline font-mono", children: job.target })
996
+ ] })
997
+ ]
998
+ },
999
+ job.name
1000
+ ))
1001
+ ] }),
1002
+ failed > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 py-2 border-t border-tollerud-border", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[11px] text-tollerud-error", children: [
1003
+ failed,
1004
+ " job",
1005
+ failed !== 1 ? "s" : "",
1006
+ " failed \u2014 check logs"
1007
+ ] }) })
1008
+ ]
1009
+ }
1010
+ );
1011
+ }
1012
+ );
1013
+ BackupStatusPanel.displayName = "BackupStatusPanel";
1014
+ var Timeline = React2.forwardRef(
1015
+ ({ className, items, active, loading, ...props }, ref) => {
1016
+ return /* @__PURE__ */ jsxRuntime.jsx(
1017
+ "div",
1018
+ {
1019
+ ref,
1020
+ className: cn("tollerud-timeline", loading && "animate-pulse", className),
1021
+ role: "list",
1022
+ "aria-label": "Activity timeline",
1023
+ ...props,
1024
+ children: items.map((item, i) => {
1025
+ const isLast = i === items.length - 1;
1026
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "tollerud-timeline__item", role: "listitem", children: [
1027
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "tollerud-timeline__marker", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "tollerud-timeline__dot-group", children: [
1028
+ item.icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tollerud-timeline__icon", children: item.icon }) : /* @__PURE__ */ jsxRuntime.jsx(
1029
+ "span",
1030
+ {
1031
+ className: cn(
1032
+ "tollerud-timeline__dot",
1033
+ active && "tollerud-timeline__dot--active",
1034
+ item.status === "online" && "bg-tollerud-success shadow-[0_0_6px_rgba(34,197,94,0.5)]",
1035
+ item.status === "offline" && "bg-tollerud-error",
1036
+ item.status === "warning" && "bg-tollerud-yellow shadow-[0_0_6px_rgba(232,213,0,0.5)]",
1037
+ !item.status && "bg-tollerud-noir-500"
1038
+ )
1039
+ }
1040
+ ),
1041
+ !isLast && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "tollerud-timeline__line" })
1042
+ ] }) }),
1043
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "tollerud-timeline__content", children: [
1044
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-2", children: [
1045
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tollerud-timeline__title", children: item.title }),
1046
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tollerud-timeline__time", children: item.time })
1047
+ ] }),
1048
+ item.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "tollerud-timeline__description", children: item.description }),
1049
+ item.meta && item.meta.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-1.5 mt-1", children: item.meta.map((m) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tollerud-timeline__meta", children: m }, m)) })
1050
+ ] })
1051
+ ] }, item.id);
1052
+ })
1053
+ }
1054
+ );
1055
+ }
1056
+ );
1057
+ Timeline.displayName = "Timeline";
1058
+ var AlertInbox = React2.forwardRef(
1059
+ ({ className, alerts, filterSeverity = "", onAcknowledge, loading, emptyMessage = "All clear \u2014 no incidents", ...props }, ref) => {
1060
+ const filtered = filterSeverity ? alerts.filter((a) => a.severity === filterSeverity) : alerts;
1061
+ const counts = {
1062
+ total: alerts.length,
1063
+ unacknowledged: alerts.filter((a) => !a.acknowledged).length,
1064
+ critical: alerts.filter((a) => a.severity === "critical" && !a.acknowledged).length
1065
+ };
1066
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1067
+ "div",
1068
+ {
1069
+ ref,
1070
+ className: cn(
1071
+ "rounded-lg border border-tollerud-border bg-tollerud-surface-raised overflow-hidden",
1072
+ loading && "animate-pulse",
1073
+ className
1074
+ ),
1075
+ ...props,
1076
+ children: [
1077
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-4 py-3 border-b border-tollerud-border", children: [
1078
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1079
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold text-tollerud-foreground", children: "Alerts" }),
1080
+ counts.unacknowledged > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1 text-[11px] text-tollerud-error font-medium", children: [
1081
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-1.5 h-1.5 rounded-full bg-tollerud-error animate-pulse" }),
1082
+ counts.unacknowledged,
1083
+ " unread"
1084
+ ] }),
1085
+ counts.critical > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[11px] text-tollerud-error font-bold", children: [
1086
+ counts.critical,
1087
+ " critical"
1088
+ ] })
1089
+ ] }),
1090
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-tollerud-text-muted", children: [
1091
+ filtered.length,
1092
+ " of ",
1093
+ alerts.length
1094
+ ] })
1095
+ ] }),
1096
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "divide-y divide-tollerud-border/50 max-h-[480px] overflow-y-auto", children: [
1097
+ filtered.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 py-8 text-xs text-center text-tollerud-text-muted", children: emptyMessage }),
1098
+ filtered.map((alert) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative group", children: [
1099
+ /* @__PURE__ */ jsxRuntime.jsx(
1100
+ IncidentCard,
1101
+ {
1102
+ title: alert.title,
1103
+ severity: alert.severity,
1104
+ timestamp: alert.timestamp,
1105
+ description: alert.description,
1106
+ service: alert.service,
1107
+ acknowledged: alert.acknowledged,
1108
+ className: "border-0 rounded-none bg-transparent hover:bg-tollerud-noir-800/30"
1109
+ }
1110
+ ),
1111
+ alert.acknowledged && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute bottom-2 right-3 text-[10px] font-medium text-tollerud-text-muted/50", children: "Acknowledged" }),
1112
+ !alert.acknowledged && onAcknowledge && /* @__PURE__ */ jsxRuntime.jsx(
1113
+ "button",
1114
+ {
1115
+ type: "button",
1116
+ onClick: () => onAcknowledge(alert.id),
1117
+ className: cn(
1118
+ "absolute bottom-2 right-3 text-[10px] font-medium px-2 py-0.5 rounded",
1119
+ "text-tollerud-yellow/70 hover:text-tollerud-yellow hover:bg-tollerud-yellow/10",
1120
+ "opacity-0 group-hover:opacity-100 transition-opacity duration-150"
1121
+ ),
1122
+ children: "Acknowledge"
1123
+ }
1124
+ )
1125
+ ] }, alert.id))
1126
+ ] })
1127
+ ]
1128
+ }
1129
+ );
1130
+ }
1131
+ );
1132
+ AlertInbox.displayName = "AlertInbox";
1133
+ var stepIcon = {
1134
+ pending: "\u25CB",
1135
+ running: "\u25C9",
1136
+ success: "\u25CF",
1137
+ failed: "\u2715",
1138
+ skipped: "\u2014"
1139
+ };
1140
+ var stepStyles = {
1141
+ pending: "text-tollerud-noir-400",
1142
+ running: "text-tollerud-yellow animate-pulse",
1143
+ success: "text-tollerud-success",
1144
+ failed: "text-tollerud-error",
1145
+ skipped: "text-tollerud-noir-500"
1146
+ };
1147
+ var RollbackPlan = React2.forwardRef(
1148
+ ({ className, name, steps, executing, loading, ...props }, ref) => {
1149
+ const statusSummary = {
1150
+ pending: steps.filter((s) => s.status === "pending").length,
1151
+ running: steps.filter((s) => s.status === "running").length,
1152
+ success: steps.filter((s) => s.status === "success").length,
1153
+ failed: steps.filter((s) => s.status === "failed").length,
1154
+ skipped: steps.filter((s) => s.status === "skipped").length
1155
+ };
1156
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1157
+ "div",
1158
+ {
1159
+ ref,
1160
+ className: cn(
1161
+ "rounded-lg border border-tollerud-border bg-tollerud-surface-raised",
1162
+ loading && "animate-pulse",
1163
+ className
1164
+ ),
1165
+ ...props,
1166
+ children: [
1167
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-4 py-3 border-b border-tollerud-border", children: [
1168
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1169
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold text-tollerud-foreground", children: name }),
1170
+ executing && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] text-tollerud-yellow font-medium animate-pulse", children: "Executing\u2026" })
1171
+ ] }),
1172
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-[11px] text-tollerud-text-muted", children: [
1173
+ statusSummary.success > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-tollerud-success", children: [
1174
+ statusSummary.success,
1175
+ " done"
1176
+ ] }),
1177
+ statusSummary.failed > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-tollerud-error", children: [
1178
+ statusSummary.failed,
1179
+ " failed"
1180
+ ] }),
1181
+ statusSummary.running > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-tollerud-yellow", children: [
1182
+ statusSummary.running,
1183
+ " running"
1184
+ ] })
1185
+ ] })
1186
+ ] }),
1187
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-1", children: steps.map((step) => /* @__PURE__ */ jsxRuntime.jsxs(
1188
+ "div",
1189
+ {
1190
+ className: cn(
1191
+ "flex items-start gap-3 px-3 py-2 rounded-md",
1192
+ "transition-colors duration-[150ms]",
1193
+ step.status === "failed" && "bg-tollerud-error/5",
1194
+ step.status === "running" && "bg-tollerud-yellow/5"
1195
+ ),
1196
+ children: [
1197
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("font-mono text-sm mt-0.5 flex-shrink-0", stepStyles[step.status]), children: stepIcon[step.status] }),
1198
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
1199
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
1200
+ "text-xs font-medium",
1201
+ step.status === "success" ? "text-tollerud-success" : step.status === "failed" ? "text-tollerud-error" : step.status === "skipped" ? "text-tollerud-noir-500" : "text-tollerud-foreground"
1202
+ ), children: step.label }),
1203
+ step.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] text-tollerud-text-muted mt-0.5", children: step.description })
1204
+ ] }),
1205
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
1206
+ "text-[10px] uppercase font-semibold flex-shrink-0",
1207
+ stepStyles[step.status]
1208
+ ), children: step.status })
1209
+ ]
1210
+ },
1211
+ step.id
1212
+ )) })
1213
+ ]
1214
+ }
1215
+ );
1216
+ }
1217
+ );
1218
+ RollbackPlan.displayName = "RollbackPlan";
1219
+ var diffStyles = {
1220
+ add: "bg-tollerud-success/[0.06] text-tollerud-success hover:bg-tollerud-success/[0.10]",
1221
+ remove: "bg-tollerud-error/[0.06] text-tollerud-error hover:bg-tollerud-error/[0.10]",
1222
+ context: "text-tollerud-noir-300"
1223
+ };
1224
+ var diffPrefix = {
1225
+ add: "+",
1226
+ remove: "-",
1227
+ context: " "
1228
+ };
1229
+ var ActionDiff = React2.forwardRef(
1230
+ ({ className, lines, label, view = "unified", loading, ...props }, ref) => {
1231
+ const [showContext, setShowContext] = React2.useState(true);
1232
+ const stats = React2.useMemo(() => {
1233
+ const adds = lines.filter((l) => l.type === "add").length;
1234
+ const rems = lines.filter((l) => l.type === "remove").length;
1235
+ return { adds, rems };
1236
+ }, [lines]);
1237
+ const displayLines = showContext ? lines : lines.filter((l) => l.type !== "context");
1238
+ const hasContext = lines.some((l) => l.type === "context");
1239
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1240
+ "div",
1241
+ {
1242
+ ref,
1243
+ className: cn(
1244
+ "rounded-lg border border-tollerud-border bg-[var(--color-tollerud-surface-raised)] overflow-hidden",
1245
+ loading && "animate-pulse",
1246
+ className
1247
+ ),
1248
+ ...props,
1249
+ children: [
1250
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-4 py-2.5 border-b border-tollerud-border bg-tollerud-noir-900", children: [
1251
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2 min-w-0", children: label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-tollerud-foreground font-mono truncate", children: label }) }),
1252
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 text-[11px]", children: [
1253
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-tollerud-success", children: [
1254
+ "+",
1255
+ stats.adds
1256
+ ] }),
1257
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-tollerud-error", children: [
1258
+ "-",
1259
+ stats.rems
1260
+ ] }),
1261
+ hasContext && /* @__PURE__ */ jsxRuntime.jsx(
1262
+ "button",
1263
+ {
1264
+ type: "button",
1265
+ onClick: () => setShowContext(!showContext),
1266
+ className: "text-tollerud-text-muted hover:text-tollerud-foreground transition-colors",
1267
+ children: showContext ? "Hide context" : "Show context"
1268
+ }
1269
+ )
1270
+ ] })
1271
+ ] }),
1272
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto font-mono text-xs leading-relaxed", children: /* @__PURE__ */ jsxRuntime.jsx("table", { className: "w-full border-collapse", children: /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: displayLines.map((line, i) => /* @__PURE__ */ jsxRuntime.jsxs(
1273
+ "tr",
1274
+ {
1275
+ className: cn(
1276
+ "transition-colors duration-[100ms]",
1277
+ diffStyles[line.type]
1278
+ ),
1279
+ children: [
1280
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: cn(
1281
+ "w-10 text-right px-2 py-px select-none",
1282
+ "text-tollerud-noir-500 border-r border-tollerud-border/30",
1283
+ "text-[10px] align-top"
1284
+ ), children: line.oldLine ?? "" }),
1285
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: cn(
1286
+ "w-10 text-right px-2 py-px select-none",
1287
+ "text-tollerud-noir-500 border-r border-tollerud-border/30",
1288
+ "text-[10px] align-top"
1289
+ ), children: line.newLine ?? "" }),
1290
+ /* @__PURE__ */ jsxRuntime.jsxs("td", { className: "px-2 py-px whitespace-pre-wrap", children: [
1291
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "select-none opacity-50 mr-2", children: diffPrefix[line.type] }),
1292
+ line.text
1293
+ ] })
1294
+ ]
1295
+ },
1296
+ i
1297
+ )) }) }) })
1298
+ ]
1299
+ }
1300
+ );
1301
+ }
1302
+ );
1303
+ ActionDiff.displayName = "ActionDiff";
1304
+ var levelStyles = {
1305
+ debug: "text-tollerud-noir-400",
1306
+ trace: "text-tollerud-noir-300",
1307
+ info: "text-tollerud-foreground",
1308
+ warn: "text-tollerud-amber",
1309
+ error: "text-tollerud-error"
1310
+ };
1311
+ var levelLabels = {
1312
+ debug: "DBG",
1313
+ trace: "TRC",
1314
+ info: "INF",
1315
+ warn: "WRN",
1316
+ error: "ERR"
1317
+ };
1318
+ var LogViewer = React2.forwardRef(
1319
+ ({ className, lines, maxLines = 5e3, showLineNumbers = true, showTimestamps = true, follow = true, searchable, height = "400px", loading, ...props }, ref) => {
1320
+ const [search, setSearch] = React2.useState("");
1321
+ const [isFollowing, setIsFollowing] = React2.useState(follow);
1322
+ const scrollRef = React2.useRef(null);
1323
+ const displayedLines = React2.useMemo(() => {
1324
+ return lines.length > maxLines ? lines.slice(-maxLines) : lines;
1325
+ }, [lines, maxLines]);
1326
+ const filteredLines = React2.useMemo(() => {
1327
+ if (!search.trim()) return displayedLines;
1328
+ return displayedLines.filter(
1329
+ (l) => l.text.toLowerCase().includes(search.toLowerCase()) || l.source?.toLowerCase().includes(search.toLowerCase())
1330
+ );
1331
+ }, [displayedLines, search]);
1332
+ React2.useEffect(() => {
1333
+ if (isFollowing && scrollRef.current) {
1334
+ scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
1335
+ }
1336
+ }, [filteredLines.length, isFollowing]);
1337
+ const handleScroll = (e) => {
1338
+ const el = e.currentTarget;
1339
+ const atBottom = el.scrollHeight - el.scrollTop - el.clientHeight < 40;
1340
+ setIsFollowing(atBottom);
1341
+ };
1342
+ const filteredFrom = displayedLines.indexOf(filteredLines[0]);
1343
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1344
+ "div",
1345
+ {
1346
+ ref,
1347
+ className: cn(
1348
+ "rounded-lg border border-tollerud-border bg-[var(--color-tollerud-surface-raised)] overflow-hidden tollerud-log-viewer",
1349
+ loading && "animate-pulse",
1350
+ className
1351
+ ),
1352
+ ...props,
1353
+ children: [
1354
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-3 py-2 border-b border-tollerud-border bg-tollerud-noir-900", children: [
1355
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-xs text-tollerud-text-muted", children: [
1356
+ isFollowing ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-tollerud-yellow font-medium", children: "\u25CF Live" }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-tollerud-noir-400", children: "\u25CF Paused" }),
1357
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
1358
+ filteredLines.length,
1359
+ " lines"
1360
+ ] }),
1361
+ lines.length > maxLines && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-tollerud-amber", children: [
1362
+ "(showing last ",
1363
+ maxLines,
1364
+ ")"
1365
+ ] })
1366
+ ] }),
1367
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: searchable && /* @__PURE__ */ jsxRuntime.jsx(
1368
+ "input",
1369
+ {
1370
+ type: "text",
1371
+ value: search,
1372
+ onChange: (e) => setSearch(e.target.value),
1373
+ placeholder: "Search logs\u2026",
1374
+ className: cn(
1375
+ "w-40 text-[11px] px-2 py-1 rounded bg-tollerud-noir-800",
1376
+ "border border-tollerud-noir-600 text-tollerud-foreground",
1377
+ "placeholder:text-tollerud-noir-400 outline-none",
1378
+ "focus:border-tollerud-yellow/50 transition-colors"
1379
+ )
1380
+ }
1381
+ ) })
1382
+ ] }),
1383
+ /* @__PURE__ */ jsxRuntime.jsxs(
1384
+ "div",
1385
+ {
1386
+ ref: scrollRef,
1387
+ onScroll: handleScroll,
1388
+ className: "overflow-y-auto font-mono text-xs leading-relaxed p-3",
1389
+ style: { height },
1390
+ children: [
1391
+ filteredLines.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-full text-tollerud-noir-400 text-xs", children: search ? "No matching log lines" : "No log output" }),
1392
+ filteredLines.map((line, i) => {
1393
+ const absLineNum = filteredFrom >= 0 ? filteredFrom + i + 1 : i + 1;
1394
+ const level = line.level ?? "info";
1395
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1396
+ "div",
1397
+ {
1398
+ className: cn(
1399
+ "flex gap-3 hover:bg-[var(--color-tollerud-surface-hover)] px-1 py-px rounded-sm",
1400
+ levelStyles[level]
1401
+ ),
1402
+ children: [
1403
+ showLineNumbers && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-tollerud-noir-500 text-right select-none w-8 flex-shrink-0", children: absLineNum }),
1404
+ showTimestamps && line.timestamp && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-tollerud-noir-400 flex-shrink-0 select-none", children: line.timestamp }),
1405
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0 w-7 text-center font-bold text-[10px] uppercase opacity-60", children: levelLabels[level] }),
1406
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "whitespace-pre-wrap break-all", children: line.text })
1407
+ ]
1408
+ },
1409
+ `${absLineNum}-${i}`
1410
+ );
1411
+ })
1412
+ ]
1413
+ }
1414
+ )
1415
+ ]
1416
+ }
1417
+ );
1418
+ }
1419
+ );
1420
+ LogViewer.displayName = "LogViewer";
1421
+ var Textarea = React2.forwardRef(
1422
+ ({ className, label, error, id, ...props }, ref) => {
1423
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
1424
+ label && /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: "text-xs font-medium text-tollerud-text-muted", children: label }),
1425
+ /* @__PURE__ */ jsxRuntime.jsx(
1426
+ "textarea",
1427
+ {
1428
+ ref,
1429
+ id,
1430
+ className: cn(
1431
+ "font-sans text-base px-3 py-2 rounded min-h-[80px] resize-y",
1432
+ "bg-tollerud-surface-raised border",
1433
+ "text-tollerud-text-primary",
1434
+ "placeholder:text-tollerud-text-muted",
1435
+ "transition-[border-color] duration-[150ms]",
1436
+ "focus:outline-none focus:border-tollerud-yellow focus:shadow-[0_0_0_1px_#E8D500]",
1437
+ error ? "border-tollerud-error" : "border-tollerud-border",
1438
+ className
1439
+ ),
1440
+ ...props
1441
+ }
1442
+ ),
1443
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-tollerud-error mt-0.5", children: error })
1444
+ ] });
1445
+ }
1446
+ );
1447
+ Textarea.displayName = "Textarea";
1448
+ var Select = React2.forwardRef(
1449
+ ({ className, label, error, placeholder, options = [], value, onChange, ...props }, ref) => {
1450
+ const [open, setOpen] = React2.useState(false);
1451
+ const [highlightedIdx, setHighlightedIdx] = React2.useState(0);
1452
+ const containerRef = React2.useRef(null);
1453
+ const listRef = React2.useRef(null);
1454
+ const selectedOption = options.find((o) => o.value === value);
1455
+ React2.useEffect(() => {
1456
+ if (!open) return;
1457
+ const handleClick = (e) => {
1458
+ if (containerRef.current && !containerRef.current.contains(e.target)) {
1459
+ setOpen(false);
1460
+ }
1461
+ };
1462
+ document.addEventListener("mousedown", handleClick);
1463
+ return () => document.removeEventListener("mousedown", handleClick);
1464
+ }, [open]);
1465
+ React2.useEffect(() => {
1466
+ if (open) {
1467
+ const idx = value ? options.findIndex((o) => o.value === value) : -1;
1468
+ setHighlightedIdx(idx >= 0 ? idx : 0);
1469
+ }
1470
+ }, [open, options, value]);
1471
+ React2.useEffect(() => {
1472
+ if (open && listRef.current) {
1473
+ const item = listRef.current.children[highlightedIdx];
1474
+ item?.scrollIntoView({ block: "nearest" });
1475
+ }
1476
+ }, [open, highlightedIdx]);
1477
+ const selectOption = React2.useCallback(
1478
+ (opt) => {
1479
+ onChange?.(opt.value);
1480
+ setOpen(false);
1481
+ },
1482
+ [onChange]
1483
+ );
1484
+ const handleKeyDown = (e) => {
1485
+ if (!open) {
1486
+ if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") {
1487
+ e.preventDefault();
1488
+ setOpen(true);
1489
+ }
1490
+ return;
1491
+ }
1492
+ switch (e.key) {
1493
+ case "Escape":
1494
+ e.preventDefault();
1495
+ setOpen(false);
1496
+ break;
1497
+ case "ArrowDown":
1498
+ e.preventDefault();
1499
+ setHighlightedIdx((prev) => Math.min(prev + 1, options.length - 1));
1500
+ break;
1501
+ case "ArrowUp":
1502
+ e.preventDefault();
1503
+ setHighlightedIdx((prev) => Math.max(prev - 1, 0));
1504
+ break;
1505
+ case "Enter":
1506
+ e.preventDefault();
1507
+ if (options[highlightedIdx]) {
1508
+ selectOption(options[highlightedIdx]);
1509
+ }
1510
+ break;
1511
+ }
1512
+ };
1513
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5", ref, children: [
1514
+ label && /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-xs font-medium text-tollerud-text-muted", children: label }),
1515
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: "relative", children: [
1516
+ /* @__PURE__ */ jsxRuntime.jsxs(
1517
+ "button",
1518
+ {
1519
+ type: "button",
1520
+ onClick: () => setOpen(!open),
1521
+ onKeyDown: handleKeyDown,
1522
+ "aria-haspopup": "listbox",
1523
+ "aria-expanded": open,
1524
+ className: cn(
1525
+ "font-sans text-sm w-full flex items-center justify-between px-3 py-2.5 rounded-lg",
1526
+ "bg-tollerud-surface-raised",
1527
+ "text-tollerud-text-primary text-left",
1528
+ "transition-all duration-150 ease-out cursor-pointer",
1529
+ error ? "border-tollerud-error/70 focus:border-tollerud-error focus:shadow-[0_0_0_1px_#EF4444]" : "border-tollerud-border focus:border-tollerud-yellow focus:shadow-[0_0_0_1px_#E8D500]",
1530
+ "border hover:border-tollerud-noir-400",
1531
+ "focus:outline-none",
1532
+ className
1533
+ ),
1534
+ children: [
1535
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(!selectedOption && "text-tollerud-text-muted"), children: selectedOption ? selectedOption.label : placeholder || "Select\u2026" }),
1536
+ /* @__PURE__ */ jsxRuntime.jsx(
1537
+ "svg",
1538
+ {
1539
+ className: cn(
1540
+ "h-4 w-4 text-tollerud-text-muted transition-transform duration-150 flex-shrink-0",
1541
+ open && "rotate-180"
1542
+ ),
1543
+ fill: "none",
1544
+ viewBox: "0 0 24 24",
1545
+ stroke: "currentColor",
1546
+ strokeWidth: 2,
1547
+ "aria-hidden": "true",
1548
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 9l6 6 6-6" })
1549
+ }
1550
+ )
1551
+ ]
1552
+ }
1553
+ ),
1554
+ open && /* @__PURE__ */ jsxRuntime.jsxs(
1555
+ "div",
1556
+ {
1557
+ ref: listRef,
1558
+ role: "listbox",
1559
+ className: cn(
1560
+ "absolute z-10 left-0 right-0 mt-1 py-1",
1561
+ "rounded-lg border border-tollerud-border bg-tollerud-surface-overlay",
1562
+ "shadow-[0_8px_24px_rgba(0,0,0,0.4)]",
1563
+ "max-h-60 overflow-y-auto"
1564
+ ),
1565
+ children: [
1566
+ options.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-2 text-xs text-tollerud-text-muted text-center", children: "No options" }),
1567
+ options.map((opt, idx) => /* @__PURE__ */ jsxRuntime.jsx(
1568
+ "button",
1569
+ {
1570
+ type: "button",
1571
+ role: "option",
1572
+ "aria-selected": opt.value === value,
1573
+ onClick: () => selectOption(opt),
1574
+ onMouseEnter: () => setHighlightedIdx(idx),
1575
+ className: cn(
1576
+ "w-full text-sm text-left px-3 py-2 transition-colors duration-75",
1577
+ "cursor-pointer",
1578
+ opt.value === value ? "text-tollerud-yellow" : "text-tollerud-text-primary",
1579
+ idx === highlightedIdx && !(opt.value === value) ? "bg-tollerud-noir-700" : "hover:bg-tollerud-noir-700/60",
1580
+ opt.value === value && highlightedIdx === idx && "bg-tollerud-noir-700"
1581
+ ),
1582
+ children: opt.label
1583
+ },
1584
+ opt.value
1585
+ ))
1586
+ ]
1587
+ }
1588
+ )
1589
+ ] }),
1590
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-tollerud-error mt-0.5", children: error })
1591
+ ] });
1592
+ }
1593
+ );
1594
+ Select.displayName = "Select";
1595
+ var Checkbox = React2.forwardRef(
1596
+ ({ className, label, id: idProp, checked, ...props }, ref) => {
1597
+ const autoId = React2.useId();
1598
+ const id = idProp ?? autoId;
1599
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1600
+ "label",
1601
+ {
1602
+ htmlFor: id,
1603
+ className: cn(
1604
+ "inline-flex items-center gap-2 cursor-pointer select-none group",
1605
+ "text-sm text-tollerud-text-primary",
1606
+ props.disabled && "opacity-50 pointer-events-none",
1607
+ className
1608
+ ),
1609
+ children: [
1610
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "relative flex items-center justify-center", children: [
1611
+ /* @__PURE__ */ jsxRuntime.jsx(
1612
+ "input",
1613
+ {
1614
+ ref,
1615
+ id,
1616
+ type: "checkbox",
1617
+ checked,
1618
+ className: "peer sr-only",
1619
+ ...props
1620
+ }
1621
+ ),
1622
+ /* @__PURE__ */ jsxRuntime.jsx(
1623
+ "span",
1624
+ {
1625
+ className: cn(
1626
+ "h-4 w-4 rounded border transition-all duration-[150ms]",
1627
+ "flex items-center justify-center",
1628
+ "bg-tollerud-surface-raised border-tollerud-border",
1629
+ "peer-focus-visible:outline-2 peer-focus-visible:outline-tollerud-yellow",
1630
+ "peer-checked:bg-tollerud-yellow peer-checked:border-tollerud-yellow",
1631
+ "group-hover:border-tollerud-text-secondary"
1632
+ ),
1633
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1634
+ "svg",
1635
+ {
1636
+ className: cn(
1637
+ "h-3 w-3 text-tollerud-noir-black transition-opacity duration-[150ms]",
1638
+ checked ? "opacity-100" : "opacity-0"
1639
+ ),
1640
+ viewBox: "0 0 12 12",
1641
+ fill: "none",
1642
+ "aria-hidden": "true",
1643
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1644
+ "path",
1645
+ {
1646
+ d: "M2.5 6l2.5 2.5 4.5-5",
1647
+ stroke: "currentColor",
1648
+ strokeWidth: 2,
1649
+ strokeLinecap: "round",
1650
+ strokeLinejoin: "round"
1651
+ }
1652
+ )
1653
+ }
1654
+ )
1655
+ }
1656
+ )
1657
+ ] }),
1658
+ label && /* @__PURE__ */ jsxRuntime.jsx("span", { children: label })
1659
+ ]
1660
+ }
1661
+ );
1662
+ }
1663
+ );
1664
+ Checkbox.displayName = "Checkbox";
1665
+ var Switch = React2.forwardRef(
1666
+ ({ className, label, id: idProp, checked, ...props }, ref) => {
1667
+ const autoId = React2.useId();
1668
+ const id = idProp ?? autoId;
1669
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1670
+ "label",
1671
+ {
1672
+ htmlFor: id,
1673
+ className: cn(
1674
+ "inline-flex items-center gap-2.5 cursor-pointer select-none group",
1675
+ "text-sm text-tollerud-text-primary",
1676
+ props.disabled && "opacity-40 pointer-events-none cursor-not-allowed",
1677
+ className
1678
+ ),
1679
+ children: [
1680
+ /* @__PURE__ */ jsxRuntime.jsxs(
1681
+ "span",
1682
+ {
1683
+ className: cn(
1684
+ "relative inline-flex items-center h-5 w-9 flex-shrink-0 rounded-full",
1685
+ "transition-colors duration-200 ease-out",
1686
+ checked ? "bg-tollerud-yellow" : "bg-tollerud-noir-600",
1687
+ "group-hover:bg-tollerud-noir-500",
1688
+ checked && "group-hover:bg-tollerud-yellow-bright",
1689
+ "peer-focus-visible:outline-2 peer-focus-visible:outline-tollerud-yellow peer-focus-visible:outline-offset-2"
1690
+ ),
1691
+ children: [
1692
+ /* @__PURE__ */ jsxRuntime.jsx(
1693
+ "input",
1694
+ {
1695
+ ref,
1696
+ id,
1697
+ type: "checkbox",
1698
+ role: "switch",
1699
+ checked,
1700
+ className: "peer absolute inset-0 opacity-0 w-full h-full cursor-pointer z-10",
1701
+ ...props
1702
+ }
1703
+ ),
1704
+ /* @__PURE__ */ jsxRuntime.jsx(
1705
+ "span",
1706
+ {
1707
+ className: cn(
1708
+ "block h-3.5 w-3.5 rounded-full shadow-sm",
1709
+ "transition-all duration-200 ease-out",
1710
+ checked ? "translate-x-[18px] bg-tollerud-black" : "translate-x-[3px] bg-tollerud-white"
1711
+ )
1712
+ }
1713
+ )
1714
+ ]
1715
+ }
1716
+ ),
1717
+ label && /* @__PURE__ */ jsxRuntime.jsx("span", { children: label })
1718
+ ]
1719
+ }
1720
+ );
1721
+ }
1722
+ );
1723
+ Switch.displayName = "Switch";
1724
+ var RadioGroup = React2.forwardRef(
1725
+ ({ label, error, children, className }, ref) => {
1726
+ React2.useId();
1727
+ return /* @__PURE__ */ jsxRuntime.jsxs("fieldset", { ref, className: cn("flex flex-col gap-1", className), children: [
1728
+ label && /* @__PURE__ */ jsxRuntime.jsx("legend", { className: "text-xs font-medium text-tollerud-text-muted mb-1", children: label }),
1729
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-2", children }),
1730
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-tollerud-error mt-0.5", children: error })
1731
+ ] });
1732
+ }
1733
+ );
1734
+ RadioGroup.displayName = "RadioGroup";
1735
+ var Radio = React2.forwardRef(
1736
+ ({ className, label, id: idProp, ...props }, ref) => {
1737
+ const autoId = React2.useId();
1738
+ const id = idProp ?? autoId;
1739
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1740
+ "label",
1741
+ {
1742
+ htmlFor: id,
1743
+ className: cn(
1744
+ "inline-flex items-center gap-2 cursor-pointer select-none group",
1745
+ "text-sm text-tollerud-text-primary",
1746
+ props.disabled && "opacity-50 pointer-events-none",
1747
+ className
1748
+ ),
1749
+ children: [
1750
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "relative flex items-center justify-center", children: [
1751
+ /* @__PURE__ */ jsxRuntime.jsx(
1752
+ "input",
1753
+ {
1754
+ ref,
1755
+ id,
1756
+ type: "radio",
1757
+ className: "peer sr-only",
1758
+ ...props
1759
+ }
1760
+ ),
1761
+ /* @__PURE__ */ jsxRuntime.jsx(
1762
+ "span",
1763
+ {
1764
+ className: cn(
1765
+ "h-4 w-4 rounded-full border transition-all duration-[150ms]",
1766
+ "bg-tollerud-surface-raised border-tollerud-border",
1767
+ "peer-focus-visible:outline-2 peer-focus-visible:outline-tollerud-yellow",
1768
+ "peer-checked:border-tollerud-yellow",
1769
+ "group-hover:border-tollerud-text-secondary",
1770
+ "flex items-center justify-center"
1771
+ ),
1772
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1773
+ "span",
1774
+ {
1775
+ className: cn(
1776
+ "h-2 w-2 rounded-full bg-tollerud-yellow transition-opacity duration-[150ms]",
1777
+ props.checked ? "opacity-100" : "opacity-0"
1778
+ )
1779
+ }
1780
+ )
1781
+ }
1782
+ )
1783
+ ] }),
1784
+ label && /* @__PURE__ */ jsxRuntime.jsx("span", { children: label })
1785
+ ]
1786
+ }
1787
+ );
1788
+ }
1789
+ );
1790
+ Radio.displayName = "Radio";
1791
+ var defaultLabels = {
1792
+ tollerudProject: "A Tollerud Project",
1793
+ allRightsReserved: "All rights reserved."
1794
+ };
1795
+ var MONOGRAM_PATH = "M82.4839273,140.272626 L95.1738252,140.272626 L95.1738252,143 L34.8114657,143 L34.8114657,140.272626 L47.5013636,140.272626 L47.5013636,28.2924381 C40.1277806,26.4177752 32.9252955,25.2241422 26.4088393,25.2241422 C12.1757856,25.2241422 4.11617359,34.5982703 4.11617359,39.8821508 C4.11617359,40.9049161 4.63028596,41.5867596 5.65932936,41.5867596 C7.20248513,41.5867596 7.37440169,40.3931266 8.06043062,38.8593855 C10.4615319,33.575505 15.6059302,31.5307881 20.4073141,31.5307881 C29.152955,31.5307881 35.1552988,38.5184637 35.1552988,47.2107482 C35.1552988,56.2447681 28.8107592,62.8907084 18.0070315,62.8907084 C7.5454996,62.891522 0,53.6882617 0,43.8023442 C0,30.8497582 11.3178401,21.986606 26.5799372,21.986606 C51.1026062,21.986606 84.1989996,39.2011209 104.948509,39.2011209 C118.495534,39.2011209 126.384048,31.7016558 126.384048,19.4300996 C126.384048,10.3968933 118.667451,4.60203698 115.580321,4.60203698 C114.552096,4.60203698 113.69415,5.1130128 113.69415,6.13577809 C113.69415,7.49946515 114.552096,7.6695192 115.409223,8.01044097 C115.752237,8.18049502 122.268693,10.5669474 122.268693,19.2592319 C122.268693,28.2924381 115.238125,34.0872945 107.177694,34.0872945 C97.7460244,34.0872945 91.0584702,26.4177752 91.0584702,17.8955448 C91.0584702,6.64675391 99.9760277,0 109.749893,0 C122.268693,0 129.642276,9.88510384 129.642276,19.6001536 C129.642276,34.2581622 119.181563,42.4386572 104.947691,42.4386572 C98.0890388,42.4386572 90.5443579,40.9049161 82.4839273,38.6901451 L82.4839273,140.272626 Z";
1796
+ function Footer({
1797
+ labels,
1798
+ layout = "responsive",
1799
+ className,
1800
+ style,
1801
+ unstyled = false,
1802
+ accent = false,
1803
+ classNameInner,
1804
+ classNameLogo,
1805
+ classNameText,
1806
+ classNameLink
1807
+ }) {
1808
+ const t = { ...defaultLabels, ...labels };
1809
+ const attribution = t.attribution?.trim();
1810
+ const footerSurface = unstyled ? "" : accent ? "border-t border-tollerud-yellow/20 bg-tollerud-yellow/5" : "border-t border-tollerud-border bg-tollerud-noir-900/80";
1811
+ const innerLayoutClasses = layout === "row" ? "max-w-7xl mx-auto px-8 flex flex-row items-center justify-between gap-4" : "max-w-7xl mx-auto px-8 flex flex-col md:flex-row items-center justify-center md:justify-between gap-4 md:gap-0";
1812
+ const logoColor = unstyled ? "" : accent ? "text-tollerud-yellow" : "text-tollerud-text-muted";
1813
+ const textWrapperClasses = layout === "row" ? "flex-1 text-right ml-4" : "flex-1 text-center md:text-right md:ml-4";
1814
+ const textLayoutClasses = layout === "row" ? "text-sm text-tollerud-text-secondary inline-flex flex-row items-center justify-end text-right gap-0" : "text-sm text-tollerud-text-secondary flex flex-col md:flex-row md:inline gap-0";
1815
+ return /* @__PURE__ */ jsxRuntime.jsx("footer", { className: cn("w-full pt-4 pb-4", footerSurface, className), style, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(innerLayoutClasses, classNameInner), children: [
1816
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0 md:flex-shrink-0", children: /* @__PURE__ */ jsxRuntime.jsxs(
1817
+ "svg",
1818
+ {
1819
+ width: "24",
1820
+ height: "24",
1821
+ viewBox: "0 0 130 143",
1822
+ version: "1.1",
1823
+ xmlns: "http://www.w3.org/2000/svg",
1824
+ xmlnsXlink: "http://www.w3.org/1999/xlink",
1825
+ className: cn("h-5 w-5", logoColor, classNameLogo),
1826
+ role: "img",
1827
+ children: [
1828
+ /* @__PURE__ */ jsxRuntime.jsx("title", { children: "Tollerud Logo" }),
1829
+ /* @__PURE__ */ jsxRuntime.jsx("g", { id: "Page-1", stroke: "none", strokeWidth: "1", fill: "none", fillRule: "evenodd", children: /* @__PURE__ */ jsxRuntime.jsx("g", { id: "Tollerud-Monogram", transform: "translate(-86.000000, -109.000000)", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("g", { id: "Group-2", transform: "translate(32.000000, 55.000000)", children: /* @__PURE__ */ jsxRuntime.jsx("g", { id: "Group", transform: "translate(54.000000, 54.000000)", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: MONOGRAM_PATH, id: "Monogram" }) }) }) }) })
1830
+ ]
1831
+ }
1832
+ ) }),
1833
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: textWrapperClasses, children: /* @__PURE__ */ jsxRuntime.jsxs("p", { className: cn(textLayoutClasses, classNameText), children: [
1834
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
1835
+ /* @__PURE__ */ jsxRuntime.jsx(
1836
+ "a",
1837
+ {
1838
+ href: "https://tollerud.no",
1839
+ target: "_blank",
1840
+ rel: "noopener noreferrer",
1841
+ className: cn(
1842
+ "underline decoration-tollerud-yellow decoration-[3px] underline-offset-[4px] hover:opacity-80 transition-opacity",
1843
+ classNameLink
1844
+ ),
1845
+ style: {
1846
+ textDecorationThickness: "3px",
1847
+ textUnderlineOffset: "4px"
1848
+ },
1849
+ children: t.tollerudProject
1850
+ }
1851
+ ),
1852
+ attribution ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1853
+ " ",
1854
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: attribution })
1855
+ ] }) : null,
1856
+ " "
1857
+ ] }),
1858
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: layout === "row" ? "ml-1" : "md:ml-1", children: t.allRightsReserved })
1859
+ ] }) })
1860
+ ] }) });
1861
+ }
1862
+ var Dialog = DialogPrimitive__namespace.Root;
1863
+ var DialogTrigger = DialogPrimitive__namespace.Trigger;
1864
+ var DialogPortal = DialogPrimitive__namespace.Portal;
1865
+ var DialogClose = DialogPrimitive__namespace.Close;
1866
+ var DialogOverlay = React2__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1867
+ DialogPrimitive__namespace.Overlay,
1868
+ {
1869
+ ref,
1870
+ className: cn(
1871
+ "fixed inset-0 z-50 bg-black/60 backdrop-blur-sm",
1872
+ className
1873
+ ),
1874
+ ...props
1875
+ }
1876
+ ));
1877
+ DialogOverlay.displayName = "DialogOverlay";
1878
+ var DialogContent = React2__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(DialogPortal, { children: [
1879
+ /* @__PURE__ */ jsxRuntime.jsx(DialogOverlay, {}),
1880
+ /* @__PURE__ */ jsxRuntime.jsxs(
1881
+ DialogPrimitive__namespace.Content,
1882
+ {
1883
+ ref,
1884
+ className: cn(
1885
+ "fixed top-1/2 left-1/2 z-50 w-full max-w-lg -translate-x-1/2 -translate-y-1/2",
1886
+ "rounded-lg border border-tollerud-border/30 bg-tollerud-noir-900 p-6 shadow-xl",
1887
+ "data-[state=open]:animate-none data-[state=closed]:animate-none",
1888
+ className
1889
+ ),
1890
+ ...props,
1891
+ children: [
1892
+ children,
1893
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogPrimitive__namespace.Close, { className: "absolute top-4 right-4 rounded-sm p-1 text-tollerud-text-muted hover:text-tollerud-foreground transition-colors cursor-pointer", children: [
1894
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-4 w-4" }),
1895
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Close" })
1896
+ ] })
1897
+ ]
1898
+ }
1899
+ )
1900
+ ] }));
1901
+ DialogContent.displayName = "DialogContent";
1902
+ var DialogHeader = ({
1903
+ className,
1904
+ ...props
1905
+ }) => /* @__PURE__ */ jsxRuntime.jsx(
1906
+ "div",
1907
+ {
1908
+ className: cn("flex flex-col gap-1.5 mb-4", className),
1909
+ ...props
1910
+ }
1911
+ );
1912
+ DialogHeader.displayName = "DialogHeader";
1913
+ var DialogFooter = ({
1914
+ className,
1915
+ ...props
1916
+ }) => /* @__PURE__ */ jsxRuntime.jsx(
1917
+ "div",
1918
+ {
1919
+ className: cn("flex flex-col-reverse sm:flex-row sm:justify-end gap-2 mt-6", className),
1920
+ ...props
1921
+ }
1922
+ );
1923
+ DialogFooter.displayName = "DialogFooter";
1924
+ var DialogTitle = React2__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1925
+ DialogPrimitive__namespace.Title,
1926
+ {
1927
+ ref,
1928
+ className: cn("text-base font-semibold text-tollerud-foreground", className),
1929
+ ...props
1930
+ }
1931
+ ));
1932
+ DialogTitle.displayName = "DialogTitle";
1933
+ var DialogDescription = React2__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1934
+ DialogPrimitive__namespace.Description,
1935
+ {
1936
+ ref,
1937
+ className: cn("text-sm text-tollerud-text-secondary", className),
1938
+ ...props
1939
+ }
1940
+ ));
1941
+ DialogDescription.displayName = "DialogDescription";
1942
+ var TooltipProvider = TooltipPrimitive__namespace.Provider;
1943
+ var TooltipContext = React2__namespace.createContext(null);
1944
+ function Tooltip({
1945
+ children,
1946
+ defaultOpen,
1947
+ open: controlledOpen,
1948
+ onOpenChange: controlledOnOpenChange,
1949
+ ...props
1950
+ }) {
1951
+ const [internalOpen, setInternalOpen] = React2__namespace.useState(defaultOpen ?? false);
1952
+ const isControlled = controlledOpen !== void 0;
1953
+ const open = isControlled ? controlledOpen : internalOpen;
1954
+ const setOpen = isControlled ? controlledOnOpenChange ?? setInternalOpen : setInternalOpen;
1955
+ return /* @__PURE__ */ jsxRuntime.jsx(TooltipContext.Provider, { value: { open, setOpen }, children: /* @__PURE__ */ jsxRuntime.jsx(TooltipPrimitive__namespace.Root, { open, onOpenChange: (v) => setOpen(v), ...props, children }) });
1956
+ }
1957
+ Tooltip.displayName = "Tooltip";
1958
+ var TooltipTrigger = React2__namespace.forwardRef(({ onClick, onTouchStart, children, ...props }, ref) => {
1959
+ const ctx = React2__namespace.useContext(TooltipContext);
1960
+ const touchFired = React2__namespace.useRef(false);
1961
+ return /* @__PURE__ */ jsxRuntime.jsx(
1962
+ TooltipPrimitive__namespace.Trigger,
1963
+ {
1964
+ ref,
1965
+ onClick: (e) => {
1966
+ if (touchFired.current) {
1967
+ touchFired.current = false;
1968
+ return;
1969
+ }
1970
+ if (ctx) {
1971
+ ctx.setOpen(!ctx.open);
1972
+ }
1973
+ onClick?.(e);
1974
+ },
1975
+ onTouchStart: (e) => {
1976
+ touchFired.current = true;
1977
+ if (ctx && !ctx.open) {
1978
+ ctx.setOpen(true);
1979
+ }
1980
+ onTouchStart?.(e);
1981
+ },
1982
+ ...props,
1983
+ children
1984
+ }
1985
+ );
1986
+ });
1987
+ TooltipTrigger.displayName = "TooltipTrigger";
1988
+ var TooltipContent = React2__namespace.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1989
+ TooltipPrimitive__namespace.Content,
1990
+ {
1991
+ ref,
1992
+ sideOffset,
1993
+ className: cn(
1994
+ "z-50 overflow-hidden rounded-md border border-tollerud-border/30",
1995
+ "bg-tollerud-noir-800 px-3 py-1.5 text-xs text-tollerud-foreground",
1996
+ "shadow-md",
1997
+ "animate-in fade-in-0 zoom-in-95",
1998
+ "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
1999
+ "data-[side=bottom]:slide-in-from-top-1",
2000
+ "data-[side=left]:slide-in-from-right-1",
2001
+ "data-[side=right]:slide-in-from-left-1",
2002
+ "data-[side=top]:slide-in-from-bottom-1",
2003
+ className
2004
+ ),
2005
+ ...props
2006
+ }
2007
+ ));
2008
+ TooltipContent.displayName = "TooltipContent";
2009
+ var Tabs = TabsPrimitive__namespace.Root;
2010
+ var TabsList = React2__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2011
+ TabsPrimitive__namespace.List,
2012
+ {
2013
+ ref,
2014
+ className: cn(
2015
+ "inline-flex h-9 items-center justify-center rounded-lg",
2016
+ "bg-tollerud-noir-800 p-1 text-tollerud-text-muted",
2017
+ className
2018
+ ),
2019
+ ...props
2020
+ }
2021
+ ));
2022
+ TabsList.displayName = "TabsList";
2023
+ var TabsTrigger = React2__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2024
+ TabsPrimitive__namespace.Trigger,
2025
+ {
2026
+ ref,
2027
+ className: cn(
2028
+ "inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1",
2029
+ "text-xs font-medium transition-all",
2030
+ "text-tollerud-text-muted hover:text-tollerud-foreground",
2031
+ "data-[state=active]:bg-tollerud-surface-raised data-[state=active]:text-tollerud-foreground data-[state=active]:shadow-sm",
2032
+ "disabled:pointer-events-none disabled:opacity-50",
2033
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-tollerud-yellow/50",
2034
+ className
2035
+ ),
2036
+ ...props
2037
+ }
2038
+ ));
2039
+ TabsTrigger.displayName = "TabsTrigger";
2040
+ var TabsContent = React2__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2041
+ TabsPrimitive__namespace.Content,
2042
+ {
2043
+ ref,
2044
+ className: cn(
2045
+ "mt-2 ring-offset-tollerud-black focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-tollerud-yellow/50 focus-visible:ring-offset-2",
2046
+ className
2047
+ ),
2048
+ ...props
2049
+ }
2050
+ ));
2051
+ TabsContent.displayName = "TabsContent";
2052
+ function Skeleton({
2053
+ className,
2054
+ ...props
2055
+ }) {
2056
+ return /* @__PURE__ */ jsxRuntime.jsx(
2057
+ "div",
2058
+ {
2059
+ className: cn(
2060
+ "animate-pulse rounded-md bg-tollerud-noir-800",
2061
+ className
2062
+ ),
2063
+ ...props
2064
+ }
2065
+ );
2066
+ }
2067
+ var Progress = React2__namespace.forwardRef(({ className, value, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2068
+ ProgressPrimitive__namespace.Root,
2069
+ {
2070
+ ref,
2071
+ className: cn(
2072
+ "relative h-2 w-full overflow-hidden rounded-full bg-tollerud-noir-800",
2073
+ className
2074
+ ),
2075
+ ...props,
2076
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2077
+ ProgressPrimitive__namespace.Indicator,
2078
+ {
2079
+ className: "h-full w-full flex-1 rounded-full bg-tollerud-yellow transition-all duration-300 ease-in-out",
2080
+ style: { transform: `translateX(-${100 - (value || 0)}%)` }
2081
+ }
2082
+ )
2083
+ }
2084
+ ));
2085
+ Progress.displayName = "Progress";
2086
+ var Toaster = ({ theme = "dark", ...props }) => {
2087
+ const [mobile, setMobile] = React2.useState(false);
2088
+ React2.useEffect(() => {
2089
+ const check = () => setMobile(window.innerWidth < 640);
2090
+ check();
2091
+ window.addEventListener("resize", check);
2092
+ return () => window.removeEventListener("resize", check);
2093
+ }, []);
2094
+ return /* @__PURE__ */ jsxRuntime.jsx(
2095
+ sonner.Toaster,
2096
+ {
2097
+ position: mobile ? "top-center" : "top-right",
2098
+ theme,
2099
+ className: "toaster group",
2100
+ toastOptions: {
2101
+ classNames: {
2102
+ toast: "group toast group-[.toaster]:bg-tollerud-noir-900 group-[.toaster]:text-tollerud-foreground group-[.toaster]:border group-[.toaster]:border-tollerud-border/30 group-[.toaster]:shadow-lg",
2103
+ description: "group-[.toast]:text-tollerud-text-muted text-xs",
2104
+ actionButton: "group-[.toast]:bg-tollerud-yellow group-[.toast]:text-tollerud-black group-[.toast]:text-xs group-[.toast]:font-medium group-[.toast]:px-3 group-[.toast]:py-1 group-[.toast]:rounded",
2105
+ cancelButton: "group-[.toast]:bg-tollerud-noir-800 group-[.toast]:text-tollerud-text-muted group-[.toast]:text-xs group-[.toast]:px-3 group-[.toast]:py-1 group-[.toast]:rounded",
2106
+ success: "group-[.toast]:border-l-tollerud-success group-[.toast]:border-l-2",
2107
+ error: "group-[.toast]:border-l-tollerud-error group-[.toast]:border-l-2",
2108
+ warning: "group-[.toast]:border-l-tollerud-yellow group-[.toast]:border-l-2",
2109
+ info: "group-[.toast]:border-l-tollerud-info group-[.toast]:border-l-2"
2110
+ }
2111
+ },
2112
+ ...props
2113
+ }
2114
+ );
2115
+ };
2116
+ var Empty = React2.forwardRef(
2117
+ ({ className, ...props }, ref) => {
2118
+ return /* @__PURE__ */ jsxRuntime.jsx(
2119
+ "div",
2120
+ {
2121
+ ref,
2122
+ className: cn(
2123
+ "flex w-full flex-1 flex-col items-center justify-center text-center py-12",
2124
+ className
2125
+ ),
2126
+ ...props
2127
+ }
2128
+ );
2129
+ }
2130
+ );
2131
+ Empty.displayName = "Empty";
2132
+ var EmptyHeader = React2.forwardRef(
2133
+ ({ className, ...props }, ref) => {
2134
+ return /* @__PURE__ */ jsxRuntime.jsx(
2135
+ "div",
2136
+ {
2137
+ ref,
2138
+ className: cn(
2139
+ "flex max-w-sm flex-col items-center gap-2",
2140
+ className
2141
+ ),
2142
+ ...props
2143
+ }
2144
+ );
2145
+ }
2146
+ );
2147
+ EmptyHeader.displayName = "EmptyHeader";
2148
+ var EmptyIcon = React2.forwardRef(
2149
+ ({ className, ...props }, ref) => {
2150
+ return /* @__PURE__ */ jsxRuntime.jsx(
2151
+ "div",
2152
+ {
2153
+ ref,
2154
+ className: cn(
2155
+ "flex items-center justify-center w-12 h-12 rounded-full bg-tollerud-noir-800 text-tollerud-text-muted mb-2",
2156
+ className
2157
+ ),
2158
+ ...props
2159
+ }
2160
+ );
2161
+ }
2162
+ );
2163
+ EmptyIcon.displayName = "EmptyIcon";
2164
+ var EmptyTitle = React2.forwardRef(
2165
+ ({ className, ...props }, ref) => {
2166
+ return /* @__PURE__ */ jsxRuntime.jsx(
2167
+ "h3",
2168
+ {
2169
+ ref,
2170
+ className: cn(
2171
+ "text-base font-semibold text-tollerud-foreground",
2172
+ className
2173
+ ),
2174
+ ...props
2175
+ }
2176
+ );
2177
+ }
2178
+ );
2179
+ EmptyTitle.displayName = "EmptyTitle";
2180
+ var EmptyDescription = React2.forwardRef(
2181
+ ({ className, ...props }, ref) => {
2182
+ return /* @__PURE__ */ jsxRuntime.jsx(
2183
+ "p",
2184
+ {
2185
+ ref,
2186
+ className: cn(
2187
+ "text-sm text-tollerud-text-secondary max-w-sm",
2188
+ className
2189
+ ),
2190
+ ...props
2191
+ }
2192
+ );
2193
+ }
2194
+ );
2195
+ EmptyDescription.displayName = "EmptyDescription";
2196
+ var EmptyContent = React2.forwardRef(
2197
+ ({ className, ...props }, ref) => {
2198
+ return /* @__PURE__ */ jsxRuntime.jsx(
2199
+ "div",
2200
+ {
2201
+ ref,
2202
+ className: cn(
2203
+ "flex w-full max-w-sm flex-col items-center gap-4 mt-4",
2204
+ className
2205
+ ),
2206
+ ...props
2207
+ }
2208
+ );
2209
+ }
2210
+ );
2211
+ EmptyContent.displayName = "EmptyContent";
2212
+ var DropdownMenu = DropdownMenuPrimitive__namespace.Root;
2213
+ var DropdownMenuTrigger = DropdownMenuPrimitive__namespace.Trigger;
2214
+ var DropdownMenuContent = React2.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
2215
+ DropdownMenuPrimitive__namespace.Content,
2216
+ {
2217
+ ref,
2218
+ sideOffset,
2219
+ className: cn(
2220
+ "z-50 min-w-[9rem] overflow-hidden rounded-lg border p-1 shadow-md",
2221
+ "bg-tollerud-noir-850 border-tollerud-border/30 text-tollerud-text-primary",
2222
+ "data-[state=open]:animate-in data-[state=closed]:animate-out",
2223
+ "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
2224
+ "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
2225
+ "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2",
2226
+ "data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
2227
+ className
2228
+ ),
2229
+ ...props
2230
+ }
2231
+ ) }));
2232
+ DropdownMenuContent.displayName = "DropdownMenuContent";
2233
+ var DropdownMenuItem = React2.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2234
+ DropdownMenuPrimitive__namespace.Item,
2235
+ {
2236
+ ref,
2237
+ className: cn(
2238
+ "relative flex cursor-default select-none items-center rounded-md px-2 py-1.5 text-sm outline-none",
2239
+ "text-tollerud-text-secondary data-[highlighted]:text-tollerud-text-primary",
2240
+ "data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
2241
+ "data-[highlighted]:bg-tollerud-surface-raised",
2242
+ inset && "pl-8",
2243
+ className
2244
+ ),
2245
+ ...props
2246
+ }
2247
+ ));
2248
+ DropdownMenuItem.displayName = "DropdownMenuItem";
2249
+ var DropdownMenuSeparator = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2250
+ DropdownMenuPrimitive__namespace.Separator,
2251
+ {
2252
+ ref,
2253
+ className: cn("-mx-1 my-1 h-px bg-tollerud-border/30", className),
2254
+ ...props
2255
+ }
2256
+ ));
2257
+ DropdownMenuSeparator.displayName = "DropdownMenuSeparator";
2258
+ var DropdownMenuLabel = React2.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2259
+ DropdownMenuPrimitive__namespace.Label,
2260
+ {
2261
+ ref,
2262
+ className: cn("px-2 py-1.5 text-xs font-semibold text-tollerud-text-muted", inset && "pl-8", className),
2263
+ ...props
2264
+ }
2265
+ ));
2266
+ DropdownMenuLabel.displayName = "DropdownMenuLabel";
2267
+ var Sheet = ({ open, onOpenChange, children }) => /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Root, { open, onOpenChange, children });
2268
+ var SheetTrigger = DialogPrimitive__namespace.Trigger;
2269
+ var SheetClose = DialogPrimitive__namespace.Close;
2270
+ var SheetOverlay = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2271
+ DialogPrimitive__namespace.Overlay,
2272
+ {
2273
+ ref,
2274
+ className: cn(
2275
+ "fixed inset-0 z-50 bg-black/60 backdrop-blur-sm",
2276
+ "data-[state=open]:animate-in data-[state=closed]:animate-out",
2277
+ "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
2278
+ className
2279
+ ),
2280
+ ...props
2281
+ }
2282
+ ));
2283
+ SheetOverlay.displayName = "SheetOverlay";
2284
+ var SheetContent = React2.forwardRef(({ className, children, side = "right", ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(SheetOverlay, { children: /* @__PURE__ */ jsxRuntime.jsxs(
2285
+ DialogPrimitive__namespace.Content,
2286
+ {
2287
+ ref,
2288
+ className: cn(
2289
+ "fixed z-50 gap-4 bg-tollerud-noir-900 border-tollerud-border/30 p-6 shadow-lg",
2290
+ "data-[state=open]:animate-in data-[state=closed]:animate-out",
2291
+ side === "right" && [
2292
+ "inset-y-0 right-0 h-full w-full max-w-md border-l",
2293
+ "data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right"
2294
+ ],
2295
+ side === "left" && [
2296
+ "inset-y-0 left-0 h-full w-full max-w-md border-r",
2297
+ "data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left"
2298
+ ],
2299
+ className
2300
+ ),
2301
+ ...props,
2302
+ children: [
2303
+ children,
2304
+ /* @__PURE__ */ jsxRuntime.jsxs(SheetClose, { className: "absolute right-4 top-4 rounded-sm opacity-70 hover:opacity-100 transition-opacity text-tollerud-text-muted hover:text-tollerud-text-primary", children: [
2305
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
2306
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18" }),
2307
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m6 6 12 12" })
2308
+ ] }),
2309
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Close" })
2310
+ ] })
2311
+ ]
2312
+ }
2313
+ ) }));
2314
+ SheetContent.displayName = "SheetContent";
2315
+ var SheetHeader = ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-col space-y-1.5 text-left", className), ...props });
2316
+ var SheetTitle = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2317
+ DialogPrimitive__namespace.Title,
2318
+ {
2319
+ ref,
2320
+ className: cn("text-base font-semibold text-tollerud-text-primary", className),
2321
+ ...props
2322
+ }
2323
+ ));
2324
+ SheetTitle.displayName = "SheetTitle";
2325
+ var SheetDescription = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2326
+ DialogPrimitive__namespace.Description,
2327
+ {
2328
+ ref,
2329
+ className: cn("text-sm text-tollerud-text-secondary", className),
2330
+ ...props
2331
+ }
2332
+ ));
2333
+ SheetDescription.displayName = "SheetDescription";
2334
+ function DataTableInner({
2335
+ columns,
2336
+ data,
2337
+ rowKey,
2338
+ onRowClick,
2339
+ className,
2340
+ emptyMessage = "No data",
2341
+ forwardedRef
2342
+ }) {
2343
+ const [sortKey, setSortKey] = React2.useState(null);
2344
+ const [sortDir, setSortDir] = React2.useState("asc");
2345
+ const [filters, setFilters] = React2.useState({});
2346
+ const filtered = React2.useMemo(() => {
2347
+ const activeFilters = Object.entries(filters).filter(([, v]) => v.trim() !== "");
2348
+ if (activeFilters.length === 0) return data;
2349
+ return data.filter(
2350
+ (row) => activeFilters.every(([key, filterValue]) => {
2351
+ const cellValue = String(row[key] ?? "").toLowerCase();
2352
+ return cellValue.includes(filterValue.toLowerCase());
2353
+ })
2354
+ );
2355
+ }, [data, filters]);
2356
+ const sorted = React2.useMemo(() => {
2357
+ if (!sortKey) return filtered;
2358
+ const col = columns.find((c) => c.key === sortKey);
2359
+ if (!col?.sortable) return filtered;
2360
+ return [...filtered].sort((a, b) => {
2361
+ const aVal = a[sortKey];
2362
+ const bVal = b[sortKey];
2363
+ if (typeof aVal === "number" && typeof bVal === "number") {
2364
+ return sortDir === "asc" ? aVal - bVal : bVal - aVal;
2365
+ }
2366
+ const aStr = String(aVal ?? "");
2367
+ const bStr = String(bVal ?? "");
2368
+ const cmp = aStr.localeCompare(bStr, "nb", { numeric: true });
2369
+ return sortDir === "asc" ? cmp : -cmp;
2370
+ });
2371
+ }, [filtered, sortKey, sortDir, columns]);
2372
+ const getRowKey = (row, i) => {
2373
+ if (typeof rowKey === "function") return rowKey(row);
2374
+ if (rowKey) return row[rowKey];
2375
+ return row.id ?? row.key ?? i;
2376
+ };
2377
+ const toggleSort = (key) => {
2378
+ if (sortKey === key) {
2379
+ setSortDir((d) => d === "asc" ? "desc" : "asc");
2380
+ } else {
2381
+ setSortKey(key);
2382
+ setSortDir("asc");
2383
+ }
2384
+ };
2385
+ const updateFilter = (key, value) => {
2386
+ setFilters((prev) => {
2387
+ const next = { ...prev };
2388
+ if (value.trim() === "") {
2389
+ delete next[key];
2390
+ } else {
2391
+ next[key] = value;
2392
+ }
2393
+ return next;
2394
+ });
2395
+ };
2396
+ const hasActiveFilters = Object.values(filters).some((v) => v.trim() !== "");
2397
+ const filterableColumns = columns.filter((c) => c.filterable);
2398
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: forwardedRef, className: cn("overflow-x-auto rounded-lg border border-tollerud-border/30", className), children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full text-sm", children: [
2399
+ /* @__PURE__ */ jsxRuntime.jsxs("thead", { children: [
2400
+ /* @__PURE__ */ jsxRuntime.jsx("tr", { className: "border-b border-tollerud-border/30 bg-tollerud-noir-900", children: columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx(
2401
+ "th",
2402
+ {
2403
+ className: cn(
2404
+ "px-3 py-2.5 text-xs font-semibold text-tollerud-text-muted uppercase tracking-wider",
2405
+ col.sortable && "cursor-pointer select-none hover:text-tollerud-text-primary transition-colors",
2406
+ col.align === "right" && "text-right",
2407
+ col.align === "center" && "text-center"
2408
+ ),
2409
+ style: col.width ? { width: col.width } : void 0,
2410
+ onClick: () => col.sortable && toggleSort(col.key),
2411
+ children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1.5", children: [
2412
+ col.label,
2413
+ col.sortable && sortKey === col.key && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-tollerud-accent", children: sortDir === "asc" ? "\u2191" : "\u2193" }),
2414
+ col.sortable && sortKey !== col.key && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-tollerud-text-muted/30", children: "\u2195" }),
2415
+ col.filterable && /* @__PURE__ */ jsxRuntime.jsx(
2416
+ "svg",
2417
+ {
2418
+ width: "12",
2419
+ height: "12",
2420
+ viewBox: "0 0 24 24",
2421
+ fill: "none",
2422
+ stroke: "currentColor",
2423
+ strokeWidth: "2",
2424
+ strokeLinecap: "round",
2425
+ strokeLinejoin: "round",
2426
+ className: cn(
2427
+ "opacity-40",
2428
+ filters[col.key] && "opacity-100 text-tollerud-yellow"
2429
+ ),
2430
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4 4h16v2.172a2 2 0 0 1-.586 1.414L15 12v7l-6 2v-8.5L4.52 7.53A2 2 0 0 1 4 6.16V4z" })
2431
+ }
2432
+ )
2433
+ ] })
2434
+ },
2435
+ col.key
2436
+ )) }),
2437
+ filterableColumns.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("tr", { className: "border-b border-tollerud-border/20", children: columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx(
2438
+ "th",
2439
+ {
2440
+ className: cn(
2441
+ "px-1.5 py-1",
2442
+ col.align === "right" && "text-right",
2443
+ col.align === "center" && "text-center"
2444
+ ),
2445
+ children: col.filterable ? /* @__PURE__ */ jsxRuntime.jsx(
2446
+ "input",
2447
+ {
2448
+ type: "text",
2449
+ placeholder: `Filter ${col.label.toLowerCase()}\u2026`,
2450
+ value: filters[col.key] ?? "",
2451
+ onChange: (e) => updateFilter(col.key, e.target.value),
2452
+ className: cn(
2453
+ "w-full px-2 py-1 text-xs rounded border transition-colors outline-none",
2454
+ "bg-tollerud-noir-900/50 border-tollerud-border/20 text-tollerud-text-primary placeholder:text-tollerud-text-muted/40",
2455
+ "focus:border-tollerud-yellow/40 focus:ring-1 focus:ring-tollerud-yellow/20"
2456
+ )
2457
+ }
2458
+ ) : null
2459
+ },
2460
+ `filter-${col.key}`
2461
+ )) })
2462
+ ] }),
2463
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: sorted.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx(
2464
+ "td",
2465
+ {
2466
+ colSpan: columns.length,
2467
+ className: "px-3 py-8 text-center text-sm text-tollerud-text-muted",
2468
+ children: hasActiveFilters ? "No matching rows" : emptyMessage
2469
+ }
2470
+ ) }) : sorted.map((row, i) => /* @__PURE__ */ jsxRuntime.jsx(
2471
+ "tr",
2472
+ {
2473
+ className: cn(
2474
+ "border-b border-tollerud-border/20 transition-colors",
2475
+ onRowClick && "cursor-pointer hover:bg-tollerud-surface-raised/50"
2476
+ ),
2477
+ onClick: () => onRowClick?.(row),
2478
+ children: columns.map((col) => {
2479
+ const value = row[col.key];
2480
+ return /* @__PURE__ */ jsxRuntime.jsx(
2481
+ "td",
2482
+ {
2483
+ className: cn(
2484
+ "px-3 py-2.5 text-tollerud-text-secondary",
2485
+ col.align === "right" && "text-right",
2486
+ col.align === "center" && "text-center",
2487
+ "font-mono text-xs"
2488
+ ),
2489
+ children: col.render ? col.render(value, row) : String(value ?? "\u2014")
2490
+ },
2491
+ col.key
2492
+ );
2493
+ })
2494
+ },
2495
+ getRowKey(row, i)
2496
+ )) })
2497
+ ] }) });
2498
+ }
2499
+ var DataTable = React2.forwardRef((props, ref) => /* @__PURE__ */ jsxRuntime.jsx(DataTableInner, { ...props, forwardedRef: ref }));
2500
+ DataTable.displayName = "DataTable";
2501
+ function GlowCard({
2502
+ children,
2503
+ className,
2504
+ glowColor = "var(--tollerud-accent, #FFFF00)",
2505
+ intensity = 0.15
2506
+ }) {
2507
+ const ref = React2.useRef(null);
2508
+ const [pos, setPos] = React2.useState({ x: 0, y: 0 });
2509
+ const [isHovered, setIsHovered] = React2.useState(false);
2510
+ const handleMouseMove = (e) => {
2511
+ if (!ref.current) return;
2512
+ const rect = ref.current.getBoundingClientRect();
2513
+ setPos({
2514
+ x: (e.clientX - rect.left) / rect.width * 100,
2515
+ y: (e.clientY - rect.top) / rect.height * 100
2516
+ });
2517
+ };
2518
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2519
+ "div",
2520
+ {
2521
+ ref,
2522
+ className: cn("relative overflow-hidden", className),
2523
+ onMouseMove: handleMouseMove,
2524
+ onMouseEnter: () => setIsHovered(true),
2525
+ onMouseLeave: () => setIsHovered(false),
2526
+ children: [
2527
+ /* @__PURE__ */ jsxRuntime.jsx(
2528
+ "div",
2529
+ {
2530
+ className: "pointer-events-none absolute inset-0 transition-opacity duration-300",
2531
+ style: {
2532
+ opacity: isHovered ? 1 : 0,
2533
+ background: `radial-gradient(600px circle at ${pos.x}% ${pos.y}%, ${glowColor} ${intensity * 100}%, transparent 70%)`
2534
+ }
2535
+ }
2536
+ ),
2537
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative z-10", children })
2538
+ ]
2539
+ }
2540
+ );
2541
+ }
2542
+ function BentoDashboard({
2543
+ title,
2544
+ hosts = [],
2545
+ metrics = [],
2546
+ services = [],
2547
+ incidents = [],
2548
+ className
2549
+ }) {
2550
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("space-y-4", className), children: [
2551
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2552
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-lg font-semibold text-tollerud-text-primary", children: title }),
2553
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-tollerud-text-muted", children: [
2554
+ hosts.length,
2555
+ " hosts \xB7 ",
2556
+ services.length,
2557
+ " services",
2558
+ incidents.length > 0 && ` \xB7 ${incidents.length} active incident${incidents.length > 1 ? "s" : ""}`
2559
+ ] })
2560
+ ] }) }),
2561
+ hosts.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-3", children: [
2562
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "md:col-span-2 lg:col-span-1", children: /* @__PURE__ */ jsxRuntime.jsx(HostCardComponent, { host: hosts[0] }) }),
2563
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-3 md:col-span-2 lg:col-span-1", children: hosts.slice(1).map((h, i) => /* @__PURE__ */ jsxRuntime.jsx(HostCardComponent, { host: h }, h.hostname ?? i)) })
2564
+ ] }),
2565
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-3 gap-3", children: [
2566
+ metrics.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lg:col-span-2", children: [
2567
+ /* @__PURE__ */ jsxRuntime.jsx(SectionLabel, { children: "Metrics" }),
2568
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 sm:grid-cols-4 gap-2", children: metrics.map((m, i) => /* @__PURE__ */ jsxRuntime.jsx(StatCardComponent, { stat: m }, m.label ?? i)) })
2569
+ ] }),
2570
+ services.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2571
+ /* @__PURE__ */ jsxRuntime.jsx(SectionLabel, { children: "Services" }),
2572
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: services.slice(0, 4).map((s, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-tollerud-border/20 bg-tollerud-surface p-3", children: [
2573
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
2574
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-tollerud-text-primary", children: s.service }),
2575
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
2576
+ "text-xs px-1.5 py-0.5 rounded-full font-medium",
2577
+ s.status === "online" && "text-tollerud-accent bg-tollerud-accent/10",
2578
+ s.status === "warning" && "text-tollerud-warning bg-tollerud-warning/10",
2579
+ s.status === "offline" && "text-tollerud-error bg-tollerud-error/10",
2580
+ s.status === "idle" && "text-tollerud-text-muted bg-tollerud-noir-800"
2581
+ ), children: s.status })
2582
+ ] }),
2583
+ s.responseTime && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-tollerud-text-muted mt-1", children: [
2584
+ s.responseTime,
2585
+ " response"
2586
+ ] })
2587
+ ] }, s.service ?? i)) })
2588
+ ] })
2589
+ ] }),
2590
+ incidents.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2591
+ /* @__PURE__ */ jsxRuntime.jsx(SectionLabel, { children: "Recent Incidents" }),
2592
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1.5", children: incidents.slice(0, 4).map((inc, i) => /* @__PURE__ */ jsxRuntime.jsx(IncidentCardItem, { incident: inc }, inc.title + i)) })
2593
+ ] })
2594
+ ] });
2595
+ }
2596
+ function SectionLabel({ children }) {
2597
+ return /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-semibold text-tollerud-text-muted uppercase tracking-wider mb-2", children });
2598
+ }
2599
+ function HostCardComponent({ host }) {
2600
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(
2601
+ "rounded-xl border p-4",
2602
+ host.status === "online" ? "border-tollerud-border/30 bg-tollerud-surface" : host.status === "warning" ? "border-tollerud-warning/30 bg-tollerud-warning/5" : "border-tollerud-border/20 bg-tollerud-surface opacity-70"
2603
+ ), children: [
2604
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-3", children: [
2605
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2606
+ /* @__PURE__ */ jsxRuntime.jsx(StatusDotComp, { status: host.status }),
2607
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold text-tollerud-text-primary", children: host.hostname })
2608
+ ] }),
2609
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-tollerud-text-muted font-mono", children: host.ip })
2610
+ ] }),
2611
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-2 text-xs", children: [
2612
+ host.cpu && /* @__PURE__ */ jsxRuntime.jsx(MetricBadge, { label: "CPU", value: host.cpu }),
2613
+ host.memory && /* @__PURE__ */ jsxRuntime.jsx(MetricBadge, { label: "Mem", value: host.memory }),
2614
+ host.disk && /* @__PURE__ */ jsxRuntime.jsx(MetricBadge, { label: "Disk", value: host.disk }),
2615
+ host.uptime && /* @__PURE__ */ jsxRuntime.jsx(MetricBadge, { label: "Up", value: host.uptime })
2616
+ ] })
2617
+ ] });
2618
+ }
2619
+ function StatCardComponent({ stat }) {
2620
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-tollerud-border/20 bg-tollerud-surface p-3", children: [
2621
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-tollerud-text-muted", children: stat.label }),
2622
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-lg font-semibold text-tollerud-text-primary mt-0.5", children: stat.value }),
2623
+ stat.change && /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
2624
+ "text-xs font-medium",
2625
+ stat.change.direction === "up" ? "text-tollerud-accent" : "text-tollerud-error"
2626
+ ), children: stat.change.value })
2627
+ ] });
2628
+ }
2629
+ function IncidentCardItem({ incident }) {
2630
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(
2631
+ "flex items-start gap-3 rounded-lg border p-3",
2632
+ incident.acknowledged ? "border-tollerud-border/10 bg-tollerud-noir-900/50 opacity-60" : "border-tollerud-border/20 bg-tollerud-surface"
2633
+ ), children: [
2634
+ /* @__PURE__ */ jsxRuntime.jsx(SeverityDot, { severity: incident.severity }),
2635
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
2636
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2637
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-tollerud-text-primary truncate", children: incident.title }),
2638
+ incident.acknowledged && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-tollerud-text-muted", children: "(acknowledged)" })
2639
+ ] }),
2640
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-xs text-tollerud-text-muted mt-0.5", children: [
2641
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: incident.service }),
2642
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "\xB7" }),
2643
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: incident.timestamp })
2644
+ ] }),
2645
+ incident.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-tollerud-text-secondary mt-1", children: incident.description })
2646
+ ] })
2647
+ ] });
2648
+ }
2649
+ function StatusDotComp({ status }) {
2650
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
2651
+ "inline-block w-2 h-2 rounded-full",
2652
+ status === "online" && "bg-tollerud-accent shadow-[0_0_4px_var(--tollerud-accent)]",
2653
+ status === "warning" && "bg-tollerud-warning",
2654
+ status === "offline" && "bg-tollerud-error"
2655
+ ) });
2656
+ }
2657
+ function SeverityDot({ severity }) {
2658
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
2659
+ "inline-block w-2 h-2 rounded-full mt-1 shrink-0",
2660
+ severity === "critical" && "bg-tollerud-error shadow-[0_0_4px_var(--tollerud-error)]",
2661
+ severity === "high" && "bg-tollerud-warning",
2662
+ severity === "medium" && "bg-tollerud-accent",
2663
+ severity === "low" && "bg-tollerud-text-muted",
2664
+ severity === "info" && "bg-tollerud-info"
2665
+ ) });
2666
+ }
2667
+ function MetricBadge({ label, value }) {
2668
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded bg-tollerud-noir-800 px-2 py-1.5", children: [
2669
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-tollerud-text-muted", children: label }),
2670
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "float-right text-tollerud-text-primary font-mono", children: value })
2671
+ ] });
2672
+ }
2673
+
2674
+ exports.ActionDiff = ActionDiff;
2675
+ exports.ActionRow = ActionRow;
2676
+ exports.Alert = Alert;
2677
+ exports.AlertInbox = AlertInbox;
2678
+ exports.ApprovalCard = ApprovalCard;
2679
+ exports.BackupStatusPanel = BackupStatusPanel;
2680
+ exports.Badge = Badge;
2681
+ exports.BentoDashboard = BentoDashboard;
2682
+ exports.Button = Button;
2683
+ exports.Card = Card;
2684
+ exports.Checkbox = Checkbox;
2685
+ exports.CodeBlock = CodeBlock;
2686
+ exports.CommandMenu = CommandMenu;
2687
+ exports.Container = Container;
2688
+ exports.DataTable = DataTable;
2689
+ exports.Dialog = Dialog;
2690
+ exports.DialogClose = DialogClose;
2691
+ exports.DialogContent = DialogContent;
2692
+ exports.DialogDescription = DialogDescription;
2693
+ exports.DialogFooter = DialogFooter;
2694
+ exports.DialogHeader = DialogHeader;
2695
+ exports.DialogOverlay = DialogOverlay;
2696
+ exports.DialogPortal = DialogPortal;
2697
+ exports.DialogTitle = DialogTitle;
2698
+ exports.DialogTrigger = DialogTrigger;
2699
+ exports.DockerStackCard = DockerStackCard;
2700
+ exports.DropdownMenu = DropdownMenu;
2701
+ exports.DropdownMenuContent = DropdownMenuContent;
2702
+ exports.DropdownMenuItem = DropdownMenuItem;
2703
+ exports.DropdownMenuLabel = DropdownMenuLabel;
2704
+ exports.DropdownMenuSeparator = DropdownMenuSeparator;
2705
+ exports.DropdownMenuTrigger = DropdownMenuTrigger;
2706
+ exports.Empty = Empty;
2707
+ exports.EmptyContent = EmptyContent;
2708
+ exports.EmptyDescription = EmptyDescription;
2709
+ exports.EmptyHeader = EmptyHeader;
2710
+ exports.EmptyIcon = EmptyIcon;
2711
+ exports.EmptyTitle = EmptyTitle;
2712
+ exports.Footer = Footer;
2713
+ exports.GlowCard = GlowCard;
2714
+ exports.HostCard = HostCard;
2715
+ exports.IncidentCard = IncidentCard;
2716
+ exports.Input = Input;
2717
+ exports.Kbd = Kbd;
2718
+ exports.LogViewer = LogViewer;
2719
+ exports.NoirGlowBackground = NoirGlowBackground;
2720
+ exports.Progress = Progress;
2721
+ exports.Radio = Radio;
2722
+ exports.RadioGroup = RadioGroup;
2723
+ exports.RollbackPlan = RollbackPlan;
2724
+ exports.Select = Select;
2725
+ exports.ServiceHealthCard = ServiceHealthCard;
2726
+ exports.Sheet = Sheet;
2727
+ exports.SheetClose = SheetClose;
2728
+ exports.SheetContent = SheetContent;
2729
+ exports.SheetDescription = SheetDescription;
2730
+ exports.SheetHeader = SheetHeader;
2731
+ exports.SheetTitle = SheetTitle;
2732
+ exports.SheetTrigger = SheetTrigger;
2733
+ exports.Skeleton = Skeleton;
2734
+ exports.StatCard = StatCard;
2735
+ exports.StatusDot = StatusDot;
2736
+ exports.Switch = Switch;
2737
+ exports.Tabs = Tabs;
2738
+ exports.TabsContent = TabsContent;
2739
+ exports.TabsList = TabsList;
2740
+ exports.TabsTrigger = TabsTrigger;
2741
+ exports.Textarea = Textarea;
2742
+ exports.Timeline = Timeline;
2743
+ exports.Toaster = Toaster;
2744
+ exports.Tooltip = Tooltip;
2745
+ exports.TooltipContent = TooltipContent;
2746
+ exports.TooltipProvider = TooltipProvider;
2747
+ exports.TooltipTrigger = TooltipTrigger;
2748
+ exports.cn = cn;
2749
+ //# sourceMappingURL=index.cjs.map
2750
+ //# sourceMappingURL=index.cjs.map