uilint-react 0.1.19 → 0.1.21
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/README.md +50 -93
- package/dist/{InspectionPanel-6DBGEWWD.js → InspectionPanel-ZBDXQ2LU.js} +2 -2
- package/dist/LocatorOverlay-3H446RPO.js +11 -0
- package/dist/{UILintToolbar-7ZYCQC4M.js → UILintToolbar-C6HOAJA4.js} +2 -2
- package/dist/{chunk-KUFV22FO.js → chunk-3DNDKMZ4.js} +72 -2
- package/dist/{chunk-3TA6OKS6.js → chunk-CWCKS753.js} +417 -90
- package/dist/{chunk-7WYVWDRU.js → chunk-EBU7YY73.js} +53 -218
- package/dist/chunk-GUF36FGA.js +276 -0
- package/dist/index.d.ts +26 -65
- package/dist/index.js +33 -1097
- package/package.json +2 -2
- package/dist/LocatorOverlay-FQEYAMT6.js +0 -9
- package/dist/SourceOverlays-2SEINA2B.js +0 -9
- package/dist/chunk-MEP7WO7U.js +0 -210
- package/dist/chunk-OWX36QE3.js +0 -595
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
buildEditorUrl,
|
|
4
4
|
useUILintContext
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-EBU7YY73.js";
|
|
6
6
|
|
|
7
7
|
// src/components/ui-lint/InspectionPanel.tsx
|
|
8
8
|
import { useState, useEffect, useCallback } from "react";
|
|
@@ -11,7 +11,7 @@ import { createPortal } from "react-dom";
|
|
|
11
11
|
// src/components/ui-lint/source-fetcher.ts
|
|
12
12
|
var sourceCache = /* @__PURE__ */ new Map();
|
|
13
13
|
var CACHE_TTL = 5 * 60 * 1e3;
|
|
14
|
-
var API_ENDPOINT = "/api/
|
|
14
|
+
var API_ENDPOINT = "/api/.uilint/source";
|
|
15
15
|
async function fetchSource(filePath) {
|
|
16
16
|
const cached = sourceCache.get(filePath);
|
|
17
17
|
if (cached && Date.now() - cached.fetchedAt < CACHE_TTL) {
|
|
@@ -82,7 +82,7 @@ async function prefetchSources(filePaths) {
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
// src/components/ui-lint/InspectionPanel.tsx
|
|
85
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
85
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
86
86
|
var STYLES = {
|
|
87
87
|
bg: "rgba(17, 24, 39, 0.95)",
|
|
88
88
|
bgSurface: "rgba(31, 41, 55, 0.9)",
|
|
@@ -92,23 +92,24 @@ var STYLES = {
|
|
|
92
92
|
textDim: "#6B7280",
|
|
93
93
|
accent: "#3B82F6",
|
|
94
94
|
accentHover: "#2563EB",
|
|
95
|
+
success: "#10B981",
|
|
96
|
+
warning: "#F59E0B",
|
|
95
97
|
shadow: "0 -8px 32px rgba(0, 0, 0, 0.4)",
|
|
96
98
|
blur: "blur(16px)",
|
|
97
99
|
font: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
|
|
98
100
|
fontMono: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace'
|
|
99
101
|
};
|
|
100
|
-
var PANEL_WIDTH =
|
|
102
|
+
var PANEL_WIDTH = 420;
|
|
101
103
|
function InspectionPanel() {
|
|
102
|
-
const {
|
|
104
|
+
const { inspectedElement, setInspectedElement } = useUILintContext();
|
|
103
105
|
const [mounted, setMounted] = useState(false);
|
|
104
|
-
const [activeTab, setActiveTab] = useState(
|
|
106
|
+
const [activeTab, setActiveTab] = useState(
|
|
107
|
+
"info"
|
|
108
|
+
);
|
|
105
109
|
useEffect(() => {
|
|
106
110
|
setMounted(true);
|
|
107
111
|
}, []);
|
|
108
|
-
|
|
109
|
-
(f) => f.elements.some((e) => e.id === selectedElement.id)
|
|
110
|
-
) ?? null : null;
|
|
111
|
-
if (!mounted) return null;
|
|
112
|
+
if (!mounted || !inspectedElement) return null;
|
|
112
113
|
const content = /* @__PURE__ */ jsxs(
|
|
113
114
|
"div",
|
|
114
115
|
{
|
|
@@ -118,16 +119,15 @@ function InspectionPanel() {
|
|
|
118
119
|
top: 0,
|
|
119
120
|
right: 0,
|
|
120
121
|
bottom: 0,
|
|
121
|
-
width:
|
|
122
|
+
width: PANEL_WIDTH,
|
|
122
123
|
backgroundColor: STYLES.bg,
|
|
123
124
|
backdropFilter: STYLES.blur,
|
|
124
125
|
WebkitBackdropFilter: STYLES.blur,
|
|
125
126
|
borderLeft: `1px solid ${STYLES.border}`,
|
|
126
|
-
boxShadow:
|
|
127
|
+
boxShadow: STYLES.shadow,
|
|
127
128
|
fontFamily: STYLES.font,
|
|
128
129
|
color: STYLES.text,
|
|
129
130
|
overflow: "hidden",
|
|
130
|
-
transition: "width 0.2s ease-out",
|
|
131
131
|
zIndex: 99998
|
|
132
132
|
},
|
|
133
133
|
children: [
|
|
@@ -136,8 +136,12 @@ function InspectionPanel() {
|
|
|
136
136
|
from { transform: translateX(100%); }
|
|
137
137
|
to { transform: translateX(0); }
|
|
138
138
|
}
|
|
139
|
+
@keyframes uilint-spin {
|
|
140
|
+
from { transform: rotate(0deg); }
|
|
141
|
+
to { transform: rotate(360deg); }
|
|
142
|
+
}
|
|
139
143
|
` }),
|
|
140
|
-
|
|
144
|
+
/* @__PURE__ */ jsxs(
|
|
141
145
|
"div",
|
|
142
146
|
{
|
|
143
147
|
style: {
|
|
@@ -150,9 +154,8 @@ function InspectionPanel() {
|
|
|
150
154
|
/* @__PURE__ */ jsx(
|
|
151
155
|
PanelHeader,
|
|
152
156
|
{
|
|
153
|
-
element:
|
|
154
|
-
|
|
155
|
-
onClose: () => setSelectedElement(null)
|
|
157
|
+
element: inspectedElement,
|
|
158
|
+
onClose: () => setInspectedElement(null)
|
|
156
159
|
}
|
|
157
160
|
),
|
|
158
161
|
/* @__PURE__ */ jsxs(
|
|
@@ -178,11 +181,24 @@ function InspectionPanel() {
|
|
|
178
181
|
active: activeTab === "source",
|
|
179
182
|
onClick: () => setActiveTab("source")
|
|
180
183
|
}
|
|
184
|
+
),
|
|
185
|
+
/* @__PURE__ */ jsx(
|
|
186
|
+
TabButton,
|
|
187
|
+
{
|
|
188
|
+
label: "Scan",
|
|
189
|
+
active: activeTab === "scan",
|
|
190
|
+
onClick: () => setActiveTab("scan"),
|
|
191
|
+
accent: true
|
|
192
|
+
}
|
|
181
193
|
)
|
|
182
194
|
]
|
|
183
195
|
}
|
|
184
196
|
),
|
|
185
|
-
/* @__PURE__ */
|
|
197
|
+
/* @__PURE__ */ jsxs("div", { style: { flex: 1, overflow: "auto" }, children: [
|
|
198
|
+
activeTab === "info" && /* @__PURE__ */ jsx(InfoTab, { element: inspectedElement }),
|
|
199
|
+
activeTab === "source" && /* @__PURE__ */ jsx(SourceTab, { element: inspectedElement }),
|
|
200
|
+
activeTab === "scan" && /* @__PURE__ */ jsx(ScanTab, { element: inspectedElement })
|
|
201
|
+
] })
|
|
186
202
|
]
|
|
187
203
|
}
|
|
188
204
|
)
|
|
@@ -193,11 +209,10 @@ function InspectionPanel() {
|
|
|
193
209
|
}
|
|
194
210
|
function PanelHeader({
|
|
195
211
|
element,
|
|
196
|
-
sourceFile,
|
|
197
212
|
onClose
|
|
198
213
|
}) {
|
|
199
|
-
const componentName = element.componentStack[0]?.name || element.tagName.
|
|
200
|
-
const
|
|
214
|
+
const componentName = element.componentStack[0]?.name || element.element.tagName.toLowerCase();
|
|
215
|
+
const handleOpenInCursor = useCallback(() => {
|
|
201
216
|
if (element.source) {
|
|
202
217
|
const url = buildEditorUrl(element.source, "cursor");
|
|
203
218
|
window.open(url, "_blank");
|
|
@@ -215,32 +230,19 @@ function PanelHeader({
|
|
|
215
230
|
backgroundColor: STYLES.bgSurface
|
|
216
231
|
},
|
|
217
232
|
children: [
|
|
218
|
-
/* @__PURE__ */ jsxs("div", {
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
height: "12px",
|
|
225
|
-
borderRadius: "50%",
|
|
226
|
-
backgroundColor: sourceFile.color
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
),
|
|
230
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
231
|
-
/* @__PURE__ */ jsx("div", { style: { fontSize: "14px", fontWeight: 600 }, children: componentName }),
|
|
232
|
-
/* @__PURE__ */ jsxs("div", { style: { fontSize: "11px", color: STYLES.textMuted }, children: [
|
|
233
|
-
"<",
|
|
234
|
-
element.tagName,
|
|
235
|
-
">"
|
|
236
|
-
] })
|
|
233
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
234
|
+
/* @__PURE__ */ jsx("div", { style: { fontSize: "14px", fontWeight: 600 }, children: componentName }),
|
|
235
|
+
/* @__PURE__ */ jsxs("div", { style: { fontSize: "11px", color: STYLES.textMuted }, children: [
|
|
236
|
+
"<",
|
|
237
|
+
element.element.tagName.toLowerCase(),
|
|
238
|
+
">"
|
|
237
239
|
] })
|
|
238
240
|
] }),
|
|
239
241
|
/* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
240
242
|
element.source && /* @__PURE__ */ jsxs(
|
|
241
243
|
"button",
|
|
242
244
|
{
|
|
243
|
-
onClick:
|
|
245
|
+
onClick: handleOpenInCursor,
|
|
244
246
|
style: {
|
|
245
247
|
display: "flex",
|
|
246
248
|
alignItems: "center",
|
|
@@ -261,9 +263,10 @@ function PanelHeader({
|
|
|
261
263
|
onMouseLeave: (e) => {
|
|
262
264
|
e.currentTarget.style.backgroundColor = STYLES.accent;
|
|
263
265
|
},
|
|
266
|
+
title: "Open in Cursor",
|
|
264
267
|
children: [
|
|
265
|
-
/* @__PURE__ */ jsx(
|
|
266
|
-
"Open"
|
|
268
|
+
/* @__PURE__ */ jsx(CursorIcon, {}),
|
|
269
|
+
"Open in Cursor"
|
|
267
270
|
]
|
|
268
271
|
}
|
|
269
272
|
),
|
|
@@ -303,7 +306,8 @@ function PanelHeader({
|
|
|
303
306
|
function TabButton({
|
|
304
307
|
label,
|
|
305
308
|
active,
|
|
306
|
-
onClick
|
|
309
|
+
onClick,
|
|
310
|
+
accent
|
|
307
311
|
}) {
|
|
308
312
|
return /* @__PURE__ */ jsx(
|
|
309
313
|
"button",
|
|
@@ -314,11 +318,11 @@ function TabButton({
|
|
|
314
318
|
padding: "10px 16px",
|
|
315
319
|
border: "none",
|
|
316
320
|
backgroundColor: "transparent",
|
|
317
|
-
color: active ? STYLES.accent : STYLES.textMuted,
|
|
321
|
+
color: active ? accent ? STYLES.success : STYLES.accent : STYLES.textMuted,
|
|
318
322
|
fontSize: "12px",
|
|
319
323
|
fontWeight: 500,
|
|
320
324
|
cursor: "pointer",
|
|
321
|
-
borderBottom: active ? `2px solid ${STYLES.accent}` : "2px solid transparent",
|
|
325
|
+
borderBottom: active ? `2px solid ${accent ? STYLES.success : STYLES.accent}` : "2px solid transparent",
|
|
322
326
|
marginBottom: "-1px",
|
|
323
327
|
transition: "all 0.15s"
|
|
324
328
|
},
|
|
@@ -326,61 +330,44 @@ function TabButton({
|
|
|
326
330
|
}
|
|
327
331
|
);
|
|
328
332
|
}
|
|
329
|
-
function InfoTab({
|
|
330
|
-
element,
|
|
331
|
-
sourceFile
|
|
332
|
-
}) {
|
|
333
|
+
function InfoTab({ element }) {
|
|
333
334
|
return /* @__PURE__ */ jsxs("div", { style: { padding: "16px" }, children: [
|
|
334
335
|
/* @__PURE__ */ jsxs(Section, { title: "Element", children: [
|
|
335
|
-
/* @__PURE__ */ jsx(
|
|
336
|
-
element.className && /* @__PURE__ */ jsx(InfoRow, { label: "Classes", value: element.className, mono: true }),
|
|
337
|
-
element.source && /* @__PURE__ */ jsx(
|
|
336
|
+
/* @__PURE__ */ jsx(
|
|
338
337
|
InfoRow,
|
|
339
338
|
{
|
|
340
|
-
label: "
|
|
341
|
-
value:
|
|
339
|
+
label: "Tag",
|
|
340
|
+
value: `<${element.element.tagName.toLowerCase()}>`
|
|
342
341
|
}
|
|
343
|
-
)
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
/* @__PURE__ */ jsxs(
|
|
347
|
-
"div",
|
|
342
|
+
),
|
|
343
|
+
element.element.className && /* @__PURE__ */ jsx(
|
|
344
|
+
InfoRow,
|
|
348
345
|
{
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
gap: "8px",
|
|
353
|
-
marginBottom: "8px"
|
|
354
|
-
},
|
|
355
|
-
children: [
|
|
356
|
-
/* @__PURE__ */ jsx(
|
|
357
|
-
"div",
|
|
358
|
-
{
|
|
359
|
-
style: {
|
|
360
|
-
width: "10px",
|
|
361
|
-
height: "10px",
|
|
362
|
-
borderRadius: "50%",
|
|
363
|
-
backgroundColor: sourceFile.color
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
),
|
|
367
|
-
/* @__PURE__ */ jsx("span", { style: { fontSize: "12px", fontWeight: 500 }, children: sourceFile.displayName })
|
|
368
|
-
]
|
|
346
|
+
label: "Classes",
|
|
347
|
+
value: typeof element.element.className === "string" ? element.element.className : "",
|
|
348
|
+
mono: true
|
|
369
349
|
}
|
|
370
350
|
),
|
|
371
|
-
/* @__PURE__ */ jsx(
|
|
372
|
-
|
|
351
|
+
element.source && /* @__PURE__ */ jsx(
|
|
352
|
+
InfoRow,
|
|
373
353
|
{
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
color: STYLES.textDim,
|
|
377
|
-
fontFamily: STYLES.fontMono,
|
|
378
|
-
wordBreak: "break-all"
|
|
379
|
-
},
|
|
380
|
-
children: sourceFile.path
|
|
354
|
+
label: "Location",
|
|
355
|
+
value: `Line ${element.source.lineNumber}${element.source.columnNumber ? `, Col ${element.source.columnNumber}` : ""}`
|
|
381
356
|
}
|
|
382
357
|
)
|
|
383
358
|
] }),
|
|
359
|
+
element.source && /* @__PURE__ */ jsx(Section, { title: "Source File", children: /* @__PURE__ */ jsx(
|
|
360
|
+
"div",
|
|
361
|
+
{
|
|
362
|
+
style: {
|
|
363
|
+
fontSize: "11px",
|
|
364
|
+
color: STYLES.textDim,
|
|
365
|
+
fontFamily: STYLES.fontMono,
|
|
366
|
+
wordBreak: "break-all"
|
|
367
|
+
},
|
|
368
|
+
children: element.source.fileName
|
|
369
|
+
}
|
|
370
|
+
) }),
|
|
384
371
|
element.componentStack.length > 0 && /* @__PURE__ */ jsx(Section, { title: "Component Stack", children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "4px" }, children: [
|
|
385
372
|
element.componentStack.slice(0, 10).map((comp, index) => /* @__PURE__ */ jsx(
|
|
386
373
|
ComponentStackItem,
|
|
@@ -570,6 +557,299 @@ function SourceTab({ element }) {
|
|
|
570
557
|
)
|
|
571
558
|
] });
|
|
572
559
|
}
|
|
560
|
+
function ScanTab({ element }) {
|
|
561
|
+
const [scanning, setScanning] = useState(false);
|
|
562
|
+
const [error, setError] = useState(null);
|
|
563
|
+
const [fixPrompt, setFixPrompt] = useState(null);
|
|
564
|
+
const [copied, setCopied] = useState(false);
|
|
565
|
+
const componentName = element.componentStack[0]?.name || element.element.tagName.toLowerCase();
|
|
566
|
+
const componentLine = element.source?.lineNumber;
|
|
567
|
+
const handleScan = useCallback(async () => {
|
|
568
|
+
if (!element.source) {
|
|
569
|
+
setError("No source information available");
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
setScanning(true);
|
|
573
|
+
setError(null);
|
|
574
|
+
setFixPrompt(null);
|
|
575
|
+
try {
|
|
576
|
+
const sourceResponse = await fetch(
|
|
577
|
+
`/api/.uilint/source?path=${encodeURIComponent(element.source.fileName)}`
|
|
578
|
+
);
|
|
579
|
+
if (!sourceResponse.ok) {
|
|
580
|
+
throw new Error("Failed to fetch source code");
|
|
581
|
+
}
|
|
582
|
+
const sourceData = await sourceResponse.json();
|
|
583
|
+
const sourceCode = sourceData.content;
|
|
584
|
+
const relativePath = sourceData.relativePath || element.source.fileName;
|
|
585
|
+
const analyzeResponse = await fetch("/api/.uilint/analyze", {
|
|
586
|
+
method: "POST",
|
|
587
|
+
headers: { "Content-Type": "application/json" },
|
|
588
|
+
body: JSON.stringify({
|
|
589
|
+
sourceCode,
|
|
590
|
+
filePath: relativePath,
|
|
591
|
+
componentName,
|
|
592
|
+
componentLine
|
|
593
|
+
})
|
|
594
|
+
});
|
|
595
|
+
if (!analyzeResponse.ok) {
|
|
596
|
+
throw new Error("Failed to analyze source code");
|
|
597
|
+
}
|
|
598
|
+
const result = await analyzeResponse.json();
|
|
599
|
+
const issues = result.issues || [];
|
|
600
|
+
if (issues.length === 0) {
|
|
601
|
+
setFixPrompt(
|
|
602
|
+
`No style issues found in the \`${componentName}\` component in \`${relativePath}\`. The component appears to follow the styleguide.`
|
|
603
|
+
);
|
|
604
|
+
} else {
|
|
605
|
+
const issueList = issues.map((issue) => {
|
|
606
|
+
const lineInfo = issue.line ? `Line ${issue.line}: ` : "";
|
|
607
|
+
return `- ${lineInfo}${issue.message}`;
|
|
608
|
+
}).join("\n");
|
|
609
|
+
setFixPrompt(
|
|
610
|
+
`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
|
+
}
|
|
618
|
+
} catch (err) {
|
|
619
|
+
setError(
|
|
620
|
+
err instanceof Error ? err.message : "An error occurred during scanning"
|
|
621
|
+
);
|
|
622
|
+
} finally {
|
|
623
|
+
setScanning(false);
|
|
624
|
+
}
|
|
625
|
+
}, [element.source, componentName, componentLine]);
|
|
626
|
+
const handleCopy = useCallback(async () => {
|
|
627
|
+
if (!fixPrompt) return;
|
|
628
|
+
try {
|
|
629
|
+
await navigator.clipboard.writeText(fixPrompt);
|
|
630
|
+
setCopied(true);
|
|
631
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
632
|
+
} catch {
|
|
633
|
+
setError("Failed to copy to clipboard");
|
|
634
|
+
}
|
|
635
|
+
}, [fixPrompt]);
|
|
636
|
+
return /* @__PURE__ */ jsxs("div", { style: { padding: "16px" }, children: [
|
|
637
|
+
!fixPrompt && !scanning && /* @__PURE__ */ jsxs("div", { style: { textAlign: "center", padding: "24px 0" }, children: [
|
|
638
|
+
/* @__PURE__ */ jsxs(
|
|
639
|
+
"button",
|
|
640
|
+
{
|
|
641
|
+
onClick: handleScan,
|
|
642
|
+
disabled: !element.source,
|
|
643
|
+
style: {
|
|
644
|
+
display: "inline-flex",
|
|
645
|
+
alignItems: "center",
|
|
646
|
+
gap: "8px",
|
|
647
|
+
padding: "12px 24px",
|
|
648
|
+
borderRadius: "8px",
|
|
649
|
+
border: "none",
|
|
650
|
+
backgroundColor: element.source ? STYLES.success : STYLES.textDim,
|
|
651
|
+
color: "#FFFFFF",
|
|
652
|
+
fontSize: "14px",
|
|
653
|
+
fontWeight: 600,
|
|
654
|
+
cursor: element.source ? "pointer" : "not-allowed",
|
|
655
|
+
transition: "all 0.15s"
|
|
656
|
+
},
|
|
657
|
+
onMouseEnter: (e) => {
|
|
658
|
+
if (element.source) {
|
|
659
|
+
e.currentTarget.style.backgroundColor = "#059669";
|
|
660
|
+
}
|
|
661
|
+
},
|
|
662
|
+
onMouseLeave: (e) => {
|
|
663
|
+
if (element.source) {
|
|
664
|
+
e.currentTarget.style.backgroundColor = STYLES.success;
|
|
665
|
+
}
|
|
666
|
+
},
|
|
667
|
+
children: [
|
|
668
|
+
/* @__PURE__ */ jsx(ScanIcon, {}),
|
|
669
|
+
"Scan with LLM"
|
|
670
|
+
]
|
|
671
|
+
}
|
|
672
|
+
),
|
|
673
|
+
/* @__PURE__ */ jsx(
|
|
674
|
+
"div",
|
|
675
|
+
{
|
|
676
|
+
style: {
|
|
677
|
+
marginTop: "12px",
|
|
678
|
+
fontSize: "12px",
|
|
679
|
+
color: STYLES.textMuted
|
|
680
|
+
},
|
|
681
|
+
children: "Analyze this component for style issues"
|
|
682
|
+
}
|
|
683
|
+
),
|
|
684
|
+
!element.source && /* @__PURE__ */ jsx(
|
|
685
|
+
"div",
|
|
686
|
+
{
|
|
687
|
+
style: {
|
|
688
|
+
marginTop: "8px",
|
|
689
|
+
fontSize: "11px",
|
|
690
|
+
color: STYLES.warning
|
|
691
|
+
},
|
|
692
|
+
children: "No source information available"
|
|
693
|
+
}
|
|
694
|
+
)
|
|
695
|
+
] }),
|
|
696
|
+
scanning && /* @__PURE__ */ jsxs(
|
|
697
|
+
"div",
|
|
698
|
+
{
|
|
699
|
+
style: {
|
|
700
|
+
display: "flex",
|
|
701
|
+
flexDirection: "column",
|
|
702
|
+
alignItems: "center",
|
|
703
|
+
justifyContent: "center",
|
|
704
|
+
padding: "48px 24px",
|
|
705
|
+
gap: "16px"
|
|
706
|
+
},
|
|
707
|
+
children: [
|
|
708
|
+
/* @__PURE__ */ jsx(
|
|
709
|
+
"div",
|
|
710
|
+
{
|
|
711
|
+
style: {
|
|
712
|
+
width: "32px",
|
|
713
|
+
height: "32px",
|
|
714
|
+
border: `3px solid ${STYLES.border}`,
|
|
715
|
+
borderTopColor: STYLES.success,
|
|
716
|
+
borderRadius: "50%",
|
|
717
|
+
animation: "uilint-spin 1s linear infinite"
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
),
|
|
721
|
+
/* @__PURE__ */ jsx("div", { style: { color: STYLES.textMuted, fontSize: "13px" }, children: "Analyzing source code..." })
|
|
722
|
+
]
|
|
723
|
+
}
|
|
724
|
+
),
|
|
725
|
+
error && /* @__PURE__ */ jsx(
|
|
726
|
+
"div",
|
|
727
|
+
{
|
|
728
|
+
style: {
|
|
729
|
+
padding: "16px",
|
|
730
|
+
backgroundColor: "rgba(239, 68, 68, 0.1)",
|
|
731
|
+
border: "1px solid rgba(239, 68, 68, 0.3)",
|
|
732
|
+
borderRadius: "8px",
|
|
733
|
+
color: "#EF4444",
|
|
734
|
+
fontSize: "13px"
|
|
735
|
+
},
|
|
736
|
+
children: error
|
|
737
|
+
}
|
|
738
|
+
),
|
|
739
|
+
fixPrompt && /* @__PURE__ */ jsxs("div", { children: [
|
|
740
|
+
/* @__PURE__ */ jsxs(
|
|
741
|
+
"div",
|
|
742
|
+
{
|
|
743
|
+
style: {
|
|
744
|
+
display: "flex",
|
|
745
|
+
alignItems: "center",
|
|
746
|
+
justifyContent: "space-between",
|
|
747
|
+
marginBottom: "12px"
|
|
748
|
+
},
|
|
749
|
+
children: [
|
|
750
|
+
/* @__PURE__ */ jsx(
|
|
751
|
+
"div",
|
|
752
|
+
{
|
|
753
|
+
style: {
|
|
754
|
+
fontSize: "12px",
|
|
755
|
+
fontWeight: 600,
|
|
756
|
+
color: STYLES.text
|
|
757
|
+
},
|
|
758
|
+
children: "Fix Prompt"
|
|
759
|
+
}
|
|
760
|
+
),
|
|
761
|
+
/* @__PURE__ */ jsx(
|
|
762
|
+
"button",
|
|
763
|
+
{
|
|
764
|
+
onClick: handleCopy,
|
|
765
|
+
style: {
|
|
766
|
+
display: "flex",
|
|
767
|
+
alignItems: "center",
|
|
768
|
+
gap: "6px",
|
|
769
|
+
padding: "6px 12px",
|
|
770
|
+
borderRadius: "6px",
|
|
771
|
+
border: "none",
|
|
772
|
+
backgroundColor: copied ? STYLES.success : STYLES.accent,
|
|
773
|
+
color: "#FFFFFF",
|
|
774
|
+
fontSize: "11px",
|
|
775
|
+
fontWeight: 500,
|
|
776
|
+
cursor: "pointer",
|
|
777
|
+
transition: "all 0.15s"
|
|
778
|
+
},
|
|
779
|
+
children: copied ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
780
|
+
/* @__PURE__ */ jsx(CheckIcon, {}),
|
|
781
|
+
"Copied!"
|
|
782
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
783
|
+
/* @__PURE__ */ jsx(CopyIcon, {}),
|
|
784
|
+
"Copy to Clipboard"
|
|
785
|
+
] })
|
|
786
|
+
}
|
|
787
|
+
)
|
|
788
|
+
]
|
|
789
|
+
}
|
|
790
|
+
),
|
|
791
|
+
/* @__PURE__ */ jsx(
|
|
792
|
+
"div",
|
|
793
|
+
{
|
|
794
|
+
style: {
|
|
795
|
+
padding: "12px",
|
|
796
|
+
backgroundColor: STYLES.bgSurface,
|
|
797
|
+
border: `1px solid ${STYLES.border}`,
|
|
798
|
+
borderRadius: "8px",
|
|
799
|
+
fontFamily: STYLES.fontMono,
|
|
800
|
+
fontSize: "12px",
|
|
801
|
+
lineHeight: 1.6,
|
|
802
|
+
whiteSpace: "pre-wrap",
|
|
803
|
+
color: STYLES.text,
|
|
804
|
+
maxHeight: "300px",
|
|
805
|
+
overflow: "auto"
|
|
806
|
+
},
|
|
807
|
+
children: fixPrompt
|
|
808
|
+
}
|
|
809
|
+
),
|
|
810
|
+
/* @__PURE__ */ jsx(
|
|
811
|
+
"div",
|
|
812
|
+
{
|
|
813
|
+
style: {
|
|
814
|
+
marginTop: "12px",
|
|
815
|
+
fontSize: "11px",
|
|
816
|
+
color: STYLES.textMuted,
|
|
817
|
+
textAlign: "center"
|
|
818
|
+
},
|
|
819
|
+
children: "Paste this prompt into Cursor to fix the issues"
|
|
820
|
+
}
|
|
821
|
+
),
|
|
822
|
+
/* @__PURE__ */ jsx("div", { style: { textAlign: "center", marginTop: "16px" }, children: /* @__PURE__ */ jsx(
|
|
823
|
+
"button",
|
|
824
|
+
{
|
|
825
|
+
onClick: () => {
|
|
826
|
+
setFixPrompt(null);
|
|
827
|
+
handleScan();
|
|
828
|
+
},
|
|
829
|
+
style: {
|
|
830
|
+
padding: "8px 16px",
|
|
831
|
+
borderRadius: "6px",
|
|
832
|
+
border: `1px solid ${STYLES.border}`,
|
|
833
|
+
backgroundColor: "transparent",
|
|
834
|
+
color: STYLES.textMuted,
|
|
835
|
+
fontSize: "12px",
|
|
836
|
+
cursor: "pointer",
|
|
837
|
+
transition: "all 0.15s"
|
|
838
|
+
},
|
|
839
|
+
onMouseEnter: (e) => {
|
|
840
|
+
e.currentTarget.style.borderColor = STYLES.accent;
|
|
841
|
+
e.currentTarget.style.color = STYLES.text;
|
|
842
|
+
},
|
|
843
|
+
onMouseLeave: (e) => {
|
|
844
|
+
e.currentTarget.style.borderColor = STYLES.border;
|
|
845
|
+
e.currentTarget.style.color = STYLES.textMuted;
|
|
846
|
+
},
|
|
847
|
+
children: "Scan Again"
|
|
848
|
+
}
|
|
849
|
+
) })
|
|
850
|
+
] })
|
|
851
|
+
] });
|
|
852
|
+
}
|
|
573
853
|
function Section({
|
|
574
854
|
title,
|
|
575
855
|
children
|
|
@@ -690,7 +970,7 @@ function ComponentStackItem({
|
|
|
690
970
|
}
|
|
691
971
|
);
|
|
692
972
|
}
|
|
693
|
-
function
|
|
973
|
+
function CursorIcon() {
|
|
694
974
|
return /* @__PURE__ */ jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx(
|
|
695
975
|
"path",
|
|
696
976
|
{
|
|
@@ -714,6 +994,53 @@ function CloseIcon() {
|
|
|
714
994
|
}
|
|
715
995
|
) });
|
|
716
996
|
}
|
|
997
|
+
function ScanIcon() {
|
|
998
|
+
return /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx(
|
|
999
|
+
"path",
|
|
1000
|
+
{
|
|
1001
|
+
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",
|
|
1002
|
+
stroke: "currentColor",
|
|
1003
|
+
strokeWidth: "2",
|
|
1004
|
+
strokeLinecap: "round"
|
|
1005
|
+
}
|
|
1006
|
+
) });
|
|
1007
|
+
}
|
|
1008
|
+
function CopyIcon() {
|
|
1009
|
+
return /* @__PURE__ */ jsxs("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", children: [
|
|
1010
|
+
/* @__PURE__ */ jsx(
|
|
1011
|
+
"rect",
|
|
1012
|
+
{
|
|
1013
|
+
x: "9",
|
|
1014
|
+
y: "9",
|
|
1015
|
+
width: "13",
|
|
1016
|
+
height: "13",
|
|
1017
|
+
rx: "2",
|
|
1018
|
+
stroke: "currentColor",
|
|
1019
|
+
strokeWidth: "2"
|
|
1020
|
+
}
|
|
1021
|
+
),
|
|
1022
|
+
/* @__PURE__ */ jsx(
|
|
1023
|
+
"path",
|
|
1024
|
+
{
|
|
1025
|
+
d: "M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1",
|
|
1026
|
+
stroke: "currentColor",
|
|
1027
|
+
strokeWidth: "2"
|
|
1028
|
+
}
|
|
1029
|
+
)
|
|
1030
|
+
] });
|
|
1031
|
+
}
|
|
1032
|
+
function CheckIcon() {
|
|
1033
|
+
return /* @__PURE__ */ jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx(
|
|
1034
|
+
"path",
|
|
1035
|
+
{
|
|
1036
|
+
d: "M20 6L9 17l-5-5",
|
|
1037
|
+
stroke: "currentColor",
|
|
1038
|
+
strokeWidth: "2",
|
|
1039
|
+
strokeLinecap: "round",
|
|
1040
|
+
strokeLinejoin: "round"
|
|
1041
|
+
}
|
|
1042
|
+
) });
|
|
1043
|
+
}
|
|
717
1044
|
|
|
718
1045
|
export {
|
|
719
1046
|
fetchSource,
|