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
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import {
|
|
3
|
+
BADGE_COLORS,
|
|
4
|
+
Badge
|
|
5
|
+
} from "./chunk-W42PI2OF.js";
|
|
2
6
|
import {
|
|
3
7
|
groupBySourceFile,
|
|
4
8
|
useUILintContext,
|
|
5
9
|
useUILintStore
|
|
6
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-HECINZHM.js";
|
|
7
11
|
|
|
8
12
|
// src/components/ui-lint/UILintToolbar.tsx
|
|
9
13
|
import { useState as useState2, useRef as useRef2, useEffect as useEffect2, useCallback as useCallback2 } from "react";
|
|
@@ -55,10 +59,6 @@ var STYLES = {
|
|
|
55
59
|
transition: "all 0.15s ease-out",
|
|
56
60
|
transitionFast: "all 0.1s ease-out"
|
|
57
61
|
};
|
|
58
|
-
function getStatusColor(issueCount) {
|
|
59
|
-
if (issueCount === 0) return STYLES.success;
|
|
60
|
-
return STYLES.warning;
|
|
61
|
-
}
|
|
62
62
|
|
|
63
63
|
// src/components/ui-lint/SettingsPopover.tsx
|
|
64
64
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -235,9 +235,6 @@ import { useState, useCallback, useMemo } from "react";
|
|
|
235
235
|
|
|
236
236
|
// src/components/ui-lint/toolbar-icons.tsx
|
|
237
237
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
238
|
-
function StopIcon() {
|
|
239
|
-
return /* @__PURE__ */ jsx2("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx2("rect", { x: "6", y: "6", width: "12", height: "12", rx: "1", fill: "currentColor" }) });
|
|
240
|
-
}
|
|
241
238
|
function ChevronIcon() {
|
|
242
239
|
return /* @__PURE__ */ jsx2("svg", { width: "10", height: "10", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx2(
|
|
243
240
|
"path",
|
|
@@ -252,7 +249,7 @@ function ChevronIcon() {
|
|
|
252
249
|
}
|
|
253
250
|
|
|
254
251
|
// src/components/ui-lint/ScanResultsPopover.tsx
|
|
255
|
-
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
252
|
+
import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
256
253
|
function getDisambiguatedName(path, allPaths) {
|
|
257
254
|
const parts = path.split("/");
|
|
258
255
|
const fileName = parts[parts.length - 1] || path;
|
|
@@ -268,11 +265,12 @@ function getDisambiguatedName(path, allPaths) {
|
|
|
268
265
|
}
|
|
269
266
|
return fileName;
|
|
270
267
|
}
|
|
271
|
-
function ScanResultsPopover() {
|
|
272
|
-
const { autoScanState, liveScanEnabled
|
|
268
|
+
function ScanResultsPopover({ onClose }) {
|
|
269
|
+
const { autoScanState, liveScanEnabled } = useUILintContext();
|
|
273
270
|
const elementIssuesCache = useUILintStore(
|
|
274
271
|
(s) => s.elementIssuesCache
|
|
275
272
|
);
|
|
273
|
+
const fileIssuesCache = useUILintStore((s) => s.fileIssuesCache);
|
|
276
274
|
const setLocatorTarget = useUILintStore(
|
|
277
275
|
(s) => s.setLocatorTarget
|
|
278
276
|
);
|
|
@@ -286,6 +284,7 @@ function ScanResultsPopover() {
|
|
|
286
284
|
const allFilesWithIssues = useMemo(() => {
|
|
287
285
|
const sourceFiles = groupBySourceFile(autoScanState.elements);
|
|
288
286
|
const allPaths = sourceFiles.map((sf) => sf.path);
|
|
287
|
+
const filePathsSet = new Set(sourceFiles.map((sf) => sf.path));
|
|
289
288
|
const result = [];
|
|
290
289
|
for (const sf of sourceFiles) {
|
|
291
290
|
const elementsWithIssues = [];
|
|
@@ -301,26 +300,44 @@ function ScanResultsPopover() {
|
|
|
301
300
|
elementsWithIssues.push({ element: el, issueCount, ruleIds });
|
|
302
301
|
}
|
|
303
302
|
}
|
|
304
|
-
|
|
303
|
+
const fileLevelIssues = fileIssuesCache.get(sf.path) || [];
|
|
304
|
+
const elementIssueCount = elementsWithIssues.reduce(
|
|
305
|
+
(sum, e) => sum + e.issueCount,
|
|
306
|
+
0
|
|
307
|
+
);
|
|
308
|
+
const totalIssues2 = elementIssueCount + fileLevelIssues.length;
|
|
309
|
+
if (totalIssues2 > 0) {
|
|
305
310
|
elementsWithIssues.sort(
|
|
306
311
|
(a, b) => a.element.source.lineNumber - b.element.source.lineNumber
|
|
307
312
|
);
|
|
308
|
-
const totalIssues2 = elementsWithIssues.reduce(
|
|
309
|
-
(sum, e) => sum + e.issueCount,
|
|
310
|
-
0
|
|
311
|
-
);
|
|
312
313
|
result.push({
|
|
313
314
|
path: sf.path,
|
|
314
315
|
displayName: sf.displayName,
|
|
315
316
|
disambiguatedName: getDisambiguatedName(sf.path, allPaths),
|
|
316
317
|
issueCount: totalIssues2,
|
|
317
|
-
elementsWithIssues
|
|
318
|
+
elementsWithIssues,
|
|
319
|
+
fileLevelIssues
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
for (const [filePath, fileLevelIssues] of fileIssuesCache.entries()) {
|
|
324
|
+
if (!filePathsSet.has(filePath) && fileLevelIssues.length > 0) {
|
|
325
|
+
const parts = filePath.split("/");
|
|
326
|
+
const displayName = parts[parts.length - 1] || filePath;
|
|
327
|
+
const allPaths2 = Array.from(filePathsSet).concat([filePath]);
|
|
328
|
+
result.push({
|
|
329
|
+
path: filePath,
|
|
330
|
+
displayName,
|
|
331
|
+
disambiguatedName: getDisambiguatedName(filePath, allPaths2),
|
|
332
|
+
issueCount: fileLevelIssues.length,
|
|
333
|
+
elementsWithIssues: [],
|
|
334
|
+
fileLevelIssues
|
|
318
335
|
});
|
|
319
336
|
}
|
|
320
337
|
}
|
|
321
338
|
result.sort((a, b) => b.issueCount - a.issueCount);
|
|
322
339
|
return result;
|
|
323
|
-
}, [autoScanState.elements, elementIssuesCache]);
|
|
340
|
+
}, [autoScanState.elements, elementIssuesCache, fileIssuesCache]);
|
|
324
341
|
const filesWithIssues = useMemo(() => {
|
|
325
342
|
if (!searchQuery.trim()) {
|
|
326
343
|
return allFilesWithIssues;
|
|
@@ -403,15 +420,32 @@ function ScanResultsPopover() {
|
|
|
403
420
|
},
|
|
404
421
|
[setInspectedElement, setLocatorTarget]
|
|
405
422
|
);
|
|
423
|
+
const handleFileLevelIssueClick = useCallback(
|
|
424
|
+
(filePath, issue) => {
|
|
425
|
+
const dummyElement = document.createElement("div");
|
|
426
|
+
dummyElement.style.position = "fixed";
|
|
427
|
+
dummyElement.style.top = "-9999px";
|
|
428
|
+
dummyElement.style.left = "-9999px";
|
|
429
|
+
document.body.appendChild(dummyElement);
|
|
430
|
+
const source = {
|
|
431
|
+
fileName: filePath,
|
|
432
|
+
lineNumber: issue.line,
|
|
433
|
+
columnNumber: issue.column
|
|
434
|
+
};
|
|
435
|
+
setInspectedElement({
|
|
436
|
+
element: dummyElement,
|
|
437
|
+
source,
|
|
438
|
+
rect: new DOMRect(0, 0, 0, 0)
|
|
439
|
+
});
|
|
440
|
+
},
|
|
441
|
+
[setInspectedElement]
|
|
442
|
+
);
|
|
406
443
|
return /* @__PURE__ */ jsxs3(
|
|
407
444
|
"div",
|
|
408
445
|
{
|
|
409
446
|
"data-ui-lint": true,
|
|
410
447
|
style: {
|
|
411
|
-
position: "
|
|
412
|
-
bottom: "100%",
|
|
413
|
-
left: 0,
|
|
414
|
-
marginBottom: "8px",
|
|
448
|
+
position: "relative",
|
|
415
449
|
width: "320px",
|
|
416
450
|
maxHeight: "450px",
|
|
417
451
|
borderRadius: STYLES.popoverRadius,
|
|
@@ -454,25 +488,33 @@ function ScanResultsPopover() {
|
|
|
454
488
|
children: allFilesWithIssues.length === 0 ? "No issues found" : searchQuery ? `${filesWithIssues.length} of ${allFilesWithIssues.length} files` : `${filesWithIssues.length} ${filesWithIssues.length === 1 ? "file" : "files"} with ${totalAllIssues} ${totalAllIssues === 1 ? "issue" : "issues"}`
|
|
455
489
|
}
|
|
456
490
|
),
|
|
457
|
-
|
|
491
|
+
/* @__PURE__ */ jsx3(
|
|
458
492
|
"button",
|
|
459
493
|
{
|
|
460
|
-
onClick:
|
|
494
|
+
onClick: onClose,
|
|
461
495
|
style: {
|
|
462
496
|
display: "flex",
|
|
463
497
|
alignItems: "center",
|
|
464
498
|
justifyContent: "center",
|
|
465
|
-
width: "
|
|
466
|
-
height: "
|
|
499
|
+
width: "26px",
|
|
500
|
+
height: "26px",
|
|
467
501
|
borderRadius: "6px",
|
|
468
|
-
border:
|
|
502
|
+
border: "none",
|
|
469
503
|
backgroundColor: "transparent",
|
|
470
504
|
color: STYLES.textMuted,
|
|
471
505
|
cursor: "pointer",
|
|
472
|
-
transition:
|
|
506
|
+
transition: "all 0.15s"
|
|
507
|
+
},
|
|
508
|
+
onMouseEnter: (e) => {
|
|
509
|
+
e.currentTarget.style.backgroundColor = "rgba(55, 65, 81, 0.5)";
|
|
510
|
+
e.currentTarget.style.color = STYLES.text;
|
|
511
|
+
},
|
|
512
|
+
onMouseLeave: (e) => {
|
|
513
|
+
e.currentTarget.style.backgroundColor = "transparent";
|
|
514
|
+
e.currentTarget.style.color = STYLES.textMuted;
|
|
473
515
|
},
|
|
474
|
-
title: "
|
|
475
|
-
children: /* @__PURE__ */ jsx3(
|
|
516
|
+
title: "Close",
|
|
517
|
+
children: /* @__PURE__ */ jsx3(CloseIcon, {})
|
|
476
518
|
}
|
|
477
519
|
)
|
|
478
520
|
]
|
|
@@ -612,7 +654,8 @@ function ScanResultsPopover() {
|
|
|
612
654
|
isExpanded: expandedFiles.has(file.path),
|
|
613
655
|
onToggle: () => toggleFile(file.path),
|
|
614
656
|
onElementHover: handleElementHover,
|
|
615
|
-
onElementClick: handleElementClick
|
|
657
|
+
onElementClick: handleElementClick,
|
|
658
|
+
onFileLevelIssueClick: handleFileLevelIssueClick
|
|
616
659
|
},
|
|
617
660
|
file.path
|
|
618
661
|
))
|
|
@@ -627,7 +670,8 @@ function FileRow({
|
|
|
627
670
|
isExpanded,
|
|
628
671
|
onToggle,
|
|
629
672
|
onElementHover,
|
|
630
|
-
onElementClick
|
|
673
|
+
onElementClick,
|
|
674
|
+
onFileLevelIssueClick
|
|
631
675
|
}) {
|
|
632
676
|
return /* @__PURE__ */ jsxs3("div", { children: [
|
|
633
677
|
/* @__PURE__ */ jsxs3(
|
|
@@ -685,29 +729,11 @@ function FileRow({
|
|
|
685
729
|
children: file.disambiguatedName
|
|
686
730
|
}
|
|
687
731
|
),
|
|
688
|
-
/* @__PURE__ */ jsx3(
|
|
689
|
-
"span",
|
|
690
|
-
{
|
|
691
|
-
style: {
|
|
692
|
-
display: "inline-flex",
|
|
693
|
-
alignItems: "center",
|
|
694
|
-
justifyContent: "center",
|
|
695
|
-
minWidth: "22px",
|
|
696
|
-
height: "18px",
|
|
697
|
-
padding: "0 6px",
|
|
698
|
-
borderRadius: "9px",
|
|
699
|
-
backgroundColor: getStatusColor(file.issueCount),
|
|
700
|
-
color: "#FFFFFF",
|
|
701
|
-
fontSize: "10px",
|
|
702
|
-
fontWeight: 700
|
|
703
|
-
},
|
|
704
|
-
children: file.issueCount
|
|
705
|
-
}
|
|
706
|
-
)
|
|
732
|
+
/* @__PURE__ */ jsx3(Badge, { count: file.issueCount, size: "medium" })
|
|
707
733
|
]
|
|
708
734
|
}
|
|
709
735
|
),
|
|
710
|
-
isExpanded && /* @__PURE__ */
|
|
736
|
+
isExpanded && /* @__PURE__ */ jsxs3(
|
|
711
737
|
"div",
|
|
712
738
|
{
|
|
713
739
|
style: {
|
|
@@ -715,15 +741,52 @@ function FileRow({
|
|
|
715
741
|
borderTop: `1px solid ${STYLES.border}`,
|
|
716
742
|
borderBottom: `1px solid ${STYLES.border}`
|
|
717
743
|
},
|
|
718
|
-
children:
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
744
|
+
children: [
|
|
745
|
+
file.fileLevelIssues.length > 0 && /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
746
|
+
/* @__PURE__ */ jsx3(
|
|
747
|
+
"div",
|
|
748
|
+
{
|
|
749
|
+
style: {
|
|
750
|
+
padding: "6px 12px 4px 34px",
|
|
751
|
+
fontSize: "10px",
|
|
752
|
+
fontWeight: 600,
|
|
753
|
+
color: STYLES.textMuted,
|
|
754
|
+
textTransform: "uppercase",
|
|
755
|
+
letterSpacing: "0.5px"
|
|
756
|
+
},
|
|
757
|
+
children: "File-level issues"
|
|
758
|
+
}
|
|
759
|
+
),
|
|
760
|
+
file.fileLevelIssues.map((issue, index) => /* @__PURE__ */ jsx3(
|
|
761
|
+
FileLevelIssueRow,
|
|
762
|
+
{
|
|
763
|
+
filePath: file.path,
|
|
764
|
+
issue,
|
|
765
|
+
onClick: () => onFileLevelIssueClick(file.path, issue)
|
|
766
|
+
},
|
|
767
|
+
`${issue.line}-${issue.column}-${index}`
|
|
768
|
+
)),
|
|
769
|
+
file.elementsWithIssues.length > 0 && /* @__PURE__ */ jsx3(
|
|
770
|
+
"div",
|
|
771
|
+
{
|
|
772
|
+
style: {
|
|
773
|
+
height: "1px",
|
|
774
|
+
backgroundColor: STYLES.border,
|
|
775
|
+
margin: "4px 12px"
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
)
|
|
779
|
+
] }),
|
|
780
|
+
file.elementsWithIssues.map((item) => /* @__PURE__ */ jsx3(
|
|
781
|
+
ElementRow,
|
|
782
|
+
{
|
|
783
|
+
item,
|
|
784
|
+
onHover: onElementHover,
|
|
785
|
+
onClick: onElementClick
|
|
786
|
+
},
|
|
787
|
+
item.element.id
|
|
788
|
+
))
|
|
789
|
+
]
|
|
727
790
|
}
|
|
728
791
|
)
|
|
729
792
|
] });
|
|
@@ -792,25 +855,76 @@ function ElementRow({ item, onHover, onClick }) {
|
|
|
792
855
|
]
|
|
793
856
|
}
|
|
794
857
|
),
|
|
795
|
-
/* @__PURE__ */ jsx3(
|
|
796
|
-
|
|
858
|
+
/* @__PURE__ */ jsx3(Badge, { count: issueCount, size: "small" })
|
|
859
|
+
]
|
|
860
|
+
}
|
|
861
|
+
);
|
|
862
|
+
}
|
|
863
|
+
function FileLevelIssueRow({
|
|
864
|
+
filePath,
|
|
865
|
+
issue,
|
|
866
|
+
onClick
|
|
867
|
+
}) {
|
|
868
|
+
const fileName = filePath.split("/").pop() || filePath;
|
|
869
|
+
return /* @__PURE__ */ jsxs3(
|
|
870
|
+
"div",
|
|
871
|
+
{
|
|
872
|
+
style: {
|
|
873
|
+
display: "flex",
|
|
874
|
+
alignItems: "center",
|
|
875
|
+
padding: "6px 12px 6px 34px",
|
|
876
|
+
cursor: "pointer",
|
|
877
|
+
transition: STYLES.transitionFast,
|
|
878
|
+
backgroundColor: "transparent"
|
|
879
|
+
},
|
|
880
|
+
onMouseEnter: (e) => {
|
|
881
|
+
e.currentTarget.style.backgroundColor = "rgba(59, 130, 246, 0.15)";
|
|
882
|
+
},
|
|
883
|
+
onMouseLeave: (e) => {
|
|
884
|
+
e.currentTarget.style.backgroundColor = "transparent";
|
|
885
|
+
},
|
|
886
|
+
onClick,
|
|
887
|
+
children: [
|
|
888
|
+
/* @__PURE__ */ jsxs3(
|
|
889
|
+
"div",
|
|
797
890
|
{
|
|
798
891
|
style: {
|
|
799
|
-
display: "
|
|
892
|
+
display: "flex",
|
|
800
893
|
alignItems: "center",
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
padding: "0 5px",
|
|
805
|
-
borderRadius: "8px",
|
|
806
|
-
backgroundColor: getStatusColor(issueCount),
|
|
807
|
-
color: "#FFFFFF",
|
|
808
|
-
fontSize: "9px",
|
|
809
|
-
fontWeight: 700
|
|
894
|
+
gap: "4px",
|
|
895
|
+
flex: 1,
|
|
896
|
+
marginRight: "12px"
|
|
810
897
|
},
|
|
811
|
-
children:
|
|
898
|
+
children: [
|
|
899
|
+
/* @__PURE__ */ jsx3(
|
|
900
|
+
"span",
|
|
901
|
+
{
|
|
902
|
+
style: {
|
|
903
|
+
fontSize: "11px",
|
|
904
|
+
fontFamily: STYLES.fontMono,
|
|
905
|
+
color: STYLES.textMuted
|
|
906
|
+
},
|
|
907
|
+
children: fileName
|
|
908
|
+
}
|
|
909
|
+
),
|
|
910
|
+
/* @__PURE__ */ jsxs3(
|
|
911
|
+
"span",
|
|
912
|
+
{
|
|
913
|
+
style: {
|
|
914
|
+
fontSize: "10px",
|
|
915
|
+
color: STYLES.textDim
|
|
916
|
+
},
|
|
917
|
+
children: [
|
|
918
|
+
":",
|
|
919
|
+
issue.line,
|
|
920
|
+
issue.column ? `:${issue.column}` : ""
|
|
921
|
+
]
|
|
922
|
+
}
|
|
923
|
+
)
|
|
924
|
+
]
|
|
812
925
|
}
|
|
813
|
-
)
|
|
926
|
+
),
|
|
927
|
+
/* @__PURE__ */ jsx3(Badge, { count: 1, size: "small" })
|
|
814
928
|
]
|
|
815
929
|
}
|
|
816
930
|
);
|
|
@@ -861,6 +975,18 @@ function ClearIcon() {
|
|
|
861
975
|
}
|
|
862
976
|
) });
|
|
863
977
|
}
|
|
978
|
+
function CloseIcon() {
|
|
979
|
+
return /* @__PURE__ */ jsx3("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx3(
|
|
980
|
+
"path",
|
|
981
|
+
{
|
|
982
|
+
d: "M18 6L6 18M6 6l12 12",
|
|
983
|
+
stroke: "currentColor",
|
|
984
|
+
strokeWidth: "2",
|
|
985
|
+
strokeLinecap: "round",
|
|
986
|
+
strokeLinejoin: "round"
|
|
987
|
+
}
|
|
988
|
+
) });
|
|
989
|
+
}
|
|
864
990
|
|
|
865
991
|
// src/components/ui-lint/ScanPanelStack.tsx
|
|
866
992
|
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
@@ -896,7 +1022,19 @@ function ScanPanelStack({ show, onClose }) {
|
|
|
896
1022
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
897
1023
|
}, [show, onClose]);
|
|
898
1024
|
if (!show) return null;
|
|
899
|
-
return /* @__PURE__ */ jsx4(
|
|
1025
|
+
return /* @__PURE__ */ jsx4(
|
|
1026
|
+
"div",
|
|
1027
|
+
{
|
|
1028
|
+
ref: containerRef,
|
|
1029
|
+
style: {
|
|
1030
|
+
position: "absolute",
|
|
1031
|
+
bottom: "100%",
|
|
1032
|
+
left: 0,
|
|
1033
|
+
marginBottom: "8px"
|
|
1034
|
+
},
|
|
1035
|
+
children: /* @__PURE__ */ jsx4(ScanResultsPopover, { onClose })
|
|
1036
|
+
}
|
|
1037
|
+
);
|
|
900
1038
|
}
|
|
901
1039
|
|
|
902
1040
|
// src/components/ui-lint/UILintToolbar.tsx
|
|
@@ -915,10 +1053,10 @@ var TOKENS = {
|
|
|
915
1053
|
textDisabled: "rgba(255, 255, 255, 0.25)",
|
|
916
1054
|
accent: "#63b3ed",
|
|
917
1055
|
// Calm blue
|
|
918
|
-
success:
|
|
919
|
-
// Soft green
|
|
920
|
-
warning:
|
|
921
|
-
// Warm orange
|
|
1056
|
+
success: BADGE_COLORS.success,
|
|
1057
|
+
// Soft green (shared with Badge)
|
|
1058
|
+
warning: BADGE_COLORS.warning,
|
|
1059
|
+
// Warm orange (shared with Badge)
|
|
922
1060
|
// Typography
|
|
923
1061
|
fontFamily: `-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif`,
|
|
924
1062
|
fontMono: `"SF Mono", Monaco, "Cascadia Code", monospace`,
|
|
@@ -1146,20 +1284,6 @@ var globalStyles = `
|
|
|
1146
1284
|
transform: translateY(0);
|
|
1147
1285
|
}
|
|
1148
1286
|
|
|
1149
|
-
.uilint-badge {
|
|
1150
|
-
display: inline-flex;
|
|
1151
|
-
align-items: center;
|
|
1152
|
-
justify-content: center;
|
|
1153
|
-
min-width: 20px;
|
|
1154
|
-
height: 20px;
|
|
1155
|
-
padding: 0 6px;
|
|
1156
|
-
border-radius: 10px;
|
|
1157
|
-
font-size: 11px;
|
|
1158
|
-
font-weight: 600;
|
|
1159
|
-
font-family: ${TOKENS.fontMono};
|
|
1160
|
-
letter-spacing: -0.02em;
|
|
1161
|
-
}
|
|
1162
|
-
|
|
1163
1287
|
.uilint-scanning-indicator {
|
|
1164
1288
|
position: relative;
|
|
1165
1289
|
overflow: hidden;
|
|
@@ -1341,17 +1465,7 @@ function ScanStatus({ status, issueCount, enabled }) {
|
|
|
1341
1465
|
children: /* @__PURE__ */ jsx5(Icons.AlertTriangle, {})
|
|
1342
1466
|
}
|
|
1343
1467
|
),
|
|
1344
|
-
/* @__PURE__ */ jsx5(
|
|
1345
|
-
"span",
|
|
1346
|
-
{
|
|
1347
|
-
className: "uilint-badge",
|
|
1348
|
-
style: {
|
|
1349
|
-
backgroundColor: `${TOKENS.warning}20`,
|
|
1350
|
-
color: TOKENS.warning
|
|
1351
|
-
},
|
|
1352
|
-
children: issueCount
|
|
1353
|
-
}
|
|
1354
|
-
)
|
|
1468
|
+
/* @__PURE__ */ jsx5(Badge, { count: issueCount })
|
|
1355
1469
|
]
|
|
1356
1470
|
}
|
|
1357
1471
|
);
|
|
@@ -1367,6 +1481,7 @@ function UILintToolbar() {
|
|
|
1367
1481
|
const elementIssuesCache = useUILintStore(
|
|
1368
1482
|
(s) => s.elementIssuesCache
|
|
1369
1483
|
);
|
|
1484
|
+
const fileIssuesCache = useUILintStore((s) => s.fileIssuesCache);
|
|
1370
1485
|
const [showSettings, setShowSettings] = useState2(false);
|
|
1371
1486
|
const [showResults, setShowResults] = useState2(false);
|
|
1372
1487
|
const [mounted, setMounted] = useState2(false);
|
|
@@ -1403,10 +1518,15 @@ function UILintToolbar() {
|
|
|
1403
1518
|
}, []);
|
|
1404
1519
|
const isScanning = autoScanState.status === "scanning";
|
|
1405
1520
|
const isComplete = autoScanState.status === "complete";
|
|
1406
|
-
let
|
|
1521
|
+
let elementIssues = 0;
|
|
1407
1522
|
elementIssuesCache.forEach((el) => {
|
|
1408
|
-
|
|
1523
|
+
elementIssues += el.issues.length;
|
|
1524
|
+
});
|
|
1525
|
+
let fileLevelIssues = 0;
|
|
1526
|
+
fileIssuesCache.forEach((issues) => {
|
|
1527
|
+
fileLevelIssues += issues.length;
|
|
1409
1528
|
});
|
|
1529
|
+
const totalIssues = elementIssues + fileLevelIssues;
|
|
1410
1530
|
const hasIssues = totalIssues > 0;
|
|
1411
1531
|
useEffect2(() => {
|
|
1412
1532
|
setMounted(true);
|
|
@@ -1433,11 +1553,6 @@ function UILintToolbar() {
|
|
|
1433
1553
|
document.removeEventListener("keydown", handleEscape);
|
|
1434
1554
|
};
|
|
1435
1555
|
}, [showSettings, showResults]);
|
|
1436
|
-
useEffect2(() => {
|
|
1437
|
-
if (hasIssues && liveScanEnabled && isComplete && !showSettings) {
|
|
1438
|
-
setShowResults(true);
|
|
1439
|
-
}
|
|
1440
|
-
}, [hasIssues, liveScanEnabled, isComplete, showSettings]);
|
|
1441
1556
|
const handleToggleClick = useCallback2(() => {
|
|
1442
1557
|
if (liveScanEnabled) {
|
|
1443
1558
|
disableLiveScan();
|
|
@@ -1486,7 +1601,7 @@ function UILintToolbar() {
|
|
|
1486
1601
|
},
|
|
1487
1602
|
children: [
|
|
1488
1603
|
/* @__PURE__ */ jsx5("style", { children: globalStyles }),
|
|
1489
|
-
/* @__PURE__ */
|
|
1604
|
+
/* @__PURE__ */ jsx5(
|
|
1490
1605
|
"div",
|
|
1491
1606
|
{
|
|
1492
1607
|
className: `uilint-hint ${liveScanEnabled ? "uilint-hint--visible" : ""}`,
|
|
@@ -1495,36 +1610,27 @@ function UILintToolbar() {
|
|
|
1495
1610
|
marginBottom: "10px",
|
|
1496
1611
|
fontSize: "11px",
|
|
1497
1612
|
color: TOKENS.textMuted,
|
|
1498
|
-
letterSpacing: "0.02em"
|
|
1499
|
-
// Subtle dark halo for readability on any background
|
|
1500
|
-
textShadow: `
|
|
1501
|
-
0 0 4px rgba(0, 0, 0, 0.8),
|
|
1502
|
-
0 0 8px rgba(0, 0, 0, 0.5),
|
|
1503
|
-
0 1px 2px rgba(0, 0, 0, 0.9)
|
|
1504
|
-
`
|
|
1613
|
+
letterSpacing: "0.02em"
|
|
1505
1614
|
},
|
|
1506
1615
|
"aria-hidden": !liveScanEnabled,
|
|
1507
|
-
children:
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
{
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
),
|
|
1526
|
-
/* @__PURE__ */ jsx5("span", { children: "+ Click to inspect element" })
|
|
1527
|
-
]
|
|
1616
|
+
children: /* @__PURE__ */ jsx5(
|
|
1617
|
+
"kbd",
|
|
1618
|
+
{
|
|
1619
|
+
style: {
|
|
1620
|
+
display: "inline-block",
|
|
1621
|
+
padding: "2px 5px",
|
|
1622
|
+
marginRight: "4px",
|
|
1623
|
+
borderRadius: "4px",
|
|
1624
|
+
backgroundColor: TOKENS.bgElevated,
|
|
1625
|
+
border: `1px solid ${TOKENS.border}`,
|
|
1626
|
+
fontSize: "10px",
|
|
1627
|
+
fontFamily: TOKENS.fontMono,
|
|
1628
|
+
color: TOKENS.textSecondary,
|
|
1629
|
+
boxShadow: `0 1px 3px rgba(0, 0, 0, 0.5)`
|
|
1630
|
+
},
|
|
1631
|
+
children: "\u2325 + Click to inspect element"
|
|
1632
|
+
}
|
|
1633
|
+
)
|
|
1528
1634
|
}
|
|
1529
1635
|
),
|
|
1530
1636
|
/* @__PURE__ */ jsxs4(
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/components/ui-lint/Badge.tsx
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
var BADGE_COLORS = {
|
|
6
|
+
success: "#68d391",
|
|
7
|
+
// Soft green
|
|
8
|
+
warning: "#f6ad55",
|
|
9
|
+
// Warm orange
|
|
10
|
+
error: "#ef4444"
|
|
11
|
+
// Red (for future use)
|
|
12
|
+
};
|
|
13
|
+
var FONT_MONO = `"SF Mono", Monaco, "Cascadia Code", monospace`;
|
|
14
|
+
function getBadgeTextColor(issueCount) {
|
|
15
|
+
if (issueCount === 0) return BADGE_COLORS.success;
|
|
16
|
+
return BADGE_COLORS.warning;
|
|
17
|
+
}
|
|
18
|
+
function getBadgeBackgroundColor(issueCount) {
|
|
19
|
+
const color = getBadgeTextColor(issueCount);
|
|
20
|
+
return `${color}20`;
|
|
21
|
+
}
|
|
22
|
+
var BADGE_STYLES = {
|
|
23
|
+
default: {
|
|
24
|
+
minWidth: "20px",
|
|
25
|
+
height: "20px",
|
|
26
|
+
padding: "0 6px",
|
|
27
|
+
borderRadius: "10px",
|
|
28
|
+
fontSize: "11px",
|
|
29
|
+
fontWeight: 600,
|
|
30
|
+
letterSpacing: "-0.02em"
|
|
31
|
+
},
|
|
32
|
+
small: {
|
|
33
|
+
minWidth: "18px",
|
|
34
|
+
height: "18px",
|
|
35
|
+
padding: "0 5px",
|
|
36
|
+
borderRadius: "9px",
|
|
37
|
+
fontSize: "10px",
|
|
38
|
+
fontWeight: 700,
|
|
39
|
+
letterSpacing: "0"
|
|
40
|
+
},
|
|
41
|
+
// For file row badges (slightly larger than small)
|
|
42
|
+
medium: {
|
|
43
|
+
minWidth: "22px",
|
|
44
|
+
height: "18px",
|
|
45
|
+
padding: "0 6px",
|
|
46
|
+
borderRadius: "9px",
|
|
47
|
+
fontSize: "10px",
|
|
48
|
+
fontWeight: 700,
|
|
49
|
+
letterSpacing: "0"
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
function Badge({
|
|
53
|
+
count,
|
|
54
|
+
size = "default",
|
|
55
|
+
backgroundColor,
|
|
56
|
+
color
|
|
57
|
+
}) {
|
|
58
|
+
const sizeStyles = BADGE_STYLES[size];
|
|
59
|
+
const bgColor = backgroundColor ?? getBadgeBackgroundColor(count);
|
|
60
|
+
const textColor = color ?? getBadgeTextColor(count);
|
|
61
|
+
return /* @__PURE__ */ jsx(
|
|
62
|
+
"span",
|
|
63
|
+
{
|
|
64
|
+
style: {
|
|
65
|
+
display: "inline-flex",
|
|
66
|
+
alignItems: "center",
|
|
67
|
+
justifyContent: "center",
|
|
68
|
+
...sizeStyles,
|
|
69
|
+
backgroundColor: bgColor,
|
|
70
|
+
color: textColor,
|
|
71
|
+
fontFamily: FONT_MONO
|
|
72
|
+
},
|
|
73
|
+
children: count
|
|
74
|
+
}
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export {
|
|
79
|
+
BADGE_COLORS,
|
|
80
|
+
Badge
|
|
81
|
+
};
|