@aiready/components 0.1.21 → 0.1.22

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.d.ts CHANGED
@@ -12,6 +12,8 @@ export { RadioGroup, RadioGroupProps, RadioOption } from './components/radio-gro
12
12
  export { Switch, SwitchProps } from './components/switch.js';
13
13
  export { Textarea, TextareaProps } from './components/textarea.js';
14
14
  export { Select, SelectOption, SelectProps } from './components/select.js';
15
+ import * as react_jsx_runtime from 'react/jsx-runtime';
16
+ import React__default from 'react';
15
17
  export { cn } from './utils/cn.js';
16
18
  export { chartColors, domainColors, getDomainColor, getSeverityColor, hexToRgba, severityColors } from './utils/colors.js';
17
19
  export { formatCompactNumber, formatDate, formatDateTime, formatDecimal, formatDuration, formatFileSize, formatMetric, formatNumber, formatPercentage, formatRange, formatRelativeTime } from './utils/formatters.js';
@@ -19,13 +21,100 @@ export { useDebounce } from './hooks/useDebounce.js';
19
21
  export { useD3, useD3WithResize } from './hooks/useD3.js';
20
22
  export { ForceSimulationOptions, SimulationLink, SimulationNode, UseForceSimulationReturn, useDrag, useForceSimulation } from './hooks/useForceSimulation.js';
21
23
  export { ForceDirectedGraph, ForceDirectedGraphHandle, ForceDirectedGraphProps, GraphLink, GraphNode, LayoutType } from './charts/ForceDirectedGraph.js';
22
- import React__default from 'react';
23
24
  import 'class-variance-authority/types';
24
25
  import 'class-variance-authority';
25
- import 'react/jsx-runtime';
26
26
  import 'clsx';
27
27
  import 'd3';
28
28
 
29
+ interface CodeBlockProps {
30
+ children: React__default.ReactNode;
31
+ language?: string;
32
+ showCopy?: boolean;
33
+ showHeader?: boolean;
34
+ className?: string;
35
+ }
36
+ declare function CodeBlock({ children, language, showCopy, showHeader, className, }: CodeBlockProps): react_jsx_runtime.JSX.Element;
37
+ declare function InlineCode({ children, className }: {
38
+ children: React__default.ReactNode;
39
+ className?: string;
40
+ }): react_jsx_runtime.JSX.Element;
41
+
42
+ interface BreadcrumbItem {
43
+ label: string;
44
+ href?: string;
45
+ }
46
+ interface BreadcrumbProps {
47
+ items: BreadcrumbItem[];
48
+ separator?: React__default.ReactNode;
49
+ className?: string;
50
+ }
51
+ declare function Breadcrumb({ items, separator, className }: BreadcrumbProps): react_jsx_runtime.JSX.Element;
52
+
53
+ type ScoreRating = 'excellent' | 'good' | 'fair' | 'needs-work' | 'critical';
54
+ interface ScoreBarProps {
55
+ score: number;
56
+ maxScore?: number;
57
+ label: string;
58
+ showScore?: boolean;
59
+ size?: 'sm' | 'md' | 'lg';
60
+ className?: string;
61
+ }
62
+ declare function ScoreBar({ score, maxScore, label, showScore, size, className, }: ScoreBarProps): react_jsx_runtime.JSX.Element;
63
+ interface ScoreCardProps {
64
+ score: number;
65
+ title?: string;
66
+ breakdown?: Array<{
67
+ label: string;
68
+ score: number;
69
+ weight?: number;
70
+ }>;
71
+ className?: string;
72
+ }
73
+ declare function ScoreCard({ score, title, breakdown, className }: ScoreCardProps): react_jsx_runtime.JSX.Element;
74
+
75
+ interface LoadingSpinnerProps {
76
+ size?: 'sm' | 'md' | 'lg';
77
+ className?: string;
78
+ }
79
+ declare function LoadingSpinner({ size, className }: LoadingSpinnerProps): react_jsx_runtime.JSX.Element;
80
+ interface LoadingOverlayProps {
81
+ message?: string;
82
+ }
83
+ declare function LoadingOverlay({ message }: LoadingOverlayProps): react_jsx_runtime.JSX.Element;
84
+
85
+ interface ErrorDisplayProps {
86
+ title?: string;
87
+ message: string;
88
+ retry?: () => void;
89
+ retryLabel?: string;
90
+ }
91
+ declare function ErrorDisplay({ title, message, retry, retryLabel, }: ErrorDisplayProps): react_jsx_runtime.JSX.Element;
92
+ interface EmptyStateProps {
93
+ title: string;
94
+ description?: string;
95
+ icon?: React__default.ReactNode;
96
+ action?: {
97
+ label: string;
98
+ onClick: () => void;
99
+ };
100
+ }
101
+ declare function EmptyState({ title, description, icon, action }: EmptyStateProps): react_jsx_runtime.JSX.Element;
102
+
103
+ type Theme = 'dark' | 'light' | 'system';
104
+ type EffectiveTheme = 'dark' | 'light';
105
+ interface ThemeContextValue {
106
+ theme: Theme;
107
+ setTheme: (theme: Theme) => void;
108
+ effectiveTheme: EffectiveTheme;
109
+ }
110
+ interface ThemeProviderProps {
111
+ children: React__default.ReactNode;
112
+ defaultTheme?: Theme;
113
+ storageKey?: string;
114
+ }
115
+ declare function ThemeProvider({ children, defaultTheme, storageKey, }: ThemeProviderProps): react_jsx_runtime.JSX.Element;
116
+ declare function useTheme(): ThemeContextValue;
117
+
29
118
  interface GraphControlsProps {
30
119
  dragEnabled?: boolean;
31
120
  onDragToggle?: (enabled: boolean) => void;
@@ -43,4 +132,4 @@ interface GraphControlsProps {
43
132
  }
44
133
  declare const GraphControls: React__default.FC<GraphControlsProps>;
45
134
 
46
- export { GraphControls, type GraphControlsProps };
135
+ export { Breadcrumb, type BreadcrumbItem, type BreadcrumbProps, CodeBlock, type CodeBlockProps, type EffectiveTheme, EmptyState, type EmptyStateProps, ErrorDisplay, type ErrorDisplayProps, GraphControls, type GraphControlsProps, InlineCode, LoadingOverlay, type LoadingOverlayProps, LoadingSpinner, type LoadingSpinnerProps, ScoreBar, type ScoreBarProps, ScoreCard, type ScoreCardProps, type ScoreRating, type Theme, ThemeProvider, useTheme };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as React2 from 'react';
2
- import React2__default, { forwardRef, useRef, useState, useEffect, useCallback, useImperativeHandle } from 'react';
2
+ import React2__default, { createContext, forwardRef, useRef, useState, useEffect, useCallback, useImperativeHandle, useMemo, useContext } from 'react';
3
3
  import { cva } from 'class-variance-authority';
4
4
  import { clsx } from 'clsx';
5
5
  import { twMerge } from 'tailwind-merge';
@@ -433,6 +433,362 @@ var Select = React2.forwardRef(
433
433
  }
434
434
  );
435
435
  Select.displayName = "Select";
436
+ function dedentCode(code) {
437
+ let normalized = code.replace(/\t/g, " ").replace(/[ \t]+$/gm, "");
438
+ const lines = normalized.split("\n");
439
+ if (lines.length <= 1) return normalized.trim();
440
+ let start = 0;
441
+ while (start < lines.length && lines[start].trim() === "") start++;
442
+ let end = lines.length - 1;
443
+ while (end >= 0 && lines[end].trim() === "") end--;
444
+ if (start > end) return "";
445
+ const relevantLines = lines.slice(start, end + 1);
446
+ const nonEmpty = relevantLines.filter((l) => l.trim() !== "");
447
+ const minIndent = nonEmpty.reduce((min, line) => {
448
+ const m = line.match(/^\s*/)?.[0].length ?? 0;
449
+ return Math.min(min, m);
450
+ }, Infinity);
451
+ const dedented = minIndent === Infinity || minIndent === 0 ? relevantLines.join("\n") : relevantLines.map((l) => l.startsWith(" ".repeat(minIndent)) ? l.slice(minIndent) : l).join("\n");
452
+ return dedented;
453
+ }
454
+ function CopyButton({ code }) {
455
+ const [copied, setCopied] = useState(false);
456
+ const handleCopy = useCallback(async () => {
457
+ try {
458
+ await navigator.clipboard.writeText(code);
459
+ setCopied(true);
460
+ setTimeout(() => setCopied(false), 2e3);
461
+ } catch {
462
+ const textarea = document.createElement("textarea");
463
+ textarea.value = code;
464
+ textarea.style.position = "fixed";
465
+ textarea.style.opacity = "0";
466
+ document.body.appendChild(textarea);
467
+ textarea.select();
468
+ document.execCommand("copy");
469
+ document.body.removeChild(textarea);
470
+ setCopied(true);
471
+ setTimeout(() => setCopied(false), 2e3);
472
+ }
473
+ }, [code]);
474
+ return /* @__PURE__ */ jsx(
475
+ "button",
476
+ {
477
+ onClick: handleCopy,
478
+ className: "rounded-md p-1.5 text-slate-400 hover:text-slate-200 hover:bg-slate-700/50 transition-colors",
479
+ title: copied ? "Copied!" : "Copy code",
480
+ children: copied ? /* @__PURE__ */ jsx("svg", { className: "h-4 w-4", fill: "none", viewBox: "0 0 24 24", strokeWidth: "1.5", stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M4.5 12.75l6 6 9-13.5" }) }) : /* @__PURE__ */ jsx("svg", { className: "h-4 w-4", fill: "none", viewBox: "0 0 24 24", strokeWidth: "1.5", stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15.666 3.888A2.25 2.25 0 0013.5 2.25h-3c-1.03 0-1.9.693-2.166 1.638m7.332 0c.055.194.084.4.084.612v0a.75.75 0 01-.75.75H9a.75.75 0 01-.75-.75v0c0-.212.03-.418.084-.612m7.332 0c.646.049 1.288.11 1.927.184 1.1.128 1.907 1.077 1.907 2.185V19.5a2.25 2.25 0 01-2.25 2.25H6.75A2.25 2.25 0 014.5 19.5V6.257c0-1.108.806-2.057 1.907-2.185a48.208 48.208 0 011.927-.184" }) })
481
+ }
482
+ );
483
+ }
484
+ function CodeBlock({
485
+ children,
486
+ language = "typescript",
487
+ showCopy = true,
488
+ showHeader = true,
489
+ className = ""
490
+ }) {
491
+ const codeString = useMemo(() => {
492
+ if (typeof children === "string") {
493
+ return dedentCode(children);
494
+ }
495
+ try {
496
+ const raw = React2__default.Children.toArray(children).map((c) => typeof c === "string" ? c : typeof c === "number" ? String(c) : "").join("");
497
+ return dedentCode(raw);
498
+ } catch {
499
+ return "";
500
+ }
501
+ }, [children]);
502
+ return /* @__PURE__ */ jsxs("div", { className: `group relative my-4 overflow-hidden rounded-xl border border-slate-700 bg-slate-900 shadow-lg ${className}`, children: [
503
+ showHeader && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-b border-slate-700 bg-slate-800/50 px-4 py-2", children: [
504
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
505
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-1.5", children: [
506
+ /* @__PURE__ */ jsx("div", { className: "h-3 w-3 rounded-full bg-red-500/50" }),
507
+ /* @__PURE__ */ jsx("div", { className: "h-3 w-3 rounded-full bg-amber-500/50" }),
508
+ /* @__PURE__ */ jsx("div", { className: "h-3 w-3 rounded-full bg-emerald-500/50" })
509
+ ] }),
510
+ /* @__PURE__ */ jsx("span", { className: "ml-2 text-xs font-semibold uppercase tracking-wider text-slate-500 font-mono", children: language })
511
+ ] }),
512
+ showCopy && /* @__PURE__ */ jsx(CopyButton, { code: codeString })
513
+ ] }),
514
+ /* @__PURE__ */ jsx("pre", { className: "overflow-x-auto p-4 text-sm leading-relaxed", children: /* @__PURE__ */ jsx("code", { className: "font-mono block whitespace-pre text-slate-300", children: codeString }) })
515
+ ] });
516
+ }
517
+ function InlineCode({ children, className = "" }) {
518
+ return /* @__PURE__ */ jsx("code", { className: `rounded-md bg-slate-100 px-1.5 py-0.5 text-sm font-mono text-slate-800 ${className}`, children });
519
+ }
520
+ var DefaultSeparator = () => /* @__PURE__ */ jsx(
521
+ "svg",
522
+ {
523
+ className: "h-4 w-4 text-slate-400",
524
+ fill: "none",
525
+ viewBox: "0 0 24 24",
526
+ strokeWidth: "1.5",
527
+ stroke: "currentColor",
528
+ children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M8.25 4.5l7.5 7.5-7.5 7.5" })
529
+ }
530
+ );
531
+ function Breadcrumb({ items, separator, className }) {
532
+ const Separator2 = separator || /* @__PURE__ */ jsx(DefaultSeparator, {});
533
+ return /* @__PURE__ */ jsx("nav", { className: cn("flex items-center gap-1 text-sm", className), "aria-label": "Breadcrumb", children: /* @__PURE__ */ jsx("ol", { className: "flex items-center gap-1", children: items.map((item, index) => {
534
+ const isLast = index === items.length - 1;
535
+ return /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-1", children: [
536
+ index > 0 && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0", children: Separator2 }),
537
+ item.href && !isLast ? /* @__PURE__ */ jsx(
538
+ "a",
539
+ {
540
+ href: item.href,
541
+ className: "text-slate-600 hover:text-slate-900 transition-colors",
542
+ children: item.label
543
+ }
544
+ ) : /* @__PURE__ */ jsx("span", { className: isLast ? "font-medium text-slate-900" : "text-slate-600", children: item.label })
545
+ ] }, index);
546
+ }) }) });
547
+ }
548
+ var ratingConfig = {
549
+ excellent: { color: "bg-green-500", bgColor: "bg-green-100", label: "Excellent" },
550
+ good: { color: "bg-emerald-500", bgColor: "bg-emerald-100", label: "Good" },
551
+ fair: { color: "bg-amber-500", bgColor: "bg-amber-100", label: "Fair" },
552
+ "needs-work": { color: "bg-orange-500", bgColor: "bg-orange-100", label: "Needs Work" },
553
+ critical: { color: "bg-red-500", bgColor: "bg-red-100", label: "Critical" }
554
+ };
555
+ function getRating(score) {
556
+ if (score >= 90) return "excellent";
557
+ if (score >= 75) return "good";
558
+ if (score >= 60) return "fair";
559
+ if (score >= 40) return "needs-work";
560
+ return "critical";
561
+ }
562
+ var sizeConfig = {
563
+ sm: { height: "h-1.5", text: "text-xs", score: "text-sm" },
564
+ md: { height: "h-2", text: "text-sm", score: "text-base" },
565
+ lg: { height: "h-3", text: "text-base", score: "text-lg" }
566
+ };
567
+ function ScoreBar({
568
+ score,
569
+ maxScore = 100,
570
+ label,
571
+ showScore = true,
572
+ size = "md",
573
+ className
574
+ }) {
575
+ const percentage = Math.min(100, Math.max(0, score / maxScore * 100));
576
+ const rating = getRating(percentage);
577
+ const config = ratingConfig[rating];
578
+ const sizes = sizeConfig[size];
579
+ return /* @__PURE__ */ jsxs("div", { className: cn("space-y-1", className), children: [
580
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
581
+ /* @__PURE__ */ jsx("span", { className: cn("text-slate-700", sizes.text), children: label }),
582
+ showScore && /* @__PURE__ */ jsxs("span", { className: cn("font-bold text-slate-900", sizes.score), children: [
583
+ score,
584
+ "/",
585
+ maxScore
586
+ ] })
587
+ ] }),
588
+ /* @__PURE__ */ jsx("div", { className: cn("w-full rounded-full bg-slate-200", sizes.height), children: /* @__PURE__ */ jsx(
589
+ "div",
590
+ {
591
+ className: cn("rounded-full transition-all duration-500", config.color, sizes.height),
592
+ style: { width: `${percentage}%` }
593
+ }
594
+ ) })
595
+ ] });
596
+ }
597
+ function ScoreCard({ score, title, breakdown, className }) {
598
+ const rating = getRating(score);
599
+ const config = ratingConfig[rating];
600
+ return /* @__PURE__ */ jsxs("div", { className: cn("rounded-xl border-2 border-slate-200 bg-white p-6 shadow-lg", className), children: [
601
+ /* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
602
+ /* @__PURE__ */ jsxs("div", { className: "text-4xl font-black text-slate-900", children: [
603
+ score,
604
+ "/100"
605
+ ] }),
606
+ /* @__PURE__ */ jsxs("div", { className: cn("text-lg font-bold", `text-${rating === "excellent" ? "green" : rating === "good" ? "emerald" : rating === "fair" ? "amber" : rating === "needs-work" ? "orange" : "red"}-600`), children: [
607
+ config.label,
608
+ " Rating"
609
+ ] }),
610
+ title && /* @__PURE__ */ jsx("p", { className: "text-sm text-slate-600 mt-1", children: title })
611
+ ] }),
612
+ breakdown && breakdown.length > 0 && /* @__PURE__ */ jsx("div", { className: "space-y-3", children: breakdown.map((item, index) => /* @__PURE__ */ jsx(
613
+ ScoreBar,
614
+ {
615
+ score: item.score,
616
+ label: item.label,
617
+ size: "sm"
618
+ },
619
+ index
620
+ )) }),
621
+ breakdown && breakdown.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mt-4 text-xs text-slate-600 bg-slate-50 p-3 rounded-lg", children: [
622
+ /* @__PURE__ */ jsx("strong", { children: "Formula:" }),
623
+ " ",
624
+ breakdown.map(
625
+ (item) => `${item.score}\xD7${item.weight || 1}`
626
+ ).join(" + "),
627
+ " / 100 = ",
628
+ score
629
+ ] })
630
+ ] });
631
+ }
632
+ var sizeClasses = {
633
+ sm: "h-4 w-4",
634
+ md: "h-8 w-8",
635
+ lg: "h-12 w-12"
636
+ };
637
+ function LoadingSpinner({ size = "md", className = "" }) {
638
+ return /* @__PURE__ */ jsx("div", { className: `flex items-center justify-center ${className}`, children: /* @__PURE__ */ jsx(
639
+ "div",
640
+ {
641
+ className: `${sizeClasses[size]} animate-spin rounded-full border-2 border-slate-300 border-t-blue-600`
642
+ }
643
+ ) });
644
+ }
645
+ function LoadingOverlay({ message = "Loading..." }) {
646
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center min-h-[200px] gap-4", children: [
647
+ /* @__PURE__ */ jsx(LoadingSpinner, { size: "lg" }),
648
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-slate-500 animate-pulse", children: message })
649
+ ] });
650
+ }
651
+ function ErrorDisplay({
652
+ title = "Something went wrong",
653
+ message,
654
+ retry,
655
+ retryLabel = "Try again"
656
+ }) {
657
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center min-h-[200px] gap-4 p-8", children: [
658
+ /* @__PURE__ */ jsx("div", { className: "rounded-full bg-red-100 p-3", children: /* @__PURE__ */ jsx(
659
+ "svg",
660
+ {
661
+ className: "h-6 w-6 text-red-600",
662
+ fill: "none",
663
+ viewBox: "0 0 24 24",
664
+ strokeWidth: "1.5",
665
+ stroke: "currentColor",
666
+ children: /* @__PURE__ */ jsx(
667
+ "path",
668
+ {
669
+ strokeLinecap: "round",
670
+ strokeLinejoin: "round",
671
+ d: "M12 9v3.75m9-.75a9 9 0 11-18 0 9 9 0 0118 0zm-9 3.75h.008v.008H12v-.008z"
672
+ }
673
+ )
674
+ }
675
+ ) }),
676
+ /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
677
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-slate-900", children: title }),
678
+ /* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-slate-500", children: message })
679
+ ] }),
680
+ retry && /* @__PURE__ */ jsxs(
681
+ "button",
682
+ {
683
+ onClick: retry,
684
+ className: "mt-2 inline-flex items-center gap-2 rounded-lg bg-blue-600 px-4 py-2 text-sm font-medium text-white hover:bg-blue-700 transition-colors",
685
+ children: [
686
+ /* @__PURE__ */ jsx("svg", { className: "h-4 w-4", fill: "none", viewBox: "0 0 24 24", strokeWidth: "1.5", stroke: "currentColor", children: /* @__PURE__ */ jsx(
687
+ "path",
688
+ {
689
+ strokeLinecap: "round",
690
+ strokeLinejoin: "round",
691
+ d: "M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7M4.031 9.865a8.25 8.25 0 0113.803-3.7l3.181 3.182m0-4.991v4.99"
692
+ }
693
+ ) }),
694
+ retryLabel
695
+ ]
696
+ }
697
+ )
698
+ ] });
699
+ }
700
+ function EmptyState({ title, description, icon, action }) {
701
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center min-h-[200px] gap-4 p-8", children: [
702
+ icon && /* @__PURE__ */ jsx("div", { className: "rounded-full bg-slate-100 p-3", children: icon }),
703
+ /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
704
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-slate-900", children: title }),
705
+ description && /* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-slate-500", children: description })
706
+ ] }),
707
+ action && /* @__PURE__ */ jsx(
708
+ "button",
709
+ {
710
+ onClick: action.onClick,
711
+ className: "mt-2 inline-flex items-center gap-2 rounded-lg bg-blue-600 px-4 py-2 text-sm font-medium text-white hover:bg-blue-700 transition-colors",
712
+ children: action.label
713
+ }
714
+ )
715
+ ] });
716
+ }
717
+ var ThemeContext = createContext(void 0);
718
+ var STORAGE_KEY = "aiready-theme";
719
+ function getSystemTheme() {
720
+ if (typeof window === "undefined") return "light";
721
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
722
+ }
723
+ function getStoredTheme() {
724
+ if (typeof window === "undefined") return "system";
725
+ try {
726
+ const stored = localStorage.getItem(STORAGE_KEY);
727
+ if (stored === "dark" || stored === "light" || stored === "system") {
728
+ return stored;
729
+ }
730
+ } catch {
731
+ }
732
+ return "system";
733
+ }
734
+ function ThemeProvider({
735
+ children,
736
+ defaultTheme = "system",
737
+ storageKey = STORAGE_KEY
738
+ }) {
739
+ const [theme, setThemeState] = useState(defaultTheme);
740
+ const [effectiveTheme, setEffectiveTheme] = useState("light");
741
+ const [mounted, setMounted] = useState(false);
742
+ useEffect(() => {
743
+ const storedTheme = getStoredTheme();
744
+ setThemeState(storedTheme);
745
+ setMounted(true);
746
+ }, []);
747
+ useEffect(() => {
748
+ if (!mounted) return;
749
+ const updateEffectiveTheme = () => {
750
+ if (theme === "system") {
751
+ setEffectiveTheme(getSystemTheme());
752
+ } else {
753
+ setEffectiveTheme(theme);
754
+ }
755
+ };
756
+ updateEffectiveTheme();
757
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
758
+ const handleChange = () => {
759
+ if (theme === "system") {
760
+ setEffectiveTheme(getSystemTheme());
761
+ }
762
+ };
763
+ mediaQuery.addEventListener("change", handleChange);
764
+ return () => mediaQuery.removeEventListener("change", handleChange);
765
+ }, [theme, mounted]);
766
+ useEffect(() => {
767
+ if (!mounted) return;
768
+ const root = document.documentElement;
769
+ root.classList.remove("light", "dark");
770
+ root.classList.add(effectiveTheme);
771
+ }, [effectiveTheme, mounted]);
772
+ const setTheme = (newTheme) => {
773
+ setThemeState(newTheme);
774
+ try {
775
+ localStorage.setItem(storageKey, newTheme);
776
+ } catch {
777
+ }
778
+ };
779
+ if (!mounted) {
780
+ return /* @__PURE__ */ jsx(ThemeContext.Provider, { value: { theme: defaultTheme, setTheme: () => {
781
+ }, effectiveTheme: "light" }, children });
782
+ }
783
+ return /* @__PURE__ */ jsx(ThemeContext.Provider, { value: { theme, setTheme, effectiveTheme }, children });
784
+ }
785
+ function useTheme() {
786
+ const context = useContext(ThemeContext);
787
+ if (context === void 0) {
788
+ throw new Error("useTheme must be used within a ThemeProvider");
789
+ }
790
+ return context;
791
+ }
436
792
 
437
793
  // src/utils/colors.ts
438
794
  var severityColors = {
@@ -1633,6 +1989,6 @@ var GraphControls = ({
1633
1989
  };
1634
1990
  GraphControls.displayName = "GraphControls";
1635
1991
 
1636
- export { Badge, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, Container, ForceDirectedGraph, GraphControls, Grid, Input, Label, RadioGroup, Select, Separator, Stack, Switch, Textarea, badgeVariants, buttonVariants, chartColors, cn, domainColors, formatCompactNumber, formatDate, formatDateTime, formatDecimal, formatDuration, formatFileSize, formatMetric, formatNumber, formatPercentage, formatRange, formatRelativeTime, getDomainColor, getSeverityColor, hexToRgba, severityColors, useD3, useD3WithResize, useDebounce, useDrag, useForceSimulation };
1992
+ export { Badge, Breadcrumb, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, CodeBlock, Container, EmptyState, ErrorDisplay, ForceDirectedGraph, GraphControls, Grid, InlineCode, Input, Label, LoadingOverlay, LoadingSpinner, RadioGroup, ScoreBar, ScoreCard, Select, Separator, Stack, Switch, Textarea, ThemeProvider, badgeVariants, buttonVariants, chartColors, cn, domainColors, formatCompactNumber, formatDate, formatDateTime, formatDecimal, formatDuration, formatFileSize, formatMetric, formatNumber, formatPercentage, formatRange, formatRelativeTime, getDomainColor, getSeverityColor, hexToRgba, severityColors, useD3, useD3WithResize, useDebounce, useDrag, useForceSimulation, useTheme };
1637
1993
  //# sourceMappingURL=index.js.map
1638
1994
  //# sourceMappingURL=index.js.map