@aiready/components 0.1.21 → 0.1.24
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/charts/ForceDirectedGraph.js +8 -8
- package/dist/charts/ForceDirectedGraph.js.map +1 -1
- package/dist/index.d.ts +98 -3
- package/dist/index.js +405 -10
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/src/charts/ForceDirectedGraph.tsx +8 -8
- package/src/code-block/CodeBlock.tsx +147 -0
- package/src/code-block/index.ts +1 -0
- package/src/data-display/ScoreBar.tsx +124 -0
- package/src/data-display/index.ts +1 -0
- package/src/feedback/ErrorDisplay.tsx +86 -0
- package/src/feedback/LoadingSpinner.tsx +35 -0
- package/src/feedback/index.ts +2 -0
- package/src/index.ts +25 -0
- package/src/navigation/Breadcrumb.tsx +61 -0
- package/src/navigation/index.ts +1 -0
- package/src/theme/ThemeProvider.tsx +124 -0
- package/src/theme/index.ts +1 -0
- package/src/utils/score.ts +56 -0
package/dist/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
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';
|
|
6
6
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
7
|
+
import { getRating as getRating$1 } from '@aiready/core/client';
|
|
7
8
|
import * as d33 from 'd3';
|
|
8
9
|
|
|
9
10
|
// src/components/button.tsx
|
|
@@ -433,6 +434,366 @@ var Select = React2.forwardRef(
|
|
|
433
434
|
}
|
|
434
435
|
);
|
|
435
436
|
Select.displayName = "Select";
|
|
437
|
+
function dedentCode(code) {
|
|
438
|
+
let normalized = code.replace(/\t/g, " ").replace(/[ \t]+$/gm, "");
|
|
439
|
+
const lines = normalized.split("\n");
|
|
440
|
+
if (lines.length <= 1) return normalized.trim();
|
|
441
|
+
let start = 0;
|
|
442
|
+
while (start < lines.length && lines[start].trim() === "") start++;
|
|
443
|
+
let end = lines.length - 1;
|
|
444
|
+
while (end >= 0 && lines[end].trim() === "") end--;
|
|
445
|
+
if (start > end) return "";
|
|
446
|
+
const relevantLines = lines.slice(start, end + 1);
|
|
447
|
+
const nonEmpty = relevantLines.filter((l) => l.trim() !== "");
|
|
448
|
+
const minIndent = nonEmpty.reduce((min, line) => {
|
|
449
|
+
const m = line.match(/^\s*/)?.[0].length ?? 0;
|
|
450
|
+
return Math.min(min, m);
|
|
451
|
+
}, Infinity);
|
|
452
|
+
const dedented = minIndent === Infinity || minIndent === 0 ? relevantLines.join("\n") : relevantLines.map((l) => l.startsWith(" ".repeat(minIndent)) ? l.slice(minIndent) : l).join("\n");
|
|
453
|
+
return dedented;
|
|
454
|
+
}
|
|
455
|
+
function CopyButton({ code }) {
|
|
456
|
+
const [copied, setCopied] = useState(false);
|
|
457
|
+
const handleCopy = useCallback(async () => {
|
|
458
|
+
try {
|
|
459
|
+
await navigator.clipboard.writeText(code);
|
|
460
|
+
setCopied(true);
|
|
461
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
462
|
+
} catch {
|
|
463
|
+
const textarea = document.createElement("textarea");
|
|
464
|
+
textarea.value = code;
|
|
465
|
+
textarea.style.position = "fixed";
|
|
466
|
+
textarea.style.opacity = "0";
|
|
467
|
+
document.body.appendChild(textarea);
|
|
468
|
+
textarea.select();
|
|
469
|
+
document.execCommand("copy");
|
|
470
|
+
document.body.removeChild(textarea);
|
|
471
|
+
setCopied(true);
|
|
472
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
473
|
+
}
|
|
474
|
+
}, [code]);
|
|
475
|
+
return /* @__PURE__ */ jsx(
|
|
476
|
+
"button",
|
|
477
|
+
{
|
|
478
|
+
onClick: handleCopy,
|
|
479
|
+
className: "rounded-md p-1.5 text-slate-400 hover:text-slate-200 hover:bg-slate-700/50 transition-colors",
|
|
480
|
+
title: copied ? "Copied!" : "Copy code",
|
|
481
|
+
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" }) })
|
|
482
|
+
}
|
|
483
|
+
);
|
|
484
|
+
}
|
|
485
|
+
function CodeBlock({
|
|
486
|
+
children,
|
|
487
|
+
language = "typescript",
|
|
488
|
+
showCopy = true,
|
|
489
|
+
showHeader = true,
|
|
490
|
+
className = ""
|
|
491
|
+
}) {
|
|
492
|
+
const codeString = useMemo(() => {
|
|
493
|
+
if (typeof children === "string") {
|
|
494
|
+
return dedentCode(children);
|
|
495
|
+
}
|
|
496
|
+
try {
|
|
497
|
+
const raw = React2__default.Children.toArray(children).map((c) => typeof c === "string" ? c : typeof c === "number" ? String(c) : "").join("");
|
|
498
|
+
return dedentCode(raw);
|
|
499
|
+
} catch {
|
|
500
|
+
return "";
|
|
501
|
+
}
|
|
502
|
+
}, [children]);
|
|
503
|
+
return /* @__PURE__ */ jsxs("div", { className: `group relative my-4 overflow-hidden rounded-xl border border-slate-700 bg-slate-900 shadow-lg ${className}`, children: [
|
|
504
|
+
showHeader && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-b border-slate-700 bg-slate-800/50 px-4 py-2", children: [
|
|
505
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
506
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-1.5", children: [
|
|
507
|
+
/* @__PURE__ */ jsx("div", { className: "h-3 w-3 rounded-full bg-red-500/50" }),
|
|
508
|
+
/* @__PURE__ */ jsx("div", { className: "h-3 w-3 rounded-full bg-amber-500/50" }),
|
|
509
|
+
/* @__PURE__ */ jsx("div", { className: "h-3 w-3 rounded-full bg-emerald-500/50" })
|
|
510
|
+
] }),
|
|
511
|
+
/* @__PURE__ */ jsx("span", { className: "ml-2 text-xs font-semibold uppercase tracking-wider text-slate-500 font-mono", children: language })
|
|
512
|
+
] }),
|
|
513
|
+
showCopy && /* @__PURE__ */ jsx(CopyButton, { code: codeString })
|
|
514
|
+
] }),
|
|
515
|
+
/* @__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 }) })
|
|
516
|
+
] });
|
|
517
|
+
}
|
|
518
|
+
function InlineCode({ children, className = "" }) {
|
|
519
|
+
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 });
|
|
520
|
+
}
|
|
521
|
+
var DefaultSeparator = () => /* @__PURE__ */ jsx(
|
|
522
|
+
"svg",
|
|
523
|
+
{
|
|
524
|
+
className: "h-4 w-4 text-slate-400",
|
|
525
|
+
fill: "none",
|
|
526
|
+
viewBox: "0 0 24 24",
|
|
527
|
+
strokeWidth: "1.5",
|
|
528
|
+
stroke: "currentColor",
|
|
529
|
+
children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M8.25 4.5l7.5 7.5-7.5 7.5" })
|
|
530
|
+
}
|
|
531
|
+
);
|
|
532
|
+
function Breadcrumb({ items, separator, className }) {
|
|
533
|
+
const Separator2 = separator || /* @__PURE__ */ jsx(DefaultSeparator, {});
|
|
534
|
+
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) => {
|
|
535
|
+
const isLast = index === items.length - 1;
|
|
536
|
+
return /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-1", children: [
|
|
537
|
+
index > 0 && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0", children: Separator2 }),
|
|
538
|
+
item.href && !isLast ? /* @__PURE__ */ jsx(
|
|
539
|
+
"a",
|
|
540
|
+
{
|
|
541
|
+
href: item.href,
|
|
542
|
+
className: "text-slate-600 hover:text-slate-900 transition-colors",
|
|
543
|
+
children: item.label
|
|
544
|
+
}
|
|
545
|
+
) : /* @__PURE__ */ jsx("span", { className: isLast ? "font-medium text-slate-900" : "text-slate-600", children: item.label })
|
|
546
|
+
] }, index);
|
|
547
|
+
}) }) });
|
|
548
|
+
}
|
|
549
|
+
var ratingConfig = {
|
|
550
|
+
excellent: { color: "bg-green-500", bgColor: "bg-green-100", label: "Excellent" },
|
|
551
|
+
good: { color: "bg-emerald-500", bgColor: "bg-emerald-100", label: "Good" },
|
|
552
|
+
fair: { color: "bg-amber-500", bgColor: "bg-amber-100", label: "Fair" },
|
|
553
|
+
"needs-work": { color: "bg-orange-500", bgColor: "bg-orange-100", label: "Needs Work" },
|
|
554
|
+
critical: { color: "bg-red-500", bgColor: "bg-red-100", label: "Critical" }
|
|
555
|
+
};
|
|
556
|
+
function getRating(score) {
|
|
557
|
+
const coreRating = getRating$1(score);
|
|
558
|
+
const ratingMap = {
|
|
559
|
+
"Excellent": "excellent",
|
|
560
|
+
"Good": "good",
|
|
561
|
+
"Fair": "fair",
|
|
562
|
+
"Needs Work": "needs-work",
|
|
563
|
+
"Critical": "critical"
|
|
564
|
+
};
|
|
565
|
+
return ratingMap[coreRating] || "critical";
|
|
566
|
+
}
|
|
567
|
+
var sizeConfig = {
|
|
568
|
+
sm: { height: "h-1.5", text: "text-xs", score: "text-sm" },
|
|
569
|
+
md: { height: "h-2", text: "text-sm", score: "text-base" },
|
|
570
|
+
lg: { height: "h-3", text: "text-base", score: "text-lg" }
|
|
571
|
+
};
|
|
572
|
+
function ScoreBar({
|
|
573
|
+
score,
|
|
574
|
+
maxScore = 100,
|
|
575
|
+
label,
|
|
576
|
+
showScore = true,
|
|
577
|
+
size = "md",
|
|
578
|
+
className
|
|
579
|
+
}) {
|
|
580
|
+
const percentage = Math.min(100, Math.max(0, score / maxScore * 100));
|
|
581
|
+
const rating = getRating(percentage);
|
|
582
|
+
const config = ratingConfig[rating];
|
|
583
|
+
const sizes = sizeConfig[size];
|
|
584
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("space-y-1", className), children: [
|
|
585
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
586
|
+
/* @__PURE__ */ jsx("span", { className: cn("text-slate-700", sizes.text), children: label }),
|
|
587
|
+
showScore && /* @__PURE__ */ jsxs("span", { className: cn("font-bold text-slate-900", sizes.score), children: [
|
|
588
|
+
score,
|
|
589
|
+
"/",
|
|
590
|
+
maxScore
|
|
591
|
+
] })
|
|
592
|
+
] }),
|
|
593
|
+
/* @__PURE__ */ jsx("div", { className: cn("w-full rounded-full bg-slate-200", sizes.height), children: /* @__PURE__ */ jsx(
|
|
594
|
+
"div",
|
|
595
|
+
{
|
|
596
|
+
className: cn("rounded-full transition-all duration-500", config.color, sizes.height),
|
|
597
|
+
style: { width: `${percentage}%` }
|
|
598
|
+
}
|
|
599
|
+
) })
|
|
600
|
+
] });
|
|
601
|
+
}
|
|
602
|
+
function ScoreCard({ score, title, breakdown, className }) {
|
|
603
|
+
const rating = getRating(score);
|
|
604
|
+
const config = ratingConfig[rating];
|
|
605
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("rounded-xl border-2 border-slate-200 bg-white p-6 shadow-lg", className), children: [
|
|
606
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
607
|
+
/* @__PURE__ */ jsxs("div", { className: "text-4xl font-black text-slate-900", children: [
|
|
608
|
+
score,
|
|
609
|
+
"/100"
|
|
610
|
+
] }),
|
|
611
|
+
/* @__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: [
|
|
612
|
+
config.label,
|
|
613
|
+
" Rating"
|
|
614
|
+
] }),
|
|
615
|
+
title && /* @__PURE__ */ jsx("p", { className: "text-sm text-slate-600 mt-1", children: title })
|
|
616
|
+
] }),
|
|
617
|
+
breakdown && breakdown.length > 0 && /* @__PURE__ */ jsx("div", { className: "space-y-3", children: breakdown.map((item, index) => /* @__PURE__ */ jsx(
|
|
618
|
+
ScoreBar,
|
|
619
|
+
{
|
|
620
|
+
score: item.score,
|
|
621
|
+
label: item.label,
|
|
622
|
+
size: "sm"
|
|
623
|
+
},
|
|
624
|
+
index
|
|
625
|
+
)) }),
|
|
626
|
+
breakdown && breakdown.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mt-4 text-xs text-slate-600 bg-slate-50 p-3 rounded-lg", children: [
|
|
627
|
+
/* @__PURE__ */ jsx("strong", { children: "Formula:" }),
|
|
628
|
+
" ",
|
|
629
|
+
breakdown.map(
|
|
630
|
+
(item) => `${item.score}\xD7${item.weight || 1}`
|
|
631
|
+
).join(" + "),
|
|
632
|
+
" / 100 = ",
|
|
633
|
+
score
|
|
634
|
+
] })
|
|
635
|
+
] });
|
|
636
|
+
}
|
|
637
|
+
var sizeClasses = {
|
|
638
|
+
sm: "h-4 w-4",
|
|
639
|
+
md: "h-8 w-8",
|
|
640
|
+
lg: "h-12 w-12"
|
|
641
|
+
};
|
|
642
|
+
function LoadingSpinner({ size = "md", className = "" }) {
|
|
643
|
+
return /* @__PURE__ */ jsx("div", { className: `flex items-center justify-center ${className}`, children: /* @__PURE__ */ jsx(
|
|
644
|
+
"div",
|
|
645
|
+
{
|
|
646
|
+
className: `${sizeClasses[size]} animate-spin rounded-full border-2 border-slate-300 border-t-blue-600`
|
|
647
|
+
}
|
|
648
|
+
) });
|
|
649
|
+
}
|
|
650
|
+
function LoadingOverlay({ message = "Loading..." }) {
|
|
651
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center min-h-[200px] gap-4", children: [
|
|
652
|
+
/* @__PURE__ */ jsx(LoadingSpinner, { size: "lg" }),
|
|
653
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-slate-500 animate-pulse", children: message })
|
|
654
|
+
] });
|
|
655
|
+
}
|
|
656
|
+
function ErrorDisplay({
|
|
657
|
+
title = "Something went wrong",
|
|
658
|
+
message,
|
|
659
|
+
retry,
|
|
660
|
+
retryLabel = "Try again"
|
|
661
|
+
}) {
|
|
662
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center min-h-[200px] gap-4 p-8", children: [
|
|
663
|
+
/* @__PURE__ */ jsx("div", { className: "rounded-full bg-red-100 p-3", children: /* @__PURE__ */ jsx(
|
|
664
|
+
"svg",
|
|
665
|
+
{
|
|
666
|
+
className: "h-6 w-6 text-red-600",
|
|
667
|
+
fill: "none",
|
|
668
|
+
viewBox: "0 0 24 24",
|
|
669
|
+
strokeWidth: "1.5",
|
|
670
|
+
stroke: "currentColor",
|
|
671
|
+
children: /* @__PURE__ */ jsx(
|
|
672
|
+
"path",
|
|
673
|
+
{
|
|
674
|
+
strokeLinecap: "round",
|
|
675
|
+
strokeLinejoin: "round",
|
|
676
|
+
d: "M12 9v3.75m9-.75a9 9 0 11-18 0 9 9 0 0118 0zm-9 3.75h.008v.008H12v-.008z"
|
|
677
|
+
}
|
|
678
|
+
)
|
|
679
|
+
}
|
|
680
|
+
) }),
|
|
681
|
+
/* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
682
|
+
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-slate-900", children: title }),
|
|
683
|
+
/* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-slate-500", children: message })
|
|
684
|
+
] }),
|
|
685
|
+
retry && /* @__PURE__ */ jsxs(
|
|
686
|
+
"button",
|
|
687
|
+
{
|
|
688
|
+
onClick: retry,
|
|
689
|
+
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",
|
|
690
|
+
children: [
|
|
691
|
+
/* @__PURE__ */ jsx("svg", { className: "h-4 w-4", fill: "none", viewBox: "0 0 24 24", strokeWidth: "1.5", stroke: "currentColor", children: /* @__PURE__ */ jsx(
|
|
692
|
+
"path",
|
|
693
|
+
{
|
|
694
|
+
strokeLinecap: "round",
|
|
695
|
+
strokeLinejoin: "round",
|
|
696
|
+
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"
|
|
697
|
+
}
|
|
698
|
+
) }),
|
|
699
|
+
retryLabel
|
|
700
|
+
]
|
|
701
|
+
}
|
|
702
|
+
)
|
|
703
|
+
] });
|
|
704
|
+
}
|
|
705
|
+
function EmptyState({ title, description, icon, action }) {
|
|
706
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center min-h-[200px] gap-4 p-8", children: [
|
|
707
|
+
icon && /* @__PURE__ */ jsx("div", { className: "rounded-full bg-slate-100 p-3", children: icon }),
|
|
708
|
+
/* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
709
|
+
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-slate-900", children: title }),
|
|
710
|
+
description && /* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-slate-500", children: description })
|
|
711
|
+
] }),
|
|
712
|
+
action && /* @__PURE__ */ jsx(
|
|
713
|
+
"button",
|
|
714
|
+
{
|
|
715
|
+
onClick: action.onClick,
|
|
716
|
+
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",
|
|
717
|
+
children: action.label
|
|
718
|
+
}
|
|
719
|
+
)
|
|
720
|
+
] });
|
|
721
|
+
}
|
|
722
|
+
var ThemeContext = createContext(void 0);
|
|
723
|
+
var STORAGE_KEY = "aiready-theme";
|
|
724
|
+
function getSystemTheme() {
|
|
725
|
+
if (typeof window === "undefined") return "light";
|
|
726
|
+
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
727
|
+
}
|
|
728
|
+
function getStoredTheme() {
|
|
729
|
+
if (typeof window === "undefined") return "system";
|
|
730
|
+
try {
|
|
731
|
+
const stored = localStorage.getItem(STORAGE_KEY);
|
|
732
|
+
if (stored === "dark" || stored === "light" || stored === "system") {
|
|
733
|
+
return stored;
|
|
734
|
+
}
|
|
735
|
+
} catch {
|
|
736
|
+
}
|
|
737
|
+
return "system";
|
|
738
|
+
}
|
|
739
|
+
function ThemeProvider({
|
|
740
|
+
children,
|
|
741
|
+
defaultTheme = "system",
|
|
742
|
+
storageKey = STORAGE_KEY
|
|
743
|
+
}) {
|
|
744
|
+
const [theme, setThemeState] = useState(defaultTheme);
|
|
745
|
+
const [effectiveTheme, setEffectiveTheme] = useState("light");
|
|
746
|
+
const [mounted, setMounted] = useState(false);
|
|
747
|
+
useEffect(() => {
|
|
748
|
+
const storedTheme = getStoredTheme();
|
|
749
|
+
setThemeState(storedTheme);
|
|
750
|
+
setMounted(true);
|
|
751
|
+
}, []);
|
|
752
|
+
useEffect(() => {
|
|
753
|
+
if (!mounted) return;
|
|
754
|
+
const updateEffectiveTheme = () => {
|
|
755
|
+
if (theme === "system") {
|
|
756
|
+
setEffectiveTheme(getSystemTheme());
|
|
757
|
+
} else {
|
|
758
|
+
setEffectiveTheme(theme);
|
|
759
|
+
}
|
|
760
|
+
};
|
|
761
|
+
updateEffectiveTheme();
|
|
762
|
+
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
763
|
+
const handleChange = () => {
|
|
764
|
+
if (theme === "system") {
|
|
765
|
+
setEffectiveTheme(getSystemTheme());
|
|
766
|
+
}
|
|
767
|
+
};
|
|
768
|
+
mediaQuery.addEventListener("change", handleChange);
|
|
769
|
+
return () => mediaQuery.removeEventListener("change", handleChange);
|
|
770
|
+
}, [theme, mounted]);
|
|
771
|
+
useEffect(() => {
|
|
772
|
+
if (!mounted) return;
|
|
773
|
+
const root = document.documentElement;
|
|
774
|
+
root.classList.remove("light", "dark");
|
|
775
|
+
root.classList.add(effectiveTheme);
|
|
776
|
+
}, [effectiveTheme, mounted]);
|
|
777
|
+
const setTheme = (newTheme) => {
|
|
778
|
+
setThemeState(newTheme);
|
|
779
|
+
try {
|
|
780
|
+
localStorage.setItem(storageKey, newTheme);
|
|
781
|
+
} catch {
|
|
782
|
+
}
|
|
783
|
+
};
|
|
784
|
+
if (!mounted) {
|
|
785
|
+
return /* @__PURE__ */ jsx(ThemeContext.Provider, { value: { theme: defaultTheme, setTheme: () => {
|
|
786
|
+
}, effectiveTheme: "light" }, children });
|
|
787
|
+
}
|
|
788
|
+
return /* @__PURE__ */ jsx(ThemeContext.Provider, { value: { theme, setTheme, effectiveTheme }, children });
|
|
789
|
+
}
|
|
790
|
+
function useTheme() {
|
|
791
|
+
const context = useContext(ThemeContext);
|
|
792
|
+
if (context === void 0) {
|
|
793
|
+
throw new Error("useTheme must be used within a ThemeProvider");
|
|
794
|
+
}
|
|
795
|
+
return context;
|
|
796
|
+
}
|
|
436
797
|
|
|
437
798
|
// src/utils/colors.ts
|
|
438
799
|
var severityColors = {
|
|
@@ -579,6 +940,40 @@ function formatRange(min, max) {
|
|
|
579
940
|
function formatDecimal(value, decimals = 2) {
|
|
580
941
|
return value.toFixed(decimals);
|
|
581
942
|
}
|
|
943
|
+
|
|
944
|
+
// src/utils/score.ts
|
|
945
|
+
function scoreColor(score) {
|
|
946
|
+
if (score == null) return "text-slate-400";
|
|
947
|
+
if (score >= 75) return "text-emerald-400";
|
|
948
|
+
if (score >= 50) return "text-amber-400";
|
|
949
|
+
return "text-red-400";
|
|
950
|
+
}
|
|
951
|
+
function scoreBg(score) {
|
|
952
|
+
if (score == null) return "bg-slate-800/50 border-slate-700";
|
|
953
|
+
if (score >= 75) return "bg-emerald-900/30 border-emerald-500/30";
|
|
954
|
+
if (score >= 50) return "bg-amber-900/30 border-amber-500/30";
|
|
955
|
+
return "bg-red-900/30 border-red-500/30";
|
|
956
|
+
}
|
|
957
|
+
function scoreLabel(score) {
|
|
958
|
+
if (score == null) return "Not analyzed";
|
|
959
|
+
if (score >= 75) return "AI-Ready";
|
|
960
|
+
if (score >= 50) return "Needs Improvement";
|
|
961
|
+
return "Critical Issues";
|
|
962
|
+
}
|
|
963
|
+
function scoreGlow(score) {
|
|
964
|
+
if (score == null) return "";
|
|
965
|
+
if (score >= 75) return "shadow-emerald-500/20";
|
|
966
|
+
if (score >= 50) return "shadow-amber-500/20";
|
|
967
|
+
return "shadow-red-500/20";
|
|
968
|
+
}
|
|
969
|
+
function getScoreRating(score) {
|
|
970
|
+
if (score == null) return "critical";
|
|
971
|
+
if (score >= 90) return "excellent";
|
|
972
|
+
if (score >= 75) return "good";
|
|
973
|
+
if (score >= 60) return "fair";
|
|
974
|
+
if (score >= 40) return "needs-work";
|
|
975
|
+
return "critical";
|
|
976
|
+
}
|
|
582
977
|
function useDebounce(value, delay = 300) {
|
|
583
978
|
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
584
979
|
useEffect(() => {
|
|
@@ -1058,8 +1453,8 @@ var ForceDirectedGraph = forwardRef(
|
|
|
1058
1453
|
}, [enableDrag]);
|
|
1059
1454
|
const nodes = React2__default.useMemo(() => {
|
|
1060
1455
|
if (!initialNodes || !initialNodes.length) return initialNodes;
|
|
1061
|
-
const
|
|
1062
|
-
const
|
|
1456
|
+
const centerX = width / 2;
|
|
1457
|
+
const centerY = height / 2;
|
|
1063
1458
|
if (layout === "force") {
|
|
1064
1459
|
return initialNodes.map((n) => ({
|
|
1065
1460
|
...n,
|
|
@@ -1071,8 +1466,8 @@ var ForceDirectedGraph = forwardRef(
|
|
|
1071
1466
|
const radius = Math.min(width, height) * 0.35;
|
|
1072
1467
|
return initialNodes.map((n, i) => ({
|
|
1073
1468
|
...n,
|
|
1074
|
-
x:
|
|
1075
|
-
y:
|
|
1469
|
+
x: centerX + Math.cos(2 * Math.PI * i / initialNodes.length) * radius,
|
|
1470
|
+
y: centerY + Math.sin(2 * Math.PI * i / initialNodes.length) * radius
|
|
1076
1471
|
}));
|
|
1077
1472
|
}
|
|
1078
1473
|
if (layout === "hierarchical") {
|
|
@@ -1097,14 +1492,14 @@ var ForceDirectedGraph = forwardRef(
|
|
|
1097
1492
|
useEffect(() => {
|
|
1098
1493
|
if (!nodes || nodes.length === 0) return;
|
|
1099
1494
|
const applyLayout = () => {
|
|
1100
|
-
const
|
|
1101
|
-
const
|
|
1495
|
+
const centerX = width / 2;
|
|
1496
|
+
const centerY = height / 2;
|
|
1102
1497
|
if (layout === "circular") {
|
|
1103
1498
|
const radius = Math.min(width, height) * 0.35;
|
|
1104
1499
|
nodes.forEach((node, i) => {
|
|
1105
1500
|
const angle = 2 * Math.PI * i / nodes.length;
|
|
1106
|
-
node.fx =
|
|
1107
|
-
node.fy =
|
|
1501
|
+
node.fx = centerX + Math.cos(angle) * radius;
|
|
1502
|
+
node.fy = centerY + Math.sin(angle) * radius;
|
|
1108
1503
|
});
|
|
1109
1504
|
} else if (layout === "hierarchical") {
|
|
1110
1505
|
const groups = /* @__PURE__ */ new Map();
|
|
@@ -1633,6 +2028,6 @@ var GraphControls = ({
|
|
|
1633
2028
|
};
|
|
1634
2029
|
GraphControls.displayName = "GraphControls";
|
|
1635
2030
|
|
|
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 };
|
|
2031
|
+
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, getScoreRating, getSeverityColor, hexToRgba, scoreBg, scoreColor, scoreGlow, scoreLabel, severityColors, useD3, useD3WithResize, useDebounce, useDrag, useForceSimulation, useTheme };
|
|
1637
2032
|
//# sourceMappingURL=index.js.map
|
|
1638
2033
|
//# sourceMappingURL=index.js.map
|