@aiready/components 0.1.31 → 0.1.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/README.md +2 -2
  2. package/dist/charts/ForceDirectedGraph.js +49 -13
  3. package/dist/charts/ForceDirectedGraph.js.map +1 -1
  4. package/dist/components/badge.js.map +1 -1
  5. package/dist/components/button.js.map +1 -1
  6. package/dist/components/card.js.map +1 -1
  7. package/dist/components/checkbox.js.map +1 -1
  8. package/dist/components/container.js.map +1 -1
  9. package/dist/components/grid.js.map +1 -1
  10. package/dist/components/input.d.ts +1 -2
  11. package/dist/components/input.js.map +1 -1
  12. package/dist/components/label.js +1 -8
  13. package/dist/components/label.js.map +1 -1
  14. package/dist/components/radio-group.js.map +1 -1
  15. package/dist/components/select.js.map +1 -1
  16. package/dist/components/separator.js.map +1 -1
  17. package/dist/components/stack.js.map +1 -1
  18. package/dist/components/switch.js +29 -22
  19. package/dist/components/switch.js.map +1 -1
  20. package/dist/components/textarea.d.ts +1 -2
  21. package/dist/components/textarea.js.map +1 -1
  22. package/dist/hooks/useD3.js.map +1 -1
  23. package/dist/hooks/useDebounce.js.map +1 -1
  24. package/dist/hooks/useForceSimulation.d.ts +1 -0
  25. package/dist/hooks/useForceSimulation.js +37 -14
  26. package/dist/hooks/useForceSimulation.js.map +1 -1
  27. package/dist/index.d.ts +5 -5
  28. package/dist/index.js +337 -141
  29. package/dist/index.js.map +1 -1
  30. package/dist/utils/cn.js.map +1 -1
  31. package/dist/utils/colors.js.map +1 -1
  32. package/dist/utils/formatters.js.map +1 -1
  33. package/package.json +3 -2
  34. package/src/__tests__/smoke.test.js +1 -1
  35. package/src/__tests__/smoke.test.ts +3 -3
  36. package/src/charts/ForceDirectedGraph.tsx +583 -517
  37. package/src/charts/GraphControls.tsx +5 -2
  38. package/src/charts/LinkItem.tsx +17 -5
  39. package/src/charts/NodeItem.tsx +17 -2
  40. package/src/code-block/CodeBlock.tsx +53 -16
  41. package/src/code-block/index.ts +1 -1
  42. package/src/components/badge.tsx +3 -2
  43. package/src/components/button.tsx +3 -2
  44. package/src/components/card.tsx +8 -1
  45. package/src/components/checkbox.tsx +6 -4
  46. package/src/components/container.tsx +1 -1
  47. package/src/components/grid.tsx +1 -1
  48. package/src/components/input.tsx +2 -3
  49. package/src/components/label.tsx +4 -7
  50. package/src/components/radio-group.tsx +5 -3
  51. package/src/components/select.tsx +5 -3
  52. package/src/components/separator.tsx +1 -1
  53. package/src/components/stack.tsx +1 -1
  54. package/src/components/switch.tsx +15 -7
  55. package/src/components/textarea.tsx +2 -3
  56. package/src/data-display/ScoreBar.tsx +52 -15
  57. package/src/data-display/index.ts +7 -1
  58. package/src/feedback/ErrorDisplay.tsx +17 -4
  59. package/src/feedback/LoadingSpinner.tsx +8 -3
  60. package/src/feedback/index.ts +12 -2
  61. package/src/hooks/useD3.ts +1 -3
  62. package/src/hooks/useDebounce.ts +1 -1
  63. package/src/hooks/useForceSimulation.ts +142 -44
  64. package/src/index.ts +29 -9
  65. package/src/navigation/Breadcrumb.tsx +17 -8
  66. package/src/navigation/index.ts +5 -1
  67. package/src/theme/ThemeProvider.tsx +11 -3
  68. package/src/theme/index.ts +6 -1
  69. package/src/utils/cn.ts +1 -1
  70. package/src/utils/colors.ts +1 -1
  71. package/src/utils/formatters.ts +1 -1
  72. package/src/utils/score.ts +3 -1
  73. package/tailwind.config.js +1 -1
package/dist/index.js CHANGED
@@ -123,14 +123,7 @@ var labelVariants = cva(
123
123
  "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
124
124
  );
125
125
  var Label = React2.forwardRef(
126
- ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
127
- "label",
128
- {
129
- ref,
130
- className: cn(labelVariants(), className),
131
- ...props
132
- }
133
- )
126
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx("label", { ref, className: cn(labelVariants(), className), ...props })
134
127
  );
135
128
  Label.displayName = "Label";
136
129
  var badgeVariants = cva(
@@ -358,29 +351,36 @@ var Switch = React2.forwardRef(
358
351
  onCheckedChange?.(e.target.checked);
359
352
  };
360
353
  return /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
361
- /* @__PURE__ */ jsxs("label", { htmlFor: switchId, className: "relative inline-flex cursor-pointer items-center", children: [
362
- /* @__PURE__ */ jsx(
363
- "input",
364
- {
365
- type: "checkbox",
366
- id: switchId,
367
- ref,
368
- checked,
369
- onChange: handleChange,
370
- className: "peer sr-only",
371
- ...props
372
- }
373
- ),
374
- /* @__PURE__ */ jsx(
375
- "div",
376
- {
377
- className: cn(
378
- 'peer h-6 w-11 rounded-full bg-gray-200 after:absolute after:left-[2px] after:top-[2px] after:h-5 after:w-5 after:rounded-full after:border after:border-gray-300 after:bg-white after:transition-all after:content-[""] peer-checked:bg-primary peer-checked:after:translate-x-full peer-checked:after:border-white peer-focus:outline-none peer-focus:ring-2 peer-focus:ring-ring peer-focus:ring-offset-2 peer-disabled:cursor-not-allowed peer-disabled:opacity-50',
379
- className
354
+ /* @__PURE__ */ jsxs(
355
+ "label",
356
+ {
357
+ htmlFor: switchId,
358
+ className: "relative inline-flex cursor-pointer items-center",
359
+ children: [
360
+ /* @__PURE__ */ jsx(
361
+ "input",
362
+ {
363
+ type: "checkbox",
364
+ id: switchId,
365
+ ref,
366
+ checked,
367
+ onChange: handleChange,
368
+ className: "peer sr-only",
369
+ ...props
370
+ }
371
+ ),
372
+ /* @__PURE__ */ jsx(
373
+ "div",
374
+ {
375
+ className: cn(
376
+ 'peer h-6 w-11 rounded-full bg-gray-200 after:absolute after:left-[2px] after:top-[2px] after:h-5 after:w-5 after:rounded-full after:border after:border-gray-300 after:bg-white after:transition-all after:content-[""] peer-checked:bg-primary peer-checked:after:translate-x-full peer-checked:after:border-white peer-focus:outline-none peer-focus:ring-2 peer-focus:ring-ring peer-focus:ring-offset-2 peer-disabled:cursor-not-allowed peer-disabled:opacity-50',
377
+ className
378
+ )
379
+ }
380
380
  )
381
- }
382
- )
383
- ] }),
381
+ ]
382
+ }
383
+ ),
384
384
  label && /* @__PURE__ */ jsx("span", { className: "ml-3 text-sm font-medium text-foreground", children: label })
385
385
  ] });
386
386
  }
@@ -435,7 +435,7 @@ var Select = React2.forwardRef(
435
435
  );
436
436
  Select.displayName = "Select";
437
437
  function dedentCode(code) {
438
- let normalized = code.replace(/\t/g, " ").replace(/[ \t]+$/gm, "");
438
+ const normalized = code.replace(/\t/g, " ").replace(/[ \t]+$/gm, "");
439
439
  const lines = normalized.split("\n");
440
440
  if (lines.length <= 1) return normalized.trim();
441
441
  let start = 0;
@@ -449,7 +449,9 @@ function dedentCode(code) {
449
449
  const m = line.match(/^\s*/)?.[0].length ?? 0;
450
450
  return Math.min(min, m);
451
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");
452
+ const dedented = minIndent === Infinity || minIndent === 0 ? relevantLines.join("\n") : relevantLines.map(
453
+ (l) => l.startsWith(" ".repeat(minIndent)) ? l.slice(minIndent) : l
454
+ ).join("\n");
453
455
  return dedented;
454
456
  }
455
457
  function CopyButton({ code }) {
@@ -478,7 +480,41 @@ function CopyButton({ code }) {
478
480
  onClick: handleCopy,
479
481
  className: "rounded-md p-1.5 text-slate-400 hover:text-slate-200 hover:bg-slate-700/50 transition-colors",
480
482
  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" }) })
483
+ children: copied ? /* @__PURE__ */ jsx(
484
+ "svg",
485
+ {
486
+ className: "h-4 w-4",
487
+ fill: "none",
488
+ viewBox: "0 0 24 24",
489
+ strokeWidth: "1.5",
490
+ stroke: "currentColor",
491
+ children: /* @__PURE__ */ jsx(
492
+ "path",
493
+ {
494
+ strokeLinecap: "round",
495
+ strokeLinejoin: "round",
496
+ d: "M4.5 12.75l6 6 9-13.5"
497
+ }
498
+ )
499
+ }
500
+ ) : /* @__PURE__ */ jsx(
501
+ "svg",
502
+ {
503
+ className: "h-4 w-4",
504
+ fill: "none",
505
+ viewBox: "0 0 24 24",
506
+ strokeWidth: "1.5",
507
+ stroke: "currentColor",
508
+ children: /* @__PURE__ */ jsx(
509
+ "path",
510
+ {
511
+ strokeLinecap: "round",
512
+ strokeLinejoin: "round",
513
+ 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"
514
+ }
515
+ )
516
+ }
517
+ )
482
518
  }
483
519
  );
484
520
  }
@@ -494,29 +530,46 @@ function CodeBlock({
494
530
  return dedentCode(children);
495
531
  }
496
532
  try {
497
- const raw = React2__default.Children.toArray(children).map((c) => typeof c === "string" ? c : typeof c === "number" ? String(c) : "").join("");
533
+ const raw = React2__default.Children.toArray(children).map(
534
+ (c) => typeof c === "string" ? c : typeof c === "number" ? String(c) : ""
535
+ ).join("");
498
536
  return dedentCode(raw);
499
537
  } catch {
500
538
  return "";
501
539
  }
502
540
  }, [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" })
541
+ return /* @__PURE__ */ jsxs(
542
+ "div",
543
+ {
544
+ className: `group relative my-4 overflow-hidden rounded-xl border border-slate-700 bg-slate-900 shadow-lg ${className}`,
545
+ children: [
546
+ showHeader && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-b border-slate-700 bg-slate-800/50 px-4 py-2", children: [
547
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
548
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-1.5", children: [
549
+ /* @__PURE__ */ jsx("div", { className: "h-3 w-3 rounded-full bg-red-500/50" }),
550
+ /* @__PURE__ */ jsx("div", { className: "h-3 w-3 rounded-full bg-amber-500/50" }),
551
+ /* @__PURE__ */ jsx("div", { className: "h-3 w-3 rounded-full bg-emerald-500/50" })
552
+ ] }),
553
+ /* @__PURE__ */ jsx("span", { className: "ml-2 text-xs font-semibold uppercase tracking-wider text-slate-500 font-mono", children: language })
554
+ ] }),
555
+ showCopy && /* @__PURE__ */ jsx(CopyButton, { code: codeString })
510
556
  ] }),
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
- ] });
557
+ /* @__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 }) })
558
+ ]
559
+ }
560
+ );
517
561
  }
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 });
562
+ function InlineCode({
563
+ children,
564
+ className = ""
565
+ }) {
566
+ return /* @__PURE__ */ jsx(
567
+ "code",
568
+ {
569
+ className: `rounded-md bg-slate-100 px-1.5 py-0.5 text-sm font-mono text-slate-800 ${className}`,
570
+ children
571
+ }
572
+ );
520
573
  }
521
574
  var DefaultSeparator = () => /* @__PURE__ */ jsx(
522
575
  "svg",
@@ -526,41 +579,69 @@ var DefaultSeparator = () => /* @__PURE__ */ jsx(
526
579
  viewBox: "0 0 24 24",
527
580
  strokeWidth: "1.5",
528
581
  stroke: "currentColor",
529
- children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M8.25 4.5l7.5 7.5-7.5 7.5" })
582
+ children: /* @__PURE__ */ jsx(
583
+ "path",
584
+ {
585
+ strokeLinecap: "round",
586
+ strokeLinejoin: "round",
587
+ d: "M8.25 4.5l7.5 7.5-7.5 7.5"
588
+ }
589
+ )
530
590
  }
531
591
  );
532
592
  function Breadcrumb({ items, separator, className }) {
533
593
  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
- }) }) });
594
+ return /* @__PURE__ */ jsx(
595
+ "nav",
596
+ {
597
+ className: cn("flex items-center gap-1 text-sm", className),
598
+ "aria-label": "Breadcrumb",
599
+ children: /* @__PURE__ */ jsx("ol", { className: "flex items-center gap-1", children: items.map((item, index) => {
600
+ const isLast = index === items.length - 1;
601
+ return /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-1", children: [
602
+ index > 0 && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0", children: Separator2 }),
603
+ item.href && !isLast ? /* @__PURE__ */ jsx(
604
+ "a",
605
+ {
606
+ href: item.href,
607
+ className: "text-slate-600 hover:text-slate-900 transition-colors",
608
+ children: item.label
609
+ }
610
+ ) : /* @__PURE__ */ jsx(
611
+ "span",
612
+ {
613
+ className: isLast ? "font-medium text-slate-900" : "text-slate-600",
614
+ children: item.label
615
+ }
616
+ )
617
+ ] }, index);
618
+ }) })
619
+ }
620
+ );
548
621
  }
549
622
  var ratingConfig = {
550
- excellent: { color: "bg-green-500", bgColor: "bg-green-100", label: "Excellent" },
623
+ excellent: {
624
+ color: "bg-green-500",
625
+ bgColor: "bg-green-100",
626
+ label: "Excellent"
627
+ },
551
628
  good: { color: "bg-emerald-500", bgColor: "bg-emerald-100", label: "Good" },
552
629
  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" },
630
+ "needs-work": {
631
+ color: "bg-orange-500",
632
+ bgColor: "bg-orange-100",
633
+ label: "Needs Work"
634
+ },
554
635
  critical: { color: "bg-red-500", bgColor: "bg-red-100", label: "Critical" }
555
636
  };
556
637
  function getRating(score) {
557
638
  const coreRating = getRating$1(score);
558
639
  const ratingMap = {
559
- "Excellent": "excellent",
560
- "Good": "good",
561
- "Fair": "fair",
640
+ Excellent: "excellent",
641
+ Good: "good",
642
+ Fair: "fair",
562
643
  "Needs Work": "needs-work",
563
- "Critical": "critical"
644
+ Critical: "critical"
564
645
  };
565
646
  return ratingMap[coreRating] || "critical";
566
647
  }
@@ -593,53 +674,82 @@ function ScoreBar({
593
674
  /* @__PURE__ */ jsx("div", { className: cn("w-full rounded-full bg-slate-200", sizes.height), children: /* @__PURE__ */ jsx(
594
675
  "div",
595
676
  {
596
- className: cn("rounded-full transition-all duration-500", config.color, sizes.height),
677
+ className: cn(
678
+ "rounded-full transition-all duration-500",
679
+ config.color,
680
+ sizes.height
681
+ ),
597
682
  style: { width: `${percentage}%` }
598
683
  }
599
684
  ) })
600
685
  ] });
601
686
  }
602
- function ScoreCard({ score, title, breakdown, className }) {
687
+ function ScoreCard({
688
+ score,
689
+ title,
690
+ breakdown,
691
+ className
692
+ }) {
603
693
  const rating = getRating(score);
604
694
  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
- ] });
695
+ return /* @__PURE__ */ jsxs(
696
+ "div",
697
+ {
698
+ className: cn(
699
+ "rounded-xl border-2 border-slate-200 bg-white p-6 shadow-lg",
700
+ className
701
+ ),
702
+ children: [
703
+ /* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
704
+ /* @__PURE__ */ jsxs("div", { className: "text-4xl font-black text-slate-900", children: [
705
+ score,
706
+ "/100"
707
+ ] }),
708
+ /* @__PURE__ */ jsxs(
709
+ "div",
710
+ {
711
+ className: cn(
712
+ "text-lg font-bold",
713
+ `text-${rating === "excellent" ? "green" : rating === "good" ? "emerald" : rating === "fair" ? "amber" : rating === "needs-work" ? "orange" : "red"}-600`
714
+ ),
715
+ children: [
716
+ config.label,
717
+ " Rating"
718
+ ]
719
+ }
720
+ ),
721
+ title && /* @__PURE__ */ jsx("p", { className: "text-sm text-slate-600 mt-1", children: title })
722
+ ] }),
723
+ breakdown && breakdown.length > 0 && /* @__PURE__ */ jsx("div", { className: "space-y-3", children: breakdown.map((item, index) => /* @__PURE__ */ jsx(
724
+ ScoreBar,
725
+ {
726
+ score: item.score,
727
+ label: item.label,
728
+ size: "sm"
729
+ },
730
+ index
731
+ )) }),
732
+ breakdown && breakdown.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mt-4 text-xs text-slate-600 bg-slate-50 p-3 rounded-lg", children: [
733
+ /* @__PURE__ */ jsx("strong", { children: "Formula:" }),
734
+ " ",
735
+ breakdown.map((item) => `${item.score}\xD7${item.weight || 1}`).join(" + "),
736
+ " ",
737
+ "/ 100 = ",
738
+ score
739
+ ] })
740
+ ]
741
+ }
742
+ );
636
743
  }
637
744
  var sizeClasses = {
638
745
  sm: "h-4 w-4",
639
746
  md: "h-8 w-8",
640
747
  lg: "h-12 w-12"
641
748
  };
642
- function LoadingSpinner({ size = "md", className = "" }) {
749
+ function LoadingSpinner({
750
+ size = "md",
751
+ className = ""
752
+ }) {
643
753
  return /* @__PURE__ */ jsx("div", { className: `flex items-center justify-center ${className}`, children: /* @__PURE__ */ jsx(
644
754
  "div",
645
755
  {
@@ -647,7 +757,9 @@ function LoadingSpinner({ size = "md", className = "" }) {
647
757
  }
648
758
  ) });
649
759
  }
650
- function LoadingOverlay({ message = "Loading..." }) {
760
+ function LoadingOverlay({
761
+ message = "Loading..."
762
+ }) {
651
763
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center min-h-[200px] gap-4", children: [
652
764
  /* @__PURE__ */ jsx(LoadingSpinner, { size: "lg" }),
653
765
  /* @__PURE__ */ jsx("p", { className: "text-sm text-slate-500 animate-pulse", children: message })
@@ -688,21 +800,36 @@ function ErrorDisplay({
688
800
  onClick: retry,
689
801
  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
802
  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",
803
+ /* @__PURE__ */ jsx(
804
+ "svg",
693
805
  {
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"
806
+ className: "h-4 w-4",
807
+ fill: "none",
808
+ viewBox: "0 0 24 24",
809
+ strokeWidth: "1.5",
810
+ stroke: "currentColor",
811
+ children: /* @__PURE__ */ jsx(
812
+ "path",
813
+ {
814
+ strokeLinecap: "round",
815
+ strokeLinejoin: "round",
816
+ 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"
817
+ }
818
+ )
697
819
  }
698
- ) }),
820
+ ),
699
821
  retryLabel
700
822
  ]
701
823
  }
702
824
  )
703
825
  ] });
704
826
  }
705
- function EmptyState({ title, description, icon, action }) {
827
+ function EmptyState({
828
+ title,
829
+ description,
830
+ icon,
831
+ action
832
+ }) {
706
833
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center min-h-[200px] gap-4 p-8", children: [
707
834
  icon && /* @__PURE__ */ jsx("div", { className: "rounded-full bg-slate-100 p-3", children: icon }),
708
835
  /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
@@ -782,8 +909,18 @@ function ThemeProvider({
782
909
  }
783
910
  };
784
911
  if (!mounted) {
785
- return /* @__PURE__ */ jsx(ThemeContext.Provider, { value: { theme: defaultTheme, setTheme: () => {
786
- }, effectiveTheme: "light" }, children });
912
+ return /* @__PURE__ */ jsx(
913
+ ThemeContext.Provider,
914
+ {
915
+ value: {
916
+ theme: defaultTheme,
917
+ setTheme: () => {
918
+ },
919
+ effectiveTheme: "light"
920
+ },
921
+ children
922
+ }
923
+ );
787
924
  }
788
925
  return /* @__PURE__ */ jsx(ThemeContext.Provider, { value: { theme, setTheme, effectiveTheme }, children });
789
926
  }
@@ -1028,14 +1165,11 @@ function useForceSimulation(initialNodes, initialLinks, options) {
1028
1165
  alphaTarget = 0,
1029
1166
  warmAlpha = 0.3,
1030
1167
  alphaMin = 0.01,
1031
- // @ts-ignore allow extra option
1032
- stabilizeOnStop = true,
1033
1168
  onTick,
1034
1169
  // Optional throttle in milliseconds for tick updates (reduce React re-renders)
1035
1170
  // Lower values = smoother but more CPU; default ~30ms (~33fps)
1036
- // @ts-ignore allow extra option
1171
+ stabilizeOnStop = true,
1037
1172
  tickThrottleMs = 33,
1038
- // @ts-ignore allow extra option
1039
1173
  maxSimulationTimeMs = 3e3
1040
1174
  } = options;
1041
1175
  const [nodes, setNodes] = useState(initialNodes);
@@ -1070,10 +1204,16 @@ function useForceSimulation(initialNodes, initialLinks, options) {
1070
1204
  n.vy = (Math.random() - 0.5) * 10;
1071
1205
  });
1072
1206
  }
1073
- const simulation = d33.forceSimulation(nodesCopy);
1207
+ const simulation = d33.forceSimulation(
1208
+ nodesCopy
1209
+ );
1074
1210
  try {
1075
- const linkForce = d33.forceLink(linksCopy);
1076
- linkForce.id((d) => d.id).distance((d) => d && d.distance != null ? d.distance : linkDistance).strength(linkStrength);
1211
+ const linkForce = d33.forceLink(
1212
+ linksCopy
1213
+ );
1214
+ linkForce.id((d) => d.id).distance(
1215
+ (d) => d && d.distance != null ? d.distance : linkDistance
1216
+ ).strength(linkStrength);
1077
1217
  simulation.force("link", linkForce);
1078
1218
  } catch (e) {
1079
1219
  try {
@@ -1082,25 +1222,39 @@ function useForceSimulation(initialNodes, initialLinks, options) {
1082
1222
  }
1083
1223
  }
1084
1224
  try {
1085
- simulation.force("charge", d33.forceManyBody().strength(chargeStrength));
1086
- simulation.force("center", d33.forceCenter(width / 2, height / 2).strength(centerStrength));
1225
+ simulation.force(
1226
+ "charge",
1227
+ d33.forceManyBody().strength(chargeStrength)
1228
+ );
1229
+ simulation.force(
1230
+ "center",
1231
+ d33.forceCenter(width / 2, height / 2).strength(centerStrength)
1232
+ );
1087
1233
  const collide = d33.forceCollide().radius((d) => {
1088
1234
  const nodeSize = d && d.size ? d.size : 10;
1089
1235
  return nodeSize + collisionRadius;
1090
1236
  }).strength(collisionStrength);
1091
1237
  simulation.force("collision", collide);
1092
- simulation.force("x", d33.forceX(width / 2).strength(Math.max(0.02, centerStrength * 0.5)));
1093
- simulation.force("y", d33.forceY(height / 2).strength(Math.max(0.02, centerStrength * 0.5)));
1238
+ simulation.force(
1239
+ "x",
1240
+ d33.forceX(width / 2).strength(Math.max(0.02, centerStrength * 0.5))
1241
+ );
1242
+ simulation.force(
1243
+ "y",
1244
+ d33.forceY(height / 2).strength(Math.max(0.02, centerStrength * 0.5))
1245
+ );
1094
1246
  simulation.alphaDecay(alphaDecay);
1095
1247
  simulation.velocityDecay(velocityDecay);
1096
1248
  simulation.alphaMin(alphaMin);
1097
1249
  try {
1098
1250
  simulation.alphaTarget(alphaTarget);
1099
1251
  } catch (e) {
1252
+ void e;
1100
1253
  }
1101
1254
  try {
1102
1255
  simulation.alpha(warmAlpha);
1103
1256
  } catch (e) {
1257
+ void e;
1104
1258
  }
1105
1259
  } catch (e) {
1106
1260
  }
@@ -1136,7 +1290,8 @@ function useForceSimulation(initialNodes, initialLinks, options) {
1136
1290
  let lastUpdate = 0;
1137
1291
  const tickHandler = () => {
1138
1292
  try {
1139
- if (typeof onTick === "function") onTick(nodesCopy, linksCopy, simulation);
1293
+ if (typeof onTick === "function")
1294
+ onTick(nodesCopy, linksCopy, simulation);
1140
1295
  } catch (e) {
1141
1296
  }
1142
1297
  try {
@@ -1152,6 +1307,7 @@ function useForceSimulation(initialNodes, initialLinks, options) {
1152
1307
  }
1153
1308
  simulation.stop();
1154
1309
  } catch (e) {
1310
+ void e;
1155
1311
  }
1156
1312
  setAlpha(simulation.alpha());
1157
1313
  setIsRunning(false);
@@ -1222,7 +1378,7 @@ function useForceSimulation(initialNodes, initialLinks, options) {
1222
1378
  if (simulationRef.current) {
1223
1379
  try {
1224
1380
  simulationRef.current.alphaTarget(warmAlpha).restart();
1225
- } catch (e) {
1381
+ } catch {
1226
1382
  simulationRef.current.restart();
1227
1383
  }
1228
1384
  setIsRunning(true);
@@ -1251,7 +1407,11 @@ function useForceSimulation(initialNodes, initialLinks, options) {
1251
1407
  setIsRunning(false);
1252
1408
  }
1253
1409
  };
1254
- const originalForcesRef = useRef({ charge: chargeStrength, link: linkStrength, collision: collisionStrength });
1410
+ const originalForcesRef = useRef({
1411
+ charge: chargeStrength,
1412
+ link: linkStrength,
1413
+ collision: collisionStrength
1414
+ });
1255
1415
  const forcesEnabledRef = useRef(true);
1256
1416
  const setForcesEnabled = (enabled) => {
1257
1417
  const sim = simulationRef.current;
@@ -1343,15 +1503,43 @@ var NodeItem = ({
1343
1503
  opacity: isHovered || isSelected ? 1 : 0.9
1344
1504
  }
1345
1505
  ),
1346
- pinned && /* @__PURE__ */ jsx("circle", { r: nodeSize + 4, fill: "none", stroke: "#ff6b6b", strokeWidth: 1, opacity: 0.5, className: "pointer-events-none" }),
1347
- showLabel && node.label && /* @__PURE__ */ jsx("text", { y: nodeSize + 15, fill: "#333", fontSize: "12", textAnchor: "middle", dominantBaseline: "middle", pointerEvents: "none", className: "select-none", children: node.label })
1506
+ pinned && /* @__PURE__ */ jsx(
1507
+ "circle",
1508
+ {
1509
+ r: nodeSize + 4,
1510
+ fill: "none",
1511
+ stroke: "#ff6b6b",
1512
+ strokeWidth: 1,
1513
+ opacity: 0.5,
1514
+ className: "pointer-events-none"
1515
+ }
1516
+ ),
1517
+ showLabel && node.label && /* @__PURE__ */ jsx(
1518
+ "text",
1519
+ {
1520
+ y: nodeSize + 15,
1521
+ fill: "#333",
1522
+ fontSize: "12",
1523
+ textAnchor: "middle",
1524
+ dominantBaseline: "middle",
1525
+ pointerEvents: "none",
1526
+ className: "select-none",
1527
+ children: node.label
1528
+ }
1529
+ )
1348
1530
  ]
1349
1531
  },
1350
1532
  node.id
1351
1533
  );
1352
1534
  };
1353
1535
  var NodeItem_default = NodeItem;
1354
- var LinkItem = ({ link, onClick, defaultWidth, showLabel = true, nodes = [] }) => {
1536
+ var LinkItem = ({
1537
+ link,
1538
+ onClick,
1539
+ defaultWidth,
1540
+ showLabel = true,
1541
+ nodes = []
1542
+ }) => {
1355
1543
  const src = link.source?.id ?? (typeof link.source === "string" ? link.source : void 0);
1356
1544
  const tgt = link.target?.id ?? (typeof link.target === "string" ? link.target : void 0);
1357
1545
  const getNodePosition = (nodeOrId) => {
@@ -1444,10 +1632,13 @@ var ForceDirectedGraph = forwardRef(
1444
1632
  setLayout(externalLayout);
1445
1633
  }
1446
1634
  }, [externalLayout]);
1447
- const handleLayoutChange = useCallback((newLayout) => {
1448
- setLayout(newLayout);
1449
- onLayoutChange?.(newLayout);
1450
- }, [onLayoutChange]);
1635
+ const handleLayoutChange = useCallback(
1636
+ (newLayout) => {
1637
+ setLayout(newLayout);
1638
+ onLayoutChange?.(newLayout);
1639
+ },
1640
+ [onLayoutChange]
1641
+ );
1451
1642
  useEffect(() => {
1452
1643
  internalDragEnabledRef.current = enableDrag;
1453
1644
  }, [enableDrag]);
@@ -1487,7 +1678,7 @@ var ForceDirectedGraph = forwardRef(
1487
1678
  }, []);
1488
1679
  const stop = React2__default.useCallback(() => {
1489
1680
  }, []);
1490
- const setForcesEnabled = React2__default.useCallback((_enabled) => {
1681
+ const setForcesEnabled = React2__default.useCallback((enabled) => {
1491
1682
  }, []);
1492
1683
  useEffect(() => {
1493
1684
  if (!nodes || nodes.length === 0) return;
@@ -1598,7 +1789,10 @@ var ForceDirectedGraph = forwardRef(
1598
1789
  if (gRef.current && svgRef.current) {
1599
1790
  const svg = d33.select(svgRef.current);
1600
1791
  const newTransform = d33.zoomIdentity.translate(x, y).scale(scale);
1601
- svg.transition().duration(300).call(d33.zoom().transform, newTransform);
1792
+ svg.transition().duration(300).call(
1793
+ d33.zoom().transform,
1794
+ newTransform
1795
+ );
1602
1796
  setTransform(newTransform);
1603
1797
  }
1604
1798
  },
@@ -1615,7 +1809,8 @@ var ForceDirectedGraph = forwardRef(
1615
1809
  );
1616
1810
  useEffect(() => {
1617
1811
  try {
1618
- if (typeof onManualLayoutChange === "function") onManualLayoutChange(manualLayout);
1812
+ if (typeof onManualLayoutChange === "function")
1813
+ onManualLayoutChange(manualLayout);
1619
1814
  } catch (e) {
1620
1815
  }
1621
1816
  }, [manualLayout, onManualLayoutChange]);
@@ -1640,7 +1835,10 @@ var ForceDirectedGraph = forwardRef(
1640
1835
  g.selectAll("g.node").each(function() {
1641
1836
  const datum = d33.select(this).datum();
1642
1837
  if (!datum) return;
1643
- d33.select(this).attr("transform", `translate(${datum.x || 0},${datum.y || 0})`);
1838
+ d33.select(this).attr(
1839
+ "transform",
1840
+ `translate(${datum.x || 0},${datum.y || 0})`
1841
+ );
1644
1842
  });
1645
1843
  g.selectAll("line").each(function() {
1646
1844
  const l = d33.select(this).datum();
@@ -1742,8 +1940,6 @@ var ForceDirectedGraph = forwardRef(
1742
1940
  restart();
1743
1941
  } catch (e) {
1744
1942
  }
1745
- dragNodeRef.current = null;
1746
- dragActiveRef.current = false;
1747
1943
  });
1748
1944
  try {
1749
1945
  g.selectAll("g.node").call(dragBehavior);