uilint-react 0.1.31 → 0.1.33

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.
@@ -1,9 +1,8 @@
1
1
  "use client";
2
2
  import {
3
3
  buildEditorUrl,
4
- useUILintContext,
5
- useUILintStore
6
- } from "./chunk-M3H56XIZ.js";
4
+ useUILintContext
5
+ } from "./chunk-MO4NS6EG.js";
7
6
 
8
7
  // src/components/ui-lint/InspectionPanel.tsx
9
8
  import { useState, useEffect, useCallback, useMemo } from "react";
@@ -83,7 +82,7 @@ async function prefetchSources(filePaths) {
83
82
  }
84
83
 
85
84
  // src/components/ui-lint/InspectionPanel.tsx
86
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
85
+ import { jsx, jsxs } from "react/jsx-runtime";
87
86
  var STYLES = {
88
87
  bg: "rgba(17, 24, 39, 0.95)",
89
88
  bgSurface: "rgba(31, 41, 55, 0.9)",
@@ -556,26 +555,6 @@ function SourceTab({ element }) {
556
555
  }
557
556
  function ScanSection({ element }) {
558
557
  const { elementIssuesCache, autoScanState } = useUILintContext();
559
- const [copied, setCopied] = useState(false);
560
- const manualKey = useMemo(() => {
561
- const dataLoc = element.element.getAttribute("data-loc");
562
- if (dataLoc) return `dataloc:${dataLoc}`;
563
- if (element.source) {
564
- return `src:${element.source.fileName}:${element.source.lineNumber}:${element.source.columnNumber ?? 0}`;
565
- }
566
- return `fallback:${element.element.tagName.toLowerCase()}:${Math.round(
567
- element.rect.left
568
- )}:${Math.round(element.rect.top)}`;
569
- }, [element.element, element.source, element.rect]);
570
- const manualScan = useUILintStore(
571
- (s) => s.manualScanCache.get(manualKey)
572
- );
573
- const upsertManualScan = useUILintStore(
574
- (s) => s.upsertManualScan
575
- );
576
- const includeChildren = manualScan?.includeChildren ?? false;
577
- const componentName = element.componentStack[0]?.name || element.element.tagName.toLowerCase();
578
- const componentLine = element.source?.lineNumber;
579
558
  const cachedIssue = useMemo(() => {
580
559
  if (element.scannedElementId) {
581
560
  const cached = elementIssuesCache.get(element.scannedElementId);
@@ -598,189 +577,14 @@ function ScanSection({ element }) {
598
577
  elementIssuesCache,
599
578
  autoScanState.elements
600
579
  ]);
601
- const generateFixPrompt = useCallback(
602
- (issues, relativePath) => {
603
- if (issues.length === 0) {
604
- return `No style issues found in the \`${componentName}\` component in \`${relativePath}\`. The component appears to follow the styleguide.`;
605
- }
606
- const issueList = issues.map((issue) => {
607
- const lineInfo = issue.line ? `Line ${issue.line}: ` : "";
608
- return `- ${lineInfo}${issue.message}`;
609
- }).join("\n");
610
- return `Fix the following style issues in the \`${componentName}\` component in \`${relativePath}\`:
611
-
612
- Issues found:
613
- ${issueList}
614
-
615
- Please update this component to match our styleguide.`;
616
- },
617
- [componentName]
618
- );
619
- const cachedFixPrompt = useMemo(() => {
620
- if (!cachedIssue || cachedIssue.status !== "complete") return null;
621
- const relativePath = element.source?.fileName || "unknown";
622
- return generateFixPrompt(cachedIssue.issues, relativePath);
623
- }, [cachedIssue, element.source, generateFixPrompt]);
624
- const handleScan = useCallback(async () => {
625
- if (!element.source) {
626
- upsertManualScan(manualKey, {
627
- status: "error",
628
- error: "No source information available"
629
- });
630
- return;
631
- }
632
- const MAX_DATALOCS = 80;
633
- const selectedDataLoc = element.element.getAttribute("data-loc");
634
- let dataLocList = [];
635
- if (includeChildren) {
636
- const nodes = [
637
- element.element,
638
- ...Array.from(element.element.querySelectorAll("[data-loc]"))
639
- ];
640
- for (const n of nodes) {
641
- const v = n.getAttribute("data-loc");
642
- if (v) dataLocList.push(v);
643
- }
644
- } else if (selectedDataLoc) {
645
- dataLocList = [selectedDataLoc];
646
- }
647
- dataLocList = Array.from(new Set(dataLocList)).slice(0, MAX_DATALOCS);
648
- upsertManualScan(manualKey, {
649
- status: "scanning",
650
- error: void 0,
651
- fixPrompt: void 0,
652
- issues: [],
653
- progressLine: "Preparing analysis\u2026"
654
- });
655
- try {
656
- const sourceResponse = await fetch(
657
- `/api/.uilint/source?path=${encodeURIComponent(
658
- element.source.fileName
659
- )}`
660
- );
661
- if (!sourceResponse.ok) {
662
- throw new Error("Failed to fetch source code");
663
- }
664
- const sourceData = await sourceResponse.json();
665
- const sourceCode = sourceData.content;
666
- const relativePath = sourceData.relativePath || element.source.fileName;
667
- const analyzeResponse = await fetch("/api/.uilint/analyze", {
668
- method: "POST",
669
- headers: { "Content-Type": "application/json" },
670
- body: JSON.stringify({
671
- sourceCode,
672
- filePath: relativePath,
673
- componentName,
674
- componentLine,
675
- includeChildren,
676
- dataLocs: dataLocList.length > 0 ? dataLocList : void 0,
677
- stream: true
678
- })
679
- });
680
- if (!analyzeResponse.ok) {
681
- throw new Error("Failed to analyze source code");
682
- }
683
- const contentType = analyzeResponse.headers.get("content-type") || "";
684
- if (!contentType.includes("text/event-stream") || !analyzeResponse.body) {
685
- const result = await analyzeResponse.json();
686
- const issues = result.issues || [];
687
- upsertManualScan(manualKey, {
688
- status: "complete",
689
- issues,
690
- fixPrompt: generateFixPrompt(issues, relativePath),
691
- progressLine: void 0
692
- });
693
- return;
694
- }
695
- const reader = analyzeResponse.body.getReader();
696
- const decoder = new TextDecoder();
697
- let buffer = "";
698
- while (true) {
699
- const { done, value } = await reader.read();
700
- if (done) break;
701
- buffer += decoder.decode(value, { stream: true });
702
- const parts = buffer.split("\n\n");
703
- buffer = parts.pop() || "";
704
- for (const part of parts) {
705
- const lines = part.split("\n");
706
- let eventName = "message";
707
- let dataStr = "";
708
- for (const line of lines) {
709
- if (line.startsWith("event:")) eventName = line.slice(6).trim();
710
- if (line.startsWith("data:")) dataStr += line.slice(5).trim();
711
- }
712
- if (!dataStr) continue;
713
- try {
714
- const data = JSON.parse(dataStr);
715
- if (eventName === "progress") {
716
- upsertManualScan(manualKey, {
717
- status: "scanning",
718
- progressLine: data.latestLine || data.phase || "Running analysis\u2026"
719
- });
720
- } else if (eventName === "done") {
721
- const issues = data.issues || [];
722
- upsertManualScan(manualKey, {
723
- status: "complete",
724
- issues,
725
- fixPrompt: generateFixPrompt(issues, relativePath),
726
- progressLine: void 0
727
- });
728
- } else if (eventName === "error") {
729
- upsertManualScan(manualKey, {
730
- status: "error",
731
- error: data.error || "Analysis failed",
732
- progressLine: void 0
733
- });
734
- }
735
- } catch {
736
- }
737
- }
738
- }
739
- } catch (err) {
740
- upsertManualScan(manualKey, {
741
- status: "error",
742
- error: err instanceof Error ? err.message : "An error occurred during scanning",
743
- progressLine: void 0
744
- });
745
- }
746
- }, [
747
- element.source,
748
- element.element,
749
- element.rect,
750
- componentName,
751
- componentLine,
752
- generateFixPrompt,
753
- manualKey,
754
- upsertManualScan,
755
- includeChildren
756
- ]);
757
- const handleCopy = useCallback(
758
- async (text) => {
759
- try {
760
- await navigator.clipboard.writeText(text);
761
- setCopied(true);
762
- setTimeout(() => setCopied(false), 2e3);
763
- } catch {
764
- upsertManualScan(manualKey, {
765
- status: "error",
766
- error: "Failed to copy to clipboard"
767
- });
768
- }
769
- },
770
- [manualKey, upsertManualScan]
771
- );
772
- const manualStatus = manualScan?.status ?? "idle";
773
- const showCachedScanning = cachedIssue?.status === "scanning" && manualStatus === "idle";
774
- const showCachedPending = cachedIssue?.status === "pending" && manualStatus === "idle";
775
- const showCachedError = cachedIssue?.status === "error" && manualStatus === "idle";
776
- const showCachedResult = cachedFixPrompt && manualStatus === "idle";
777
- const showScanButton = !cachedIssue && manualStatus === "idle";
778
- const showManualResult = manualStatus === "complete" && manualScan?.fixPrompt;
779
- const scanning = manualStatus === "scanning";
780
- const error = manualScan?.status === "error" ? manualScan.error : null;
781
- const fixPrompt = manualScan?.fixPrompt ?? null;
782
- const progressLine = manualScan?.progressLine ?? null;
783
- const scopeLabel = includeChildren ? "Element + children" : "Element only";
580
+ const eslintIssues = useMemo(() => {
581
+ return cachedIssue?.issues || [];
582
+ }, [cachedIssue]);
583
+ const showCachedScanning = cachedIssue?.status === "scanning";
584
+ const showCachedPending = cachedIssue?.status === "pending";
585
+ const showCachedError = cachedIssue?.status === "error";
586
+ const showCachedResult = cachedIssue?.status === "complete";
587
+ const showNoScan = !cachedIssue;
784
588
  return /* @__PURE__ */ jsx(
785
589
  "div",
786
590
  {
@@ -818,384 +622,36 @@ Please update this component to match our styleguide.`;
818
622
  ]
819
623
  }
820
624
  ),
821
- showCachedPending && /* @__PURE__ */ jsxs("div", { style: { textAlign: "center", padding: "16px 0" }, children: [
822
- /* @__PURE__ */ jsxs(
823
- "div",
824
- {
825
- style: {
826
- display: "inline-flex",
827
- alignItems: "center",
828
- gap: "8px",
829
- padding: "10px 20px",
830
- borderRadius: "8px",
831
- backgroundColor: STYLES.bg,
832
- color: STYLES.textMuted,
833
- fontSize: "12px",
834
- marginBottom: "12px"
835
- },
836
- children: [
837
- /* @__PURE__ */ jsx(
838
- "div",
839
- {
840
- style: {
841
- width: "8px",
842
- height: "8px",
843
- borderRadius: "50%",
844
- backgroundColor: "rgba(156, 163, 175, 0.5)"
845
- }
846
- }
847
- ),
848
- "Waiting in scan queue..."
849
- ]
850
- }
851
- ),
852
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
853
- "button",
854
- {
855
- onClick: handleScan,
856
- disabled: !element.source,
857
- style: {
858
- padding: "8px 16px",
859
- borderRadius: "6px",
860
- border: `1px solid ${STYLES.border}`,
861
- backgroundColor: "transparent",
862
- color: element.source ? STYLES.text : STYLES.textDim,
863
- fontSize: "12px",
864
- fontWeight: 500,
865
- cursor: element.source ? "pointer" : "not-allowed",
866
- transition: "all 0.15s"
867
- },
868
- onMouseEnter: (e) => {
869
- if (element.source) {
870
- e.currentTarget.style.borderColor = STYLES.accent;
871
- e.currentTarget.style.backgroundColor = "rgba(59, 130, 246, 0.1)";
872
- }
873
- },
874
- onMouseLeave: (e) => {
875
- e.currentTarget.style.borderColor = STYLES.border;
876
- e.currentTarget.style.backgroundColor = "transparent";
877
- },
878
- children: "Scan Now"
879
- }
880
- ) })
881
- ] }),
882
- showCachedError && /* @__PURE__ */ jsxs("div", { children: [
883
- /* @__PURE__ */ jsx(
884
- "div",
885
- {
886
- style: {
887
- padding: "12px",
888
- backgroundColor: "rgba(239, 68, 68, 0.1)",
889
- border: "1px solid rgba(239, 68, 68, 0.3)",
890
- borderRadius: "8px",
891
- color: "#EF4444",
892
- fontSize: "12px",
893
- marginBottom: "12px"
894
- },
895
- children: "Auto-scan failed for this element"
896
- }
897
- ),
898
- /* @__PURE__ */ jsx("div", { style: { textAlign: "center" }, children: /* @__PURE__ */ jsxs(
899
- "button",
900
- {
901
- onClick: handleScan,
902
- disabled: !element.source,
903
- style: {
904
- display: "inline-flex",
905
- alignItems: "center",
906
- gap: "8px",
907
- padding: "10px 20px",
908
- borderRadius: "8px",
909
- border: "none",
910
- backgroundColor: element.source ? STYLES.success : STYLES.textDim,
911
- color: "#FFFFFF",
912
- fontSize: "13px",
913
- fontWeight: 600,
914
- cursor: element.source ? "pointer" : "not-allowed",
915
- transition: "background-color 0.15s"
916
- },
917
- onMouseEnter: (e) => {
918
- if (element.source) {
919
- e.currentTarget.style.backgroundColor = "#059669";
920
- }
921
- },
922
- onMouseLeave: (e) => {
923
- if (element.source) {
924
- e.currentTarget.style.backgroundColor = STYLES.success;
925
- }
926
- },
927
- children: [
928
- /* @__PURE__ */ jsx(ScanIcon, {}),
929
- "Retry Scan"
930
- ]
931
- }
932
- ) })
933
- ] }),
934
- showCachedResult && /* @__PURE__ */ jsxs("div", { children: [
935
- /* @__PURE__ */ jsxs(
936
- "div",
937
- {
938
- style: {
939
- display: "flex",
940
- alignItems: "center",
941
- gap: "8px",
942
- marginBottom: "12px",
943
- padding: "8px 12px",
944
- backgroundColor: "rgba(16, 185, 129, 0.1)",
945
- borderRadius: "6px",
946
- fontSize: "11px",
947
- color: STYLES.success
948
- },
949
- children: [
950
- /* @__PURE__ */ jsx(CheckIconSmall, {}),
951
- "Scan complete"
952
- ]
953
- }
954
- ),
955
- /* @__PURE__ */ jsxs(
956
- "div",
957
- {
958
- style: {
959
- display: "flex",
960
- alignItems: "center",
961
- justifyContent: "space-between",
962
- marginBottom: "10px"
963
- },
964
- children: [
965
- /* @__PURE__ */ jsx(
966
- "div",
967
- {
968
- style: {
969
- fontSize: "12px",
970
- fontWeight: 600,
971
- color: STYLES.text
972
- },
973
- children: "Fix Prompt"
974
- }
975
- ),
976
- /* @__PURE__ */ jsx(
977
- "button",
978
- {
979
- onClick: () => handleCopy(cachedFixPrompt),
980
- style: {
981
- display: "flex",
982
- alignItems: "center",
983
- gap: "6px",
984
- padding: "6px 12px",
985
- borderRadius: "6px",
986
- border: "none",
987
- backgroundColor: copied ? STYLES.success : STYLES.accent,
988
- color: "#FFFFFF",
989
- fontSize: "11px",
990
- fontWeight: 500,
991
- cursor: "pointer",
992
- transition: "all 0.15s"
993
- },
994
- children: copied ? /* @__PURE__ */ jsxs(Fragment, { children: [
995
- /* @__PURE__ */ jsx(CheckIcon, {}),
996
- "Copied!"
997
- ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
998
- /* @__PURE__ */ jsx(CopyIcon, {}),
999
- "Copy"
1000
- ] })
1001
- }
1002
- )
1003
- ]
1004
- }
1005
- ),
1006
- /* @__PURE__ */ jsx(
1007
- "div",
1008
- {
1009
- style: {
1010
- padding: "12px",
1011
- backgroundColor: STYLES.bg,
1012
- border: `1px solid ${STYLES.border}`,
1013
- borderRadius: "8px",
1014
- fontFamily: STYLES.fontMono,
1015
- fontSize: "11px",
1016
- lineHeight: 1.6,
1017
- whiteSpace: "pre-wrap",
1018
- color: STYLES.text,
1019
- maxHeight: "200px",
1020
- overflow: "auto"
1021
- },
1022
- children: cachedFixPrompt
1023
- }
1024
- ),
1025
- /* @__PURE__ */ jsx("div", { style: { textAlign: "center", marginTop: "12px" }, children: /* @__PURE__ */ jsx(
1026
- "button",
1027
- {
1028
- onClick: handleScan,
1029
- style: {
1030
- padding: "6px 12px",
1031
- borderRadius: "6px",
1032
- border: `1px solid ${STYLES.border}`,
1033
- backgroundColor: "transparent",
1034
- color: STYLES.textMuted,
1035
- fontSize: "11px",
1036
- cursor: "pointer",
1037
- transition: "all 0.15s"
1038
- },
1039
- onMouseEnter: (e) => {
1040
- e.currentTarget.style.borderColor = STYLES.accent;
1041
- e.currentTarget.style.color = STYLES.text;
1042
- },
1043
- onMouseLeave: (e) => {
1044
- e.currentTarget.style.borderColor = STYLES.border;
1045
- e.currentTarget.style.color = STYLES.textMuted;
1046
- },
1047
- children: "Rescan"
1048
- }
1049
- ) })
1050
- ] }),
1051
- showScanButton && /* @__PURE__ */ jsxs("div", { style: { textAlign: "center", padding: "16px 0" }, children: [
1052
- /* @__PURE__ */ jsxs("div", { style: { marginBottom: "10px" }, children: [
1053
- /* @__PURE__ */ jsxs(
1054
- "label",
1055
- {
1056
- style: {
1057
- display: "inline-flex",
1058
- alignItems: "center",
1059
- gap: "8px",
1060
- fontSize: "12px",
1061
- color: STYLES.textMuted,
1062
- cursor: "pointer",
1063
- userSelect: "none"
1064
- },
1065
- children: [
1066
- /* @__PURE__ */ jsx(
1067
- "input",
1068
- {
1069
- type: "checkbox",
1070
- checked: includeChildren,
1071
- onChange: (e) => upsertManualScan(manualKey, {
1072
- includeChildren: e.currentTarget.checked
1073
- })
1074
- }
1075
- ),
1076
- "Include children"
1077
- ]
1078
- }
1079
- ),
1080
- /* @__PURE__ */ jsxs(
1081
- "div",
1082
- {
1083
- style: {
1084
- marginTop: "6px",
1085
- fontSize: "11px",
1086
- color: STYLES.textDim
1087
- },
1088
- children: [
1089
- "Scope: ",
1090
- scopeLabel
1091
- ]
1092
- }
1093
- )
1094
- ] }),
1095
- /* @__PURE__ */ jsxs(
1096
- "button",
1097
- {
1098
- onClick: handleScan,
1099
- disabled: !element.source,
1100
- style: {
1101
- display: "inline-flex",
1102
- alignItems: "center",
1103
- gap: "8px",
1104
- padding: "12px 24px",
1105
- borderRadius: "8px",
1106
- border: "none",
1107
- backgroundColor: element.source ? STYLES.success : STYLES.textDim,
1108
- color: "#FFFFFF",
1109
- fontSize: "14px",
1110
- fontWeight: 600,
1111
- cursor: element.source ? "pointer" : "not-allowed",
1112
- transition: "all 0.15s"
1113
- },
1114
- onMouseEnter: (e) => {
1115
- if (element.source) {
1116
- e.currentTarget.style.backgroundColor = "#059669";
1117
- }
1118
- },
1119
- onMouseLeave: (e) => {
1120
- if (element.source) {
1121
- e.currentTarget.style.backgroundColor = STYLES.success;
1122
- }
1123
- },
1124
- children: [
1125
- /* @__PURE__ */ jsx(ScanIcon, {}),
1126
- "Scan for Issues"
1127
- ]
1128
- }
1129
- ),
1130
- /* @__PURE__ */ jsx(
1131
- "div",
1132
- {
1133
- style: {
1134
- marginTop: "10px",
1135
- fontSize: "12px",
1136
- color: STYLES.textMuted
1137
- },
1138
- children: "Analyze this component for style issues"
1139
- }
1140
- ),
1141
- !element.source && /* @__PURE__ */ jsx(
1142
- "div",
1143
- {
1144
- style: {
1145
- marginTop: "8px",
1146
- fontSize: "11px",
1147
- color: STYLES.warning
1148
- },
1149
- children: "No source information available"
1150
- }
1151
- )
1152
- ] }),
1153
- scanning && /* @__PURE__ */ jsxs(
625
+ showCachedPending && /* @__PURE__ */ jsx("div", { style: { textAlign: "center", padding: "16px 0" }, children: /* @__PURE__ */ jsxs(
1154
626
  "div",
1155
627
  {
1156
628
  style: {
1157
- display: "flex",
1158
- flexDirection: "column",
629
+ display: "inline-flex",
1159
630
  alignItems: "center",
1160
- justifyContent: "center",
1161
- padding: "32px 24px",
1162
- gap: "12px"
631
+ gap: "8px",
632
+ padding: "10px 20px",
633
+ borderRadius: "8px",
634
+ backgroundColor: STYLES.bg,
635
+ color: STYLES.textMuted,
636
+ fontSize: "12px"
1163
637
  },
1164
638
  children: [
1165
639
  /* @__PURE__ */ jsx(
1166
640
  "div",
1167
641
  {
1168
642
  style: {
1169
- width: "32px",
1170
- height: "32px",
1171
- border: `3px solid ${STYLES.border}`,
1172
- borderTopColor: STYLES.success,
643
+ width: "8px",
644
+ height: "8px",
1173
645
  borderRadius: "50%",
1174
- animation: "uilint-spin 1s linear infinite"
646
+ backgroundColor: "rgba(156, 163, 175, 0.5)"
1175
647
  }
1176
648
  }
1177
649
  ),
1178
- /* @__PURE__ */ jsx("div", { style: { color: STYLES.textMuted, fontSize: "13px" }, children: "Analyzing source code..." }),
1179
- progressLine && /* @__PURE__ */ jsx(
1180
- "div",
1181
- {
1182
- style: {
1183
- color: STYLES.textDim,
1184
- fontSize: "11px",
1185
- fontFamily: STYLES.fontMono,
1186
- maxWidth: "320px",
1187
- whiteSpace: "nowrap",
1188
- overflow: "hidden",
1189
- textOverflow: "ellipsis"
1190
- },
1191
- title: progressLine,
1192
- children: progressLine
1193
- }
1194
- )
650
+ "Waiting in scan queue..."
1195
651
  ]
1196
652
  }
1197
- ),
1198
- error && /* @__PURE__ */ jsx(
653
+ ) }),
654
+ showCachedError && /* @__PURE__ */ jsx(
1199
655
  "div",
1200
656
  {
1201
657
  style: {
@@ -1204,118 +660,177 @@ Please update this component to match our styleguide.`;
1204
660
  border: "1px solid rgba(239, 68, 68, 0.3)",
1205
661
  borderRadius: "8px",
1206
662
  color: "#EF4444",
1207
- fontSize: "12px",
1208
- marginTop: "12px"
663
+ fontSize: "12px"
1209
664
  },
1210
- children: error
665
+ children: "Auto-scan failed for this element"
1211
666
  }
1212
667
  ),
1213
- showManualResult && /* @__PURE__ */ jsxs("div", { children: [
668
+ showCachedResult && /* @__PURE__ */ jsxs("div", { children: [
1214
669
  /* @__PURE__ */ jsxs(
1215
670
  "div",
1216
671
  {
1217
672
  style: {
1218
673
  display: "flex",
1219
674
  alignItems: "center",
1220
- justifyContent: "space-between",
1221
- marginBottom: "10px"
675
+ gap: "8px",
676
+ marginBottom: "12px",
677
+ padding: "8px 12px",
678
+ backgroundColor: "rgba(16, 185, 129, 0.1)",
679
+ borderRadius: "6px",
680
+ fontSize: "11px",
681
+ color: STYLES.success
1222
682
  },
1223
683
  children: [
1224
- /* @__PURE__ */ jsx(
1225
- "div",
1226
- {
1227
- style: {
1228
- fontSize: "12px",
1229
- fontWeight: 600,
1230
- color: STYLES.text
1231
- },
1232
- children: "Fix Prompt"
1233
- }
1234
- ),
1235
- /* @__PURE__ */ jsx(
1236
- "button",
1237
- {
1238
- onClick: () => {
1239
- if (!fixPrompt) return;
1240
- handleCopy(fixPrompt);
1241
- },
1242
- style: {
1243
- display: "flex",
1244
- alignItems: "center",
1245
- gap: "6px",
1246
- padding: "6px 12px",
1247
- borderRadius: "6px",
1248
- border: "none",
1249
- backgroundColor: copied ? STYLES.success : STYLES.accent,
1250
- color: "#FFFFFF",
1251
- fontSize: "11px",
1252
- fontWeight: 500,
1253
- cursor: "pointer",
1254
- transition: "all 0.15s"
1255
- },
1256
- children: copied ? /* @__PURE__ */ jsxs(Fragment, { children: [
1257
- /* @__PURE__ */ jsx(CheckIcon, {}),
1258
- "Copied!"
1259
- ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1260
- /* @__PURE__ */ jsx(CopyIcon, {}),
1261
- "Copy"
1262
- ] })
1263
- }
1264
- )
684
+ /* @__PURE__ */ jsx(CheckIconSmall, {}),
685
+ "Scan complete"
1265
686
  ]
1266
687
  }
1267
688
  ),
1268
- /* @__PURE__ */ jsx(
689
+ eslintIssues.length > 0 && /* @__PURE__ */ jsx(ESLintIssuesSection, { issues: eslintIssues }),
690
+ eslintIssues.length === 0 && /* @__PURE__ */ jsx(
1269
691
  "div",
1270
692
  {
1271
693
  style: {
1272
- padding: "12px",
1273
- backgroundColor: STYLES.bg,
1274
- border: `1px solid ${STYLES.border}`,
1275
- borderRadius: "8px",
1276
- fontFamily: STYLES.fontMono,
1277
- fontSize: "11px",
1278
- lineHeight: 1.6,
1279
- whiteSpace: "pre-wrap",
1280
- color: STYLES.text,
1281
- maxHeight: "200px",
1282
- overflow: "auto"
1283
- },
1284
- children: fixPrompt
1285
- }
1286
- ),
1287
- /* @__PURE__ */ jsx("div", { style: { textAlign: "center", marginTop: "12px" }, children: /* @__PURE__ */ jsx(
1288
- "button",
1289
- {
1290
- onClick: () => {
1291
- handleScan();
1292
- },
1293
- style: {
1294
- padding: "6px 12px",
1295
- borderRadius: "6px",
1296
- border: `1px solid ${STYLES.border}`,
1297
- backgroundColor: "transparent",
694
+ padding: "16px",
695
+ textAlign: "center",
1298
696
  color: STYLES.textMuted,
1299
- fontSize: "11px",
1300
- cursor: "pointer",
1301
- transition: "all 0.15s"
697
+ fontSize: "12px"
1302
698
  },
1303
- onMouseEnter: (e) => {
1304
- e.currentTarget.style.borderColor = STYLES.accent;
1305
- e.currentTarget.style.color = STYLES.text;
1306
- },
1307
- onMouseLeave: (e) => {
1308
- e.currentTarget.style.borderColor = STYLES.border;
1309
- e.currentTarget.style.color = STYLES.textMuted;
1310
- },
1311
- children: "Scan Again"
699
+ children: "No issues found"
1312
700
  }
1313
- ) })
1314
- ] })
701
+ )
702
+ ] }),
703
+ showNoScan && /* @__PURE__ */ jsx(
704
+ "div",
705
+ {
706
+ style: {
707
+ padding: "16px",
708
+ textAlign: "center",
709
+ color: STYLES.textMuted,
710
+ fontSize: "12px"
711
+ },
712
+ children: "Run auto-scan to analyze this element"
713
+ }
714
+ )
1315
715
  ] })
1316
716
  }
1317
717
  );
1318
718
  }
719
+ function ESLintIssuesSection({ issues }) {
720
+ if (issues.length === 0) return null;
721
+ return /* @__PURE__ */ jsxs("div", { style: { marginBottom: "16px" }, children: [
722
+ /* @__PURE__ */ jsxs(
723
+ "div",
724
+ {
725
+ style: {
726
+ display: "flex",
727
+ alignItems: "center",
728
+ gap: "8px",
729
+ marginBottom: "8px"
730
+ },
731
+ children: [
732
+ /* @__PURE__ */ jsx(ESLintIcon, {}),
733
+ /* @__PURE__ */ jsxs(
734
+ "span",
735
+ {
736
+ style: {
737
+ fontSize: "12px",
738
+ fontWeight: 600,
739
+ color: STYLES.text
740
+ },
741
+ children: [
742
+ "ESLint Issues (",
743
+ issues.length,
744
+ ")"
745
+ ]
746
+ }
747
+ )
748
+ ]
749
+ }
750
+ ),
751
+ /* @__PURE__ */ jsx(
752
+ "div",
753
+ {
754
+ style: {
755
+ display: "flex",
756
+ flexDirection: "column",
757
+ gap: "6px"
758
+ },
759
+ children: issues.map((issue, index) => /* @__PURE__ */ jsx(
760
+ "div",
761
+ {
762
+ style: {
763
+ padding: "10px 12px",
764
+ backgroundColor: "rgba(239, 68, 68, 0.1)",
765
+ border: "1px solid rgba(239, 68, 68, 0.2)",
766
+ borderRadius: "6px"
767
+ },
768
+ children: /* @__PURE__ */ jsxs(
769
+ "div",
770
+ {
771
+ style: {
772
+ display: "flex",
773
+ alignItems: "flex-start",
774
+ gap: "8px"
775
+ },
776
+ children: [
777
+ /* @__PURE__ */ jsx(WarningIcon, {}),
778
+ /* @__PURE__ */ jsxs("div", { style: { flex: 1 }, children: [
779
+ /* @__PURE__ */ jsx(
780
+ "div",
781
+ {
782
+ style: {
783
+ fontSize: "12px",
784
+ color: STYLES.text,
785
+ lineHeight: 1.4,
786
+ marginBottom: "4px"
787
+ },
788
+ children: issue.message
789
+ }
790
+ ),
791
+ /* @__PURE__ */ jsxs(
792
+ "div",
793
+ {
794
+ style: {
795
+ display: "flex",
796
+ alignItems: "center",
797
+ gap: "12px",
798
+ fontSize: "10px",
799
+ color: STYLES.textDim,
800
+ fontFamily: STYLES.fontMono
801
+ },
802
+ children: [
803
+ issue.ruleId && /* @__PURE__ */ jsx(
804
+ "span",
805
+ {
806
+ style: {
807
+ padding: "2px 6px",
808
+ backgroundColor: "rgba(239, 68, 68, 0.15)",
809
+ borderRadius: "4px",
810
+ color: "#EF4444"
811
+ },
812
+ children: issue.ruleId
813
+ }
814
+ ),
815
+ /* @__PURE__ */ jsxs("span", { children: [
816
+ "Line ",
817
+ issue.line,
818
+ issue.column ? `:${issue.column}` : ""
819
+ ] })
820
+ ]
821
+ }
822
+ )
823
+ ] })
824
+ ]
825
+ }
826
+ )
827
+ },
828
+ index
829
+ ))
830
+ }
831
+ )
832
+ ] });
833
+ }
1319
834
  function CheckIconSmall() {
1320
835
  return /* @__PURE__ */ jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx(
1321
836
  "path",
@@ -1472,52 +987,39 @@ function CloseIcon() {
1472
987
  }
1473
988
  ) });
1474
989
  }
1475
- function ScanIcon() {
1476
- return /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx(
990
+ function ESLintIcon() {
991
+ return /* @__PURE__ */ jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx(
1477
992
  "path",
1478
993
  {
1479
- d: "M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83",
1480
- stroke: "currentColor",
994
+ d: "M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5",
995
+ stroke: "#EF4444",
1481
996
  strokeWidth: "2",
1482
- strokeLinecap: "round"
997
+ strokeLinecap: "round",
998
+ strokeLinejoin: "round"
1483
999
  }
1484
1000
  ) });
1485
1001
  }
1486
- function CopyIcon() {
1487
- return /* @__PURE__ */ jsxs("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", children: [
1488
- /* @__PURE__ */ jsx(
1489
- "rect",
1490
- {
1491
- x: "9",
1492
- y: "9",
1493
- width: "13",
1494
- height: "13",
1495
- rx: "2",
1496
- stroke: "currentColor",
1497
- strokeWidth: "2"
1498
- }
1499
- ),
1500
- /* @__PURE__ */ jsx(
1501
- "path",
1502
- {
1503
- d: "M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1",
1504
- stroke: "currentColor",
1505
- strokeWidth: "2"
1506
- }
1507
- )
1508
- ] });
1509
- }
1510
- function CheckIcon() {
1511
- return /* @__PURE__ */ jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx(
1512
- "path",
1002
+ function WarningIcon() {
1003
+ return /* @__PURE__ */ jsx(
1004
+ "svg",
1513
1005
  {
1514
- d: "M20 6L9 17l-5-5",
1515
- stroke: "currentColor",
1516
- strokeWidth: "2",
1517
- strokeLinecap: "round",
1518
- strokeLinejoin: "round"
1006
+ width: "14",
1007
+ height: "14",
1008
+ viewBox: "0 0 24 24",
1009
+ fill: "none",
1010
+ style: { flexShrink: 0, marginTop: "1px" },
1011
+ children: /* @__PURE__ */ jsx(
1012
+ "path",
1013
+ {
1014
+ d: "M12 9v4M12 17h.01M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z",
1015
+ stroke: "#EF4444",
1016
+ strokeWidth: "2",
1017
+ strokeLinecap: "round",
1018
+ strokeLinejoin: "round"
1019
+ }
1020
+ )
1519
1021
  }
1520
- ) });
1022
+ );
1521
1023
  }
1522
1024
 
1523
1025
  export {