uilint-react 0.1.43 → 0.1.44
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/{ElementBadges-2I25HN6W.js → ElementBadges-OQC6YCQD.js} +1 -1
- package/dist/InspectionPanel-UW5UBZIK.js +10 -0
- package/dist/{LocatorOverlay-ERRFPXKK.js → LocatorOverlay-RMU6JIFI.js} +2 -2
- package/dist/UILintToolbar-G5AVKNXA.js +10 -0
- package/dist/{chunk-UD6HPLEZ.js → chunk-GCZ53K35.js} +1 -1
- package/dist/{chunk-LAL3JTAA.js → chunk-HECINZHM.js} +39 -7
- package/dist/{chunk-C6NUU5MF.js → chunk-RULQAXE4.js} +247 -141
- package/dist/chunk-W42PI2OF.js +81 -0
- package/dist/chunk-X4PRYONL.js +1017 -0
- package/dist/index.js +5 -4
- package/package.json +6 -3
- package/dist/InspectionPanel-4LOWGHW7.js +0 -9
- package/dist/UILintToolbar-MJH7RUZK.js +0 -9
- package/dist/chunk-2VRWAMW7.js +0 -927
|
@@ -0,0 +1,1017 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
Badge
|
|
4
|
+
} from "./chunk-W42PI2OF.js";
|
|
5
|
+
import {
|
|
6
|
+
buildEditorUrl,
|
|
7
|
+
useUILintContext,
|
|
8
|
+
useUILintStore
|
|
9
|
+
} from "./chunk-HECINZHM.js";
|
|
10
|
+
|
|
11
|
+
// src/components/ui-lint/InspectionPanel.tsx
|
|
12
|
+
import React, {
|
|
13
|
+
useState,
|
|
14
|
+
useEffect,
|
|
15
|
+
useCallback,
|
|
16
|
+
useMemo,
|
|
17
|
+
useRef
|
|
18
|
+
} from "react";
|
|
19
|
+
import { createPortal } from "react-dom";
|
|
20
|
+
|
|
21
|
+
// src/components/ui-lint/source-fetcher.ts
|
|
22
|
+
var sourceCache = /* @__PURE__ */ new Map();
|
|
23
|
+
var CACHE_TTL = 5 * 60 * 1e3;
|
|
24
|
+
var API_ENDPOINT = "/api/.uilint/source";
|
|
25
|
+
async function fetchSource(filePath) {
|
|
26
|
+
const cached = sourceCache.get(filePath);
|
|
27
|
+
if (cached && Date.now() - cached.fetchedAt < CACHE_TTL) {
|
|
28
|
+
return {
|
|
29
|
+
content: cached.content,
|
|
30
|
+
relativePath: cached.relativePath
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
const response = await fetch(
|
|
35
|
+
`${API_ENDPOINT}?path=${encodeURIComponent(filePath)}`
|
|
36
|
+
);
|
|
37
|
+
if (!response.ok) {
|
|
38
|
+
console.warn(`[UILint] Failed to fetch source: ${response.statusText}`);
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
const data = await response.json();
|
|
42
|
+
sourceCache.set(filePath, {
|
|
43
|
+
...data,
|
|
44
|
+
fetchedAt: Date.now()
|
|
45
|
+
});
|
|
46
|
+
return data;
|
|
47
|
+
} catch (error) {
|
|
48
|
+
console.error("[UILint] Error fetching source:", error);
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async function fetchSourceWithContext(source, contextLines = 5) {
|
|
53
|
+
const result = await fetchSource(source.fileName);
|
|
54
|
+
if (!result) return null;
|
|
55
|
+
const allLines = result.content.split("\n");
|
|
56
|
+
const targetLine = source.lineNumber - 1;
|
|
57
|
+
const startLine = Math.max(0, targetLine - contextLines);
|
|
58
|
+
const endLine = Math.min(allLines.length, targetLine + contextLines + 1);
|
|
59
|
+
return {
|
|
60
|
+
lines: allLines.slice(startLine, endLine),
|
|
61
|
+
startLine: startLine + 1,
|
|
62
|
+
// Back to 1-indexed
|
|
63
|
+
highlightLine: source.lineNumber,
|
|
64
|
+
relativePath: result.relativePath
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
async function fetchSourceWithWindow(source, window2) {
|
|
68
|
+
const result = await fetchSource(source.fileName);
|
|
69
|
+
if (!result) return null;
|
|
70
|
+
const allLines = result.content.split("\n");
|
|
71
|
+
const targetLine = source.lineNumber - 1;
|
|
72
|
+
const startLine = Math.max(0, targetLine - Math.max(0, window2.linesAbove));
|
|
73
|
+
const endLine = Math.min(
|
|
74
|
+
allLines.length,
|
|
75
|
+
targetLine + Math.max(0, window2.linesBelow) + 1
|
|
76
|
+
);
|
|
77
|
+
return {
|
|
78
|
+
lines: allLines.slice(startLine, endLine),
|
|
79
|
+
startLine: startLine + 1,
|
|
80
|
+
// Back to 1-indexed
|
|
81
|
+
highlightLine: source.lineNumber,
|
|
82
|
+
relativePath: result.relativePath
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function clearSourceCache() {
|
|
86
|
+
sourceCache.clear();
|
|
87
|
+
}
|
|
88
|
+
function getCachedSource(filePath) {
|
|
89
|
+
const cached = sourceCache.get(filePath);
|
|
90
|
+
if (!cached) return null;
|
|
91
|
+
if (Date.now() - cached.fetchedAt >= CACHE_TTL) {
|
|
92
|
+
sourceCache.delete(filePath);
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
content: cached.content,
|
|
97
|
+
relativePath: cached.relativePath
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
async function prefetchSources(filePaths) {
|
|
101
|
+
const uniquePaths = [...new Set(filePaths)].filter((path) => {
|
|
102
|
+
const cached = sourceCache.get(path);
|
|
103
|
+
return !cached || Date.now() - cached.fetchedAt >= CACHE_TTL;
|
|
104
|
+
});
|
|
105
|
+
const BATCH_SIZE = 5;
|
|
106
|
+
for (let i = 0; i < uniquePaths.length; i += BATCH_SIZE) {
|
|
107
|
+
const batch = uniquePaths.slice(i, i + BATCH_SIZE);
|
|
108
|
+
await Promise.all(batch.map(fetchSource));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// src/components/ui-lint/code-formatting.ts
|
|
113
|
+
function leadingWhitespace(s) {
|
|
114
|
+
const match = s.match(/^[\t ]+/);
|
|
115
|
+
return match ? match[0] : "";
|
|
116
|
+
}
|
|
117
|
+
function dedentLines(lines) {
|
|
118
|
+
if (!lines.length) return { lines, removed: 0 };
|
|
119
|
+
const nonEmpty = lines.filter((l) => l.trim().length > 0);
|
|
120
|
+
if (!nonEmpty.length) return { lines, removed: 0 };
|
|
121
|
+
let min = Infinity;
|
|
122
|
+
for (const l of nonEmpty) {
|
|
123
|
+
min = Math.min(min, leadingWhitespace(l).length);
|
|
124
|
+
if (min === 0) break;
|
|
125
|
+
}
|
|
126
|
+
if (!Number.isFinite(min) || min <= 0) return { lines, removed: 0 };
|
|
127
|
+
return {
|
|
128
|
+
removed: min,
|
|
129
|
+
lines: lines.map((l) => l.length >= min ? l.slice(min) : "")
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// src/components/ui-lint/inspection-panel-positioning.ts
|
|
134
|
+
function clamp(n, min, max) {
|
|
135
|
+
return Math.max(min, Math.min(max, n));
|
|
136
|
+
}
|
|
137
|
+
function overflowScore(left, top, size, viewport, padding) {
|
|
138
|
+
const right = left + size.width;
|
|
139
|
+
const bottom = top + size.height;
|
|
140
|
+
const oLeft = Math.max(0, padding - left);
|
|
141
|
+
const oTop = Math.max(0, padding - top);
|
|
142
|
+
const oRight = Math.max(0, right - (viewport.width - padding));
|
|
143
|
+
const oBottom = Math.max(0, bottom - (viewport.height - padding));
|
|
144
|
+
return oLeft * 2 + oRight * 2 + oTop + oBottom;
|
|
145
|
+
}
|
|
146
|
+
function intersectionArea(a, b) {
|
|
147
|
+
const x1 = Math.max(a.left, b.left);
|
|
148
|
+
const y1 = Math.max(a.top, b.top);
|
|
149
|
+
const x2 = Math.min(a.right, b.right);
|
|
150
|
+
const y2 = Math.min(a.bottom, b.bottom);
|
|
151
|
+
const w = Math.max(0, x2 - x1);
|
|
152
|
+
const h = Math.max(0, y2 - y1);
|
|
153
|
+
return w * h;
|
|
154
|
+
}
|
|
155
|
+
function computeInspectionPanelPosition(params) {
|
|
156
|
+
const { rect, popover, viewport } = params;
|
|
157
|
+
const padding = params.padding ?? 12;
|
|
158
|
+
const badge = { x: rect.right, y: rect.top };
|
|
159
|
+
const xMax = viewport.width - popover.width - padding;
|
|
160
|
+
const yMax = viewport.height - popover.height - padding;
|
|
161
|
+
const rawCandidates = [
|
|
162
|
+
{
|
|
163
|
+
placement: "right",
|
|
164
|
+
left: rect.right + padding,
|
|
165
|
+
top: rect.top
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
// keep close to the badge by aligning the right edge to rect.right
|
|
169
|
+
placement: "left",
|
|
170
|
+
left: rect.right - popover.width - padding,
|
|
171
|
+
top: rect.top
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
placement: "bottom",
|
|
175
|
+
left: rect.right - popover.width,
|
|
176
|
+
top: rect.bottom + padding
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
placement: "top",
|
|
180
|
+
left: rect.right - popover.width,
|
|
181
|
+
top: rect.top - popover.height - padding
|
|
182
|
+
}
|
|
183
|
+
];
|
|
184
|
+
const candidates = rawCandidates.map((c) => ({
|
|
185
|
+
raw: c,
|
|
186
|
+
clamped: {
|
|
187
|
+
...c,
|
|
188
|
+
left: clamp(c.left, padding, xMax),
|
|
189
|
+
top: clamp(c.top, padding, yMax)
|
|
190
|
+
}
|
|
191
|
+
}));
|
|
192
|
+
const distanceToBadge = (pos) => {
|
|
193
|
+
const nearestX = clamp(badge.x, pos.left, pos.left + popover.width);
|
|
194
|
+
const nearestY = clamp(badge.y, pos.top, pos.top + popover.height);
|
|
195
|
+
const dx = badge.x - nearestX;
|
|
196
|
+
const dy = badge.y - nearestY;
|
|
197
|
+
return dx * dx + dy * dy;
|
|
198
|
+
};
|
|
199
|
+
const score = (raw, pos) => {
|
|
200
|
+
const overflow = overflowScore(
|
|
201
|
+
pos.left,
|
|
202
|
+
pos.top,
|
|
203
|
+
popover,
|
|
204
|
+
viewport,
|
|
205
|
+
padding
|
|
206
|
+
);
|
|
207
|
+
const clampDelta = Math.abs(raw.left - pos.left) + Math.abs(raw.top - pos.top);
|
|
208
|
+
const box = {
|
|
209
|
+
left: pos.left,
|
|
210
|
+
top: pos.top,
|
|
211
|
+
right: pos.left + popover.width,
|
|
212
|
+
bottom: pos.top + popover.height
|
|
213
|
+
};
|
|
214
|
+
const overlap = intersectionArea(box, rect);
|
|
215
|
+
const dist = distanceToBadge(pos);
|
|
216
|
+
return overflow * 1e6 + clampDelta * 1e3 + overlap * 10 + dist;
|
|
217
|
+
};
|
|
218
|
+
let best = candidates[0].clamped;
|
|
219
|
+
let bestScore = score(candidates[0].raw, candidates[0].clamped);
|
|
220
|
+
for (const c of candidates.slice(1)) {
|
|
221
|
+
const s = score(c.raw, c.clamped);
|
|
222
|
+
if (s < bestScore) {
|
|
223
|
+
best = c.clamped;
|
|
224
|
+
bestScore = s;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return best;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// src/components/ui-lint/InspectionPanel.tsx
|
|
231
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
232
|
+
var STYLES = {
|
|
233
|
+
bg: "rgba(17, 24, 39, 0.98)",
|
|
234
|
+
bgSurface: "rgba(31, 41, 55, 0.95)",
|
|
235
|
+
border: "rgba(75, 85, 99, 0.6)",
|
|
236
|
+
text: "#F9FAFB",
|
|
237
|
+
textMuted: "#9CA3AF",
|
|
238
|
+
textDim: "#6B7280",
|
|
239
|
+
accent: "#3B82F6",
|
|
240
|
+
accentHover: "#2563EB",
|
|
241
|
+
success: "#10B981",
|
|
242
|
+
warning: "#F59E0B",
|
|
243
|
+
error: "#EF4444",
|
|
244
|
+
shadow: "0 8px 32px rgba(0, 0, 0, 0.5)",
|
|
245
|
+
blur: "blur(12px)",
|
|
246
|
+
font: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
|
|
247
|
+
fontMono: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace'
|
|
248
|
+
};
|
|
249
|
+
var POPOVER_WIDTH = 380;
|
|
250
|
+
var POPOVER_MAX_HEIGHT = 450;
|
|
251
|
+
function InspectionPanel() {
|
|
252
|
+
const {
|
|
253
|
+
inspectedElement,
|
|
254
|
+
setInspectedElement,
|
|
255
|
+
elementIssuesCache,
|
|
256
|
+
autoScanState
|
|
257
|
+
} = useUILintContext();
|
|
258
|
+
const fileIssuesCache = useUILintStore((s) => s.fileIssuesCache);
|
|
259
|
+
const appRoot = useUILintStore((s) => s.appRoot);
|
|
260
|
+
const workspaceRoot = useUILintStore((s) => s.workspaceRoot);
|
|
261
|
+
const editorBaseDir = appRoot || workspaceRoot;
|
|
262
|
+
const [mounted, setMounted] = useState(false);
|
|
263
|
+
const [showFullContext, setShowFullContext] = useState(true);
|
|
264
|
+
const popoverRef = useRef(null);
|
|
265
|
+
const [position, setPosition] = useState({ top: 0, left: 0 });
|
|
266
|
+
useEffect(() => {
|
|
267
|
+
setMounted(true);
|
|
268
|
+
}, []);
|
|
269
|
+
useEffect(() => {
|
|
270
|
+
if (!inspectedElement) return;
|
|
271
|
+
const handleClickOutside = (e) => {
|
|
272
|
+
const target = e.target;
|
|
273
|
+
if (target?.closest?.("[data-ui-lint]")) return;
|
|
274
|
+
const rect = inspectedElement.element.getBoundingClientRect();
|
|
275
|
+
if (rect.top < -1e3 || rect.left < -1e3) {
|
|
276
|
+
inspectedElement.element.remove();
|
|
277
|
+
}
|
|
278
|
+
setInspectedElement(null);
|
|
279
|
+
};
|
|
280
|
+
const timer = setTimeout(() => {
|
|
281
|
+
document.addEventListener("click", handleClickOutside);
|
|
282
|
+
}, 50);
|
|
283
|
+
return () => {
|
|
284
|
+
clearTimeout(timer);
|
|
285
|
+
document.removeEventListener("click", handleClickOutside);
|
|
286
|
+
};
|
|
287
|
+
}, [inspectedElement, setInspectedElement]);
|
|
288
|
+
const isFileLevelIssue = useMemo(() => {
|
|
289
|
+
if (!inspectedElement) return false;
|
|
290
|
+
const rect = inspectedElement.element.getBoundingClientRect();
|
|
291
|
+
return rect.top < -1e3 || rect.left < -1e3;
|
|
292
|
+
}, [inspectedElement]);
|
|
293
|
+
const cachedIssue = useMemo(() => {
|
|
294
|
+
if (!inspectedElement) return null;
|
|
295
|
+
if (isFileLevelIssue && inspectedElement.source) {
|
|
296
|
+
const fileIssues = fileIssuesCache.get(inspectedElement.source.fileName);
|
|
297
|
+
if (fileIssues && fileIssues.length > 0) {
|
|
298
|
+
const matchingIssues = fileIssues.filter((issue) => {
|
|
299
|
+
if (issue.line !== inspectedElement.source.lineNumber) return false;
|
|
300
|
+
if (inspectedElement.source.columnNumber && issue.column !== inspectedElement.source.columnNumber) {
|
|
301
|
+
return false;
|
|
302
|
+
}
|
|
303
|
+
return true;
|
|
304
|
+
});
|
|
305
|
+
return {
|
|
306
|
+
elementId: `file:${inspectedElement.source.fileName}`,
|
|
307
|
+
issues: matchingIssues.length > 0 ? matchingIssues : fileIssues,
|
|
308
|
+
status: "complete"
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
return null;
|
|
312
|
+
}
|
|
313
|
+
if (inspectedElement.scannedElementId) {
|
|
314
|
+
const cached = elementIssuesCache.get(inspectedElement.scannedElementId);
|
|
315
|
+
if (cached) return cached;
|
|
316
|
+
}
|
|
317
|
+
if (inspectedElement.source) {
|
|
318
|
+
for (const [, issue] of elementIssuesCache) {
|
|
319
|
+
const scannedElement = autoScanState.elements.find(
|
|
320
|
+
(el) => el.id === issue.elementId
|
|
321
|
+
);
|
|
322
|
+
if (scannedElement?.source?.fileName === inspectedElement.source.fileName) {
|
|
323
|
+
return issue;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return null;
|
|
328
|
+
}, [
|
|
329
|
+
inspectedElement,
|
|
330
|
+
elementIssuesCache,
|
|
331
|
+
fileIssuesCache,
|
|
332
|
+
autoScanState.elements,
|
|
333
|
+
isFileLevelIssue
|
|
334
|
+
]);
|
|
335
|
+
const eslintIssues = useMemo(() => cachedIssue?.issues || [], [cachedIssue]);
|
|
336
|
+
const lineRange = useMemo(() => {
|
|
337
|
+
if (!eslintIssues.length) {
|
|
338
|
+
return inspectedElement?.source.lineNumber.toString() || "0";
|
|
339
|
+
}
|
|
340
|
+
const lines = eslintIssues.map((i) => i.line).sort((a, b) => a - b);
|
|
341
|
+
const min = lines[0];
|
|
342
|
+
const max = lines[lines.length - 1];
|
|
343
|
+
return min === max ? min.toString() : `${min}-${max}`;
|
|
344
|
+
}, [eslintIssues, inspectedElement]);
|
|
345
|
+
useEffect(() => {
|
|
346
|
+
if (!inspectedElement) return;
|
|
347
|
+
let rafId = null;
|
|
348
|
+
const update = () => {
|
|
349
|
+
rafId = null;
|
|
350
|
+
if (isFileLevelIssue) {
|
|
351
|
+
const measured2 = popoverRef.current ? {
|
|
352
|
+
width: popoverRef.current.offsetWidth,
|
|
353
|
+
height: popoverRef.current.offsetHeight
|
|
354
|
+
} : null;
|
|
355
|
+
const popoverSize2 = measured2 ?? {
|
|
356
|
+
width: POPOVER_WIDTH,
|
|
357
|
+
height: POPOVER_MAX_HEIGHT
|
|
358
|
+
};
|
|
359
|
+
const allUILintElements = document.querySelectorAll("[data-ui-lint]");
|
|
360
|
+
let scanResultsPopover = null;
|
|
361
|
+
for (const el of allUILintElements) {
|
|
362
|
+
const htmlEl = el;
|
|
363
|
+
if (htmlEl === popoverRef.current) continue;
|
|
364
|
+
const style = window.getComputedStyle(htmlEl);
|
|
365
|
+
const width = htmlEl.offsetWidth;
|
|
366
|
+
const isRightWidth = width >= 310 && width <= 330;
|
|
367
|
+
const isRightPosition = style.position === "relative" || style.position === "absolute";
|
|
368
|
+
const rect2 = htmlEl.getBoundingClientRect();
|
|
369
|
+
const isVisible = rect2.width > 0 && rect2.height > 0;
|
|
370
|
+
if (isRightWidth && isRightPosition && isVisible) {
|
|
371
|
+
scanResultsPopover = htmlEl;
|
|
372
|
+
break;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
const gap = 12;
|
|
376
|
+
const padding = 12;
|
|
377
|
+
if (scanResultsPopover) {
|
|
378
|
+
const scanRect = scanResultsPopover.getBoundingClientRect();
|
|
379
|
+
const left = scanRect.right + gap;
|
|
380
|
+
const top = scanRect.top;
|
|
381
|
+
const maxLeft = window.innerWidth - popoverSize2.width - padding;
|
|
382
|
+
const adjustedLeft = Math.min(left, maxLeft);
|
|
383
|
+
const adjustedTop = Math.max(padding, top);
|
|
384
|
+
setPosition({ top: adjustedTop, left: adjustedLeft });
|
|
385
|
+
} else {
|
|
386
|
+
const top = padding;
|
|
387
|
+
const left = Math.max(
|
|
388
|
+
padding,
|
|
389
|
+
window.innerWidth - popoverSize2.width - padding
|
|
390
|
+
);
|
|
391
|
+
setPosition({ top, left });
|
|
392
|
+
}
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
const rect = inspectedElement.element.getBoundingClientRect();
|
|
396
|
+
const measured = popoverRef.current ? {
|
|
397
|
+
width: popoverRef.current.offsetWidth,
|
|
398
|
+
height: popoverRef.current.offsetHeight
|
|
399
|
+
} : null;
|
|
400
|
+
const popoverSize = measured ?? {
|
|
401
|
+
width: POPOVER_WIDTH,
|
|
402
|
+
height: POPOVER_MAX_HEIGHT
|
|
403
|
+
};
|
|
404
|
+
const next = computeInspectionPanelPosition({
|
|
405
|
+
rect,
|
|
406
|
+
popover: popoverSize,
|
|
407
|
+
viewport: { width: window.innerWidth, height: window.innerHeight },
|
|
408
|
+
padding: 12
|
|
409
|
+
});
|
|
410
|
+
setPosition({ top: next.top, left: next.left });
|
|
411
|
+
};
|
|
412
|
+
const schedule = () => {
|
|
413
|
+
if (rafId != null) return;
|
|
414
|
+
rafId = window.requestAnimationFrame(update);
|
|
415
|
+
};
|
|
416
|
+
schedule();
|
|
417
|
+
if (isFileLevelIssue) {
|
|
418
|
+
window.addEventListener("resize", schedule);
|
|
419
|
+
} else {
|
|
420
|
+
window.addEventListener("scroll", schedule, true);
|
|
421
|
+
window.addEventListener("resize", schedule);
|
|
422
|
+
}
|
|
423
|
+
return () => {
|
|
424
|
+
if (rafId != null) window.cancelAnimationFrame(rafId);
|
|
425
|
+
if (isFileLevelIssue) {
|
|
426
|
+
window.removeEventListener("resize", schedule);
|
|
427
|
+
} else {
|
|
428
|
+
window.removeEventListener("scroll", schedule, true);
|
|
429
|
+
window.removeEventListener("resize", schedule);
|
|
430
|
+
}
|
|
431
|
+
};
|
|
432
|
+
}, [inspectedElement, showFullContext, isFileLevelIssue]);
|
|
433
|
+
const handleOpenInCursor = useCallback(() => {
|
|
434
|
+
if (!inspectedElement) return;
|
|
435
|
+
const url = buildEditorUrl(
|
|
436
|
+
inspectedElement.source,
|
|
437
|
+
"cursor",
|
|
438
|
+
editorBaseDir
|
|
439
|
+
);
|
|
440
|
+
window.open(url, "_blank");
|
|
441
|
+
}, [inspectedElement, editorBaseDir]);
|
|
442
|
+
if (!mounted || !inspectedElement) return null;
|
|
443
|
+
const content = /* @__PURE__ */ jsxs(
|
|
444
|
+
"div",
|
|
445
|
+
{
|
|
446
|
+
ref: popoverRef,
|
|
447
|
+
"data-ui-lint": true,
|
|
448
|
+
onClick: (e) => e.stopPropagation(),
|
|
449
|
+
style: {
|
|
450
|
+
position: "fixed",
|
|
451
|
+
top: position.top,
|
|
452
|
+
left: position.left,
|
|
453
|
+
width: POPOVER_WIDTH,
|
|
454
|
+
maxHeight: POPOVER_MAX_HEIGHT,
|
|
455
|
+
backgroundColor: STYLES.bg,
|
|
456
|
+
backdropFilter: STYLES.blur,
|
|
457
|
+
WebkitBackdropFilter: STYLES.blur,
|
|
458
|
+
border: `1px solid ${STYLES.border}`,
|
|
459
|
+
borderRadius: "12px",
|
|
460
|
+
boxShadow: STYLES.shadow,
|
|
461
|
+
fontFamily: STYLES.font,
|
|
462
|
+
color: STYLES.text,
|
|
463
|
+
overflow: "hidden",
|
|
464
|
+
zIndex: 99998,
|
|
465
|
+
animation: "uilint-popover-appear 0.15s ease-out"
|
|
466
|
+
},
|
|
467
|
+
children: [
|
|
468
|
+
/* @__PURE__ */ jsx("style", { children: `
|
|
469
|
+
@keyframes uilint-popover-appear {
|
|
470
|
+
from { opacity: 0; transform: scale(0.95); }
|
|
471
|
+
to { opacity: 1; transform: scale(1); }
|
|
472
|
+
}
|
|
473
|
+
@keyframes uilint-spin {
|
|
474
|
+
from { transform: rotate(0deg); }
|
|
475
|
+
to { transform: rotate(360deg); }
|
|
476
|
+
}
|
|
477
|
+
` }),
|
|
478
|
+
/* @__PURE__ */ jsx(
|
|
479
|
+
PopoverHeader,
|
|
480
|
+
{
|
|
481
|
+
element: inspectedElement,
|
|
482
|
+
issueCount: eslintIssues.length,
|
|
483
|
+
lineRange,
|
|
484
|
+
onClose: () => setInspectedElement(null)
|
|
485
|
+
}
|
|
486
|
+
),
|
|
487
|
+
/* @__PURE__ */ jsxs(
|
|
488
|
+
"div",
|
|
489
|
+
{
|
|
490
|
+
style: {
|
|
491
|
+
maxHeight: POPOVER_MAX_HEIGHT - 120,
|
|
492
|
+
overflowY: "auto"
|
|
493
|
+
},
|
|
494
|
+
children: [
|
|
495
|
+
cachedIssue?.status === "scanning" && /* @__PURE__ */ jsxs(
|
|
496
|
+
"div",
|
|
497
|
+
{
|
|
498
|
+
style: {
|
|
499
|
+
display: "flex",
|
|
500
|
+
alignItems: "center",
|
|
501
|
+
justifyContent: "center",
|
|
502
|
+
padding: "32px",
|
|
503
|
+
gap: "12px"
|
|
504
|
+
},
|
|
505
|
+
children: [
|
|
506
|
+
/* @__PURE__ */ jsx(
|
|
507
|
+
"div",
|
|
508
|
+
{
|
|
509
|
+
style: {
|
|
510
|
+
width: "20px",
|
|
511
|
+
height: "20px",
|
|
512
|
+
border: `2px solid ${STYLES.border}`,
|
|
513
|
+
borderTopColor: STYLES.accent,
|
|
514
|
+
borderRadius: "50%",
|
|
515
|
+
animation: "uilint-spin 0.8s linear infinite"
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
),
|
|
519
|
+
/* @__PURE__ */ jsx("span", { style: { color: STYLES.textMuted, fontSize: "13px" }, children: "Scanning..." })
|
|
520
|
+
]
|
|
521
|
+
}
|
|
522
|
+
),
|
|
523
|
+
cachedIssue?.status === "complete" && eslintIssues.length === 0 && /* @__PURE__ */ jsxs(
|
|
524
|
+
"div",
|
|
525
|
+
{
|
|
526
|
+
style: {
|
|
527
|
+
display: "flex",
|
|
528
|
+
alignItems: "center",
|
|
529
|
+
justifyContent: "center",
|
|
530
|
+
padding: "32px",
|
|
531
|
+
gap: "8px",
|
|
532
|
+
color: STYLES.success,
|
|
533
|
+
fontSize: "13px"
|
|
534
|
+
},
|
|
535
|
+
children: [
|
|
536
|
+
/* @__PURE__ */ jsx(CheckIcon, {}),
|
|
537
|
+
"No issues found"
|
|
538
|
+
]
|
|
539
|
+
}
|
|
540
|
+
),
|
|
541
|
+
cachedIssue?.status === "complete" && eslintIssues.length > 0 && /* @__PURE__ */ jsx(
|
|
542
|
+
IssuesList,
|
|
543
|
+
{
|
|
544
|
+
issues: eslintIssues,
|
|
545
|
+
source: inspectedElement.source,
|
|
546
|
+
showFullContext
|
|
547
|
+
}
|
|
548
|
+
),
|
|
549
|
+
!cachedIssue && /* @__PURE__ */ jsx(
|
|
550
|
+
"div",
|
|
551
|
+
{
|
|
552
|
+
style: {
|
|
553
|
+
padding: "24px 16px",
|
|
554
|
+
textAlign: "center",
|
|
555
|
+
color: STYLES.textMuted,
|
|
556
|
+
fontSize: "12px"
|
|
557
|
+
},
|
|
558
|
+
children: "Enable live scanning to analyze this element"
|
|
559
|
+
}
|
|
560
|
+
)
|
|
561
|
+
]
|
|
562
|
+
}
|
|
563
|
+
),
|
|
564
|
+
cachedIssue?.status === "complete" && eslintIssues.length > 0 && /* @__PURE__ */ jsxs(
|
|
565
|
+
"div",
|
|
566
|
+
{
|
|
567
|
+
style: {
|
|
568
|
+
display: "flex",
|
|
569
|
+
alignItems: "center",
|
|
570
|
+
justifyContent: "space-between",
|
|
571
|
+
padding: "10px 14px",
|
|
572
|
+
borderTop: `1px solid ${STYLES.border}`,
|
|
573
|
+
backgroundColor: STYLES.bgSurface
|
|
574
|
+
},
|
|
575
|
+
children: [
|
|
576
|
+
/* @__PURE__ */ jsxs(
|
|
577
|
+
"button",
|
|
578
|
+
{
|
|
579
|
+
onClick: () => setShowFullContext(!showFullContext),
|
|
580
|
+
style: {
|
|
581
|
+
display: "flex",
|
|
582
|
+
alignItems: "center",
|
|
583
|
+
gap: "6px",
|
|
584
|
+
padding: "5px 10px",
|
|
585
|
+
borderRadius: "6px",
|
|
586
|
+
border: `1px solid ${STYLES.border}`,
|
|
587
|
+
backgroundColor: "transparent",
|
|
588
|
+
color: STYLES.textMuted,
|
|
589
|
+
fontSize: "11px",
|
|
590
|
+
fontWeight: 500,
|
|
591
|
+
cursor: "pointer",
|
|
592
|
+
transition: "all 0.15s"
|
|
593
|
+
},
|
|
594
|
+
onMouseEnter: (e) => {
|
|
595
|
+
e.currentTarget.style.backgroundColor = STYLES.bg;
|
|
596
|
+
e.currentTarget.style.color = STYLES.text;
|
|
597
|
+
},
|
|
598
|
+
onMouseLeave: (e) => {
|
|
599
|
+
e.currentTarget.style.backgroundColor = "transparent";
|
|
600
|
+
e.currentTarget.style.color = STYLES.textMuted;
|
|
601
|
+
},
|
|
602
|
+
children: [
|
|
603
|
+
showFullContext ? /* @__PURE__ */ jsx(CollapseIcon, {}) : /* @__PURE__ */ jsx(ExpandIcon, {}),
|
|
604
|
+
showFullContext ? "Hide context" : "Show full context"
|
|
605
|
+
]
|
|
606
|
+
}
|
|
607
|
+
),
|
|
608
|
+
/* @__PURE__ */ jsxs(
|
|
609
|
+
"button",
|
|
610
|
+
{
|
|
611
|
+
onClick: handleOpenInCursor,
|
|
612
|
+
style: {
|
|
613
|
+
display: "flex",
|
|
614
|
+
alignItems: "center",
|
|
615
|
+
gap: "4px",
|
|
616
|
+
padding: "5px 10px",
|
|
617
|
+
borderRadius: "6px",
|
|
618
|
+
border: "none",
|
|
619
|
+
backgroundColor: STYLES.accent,
|
|
620
|
+
color: "#FFFFFF",
|
|
621
|
+
fontSize: "11px",
|
|
622
|
+
fontWeight: 500,
|
|
623
|
+
cursor: "pointer",
|
|
624
|
+
transition: "background-color 0.15s"
|
|
625
|
+
},
|
|
626
|
+
onMouseEnter: (e) => {
|
|
627
|
+
e.currentTarget.style.backgroundColor = STYLES.accentHover;
|
|
628
|
+
},
|
|
629
|
+
onMouseLeave: (e) => {
|
|
630
|
+
e.currentTarget.style.backgroundColor = STYLES.accent;
|
|
631
|
+
},
|
|
632
|
+
title: "Open in Cursor",
|
|
633
|
+
children: [
|
|
634
|
+
/* @__PURE__ */ jsx(ExternalLinkIcon, {}),
|
|
635
|
+
"Open in Cursor"
|
|
636
|
+
]
|
|
637
|
+
}
|
|
638
|
+
)
|
|
639
|
+
]
|
|
640
|
+
}
|
|
641
|
+
)
|
|
642
|
+
]
|
|
643
|
+
}
|
|
644
|
+
);
|
|
645
|
+
return createPortal(content, document.body);
|
|
646
|
+
}
|
|
647
|
+
function PopoverHeader({
|
|
648
|
+
element,
|
|
649
|
+
issueCount,
|
|
650
|
+
lineRange,
|
|
651
|
+
onClose
|
|
652
|
+
}) {
|
|
653
|
+
const fileName = element.source.fileName.split("/").pop() || "Unknown";
|
|
654
|
+
return /* @__PURE__ */ jsxs(
|
|
655
|
+
"div",
|
|
656
|
+
{
|
|
657
|
+
style: {
|
|
658
|
+
display: "flex",
|
|
659
|
+
alignItems: "center",
|
|
660
|
+
justifyContent: "space-between",
|
|
661
|
+
padding: "12px 14px",
|
|
662
|
+
borderBottom: `1px solid ${STYLES.border}`,
|
|
663
|
+
backgroundColor: STYLES.bgSurface
|
|
664
|
+
},
|
|
665
|
+
children: [
|
|
666
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "10px" }, children: [
|
|
667
|
+
/* @__PURE__ */ jsxs(
|
|
668
|
+
"div",
|
|
669
|
+
{
|
|
670
|
+
style: {
|
|
671
|
+
display: "flex",
|
|
672
|
+
alignItems: "center",
|
|
673
|
+
gap: "6px",
|
|
674
|
+
fontSize: "13px",
|
|
675
|
+
fontWeight: 600
|
|
676
|
+
},
|
|
677
|
+
children: [
|
|
678
|
+
/* @__PURE__ */ jsx("span", { style: { fontFamily: STYLES.fontMono }, children: fileName }),
|
|
679
|
+
/* @__PURE__ */ jsxs("span", { style: { color: STYLES.textDim, fontWeight: 400 }, children: [
|
|
680
|
+
":",
|
|
681
|
+
lineRange
|
|
682
|
+
] })
|
|
683
|
+
]
|
|
684
|
+
}
|
|
685
|
+
),
|
|
686
|
+
issueCount > 0 && /* @__PURE__ */ jsx(Badge, { count: issueCount, backgroundColor: STYLES.error })
|
|
687
|
+
] }),
|
|
688
|
+
/* @__PURE__ */ jsx(
|
|
689
|
+
"button",
|
|
690
|
+
{
|
|
691
|
+
onClick: onClose,
|
|
692
|
+
style: {
|
|
693
|
+
display: "flex",
|
|
694
|
+
alignItems: "center",
|
|
695
|
+
justifyContent: "center",
|
|
696
|
+
width: "26px",
|
|
697
|
+
height: "26px",
|
|
698
|
+
borderRadius: "6px",
|
|
699
|
+
border: "none",
|
|
700
|
+
backgroundColor: "transparent",
|
|
701
|
+
color: STYLES.textMuted,
|
|
702
|
+
cursor: "pointer",
|
|
703
|
+
transition: "all 0.15s"
|
|
704
|
+
},
|
|
705
|
+
onMouseEnter: (e) => {
|
|
706
|
+
e.currentTarget.style.backgroundColor = STYLES.bg;
|
|
707
|
+
e.currentTarget.style.color = STYLES.text;
|
|
708
|
+
},
|
|
709
|
+
onMouseLeave: (e) => {
|
|
710
|
+
e.currentTarget.style.backgroundColor = "transparent";
|
|
711
|
+
e.currentTarget.style.color = STYLES.textMuted;
|
|
712
|
+
},
|
|
713
|
+
children: /* @__PURE__ */ jsx(CloseIcon, {})
|
|
714
|
+
}
|
|
715
|
+
)
|
|
716
|
+
]
|
|
717
|
+
}
|
|
718
|
+
);
|
|
719
|
+
}
|
|
720
|
+
function IssuesList({
|
|
721
|
+
issues,
|
|
722
|
+
source,
|
|
723
|
+
showFullContext
|
|
724
|
+
}) {
|
|
725
|
+
const issuesByLine = useMemo(() => {
|
|
726
|
+
const map = /* @__PURE__ */ new Map();
|
|
727
|
+
issues.forEach((issue) => {
|
|
728
|
+
const existing = map.get(issue.line) || [];
|
|
729
|
+
existing.push(issue);
|
|
730
|
+
map.set(issue.line, existing);
|
|
731
|
+
});
|
|
732
|
+
return map;
|
|
733
|
+
}, [issues]);
|
|
734
|
+
const sortedLines = useMemo(
|
|
735
|
+
() => Array.from(issuesByLine.keys()).sort((a, b) => a - b),
|
|
736
|
+
[issuesByLine]
|
|
737
|
+
);
|
|
738
|
+
return /* @__PURE__ */ jsx("div", { style: { padding: "12px" }, children: sortedLines.map((lineNumber, index) => /* @__PURE__ */ jsx(
|
|
739
|
+
CodeBlockWithAnnotations,
|
|
740
|
+
{
|
|
741
|
+
lineNumber,
|
|
742
|
+
issues: issuesByLine.get(lineNumber),
|
|
743
|
+
source,
|
|
744
|
+
showFullContext,
|
|
745
|
+
isLast: index === sortedLines.length - 1
|
|
746
|
+
},
|
|
747
|
+
lineNumber
|
|
748
|
+
)) });
|
|
749
|
+
}
|
|
750
|
+
function CodeBlockWithAnnotations({
|
|
751
|
+
lineNumber,
|
|
752
|
+
issues,
|
|
753
|
+
source,
|
|
754
|
+
showFullContext,
|
|
755
|
+
isLast
|
|
756
|
+
}) {
|
|
757
|
+
const [codeData, setCodeData] = useState(null);
|
|
758
|
+
const [loading, setLoading] = useState(true);
|
|
759
|
+
const contextLines = showFullContext ? 5 : 0;
|
|
760
|
+
useEffect(() => {
|
|
761
|
+
const issueSource = {
|
|
762
|
+
fileName: source.fileName,
|
|
763
|
+
lineNumber,
|
|
764
|
+
columnNumber: issues[0]?.column || 0
|
|
765
|
+
};
|
|
766
|
+
setLoading(true);
|
|
767
|
+
fetchSourceWithWindow(issueSource, {
|
|
768
|
+
linesAbove: contextLines,
|
|
769
|
+
linesBelow: contextLines
|
|
770
|
+
}).then((data) => {
|
|
771
|
+
if (data) {
|
|
772
|
+
setCodeData({
|
|
773
|
+
lines: data.lines,
|
|
774
|
+
startLine: data.startLine,
|
|
775
|
+
highlightLine: data.highlightLine
|
|
776
|
+
});
|
|
777
|
+
}
|
|
778
|
+
}).finally(() => {
|
|
779
|
+
setLoading(false);
|
|
780
|
+
});
|
|
781
|
+
}, [source.fileName, lineNumber, issues, contextLines]);
|
|
782
|
+
return /* @__PURE__ */ jsx(
|
|
783
|
+
"div",
|
|
784
|
+
{
|
|
785
|
+
style: {
|
|
786
|
+
marginBottom: isLast ? 0 : "12px",
|
|
787
|
+
backgroundColor: STYLES.bg,
|
|
788
|
+
borderRadius: "8px",
|
|
789
|
+
overflow: "hidden",
|
|
790
|
+
border: `1px solid ${STYLES.border}`
|
|
791
|
+
},
|
|
792
|
+
children: loading ? /* @__PURE__ */ jsx(
|
|
793
|
+
"div",
|
|
794
|
+
{
|
|
795
|
+
style: {
|
|
796
|
+
padding: "12px",
|
|
797
|
+
textAlign: "center",
|
|
798
|
+
color: STYLES.textDim,
|
|
799
|
+
fontSize: "11px"
|
|
800
|
+
},
|
|
801
|
+
children: "Loading..."
|
|
802
|
+
}
|
|
803
|
+
) : codeData ? /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
|
|
804
|
+
"pre",
|
|
805
|
+
{
|
|
806
|
+
style: {
|
|
807
|
+
margin: 0,
|
|
808
|
+
padding: "8px 0",
|
|
809
|
+
overflow: "auto",
|
|
810
|
+
fontSize: "11px",
|
|
811
|
+
lineHeight: "1.5",
|
|
812
|
+
fontFamily: STYLES.fontMono
|
|
813
|
+
},
|
|
814
|
+
children: dedentLines(codeData.lines).lines.map((line, index) => {
|
|
815
|
+
const currentLineNumber = codeData.startLine + index;
|
|
816
|
+
const isHighlight = currentLineNumber === codeData.highlightLine;
|
|
817
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
818
|
+
/* @__PURE__ */ jsxs(
|
|
819
|
+
"div",
|
|
820
|
+
{
|
|
821
|
+
style: {
|
|
822
|
+
display: "flex",
|
|
823
|
+
backgroundColor: isHighlight ? "rgba(239, 68, 68, 0.1)" : "transparent",
|
|
824
|
+
borderLeft: isHighlight ? `2px solid ${STYLES.error}` : "2px solid transparent"
|
|
825
|
+
},
|
|
826
|
+
children: [
|
|
827
|
+
/* @__PURE__ */ jsx(
|
|
828
|
+
"span",
|
|
829
|
+
{
|
|
830
|
+
style: {
|
|
831
|
+
display: "inline-block",
|
|
832
|
+
width: "36px",
|
|
833
|
+
paddingRight: "8px",
|
|
834
|
+
paddingLeft: "8px",
|
|
835
|
+
textAlign: "right",
|
|
836
|
+
color: isHighlight ? STYLES.error : STYLES.textDim,
|
|
837
|
+
userSelect: "none",
|
|
838
|
+
flexShrink: 0
|
|
839
|
+
},
|
|
840
|
+
children: currentLineNumber
|
|
841
|
+
}
|
|
842
|
+
),
|
|
843
|
+
/* @__PURE__ */ jsx(
|
|
844
|
+
"code",
|
|
845
|
+
{
|
|
846
|
+
style: {
|
|
847
|
+
color: isHighlight ? STYLES.text : STYLES.textMuted,
|
|
848
|
+
whiteSpace: "pre",
|
|
849
|
+
paddingRight: "8px"
|
|
850
|
+
},
|
|
851
|
+
children: line || " "
|
|
852
|
+
}
|
|
853
|
+
)
|
|
854
|
+
]
|
|
855
|
+
}
|
|
856
|
+
),
|
|
857
|
+
isHighlight && issues.map((issue, issueIndex) => /* @__PURE__ */ jsx(InlineAnnotation, { issue }, issueIndex))
|
|
858
|
+
] }, currentLineNumber);
|
|
859
|
+
})
|
|
860
|
+
}
|
|
861
|
+
) }) : /* @__PURE__ */ jsx(
|
|
862
|
+
"div",
|
|
863
|
+
{
|
|
864
|
+
style: {
|
|
865
|
+
padding: "12px",
|
|
866
|
+
textAlign: "center",
|
|
867
|
+
color: STYLES.textDim,
|
|
868
|
+
fontSize: "11px"
|
|
869
|
+
},
|
|
870
|
+
children: "Could not load source"
|
|
871
|
+
}
|
|
872
|
+
)
|
|
873
|
+
}
|
|
874
|
+
);
|
|
875
|
+
}
|
|
876
|
+
function InlineAnnotation({ issue }) {
|
|
877
|
+
const ruleUrl = issue.ruleId ? `https://github.com/peter-suggate/uilint/blob/main/packages/uilint-eslint/src/rules/${issue.ruleId.split("/").pop()}.ts` : null;
|
|
878
|
+
return /* @__PURE__ */ jsxs(
|
|
879
|
+
"div",
|
|
880
|
+
{
|
|
881
|
+
style: {
|
|
882
|
+
display: "flex",
|
|
883
|
+
alignItems: "flex-start",
|
|
884
|
+
gap: "8px",
|
|
885
|
+
padding: "6px 8px 6px 46px",
|
|
886
|
+
backgroundColor: "rgba(239, 68, 68, 0.08)",
|
|
887
|
+
borderLeft: `2px solid ${STYLES.error}`
|
|
888
|
+
},
|
|
889
|
+
children: [
|
|
890
|
+
/* @__PURE__ */ jsx(ErrorSquiggleIcon, {}),
|
|
891
|
+
/* @__PURE__ */ jsxs("div", { style: { flex: 1, fontSize: "11px", lineHeight: "1.4" }, children: [
|
|
892
|
+
/* @__PURE__ */ jsx("span", { style: { color: STYLES.text }, children: issue.message }),
|
|
893
|
+
issue.ruleId && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
894
|
+
" ",
|
|
895
|
+
/* @__PURE__ */ jsxs(
|
|
896
|
+
"a",
|
|
897
|
+
{
|
|
898
|
+
href: ruleUrl || "#",
|
|
899
|
+
target: "_blank",
|
|
900
|
+
rel: "noopener noreferrer",
|
|
901
|
+
style: {
|
|
902
|
+
color: STYLES.textDim,
|
|
903
|
+
textDecoration: "none",
|
|
904
|
+
fontFamily: STYLES.fontMono,
|
|
905
|
+
fontSize: "10px",
|
|
906
|
+
transition: "color 0.15s"
|
|
907
|
+
},
|
|
908
|
+
onMouseEnter: (e) => {
|
|
909
|
+
e.currentTarget.style.color = STYLES.accent;
|
|
910
|
+
},
|
|
911
|
+
onMouseLeave: (e) => {
|
|
912
|
+
e.currentTarget.style.color = STYLES.textDim;
|
|
913
|
+
},
|
|
914
|
+
children: [
|
|
915
|
+
"(",
|
|
916
|
+
issue.ruleId,
|
|
917
|
+
")"
|
|
918
|
+
]
|
|
919
|
+
}
|
|
920
|
+
)
|
|
921
|
+
] })
|
|
922
|
+
] })
|
|
923
|
+
]
|
|
924
|
+
}
|
|
925
|
+
);
|
|
926
|
+
}
|
|
927
|
+
function CheckIcon() {
|
|
928
|
+
return /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx(
|
|
929
|
+
"path",
|
|
930
|
+
{
|
|
931
|
+
d: "M20 6L9 17l-5-5",
|
|
932
|
+
stroke: "currentColor",
|
|
933
|
+
strokeWidth: "2",
|
|
934
|
+
strokeLinecap: "round",
|
|
935
|
+
strokeLinejoin: "round"
|
|
936
|
+
}
|
|
937
|
+
) });
|
|
938
|
+
}
|
|
939
|
+
function ExternalLinkIcon() {
|
|
940
|
+
return /* @__PURE__ */ jsx("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx(
|
|
941
|
+
"path",
|
|
942
|
+
{
|
|
943
|
+
d: "M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6M15 3h6v6M10 14L21 3",
|
|
944
|
+
stroke: "currentColor",
|
|
945
|
+
strokeWidth: "2",
|
|
946
|
+
strokeLinecap: "round",
|
|
947
|
+
strokeLinejoin: "round"
|
|
948
|
+
}
|
|
949
|
+
) });
|
|
950
|
+
}
|
|
951
|
+
function CloseIcon() {
|
|
952
|
+
return /* @__PURE__ */ jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx(
|
|
953
|
+
"path",
|
|
954
|
+
{
|
|
955
|
+
d: "M18 6L6 18M6 6l12 12",
|
|
956
|
+
stroke: "currentColor",
|
|
957
|
+
strokeWidth: "2",
|
|
958
|
+
strokeLinecap: "round",
|
|
959
|
+
strokeLinejoin: "round"
|
|
960
|
+
}
|
|
961
|
+
) });
|
|
962
|
+
}
|
|
963
|
+
function ErrorSquiggleIcon() {
|
|
964
|
+
return /* @__PURE__ */ jsx(
|
|
965
|
+
"svg",
|
|
966
|
+
{
|
|
967
|
+
width: "14",
|
|
968
|
+
height: "14",
|
|
969
|
+
viewBox: "0 0 24 24",
|
|
970
|
+
fill: "none",
|
|
971
|
+
style: { flexShrink: 0, marginTop: "1px" },
|
|
972
|
+
children: /* @__PURE__ */ jsx(
|
|
973
|
+
"path",
|
|
974
|
+
{
|
|
975
|
+
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",
|
|
976
|
+
stroke: STYLES.error,
|
|
977
|
+
strokeWidth: "2",
|
|
978
|
+
strokeLinecap: "round",
|
|
979
|
+
strokeLinejoin: "round"
|
|
980
|
+
}
|
|
981
|
+
)
|
|
982
|
+
}
|
|
983
|
+
);
|
|
984
|
+
}
|
|
985
|
+
function ExpandIcon() {
|
|
986
|
+
return /* @__PURE__ */ jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx(
|
|
987
|
+
"path",
|
|
988
|
+
{
|
|
989
|
+
d: "M8 3H5a2 2 0 00-2 2v3m18 0V5a2 2 0 00-2-2h-3m0 18h3a2 2 0 002-2v-3M3 16v3a2 2 0 002 2h3",
|
|
990
|
+
stroke: "currentColor",
|
|
991
|
+
strokeWidth: "2",
|
|
992
|
+
strokeLinecap: "round",
|
|
993
|
+
strokeLinejoin: "round"
|
|
994
|
+
}
|
|
995
|
+
) });
|
|
996
|
+
}
|
|
997
|
+
function CollapseIcon() {
|
|
998
|
+
return /* @__PURE__ */ jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx(
|
|
999
|
+
"path",
|
|
1000
|
+
{
|
|
1001
|
+
d: "M4 14h6m0 0v6m0-6l-7 7m17-11h-6m0 0V4m0 6l7-7",
|
|
1002
|
+
stroke: "currentColor",
|
|
1003
|
+
strokeWidth: "2",
|
|
1004
|
+
strokeLinecap: "round",
|
|
1005
|
+
strokeLinejoin: "round"
|
|
1006
|
+
}
|
|
1007
|
+
) });
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
export {
|
|
1011
|
+
fetchSource,
|
|
1012
|
+
fetchSourceWithContext,
|
|
1013
|
+
clearSourceCache,
|
|
1014
|
+
getCachedSource,
|
|
1015
|
+
prefetchSources,
|
|
1016
|
+
InspectionPanel
|
|
1017
|
+
};
|