uilint-react 0.1.45 → 0.1.47
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-RV7I6QXS.js → ElementBadges-N2N3CBLI.js} +73 -32
- package/dist/InspectionPanel-4P7I4QVY.js +10 -0
- package/dist/{LocatorOverlay-Z24VU27L.js → LocatorOverlay-L3EPYQEF.js} +2 -2
- package/dist/UILintToolbar-FWVC6MNG.js +10 -0
- package/dist/{chunk-YLTHKMTO.js → chunk-LNLTM7N6.js} +1 -1
- package/dist/{chunk-EQKEHJI4.js → chunk-OSYIUF52.js} +460 -387
- package/dist/{chunk-BJD2V2LF.js → chunk-RAPUZC5J.js} +4 -4
- package/dist/chunk-S4IWHBOQ.js +178 -0
- package/dist/{chunk-ZZOKTGSU.js → chunk-UF6KN2JJ.js} +18 -103
- package/dist/index.d.ts +5 -11
- package/dist/index.js +7 -6
- package/package.json +2 -2
- package/dist/InspectionPanel-QC6WR5IG.js +0 -10
- package/dist/UILintToolbar-5NK77IQJ.js +0 -10
- package/dist/chunk-W42PI2OF.js +0 -81
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import {
|
|
3
3
|
BADGE_COLORS,
|
|
4
|
-
Badge
|
|
5
|
-
|
|
4
|
+
Badge,
|
|
5
|
+
fetchSource,
|
|
6
|
+
getCachedSource
|
|
7
|
+
} from "./chunk-S4IWHBOQ.js";
|
|
6
8
|
import {
|
|
7
9
|
groupBySourceFile,
|
|
8
10
|
useUILintContext,
|
|
9
11
|
useUILintStore
|
|
10
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-RAPUZC5J.js";
|
|
11
13
|
|
|
12
14
|
// src/components/ui-lint/UILintToolbar.tsx
|
|
13
|
-
import { useState as useState2, useRef as useRef2, useEffect as
|
|
15
|
+
import React3, { useState as useState2, useRef as useRef2, useEffect as useEffect3, useCallback as useCallback2 } from "react";
|
|
14
16
|
import { createPortal } from "react-dom";
|
|
15
17
|
|
|
16
18
|
// src/components/ui-lint/toolbar-styles.ts
|
|
@@ -228,10 +230,10 @@ function SettingsPopover({ settings }) {
|
|
|
228
230
|
}
|
|
229
231
|
|
|
230
232
|
// src/components/ui-lint/ScanPanelStack.tsx
|
|
231
|
-
import { useRef, useEffect } from "react";
|
|
233
|
+
import { useRef, useEffect as useEffect2 } from "react";
|
|
232
234
|
|
|
233
235
|
// src/components/ui-lint/ScanResultsPopover.tsx
|
|
234
|
-
import { useState, useCallback, useMemo } from "react";
|
|
236
|
+
import { useState, useCallback, useMemo, useEffect } from "react";
|
|
235
237
|
|
|
236
238
|
// src/components/ui-lint/toolbar-icons.tsx
|
|
237
239
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
@@ -860,12 +862,65 @@ function ElementRow({ item, onHover, onClick }) {
|
|
|
860
862
|
}
|
|
861
863
|
);
|
|
862
864
|
}
|
|
865
|
+
function extractTagName(line, column) {
|
|
866
|
+
if (!line) return null;
|
|
867
|
+
if (column !== void 0) {
|
|
868
|
+
const searchStart = Math.max(0, column - 50);
|
|
869
|
+
const searchEnd = Math.min(line.length, column + 20);
|
|
870
|
+
const searchSlice = line.substring(searchStart, searchEnd);
|
|
871
|
+
const tagMatches = [
|
|
872
|
+
...searchSlice.matchAll(/<([a-zA-Z][a-zA-Z0-9.-]*|Fragment)\b/g)
|
|
873
|
+
];
|
|
874
|
+
for (const match of tagMatches) {
|
|
875
|
+
const tagStart = searchStart + match.index;
|
|
876
|
+
const tagEnd = tagStart + match[0].length;
|
|
877
|
+
if (column >= tagStart && column <= tagEnd + 30) {
|
|
878
|
+
return match[1];
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
const trimmed = line.trim();
|
|
883
|
+
const jsxTagMatch = trimmed.match(/^<([a-zA-Z][a-zA-Z0-9.-]*|Fragment)\b/);
|
|
884
|
+
if (jsxTagMatch) {
|
|
885
|
+
return jsxTagMatch[1];
|
|
886
|
+
}
|
|
887
|
+
return null;
|
|
888
|
+
}
|
|
863
889
|
function FileLevelIssueRow({
|
|
864
890
|
filePath,
|
|
865
891
|
issue,
|
|
866
892
|
onClick
|
|
867
893
|
}) {
|
|
868
894
|
const fileName = filePath.split("/").pop() || filePath;
|
|
895
|
+
const [tagName, setTagName] = useState(null);
|
|
896
|
+
useEffect(() => {
|
|
897
|
+
const cached = getCachedSource(filePath);
|
|
898
|
+
if (cached) {
|
|
899
|
+
const lines = cached.content.split("\n");
|
|
900
|
+
const lineIndex = issue.line - 1;
|
|
901
|
+
if (lineIndex >= 0 && lineIndex < lines.length) {
|
|
902
|
+
const line = lines[lineIndex];
|
|
903
|
+
const tag = extractTagName(line, issue.column);
|
|
904
|
+
if (tag) {
|
|
905
|
+
setTagName(tag);
|
|
906
|
+
return;
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
fetchSource(filePath).then((result) => {
|
|
911
|
+
if (result) {
|
|
912
|
+
const lines = result.content.split("\n");
|
|
913
|
+
const lineIndex = issue.line - 1;
|
|
914
|
+
if (lineIndex >= 0 && lineIndex < lines.length) {
|
|
915
|
+
const line = lines[lineIndex];
|
|
916
|
+
const tag = extractTagName(line, issue.column);
|
|
917
|
+
if (tag) {
|
|
918
|
+
setTagName(tag);
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
});
|
|
923
|
+
}, [filePath, issue.line, issue.column]);
|
|
869
924
|
return /* @__PURE__ */ jsxs3(
|
|
870
925
|
"div",
|
|
871
926
|
{
|
|
@@ -896,7 +951,22 @@ function FileLevelIssueRow({
|
|
|
896
951
|
marginRight: "12px"
|
|
897
952
|
},
|
|
898
953
|
children: [
|
|
899
|
-
/* @__PURE__ */
|
|
954
|
+
tagName && /* @__PURE__ */ jsxs3(
|
|
955
|
+
"span",
|
|
956
|
+
{
|
|
957
|
+
style: {
|
|
958
|
+
fontSize: "11px",
|
|
959
|
+
fontFamily: STYLES.fontMono,
|
|
960
|
+
color: STYLES.accent
|
|
961
|
+
},
|
|
962
|
+
children: [
|
|
963
|
+
"<",
|
|
964
|
+
tagName,
|
|
965
|
+
">"
|
|
966
|
+
]
|
|
967
|
+
}
|
|
968
|
+
),
|
|
969
|
+
!tagName && /* @__PURE__ */ jsx3(
|
|
900
970
|
"span",
|
|
901
971
|
{
|
|
902
972
|
style: {
|
|
@@ -992,26 +1062,26 @@ function CloseIcon() {
|
|
|
992
1062
|
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
993
1063
|
function ScanPanelStack({ show, onClose }) {
|
|
994
1064
|
const containerRef = useRef(null);
|
|
995
|
-
|
|
1065
|
+
useEffect2(() => {
|
|
996
1066
|
if (!show) return;
|
|
997
1067
|
const handleClickOutside = (e) => {
|
|
998
1068
|
const target = e.target;
|
|
1069
|
+
if (target?.closest?.("[data-ui-lint]")) {
|
|
1070
|
+
return;
|
|
1071
|
+
}
|
|
999
1072
|
if (containerRef.current && !containerRef.current.contains(target)) {
|
|
1000
|
-
|
|
1001
|
-
if (!isUILintElement) {
|
|
1002
|
-
onClose();
|
|
1003
|
-
}
|
|
1073
|
+
onClose();
|
|
1004
1074
|
}
|
|
1005
1075
|
};
|
|
1006
1076
|
const timeoutId = setTimeout(() => {
|
|
1007
|
-
document.addEventListener("mousedown", handleClickOutside);
|
|
1077
|
+
document.addEventListener("mousedown", handleClickOutside, true);
|
|
1008
1078
|
}, 100);
|
|
1009
1079
|
return () => {
|
|
1010
1080
|
clearTimeout(timeoutId);
|
|
1011
|
-
document.removeEventListener("mousedown", handleClickOutside);
|
|
1081
|
+
document.removeEventListener("mousedown", handleClickOutside, true);
|
|
1012
1082
|
};
|
|
1013
1083
|
}, [show, onClose]);
|
|
1014
|
-
|
|
1084
|
+
useEffect2(() => {
|
|
1015
1085
|
if (!show) return;
|
|
1016
1086
|
const handleKeyDown = (e) => {
|
|
1017
1087
|
if (e.key === "Escape") {
|
|
@@ -1021,16 +1091,25 @@ function ScanPanelStack({ show, onClose }) {
|
|
|
1021
1091
|
window.addEventListener("keydown", handleKeyDown);
|
|
1022
1092
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
1023
1093
|
}, [show, onClose]);
|
|
1094
|
+
const handleUILintInteraction = (e) => {
|
|
1095
|
+
e.stopPropagation();
|
|
1096
|
+
};
|
|
1024
1097
|
if (!show) return null;
|
|
1025
1098
|
return /* @__PURE__ */ jsx4(
|
|
1026
1099
|
"div",
|
|
1027
1100
|
{
|
|
1028
1101
|
ref: containerRef,
|
|
1102
|
+
"data-ui-lint": true,
|
|
1103
|
+
onMouseDown: handleUILintInteraction,
|
|
1104
|
+
onClick: handleUILintInteraction,
|
|
1105
|
+
onKeyDown: handleUILintInteraction,
|
|
1029
1106
|
style: {
|
|
1030
1107
|
position: "absolute",
|
|
1031
1108
|
bottom: "100%",
|
|
1032
1109
|
left: 0,
|
|
1033
|
-
marginBottom: "8px"
|
|
1110
|
+
marginBottom: "8px",
|
|
1111
|
+
pointerEvents: "auto"
|
|
1112
|
+
// Ensure panel is interactive
|
|
1034
1113
|
},
|
|
1035
1114
|
children: /* @__PURE__ */ jsx4(ScanResultsPopover, { onClose })
|
|
1036
1115
|
}
|
|
@@ -1038,10 +1117,10 @@ function ScanPanelStack({ show, onClose }) {
|
|
|
1038
1117
|
}
|
|
1039
1118
|
|
|
1040
1119
|
// src/components/ui-lint/UILintToolbar.tsx
|
|
1041
|
-
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1120
|
+
import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1042
1121
|
var TOKENS = {
|
|
1043
1122
|
// Colors
|
|
1044
|
-
bgBase: "rgba(15, 15, 15, 0.
|
|
1123
|
+
bgBase: "rgba(15, 15, 15, 0.92)",
|
|
1045
1124
|
bgElevated: "rgba(25, 25, 25, 0.95)",
|
|
1046
1125
|
bgHover: "rgba(255, 255, 255, 0.08)",
|
|
1047
1126
|
bgActive: "rgba(255, 255, 255, 0.12)",
|
|
@@ -1052,26 +1131,17 @@ var TOKENS = {
|
|
|
1052
1131
|
textMuted: "rgba(255, 255, 255, 0.4)",
|
|
1053
1132
|
textDisabled: "rgba(255, 255, 255, 0.25)",
|
|
1054
1133
|
accent: "#63b3ed",
|
|
1055
|
-
// Calm blue
|
|
1056
1134
|
success: BADGE_COLORS.success,
|
|
1057
|
-
// Soft green (shared with Badge)
|
|
1058
1135
|
warning: BADGE_COLORS.warning,
|
|
1059
|
-
|
|
1060
|
-
// Typography
|
|
1136
|
+
error: "#f56565",
|
|
1061
1137
|
fontFamily: `-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif`,
|
|
1062
1138
|
fontMono: `"SF Mono", Monaco, "Cascadia Code", monospace`,
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
buttonMinWidth: "44px",
|
|
1068
|
-
// Touch target minimum
|
|
1069
|
-
// Effects
|
|
1070
|
-
blur: "blur(20px)",
|
|
1071
|
-
shadowSm: "0 2px 8px rgba(0, 0, 0, 0.3)",
|
|
1139
|
+
pillHeight: "40px",
|
|
1140
|
+
pillRadius: "20px",
|
|
1141
|
+
buttonMinWidth: "40px",
|
|
1142
|
+
blur: "blur(16px)",
|
|
1072
1143
|
shadowMd: "0 4px 20px rgba(0, 0, 0, 0.4)",
|
|
1073
|
-
shadowGlow: (color) => `0 0
|
|
1074
|
-
// Animation
|
|
1144
|
+
shadowGlow: (color) => `0 0 16px ${color}`,
|
|
1075
1145
|
transitionFast: "150ms cubic-bezier(0.4, 0, 0.2, 1)",
|
|
1076
1146
|
transitionBase: "200ms cubic-bezier(0.4, 0, 0.2, 1)",
|
|
1077
1147
|
transitionSlow: "300ms cubic-bezier(0.4, 0, 0.2, 1)"
|
|
@@ -1080,8 +1150,8 @@ var Icons = {
|
|
|
1080
1150
|
Eye: () => /* @__PURE__ */ jsxs4(
|
|
1081
1151
|
"svg",
|
|
1082
1152
|
{
|
|
1083
|
-
width: "
|
|
1084
|
-
height: "
|
|
1153
|
+
width: "16",
|
|
1154
|
+
height: "16",
|
|
1085
1155
|
viewBox: "0 0 24 24",
|
|
1086
1156
|
fill: "none",
|
|
1087
1157
|
stroke: "currentColor",
|
|
@@ -1094,11 +1164,11 @@ var Icons = {
|
|
|
1094
1164
|
]
|
|
1095
1165
|
}
|
|
1096
1166
|
),
|
|
1097
|
-
|
|
1167
|
+
Settings: () => /* @__PURE__ */ jsxs4(
|
|
1098
1168
|
"svg",
|
|
1099
1169
|
{
|
|
1100
|
-
width: "
|
|
1101
|
-
height: "
|
|
1170
|
+
width: "15",
|
|
1171
|
+
height: "15",
|
|
1102
1172
|
viewBox: "0 0 24 24",
|
|
1103
1173
|
fill: "none",
|
|
1104
1174
|
stroke: "currentColor",
|
|
@@ -1106,16 +1176,30 @@ var Icons = {
|
|
|
1106
1176
|
strokeLinecap: "round",
|
|
1107
1177
|
strokeLinejoin: "round",
|
|
1108
1178
|
children: [
|
|
1109
|
-
/* @__PURE__ */ jsx5("
|
|
1110
|
-
/* @__PURE__ */ jsx5("
|
|
1179
|
+
/* @__PURE__ */ jsx5("circle", { cx: "12", cy: "12", r: "3" }),
|
|
1180
|
+
/* @__PURE__ */ jsx5("path", { d: "M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z" })
|
|
1111
1181
|
]
|
|
1112
1182
|
}
|
|
1113
1183
|
),
|
|
1114
|
-
|
|
1184
|
+
Check: () => /* @__PURE__ */ jsx5(
|
|
1115
1185
|
"svg",
|
|
1116
1186
|
{
|
|
1117
|
-
width: "
|
|
1118
|
-
height: "
|
|
1187
|
+
width: "12",
|
|
1188
|
+
height: "12",
|
|
1189
|
+
viewBox: "0 0 24 24",
|
|
1190
|
+
fill: "none",
|
|
1191
|
+
stroke: "currentColor",
|
|
1192
|
+
strokeWidth: "2.5",
|
|
1193
|
+
strokeLinecap: "round",
|
|
1194
|
+
strokeLinejoin: "round",
|
|
1195
|
+
children: /* @__PURE__ */ jsx5("polyline", { points: "20 6 9 17 4 12" })
|
|
1196
|
+
}
|
|
1197
|
+
),
|
|
1198
|
+
AlertTriangle: () => /* @__PURE__ */ jsxs4(
|
|
1199
|
+
"svg",
|
|
1200
|
+
{
|
|
1201
|
+
width: "12",
|
|
1202
|
+
height: "12",
|
|
1119
1203
|
viewBox: "0 0 24 24",
|
|
1120
1204
|
fill: "none",
|
|
1121
1205
|
stroke: "currentColor",
|
|
@@ -1123,29 +1207,27 @@ var Icons = {
|
|
|
1123
1207
|
strokeLinecap: "round",
|
|
1124
1208
|
strokeLinejoin: "round",
|
|
1125
1209
|
children: [
|
|
1126
|
-
/* @__PURE__ */ jsx5("path", { d: "
|
|
1127
|
-
/* @__PURE__ */ jsx5("
|
|
1128
|
-
/* @__PURE__ */ jsx5("
|
|
1129
|
-
/* @__PURE__ */ jsx5("path", { d: "M7 21H5a2 2 0 0 1-2-2v-2" }),
|
|
1130
|
-
/* @__PURE__ */ jsx5("line", { x1: "7", y1: "12", x2: "17", y2: "12" })
|
|
1210
|
+
/* @__PURE__ */ jsx5("path", { d: "M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" }),
|
|
1211
|
+
/* @__PURE__ */ jsx5("line", { x1: "12", y1: "9", x2: "12", y2: "13" }),
|
|
1212
|
+
/* @__PURE__ */ jsx5("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
|
|
1131
1213
|
]
|
|
1132
1214
|
}
|
|
1133
1215
|
),
|
|
1134
|
-
|
|
1216
|
+
ChevronDown: () => /* @__PURE__ */ jsx5(
|
|
1135
1217
|
"svg",
|
|
1136
1218
|
{
|
|
1137
|
-
width: "
|
|
1138
|
-
height: "
|
|
1219
|
+
width: "12",
|
|
1220
|
+
height: "12",
|
|
1139
1221
|
viewBox: "0 0 24 24",
|
|
1140
1222
|
fill: "none",
|
|
1141
1223
|
stroke: "currentColor",
|
|
1142
|
-
strokeWidth: "2
|
|
1224
|
+
strokeWidth: "2",
|
|
1143
1225
|
strokeLinecap: "round",
|
|
1144
1226
|
strokeLinejoin: "round",
|
|
1145
|
-
children: /* @__PURE__ */ jsx5("polyline", { points: "
|
|
1227
|
+
children: /* @__PURE__ */ jsx5("polyline", { points: "6 9 12 15 18 9" })
|
|
1146
1228
|
}
|
|
1147
1229
|
),
|
|
1148
|
-
|
|
1230
|
+
X: () => /* @__PURE__ */ jsxs4(
|
|
1149
1231
|
"svg",
|
|
1150
1232
|
{
|
|
1151
1233
|
width: "14",
|
|
@@ -1157,17 +1239,16 @@ var Icons = {
|
|
|
1157
1239
|
strokeLinecap: "round",
|
|
1158
1240
|
strokeLinejoin: "round",
|
|
1159
1241
|
children: [
|
|
1160
|
-
/* @__PURE__ */ jsx5("
|
|
1161
|
-
/* @__PURE__ */ jsx5("line", { x1: "
|
|
1162
|
-
/* @__PURE__ */ jsx5("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
|
|
1242
|
+
/* @__PURE__ */ jsx5("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
1243
|
+
/* @__PURE__ */ jsx5("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
1163
1244
|
]
|
|
1164
1245
|
}
|
|
1165
1246
|
),
|
|
1166
|
-
|
|
1247
|
+
Unplug: () => /* @__PURE__ */ jsxs4(
|
|
1167
1248
|
"svg",
|
|
1168
1249
|
{
|
|
1169
|
-
width: "
|
|
1170
|
-
height: "
|
|
1250
|
+
width: "14",
|
|
1251
|
+
height: "14",
|
|
1171
1252
|
viewBox: "0 0 24 24",
|
|
1172
1253
|
fill: "none",
|
|
1173
1254
|
stroke: "currentColor",
|
|
@@ -1175,12 +1256,15 @@ var Icons = {
|
|
|
1175
1256
|
strokeLinecap: "round",
|
|
1176
1257
|
strokeLinejoin: "round",
|
|
1177
1258
|
children: [
|
|
1178
|
-
/* @__PURE__ */ jsx5("
|
|
1179
|
-
/* @__PURE__ */ jsx5("path", { d: "
|
|
1259
|
+
/* @__PURE__ */ jsx5("path", { d: "M19 5l3-3" }),
|
|
1260
|
+
/* @__PURE__ */ jsx5("path", { d: "M2 22l3-3" }),
|
|
1261
|
+
/* @__PURE__ */ jsx5("path", { d: "M6.3 6.3a10 10 0 0 1 13.4 1.3" }),
|
|
1262
|
+
/* @__PURE__ */ jsx5("path", { d: "M17.7 17.7a10 10 0 0 1-13.4-1.3" }),
|
|
1263
|
+
/* @__PURE__ */ jsx5("path", { d: "m8 15 8-8" })
|
|
1180
1264
|
]
|
|
1181
1265
|
}
|
|
1182
1266
|
),
|
|
1183
|
-
|
|
1267
|
+
Scan: () => /* @__PURE__ */ jsxs4(
|
|
1184
1268
|
"svg",
|
|
1185
1269
|
{
|
|
1186
1270
|
width: "14",
|
|
@@ -1191,7 +1275,13 @@ var Icons = {
|
|
|
1191
1275
|
strokeWidth: "2",
|
|
1192
1276
|
strokeLinecap: "round",
|
|
1193
1277
|
strokeLinejoin: "round",
|
|
1194
|
-
children:
|
|
1278
|
+
children: [
|
|
1279
|
+
/* @__PURE__ */ jsx5("path", { d: "M3 7V5a2 2 0 0 1 2-2h2" }),
|
|
1280
|
+
/* @__PURE__ */ jsx5("path", { d: "M17 3h2a2 2 0 0 1 2 2v2" }),
|
|
1281
|
+
/* @__PURE__ */ jsx5("path", { d: "M21 17v2a2 2 0 0 1-2 2h-2" }),
|
|
1282
|
+
/* @__PURE__ */ jsx5("path", { d: "M7 21H5a2 2 0 0 1-2-2v-2" }),
|
|
1283
|
+
/* @__PURE__ */ jsx5("line", { x1: "7", y1: "12", x2: "17", y2: "12" })
|
|
1284
|
+
]
|
|
1195
1285
|
}
|
|
1196
1286
|
)
|
|
1197
1287
|
};
|
|
@@ -1208,101 +1298,72 @@ var globalStyles = `
|
|
|
1208
1298
|
|
|
1209
1299
|
@keyframes uilint-pulse {
|
|
1210
1300
|
0%, 100% { opacity: 1; }
|
|
1211
|
-
50% { opacity: 0.
|
|
1212
|
-
}
|
|
1213
|
-
|
|
1214
|
-
@keyframes uilint-scan-line {
|
|
1215
|
-
0% { transform: translateX(-100%); }
|
|
1216
|
-
100% { transform: translateX(100%); }
|
|
1301
|
+
50% { opacity: 0.6; }
|
|
1217
1302
|
}
|
|
1218
1303
|
|
|
1219
|
-
@keyframes uilint-
|
|
1220
|
-
from { transform:
|
|
1221
|
-
to { transform:
|
|
1304
|
+
@keyframes uilint-slide-up {
|
|
1305
|
+
from { opacity: 0; transform: translateY(12px); }
|
|
1306
|
+
to { opacity: 1; transform: translateY(0); }
|
|
1222
1307
|
}
|
|
1223
1308
|
|
|
1224
|
-
.uilint-
|
|
1309
|
+
.uilint-btn {
|
|
1225
1310
|
display: flex;
|
|
1226
1311
|
align-items: center;
|
|
1227
1312
|
justify-content: center;
|
|
1313
|
+
gap: 6px;
|
|
1228
1314
|
height: 100%;
|
|
1315
|
+
padding: 0 14px;
|
|
1229
1316
|
border: none;
|
|
1230
1317
|
background: transparent;
|
|
1231
1318
|
color: ${TOKENS.textSecondary};
|
|
1319
|
+
font-family: ${TOKENS.fontFamily};
|
|
1320
|
+
font-size: 13px;
|
|
1321
|
+
font-weight: 500;
|
|
1232
1322
|
cursor: pointer;
|
|
1233
1323
|
transition:
|
|
1234
1324
|
background-color ${TOKENS.transitionFast},
|
|
1235
|
-
color ${TOKENS.transitionFast}
|
|
1236
|
-
transform ${TOKENS.transitionFast};
|
|
1325
|
+
color ${TOKENS.transitionFast};
|
|
1237
1326
|
outline: none;
|
|
1238
|
-
|
|
1327
|
+
white-space: nowrap;
|
|
1239
1328
|
}
|
|
1240
1329
|
|
|
1241
|
-
.uilint-
|
|
1330
|
+
.uilint-btn:hover:not(:disabled) {
|
|
1242
1331
|
background: ${TOKENS.bgHover};
|
|
1243
1332
|
color: ${TOKENS.textPrimary};
|
|
1244
1333
|
}
|
|
1245
1334
|
|
|
1246
|
-
.uilint-
|
|
1335
|
+
.uilint-btn:active:not(:disabled) {
|
|
1247
1336
|
background: ${TOKENS.bgActive};
|
|
1248
|
-
transform: scale(0.97);
|
|
1249
1337
|
}
|
|
1250
1338
|
|
|
1251
|
-
.uilint-
|
|
1339
|
+
.uilint-btn:focus-visible {
|
|
1252
1340
|
box-shadow: inset 0 0 0 2px ${TOKENS.borderFocus};
|
|
1253
1341
|
}
|
|
1254
1342
|
|
|
1255
|
-
.uilint-
|
|
1343
|
+
.uilint-btn:disabled {
|
|
1256
1344
|
cursor: not-allowed;
|
|
1257
1345
|
color: ${TOKENS.textDisabled};
|
|
1258
1346
|
}
|
|
1259
1347
|
|
|
1260
|
-
.uilint-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
}
|
|
1264
|
-
|
|
1265
|
-
.uilint-toolbar-btn--warning {
|
|
1266
|
-
color: ${TOKENS.warning} !important;
|
|
1348
|
+
.uilint-btn--icon {
|
|
1349
|
+
padding: 0;
|
|
1350
|
+
min-width: ${TOKENS.buttonMinWidth};
|
|
1267
1351
|
}
|
|
1268
1352
|
|
|
1269
|
-
.uilint-
|
|
1270
|
-
color: ${TOKENS.
|
|
1271
|
-
}
|
|
1272
|
-
|
|
1273
|
-
.uilint-hint {
|
|
1274
|
-
opacity: 0;
|
|
1275
|
-
transform: translateY(4px);
|
|
1276
|
-
transition:
|
|
1277
|
-
opacity ${TOKENS.transitionBase},
|
|
1278
|
-
transform ${TOKENS.transitionBase};
|
|
1279
|
-
pointer-events: none;
|
|
1353
|
+
.uilint-btn--primary {
|
|
1354
|
+
color: ${TOKENS.textPrimary};
|
|
1280
1355
|
}
|
|
1281
1356
|
|
|
1282
|
-
.uilint-
|
|
1283
|
-
|
|
1284
|
-
transform: translateY(0);
|
|
1357
|
+
.uilint-btn--accent {
|
|
1358
|
+
color: ${TOKENS.accent};
|
|
1285
1359
|
}
|
|
1286
1360
|
|
|
1287
|
-
.uilint-
|
|
1288
|
-
|
|
1289
|
-
overflow: hidden;
|
|
1361
|
+
.uilint-btn--warning {
|
|
1362
|
+
color: ${TOKENS.warning};
|
|
1290
1363
|
}
|
|
1291
1364
|
|
|
1292
|
-
.uilint-
|
|
1293
|
-
|
|
1294
|
-
position: absolute;
|
|
1295
|
-
top: 0;
|
|
1296
|
-
left: 0;
|
|
1297
|
-
right: 0;
|
|
1298
|
-
bottom: 0;
|
|
1299
|
-
background: linear-gradient(
|
|
1300
|
-
90deg,
|
|
1301
|
-
transparent,
|
|
1302
|
-
rgba(99, 179, 237, 0.3),
|
|
1303
|
-
transparent
|
|
1304
|
-
);
|
|
1305
|
-
animation: uilint-scan-line 1.5s ease-in-out infinite;
|
|
1365
|
+
.uilint-btn--success {
|
|
1366
|
+
color: ${TOKENS.success};
|
|
1306
1367
|
}
|
|
1307
1368
|
|
|
1308
1369
|
.uilint-popover {
|
|
@@ -1313,80 +1374,65 @@ var globalStyles = `
|
|
|
1313
1374
|
animation: uilint-fade-out ${TOKENS.transitionBase} forwards;
|
|
1314
1375
|
}
|
|
1315
1376
|
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1377
|
+
.uilint-scanning-bar {
|
|
1378
|
+
animation: uilint-slide-up ${TOKENS.transitionSlow} forwards;
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
.uilint-scanning-dot {
|
|
1382
|
+
width: 6px;
|
|
1383
|
+
height: 6px;
|
|
1384
|
+
border-radius: 50%;
|
|
1385
|
+
background: ${TOKENS.accent};
|
|
1386
|
+
animation: uilint-pulse 1.5s ease-in-out infinite;
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
/* Scrollbar styling */
|
|
1390
|
+
[data-ui-lint] * {
|
|
1320
1391
|
scrollbar-width: thin;
|
|
1321
1392
|
scrollbar-color: rgba(255, 255, 255, 0.15) rgba(15, 15, 15, 0.3);
|
|
1322
1393
|
}
|
|
1323
1394
|
|
|
1324
|
-
|
|
1325
|
-
[data-ui-lint] *::-webkit-scrollbar,
|
|
1326
|
-
[data-ui-lint]::-webkit-scrollbar {
|
|
1395
|
+
[data-ui-lint] *::-webkit-scrollbar {
|
|
1327
1396
|
width: 8px;
|
|
1328
1397
|
height: 8px;
|
|
1329
1398
|
}
|
|
1330
1399
|
|
|
1331
|
-
[data-ui-lint] *::-webkit-scrollbar-track
|
|
1332
|
-
[data-ui-lint]::-webkit-scrollbar-track {
|
|
1400
|
+
[data-ui-lint] *::-webkit-scrollbar-track {
|
|
1333
1401
|
background: rgba(15, 15, 15, 0.3);
|
|
1334
1402
|
border-radius: 4px;
|
|
1335
1403
|
}
|
|
1336
1404
|
|
|
1337
|
-
[data-ui-lint] *::-webkit-scrollbar-thumb
|
|
1338
|
-
[data-ui-lint]::-webkit-scrollbar-thumb {
|
|
1405
|
+
[data-ui-lint] *::-webkit-scrollbar-thumb {
|
|
1339
1406
|
background: rgba(255, 255, 255, 0.15);
|
|
1340
1407
|
border-radius: 4px;
|
|
1341
|
-
border: 1px solid rgba(15, 15, 15, 0.2);
|
|
1342
|
-
transition: background ${TOKENS.transitionFast};
|
|
1343
1408
|
}
|
|
1344
1409
|
|
|
1345
|
-
[data-ui-lint] *::-webkit-scrollbar-thumb:hover
|
|
1346
|
-
[data-ui-lint]::-webkit-scrollbar-thumb:hover {
|
|
1410
|
+
[data-ui-lint] *::-webkit-scrollbar-thumb:hover {
|
|
1347
1411
|
background: rgba(255, 255, 255, 0.25);
|
|
1348
1412
|
}
|
|
1349
|
-
|
|
1350
|
-
[data-ui-lint] *::-webkit-scrollbar-thumb:active,
|
|
1351
|
-
[data-ui-lint]::-webkit-scrollbar-thumb:active {
|
|
1352
|
-
background: rgba(255, 255, 255, 0.35);
|
|
1353
|
-
}
|
|
1354
|
-
|
|
1355
|
-
[data-ui-lint] *::-webkit-scrollbar-corner,
|
|
1356
|
-
[data-ui-lint]::-webkit-scrollbar-corner {
|
|
1357
|
-
background: rgba(15, 15, 15, 0.3);
|
|
1358
|
-
}
|
|
1359
1413
|
`;
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
title,
|
|
1383
|
-
"aria-label": ariaLabel,
|
|
1384
|
-
"aria-pressed": active,
|
|
1385
|
-
style: { minWidth: width },
|
|
1386
|
-
children
|
|
1387
|
-
}
|
|
1388
|
-
);
|
|
1389
|
-
}
|
|
1414
|
+
var PillContainer = React3.forwardRef(({ children, glow, style }, ref) => /* @__PURE__ */ jsx5(
|
|
1415
|
+
"div",
|
|
1416
|
+
{
|
|
1417
|
+
ref,
|
|
1418
|
+
style: {
|
|
1419
|
+
display: "inline-flex",
|
|
1420
|
+
alignItems: "center",
|
|
1421
|
+
height: TOKENS.pillHeight,
|
|
1422
|
+
borderRadius: TOKENS.pillRadius,
|
|
1423
|
+
border: `1px solid ${TOKENS.border}`,
|
|
1424
|
+
backgroundColor: TOKENS.bgBase,
|
|
1425
|
+
backdropFilter: TOKENS.blur,
|
|
1426
|
+
WebkitBackdropFilter: TOKENS.blur,
|
|
1427
|
+
boxShadow: glow ? `${TOKENS.shadowMd}, ${TOKENS.shadowGlow(glow)}` : TOKENS.shadowMd,
|
|
1428
|
+
overflow: "hidden",
|
|
1429
|
+
transition: `box-shadow ${TOKENS.transitionBase}`,
|
|
1430
|
+
...style
|
|
1431
|
+
},
|
|
1432
|
+
children
|
|
1433
|
+
}
|
|
1434
|
+
));
|
|
1435
|
+
PillContainer.displayName = "PillContainer";
|
|
1390
1436
|
function Divider() {
|
|
1391
1437
|
return /* @__PURE__ */ jsx5(
|
|
1392
1438
|
"div",
|
|
@@ -1401,98 +1447,112 @@ function Divider() {
|
|
|
1401
1447
|
}
|
|
1402
1448
|
);
|
|
1403
1449
|
}
|
|
1404
|
-
function
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
{
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1450
|
+
function Kbd({ children }) {
|
|
1451
|
+
return /* @__PURE__ */ jsx5(
|
|
1452
|
+
"kbd",
|
|
1453
|
+
{
|
|
1454
|
+
style: {
|
|
1455
|
+
display: "inline-flex",
|
|
1456
|
+
alignItems: "center",
|
|
1457
|
+
padding: "2px 6px",
|
|
1458
|
+
borderRadius: "4px",
|
|
1459
|
+
backgroundColor: TOKENS.bgElevated,
|
|
1460
|
+
border: `1px solid ${TOKENS.border}`,
|
|
1461
|
+
fontSize: "11px",
|
|
1462
|
+
fontFamily: TOKENS.fontMono,
|
|
1463
|
+
color: TOKENS.textSecondary,
|
|
1464
|
+
boxShadow: "0 1px 2px rgba(0, 0, 0, 0.4)"
|
|
1465
|
+
},
|
|
1466
|
+
children
|
|
1467
|
+
}
|
|
1468
|
+
);
|
|
1469
|
+
}
|
|
1470
|
+
function DisconnectedToolbar({
|
|
1471
|
+
onSettingsClick,
|
|
1472
|
+
showSettings
|
|
1473
|
+
}) {
|
|
1474
|
+
return /* @__PURE__ */ jsxs4(PillContainer, { children: [
|
|
1475
|
+
/* @__PURE__ */ jsxs4(
|
|
1476
|
+
"div",
|
|
1421
1477
|
{
|
|
1422
|
-
className: "uilint-scanning-indicator",
|
|
1423
1478
|
style: {
|
|
1424
1479
|
display: "flex",
|
|
1425
1480
|
alignItems: "center",
|
|
1426
1481
|
gap: "6px",
|
|
1427
|
-
padding: "0
|
|
1482
|
+
padding: "0 12px",
|
|
1483
|
+
color: TOKENS.textMuted,
|
|
1484
|
+
fontSize: "12px"
|
|
1428
1485
|
},
|
|
1429
1486
|
children: [
|
|
1430
|
-
/* @__PURE__ */ jsx5(Icons.
|
|
1431
|
-
/* @__PURE__ */ jsx5(
|
|
1432
|
-
"span",
|
|
1433
|
-
{
|
|
1434
|
-
style: {
|
|
1435
|
-
fontSize: "12px",
|
|
1436
|
-
fontFamily: TOKENS.fontMono,
|
|
1437
|
-
animation: `uilint-pulse 1s ease-in-out infinite`
|
|
1438
|
-
},
|
|
1439
|
-
children: "Scanning"
|
|
1440
|
-
}
|
|
1441
|
-
)
|
|
1487
|
+
/* @__PURE__ */ jsx5(Icons.Unplug, {}),
|
|
1488
|
+
/* @__PURE__ */ jsx5("span", { children: "Not connected" })
|
|
1442
1489
|
]
|
|
1443
1490
|
}
|
|
1444
|
-
)
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
"span",
|
|
1491
|
+
),
|
|
1492
|
+
/* @__PURE__ */ jsx5(Divider, {}),
|
|
1493
|
+
/* @__PURE__ */ jsx5(
|
|
1494
|
+
"button",
|
|
1449
1495
|
{
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1496
|
+
className: `uilint-btn uilint-btn--icon ${showSettings ? "uilint-btn--accent" : ""}`,
|
|
1497
|
+
onClick: onSettingsClick,
|
|
1498
|
+
title: "Settings",
|
|
1499
|
+
"aria-label": "Open settings",
|
|
1500
|
+
"aria-pressed": showSettings,
|
|
1501
|
+
children: /* @__PURE__ */ jsx5(Icons.Settings, {})
|
|
1502
|
+
}
|
|
1503
|
+
)
|
|
1504
|
+
] });
|
|
1505
|
+
}
|
|
1506
|
+
function IdleToolbar({
|
|
1507
|
+
onStartScan,
|
|
1508
|
+
onSettingsClick,
|
|
1509
|
+
showSettings
|
|
1510
|
+
}) {
|
|
1511
|
+
return /* @__PURE__ */ jsxs4(PillContainer, { children: [
|
|
1512
|
+
/* @__PURE__ */ jsxs4(
|
|
1513
|
+
"button",
|
|
1514
|
+
{
|
|
1515
|
+
className: "uilint-btn uilint-btn--primary",
|
|
1516
|
+
onClick: onStartScan,
|
|
1517
|
+
title: "Start scanning (\u2325S)",
|
|
1518
|
+
"aria-label": "Start live scanning",
|
|
1455
1519
|
children: [
|
|
1456
|
-
/* @__PURE__ */ jsx5(
|
|
1457
|
-
|
|
1458
|
-
{
|
|
1459
|
-
style: {
|
|
1460
|
-
display: "flex",
|
|
1461
|
-
alignItems: "center",
|
|
1462
|
-
justifyContent: "center",
|
|
1463
|
-
width: "18px",
|
|
1464
|
-
height: "18px",
|
|
1465
|
-
borderRadius: "50%",
|
|
1466
|
-
backgroundColor: `${TOKENS.success}20`,
|
|
1467
|
-
color: TOKENS.success
|
|
1468
|
-
},
|
|
1469
|
-
children: /* @__PURE__ */ jsx5(Icons.Check, {})
|
|
1470
|
-
}
|
|
1471
|
-
),
|
|
1472
|
-
/* @__PURE__ */ jsx5(
|
|
1473
|
-
"span",
|
|
1474
|
-
{
|
|
1475
|
-
style: {
|
|
1476
|
-
fontSize: "12px",
|
|
1477
|
-
fontWeight: 500,
|
|
1478
|
-
color: TOKENS.success
|
|
1479
|
-
},
|
|
1480
|
-
children: "Clear"
|
|
1481
|
-
}
|
|
1482
|
-
)
|
|
1520
|
+
/* @__PURE__ */ jsx5(Icons.Eye, {}),
|
|
1521
|
+
/* @__PURE__ */ jsx5("span", { children: "Start Scanning" })
|
|
1483
1522
|
]
|
|
1484
1523
|
}
|
|
1485
|
-
)
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1524
|
+
),
|
|
1525
|
+
/* @__PURE__ */ jsx5(Divider, {}),
|
|
1526
|
+
/* @__PURE__ */ jsx5(
|
|
1527
|
+
"button",
|
|
1528
|
+
{
|
|
1529
|
+
className: `uilint-btn uilint-btn--icon ${showSettings ? "uilint-btn--accent" : ""}`,
|
|
1530
|
+
onClick: onSettingsClick,
|
|
1531
|
+
title: "Settings",
|
|
1532
|
+
"aria-label": "Open settings",
|
|
1533
|
+
"aria-pressed": showSettings,
|
|
1534
|
+
children: /* @__PURE__ */ jsx5(Icons.Settings, {})
|
|
1535
|
+
}
|
|
1536
|
+
)
|
|
1537
|
+
] });
|
|
1538
|
+
}
|
|
1539
|
+
function ScanningToolbar({
|
|
1540
|
+
issueCount,
|
|
1541
|
+
isScanning,
|
|
1542
|
+
showResults,
|
|
1543
|
+
onToggleResults,
|
|
1544
|
+
onStopScan
|
|
1545
|
+
}) {
|
|
1546
|
+
const hasIssues = issueCount > 0;
|
|
1547
|
+
const getStatusContent = () => {
|
|
1548
|
+
if (isScanning) {
|
|
1549
|
+
return /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
1550
|
+
/* @__PURE__ */ jsx5("div", { className: "uilint-scanning-dot" }),
|
|
1551
|
+
/* @__PURE__ */ jsx5("span", { style: { fontFamily: TOKENS.fontMono, fontSize: "12px" }, children: "Scanning..." })
|
|
1552
|
+
] });
|
|
1553
|
+
}
|
|
1554
|
+
if (hasIssues) {
|
|
1555
|
+
return /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
1496
1556
|
/* @__PURE__ */ jsx5(
|
|
1497
1557
|
"span",
|
|
1498
1558
|
{
|
|
@@ -1500,8 +1560,8 @@ function ScanStatus({ status, issueCount, enabled }) {
|
|
|
1500
1560
|
display: "flex",
|
|
1501
1561
|
alignItems: "center",
|
|
1502
1562
|
justifyContent: "center",
|
|
1503
|
-
width: "
|
|
1504
|
-
height: "
|
|
1563
|
+
width: "16px",
|
|
1564
|
+
height: "16px",
|
|
1505
1565
|
borderRadius: "50%",
|
|
1506
1566
|
backgroundColor: `${TOKENS.warning}20`,
|
|
1507
1567
|
color: TOKENS.warning
|
|
@@ -1510,6 +1570,72 @@ function ScanStatus({ status, issueCount, enabled }) {
|
|
|
1510
1570
|
}
|
|
1511
1571
|
),
|
|
1512
1572
|
/* @__PURE__ */ jsx5(Badge, { count: issueCount })
|
|
1573
|
+
] });
|
|
1574
|
+
}
|
|
1575
|
+
return /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
1576
|
+
/* @__PURE__ */ jsx5(
|
|
1577
|
+
"span",
|
|
1578
|
+
{
|
|
1579
|
+
style: {
|
|
1580
|
+
display: "flex",
|
|
1581
|
+
alignItems: "center",
|
|
1582
|
+
justifyContent: "center",
|
|
1583
|
+
width: "16px",
|
|
1584
|
+
height: "16px",
|
|
1585
|
+
borderRadius: "50%",
|
|
1586
|
+
backgroundColor: `${TOKENS.success}20`,
|
|
1587
|
+
color: TOKENS.success
|
|
1588
|
+
},
|
|
1589
|
+
children: /* @__PURE__ */ jsx5(Icons.Check, {})
|
|
1590
|
+
}
|
|
1591
|
+
),
|
|
1592
|
+
/* @__PURE__ */ jsx5(
|
|
1593
|
+
"span",
|
|
1594
|
+
{
|
|
1595
|
+
style: { fontSize: "12px", fontWeight: 500, color: TOKENS.success },
|
|
1596
|
+
children: "All clear"
|
|
1597
|
+
}
|
|
1598
|
+
)
|
|
1599
|
+
] });
|
|
1600
|
+
};
|
|
1601
|
+
const statusVariant = hasIssues ? "warning" : isScanning ? "accent" : "success";
|
|
1602
|
+
const glowColor = hasIssues ? `${TOKENS.warning}25` : void 0;
|
|
1603
|
+
return /* @__PURE__ */ jsxs4(
|
|
1604
|
+
"div",
|
|
1605
|
+
{
|
|
1606
|
+
className: "uilint-scanning-bar",
|
|
1607
|
+
style: { display: "flex", alignItems: "center", gap: "10px" },
|
|
1608
|
+
children: [
|
|
1609
|
+
/* @__PURE__ */ jsxs4(PillContainer, { glow: glowColor, children: [
|
|
1610
|
+
/* @__PURE__ */ jsxs4(
|
|
1611
|
+
"button",
|
|
1612
|
+
{
|
|
1613
|
+
className: `uilint-btn uilint-btn--${statusVariant}`,
|
|
1614
|
+
onClick: onToggleResults,
|
|
1615
|
+
title: hasIssues ? `${issueCount} issue${issueCount !== 1 ? "s" : ""} found` : "View scan results",
|
|
1616
|
+
"aria-label": "Toggle scan results",
|
|
1617
|
+
"aria-expanded": showResults,
|
|
1618
|
+
style: { paddingRight: "10px" },
|
|
1619
|
+
children: [
|
|
1620
|
+
getStatusContent(),
|
|
1621
|
+
/* @__PURE__ */ jsx5(Icons.ChevronDown, {})
|
|
1622
|
+
]
|
|
1623
|
+
}
|
|
1624
|
+
),
|
|
1625
|
+
/* @__PURE__ */ jsx5(Divider, {}),
|
|
1626
|
+
/* @__PURE__ */ jsx5(
|
|
1627
|
+
"button",
|
|
1628
|
+
{
|
|
1629
|
+
className: "uilint-btn uilint-btn--icon",
|
|
1630
|
+
onClick: onStopScan,
|
|
1631
|
+
title: "Stop scanning (\u2325S)",
|
|
1632
|
+
"aria-label": "Stop scanning",
|
|
1633
|
+
children: /* @__PURE__ */ jsx5(Icons.X, {})
|
|
1634
|
+
}
|
|
1635
|
+
)
|
|
1636
|
+
] }),
|
|
1637
|
+
/* @__PURE__ */ jsx5(Kbd, { children: "\u2325 + Click" }),
|
|
1638
|
+
/* @__PURE__ */ jsx5("span", { style: { fontSize: "12px", color: TOKENS.textMuted }, children: "to inspect" })
|
|
1513
1639
|
]
|
|
1514
1640
|
}
|
|
1515
1641
|
);
|
|
@@ -1526,6 +1652,7 @@ function UILintToolbar() {
|
|
|
1526
1652
|
(s) => s.elementIssuesCache
|
|
1527
1653
|
);
|
|
1528
1654
|
const fileIssuesCache = useUILintStore((s) => s.fileIssuesCache);
|
|
1655
|
+
const wsConnected = useUILintStore((s) => s.wsConnected);
|
|
1529
1656
|
const [showSettings, setShowSettings] = useState2(false);
|
|
1530
1657
|
const [showResults, setShowResults] = useState2(false);
|
|
1531
1658
|
const [mounted, setMounted] = useState2(false);
|
|
@@ -1533,7 +1660,17 @@ function UILintToolbar() {
|
|
|
1533
1660
|
const [nextjsOverlayVisible, setNextjsOverlayVisible] = useState2(false);
|
|
1534
1661
|
const toolbarRef = useRef2(null);
|
|
1535
1662
|
const settingsRef = useRef2(null);
|
|
1536
|
-
|
|
1663
|
+
const isScanning = autoScanState.status === "scanning" || autoScanState.status === "paused";
|
|
1664
|
+
let elementIssues = 0;
|
|
1665
|
+
elementIssuesCache.forEach((el) => {
|
|
1666
|
+
elementIssues += el.issues.length;
|
|
1667
|
+
});
|
|
1668
|
+
let fileLevelIssues = 0;
|
|
1669
|
+
fileIssuesCache.forEach((issues) => {
|
|
1670
|
+
fileLevelIssues += issues.length;
|
|
1671
|
+
});
|
|
1672
|
+
const totalIssues = elementIssues + fileLevelIssues;
|
|
1673
|
+
useEffect3(() => {
|
|
1537
1674
|
const checkForNextOverlay = () => {
|
|
1538
1675
|
const overlaySelectors = [
|
|
1539
1676
|
"nextjs-portal",
|
|
@@ -1560,29 +1697,21 @@ function UILintToolbar() {
|
|
|
1560
1697
|
});
|
|
1561
1698
|
return () => observer.disconnect();
|
|
1562
1699
|
}, []);
|
|
1563
|
-
|
|
1564
|
-
const isComplete = autoScanState.status === "complete";
|
|
1565
|
-
let elementIssues = 0;
|
|
1566
|
-
elementIssuesCache.forEach((el) => {
|
|
1567
|
-
elementIssues += el.issues.length;
|
|
1568
|
-
});
|
|
1569
|
-
let fileLevelIssues = 0;
|
|
1570
|
-
fileIssuesCache.forEach((issues) => {
|
|
1571
|
-
fileLevelIssues += issues.length;
|
|
1572
|
-
});
|
|
1573
|
-
const totalIssues = elementIssues + fileLevelIssues;
|
|
1574
|
-
const hasIssues = totalIssues > 0;
|
|
1575
|
-
useEffect2(() => {
|
|
1700
|
+
useEffect3(() => {
|
|
1576
1701
|
setMounted(true);
|
|
1577
1702
|
}, []);
|
|
1578
|
-
|
|
1703
|
+
useEffect3(() => {
|
|
1579
1704
|
const handleClickOutside = (e) => {
|
|
1580
1705
|
const target = e.target;
|
|
1706
|
+
if (target?.closest?.("[data-ui-lint]")) return;
|
|
1581
1707
|
if (showSettings && settingsRef.current && toolbarRef.current) {
|
|
1582
1708
|
if (!settingsRef.current.contains(target) && !toolbarRef.current.contains(target)) {
|
|
1583
1709
|
handleCloseSettings();
|
|
1584
1710
|
}
|
|
1585
1711
|
}
|
|
1712
|
+
if (showResults) {
|
|
1713
|
+
setShowResults(false);
|
|
1714
|
+
}
|
|
1586
1715
|
};
|
|
1587
1716
|
const handleEscape = (e) => {
|
|
1588
1717
|
if (e.key === "Escape") {
|
|
@@ -1590,35 +1719,26 @@ function UILintToolbar() {
|
|
|
1590
1719
|
if (showResults) setShowResults(false);
|
|
1591
1720
|
}
|
|
1592
1721
|
};
|
|
1593
|
-
document.addEventListener("mousedown", handleClickOutside);
|
|
1722
|
+
document.addEventListener("mousedown", handleClickOutside, true);
|
|
1594
1723
|
document.addEventListener("keydown", handleEscape);
|
|
1595
1724
|
return () => {
|
|
1596
|
-
document.removeEventListener("mousedown", handleClickOutside);
|
|
1725
|
+
document.removeEventListener("mousedown", handleClickOutside, true);
|
|
1597
1726
|
document.removeEventListener("keydown", handleEscape);
|
|
1598
1727
|
};
|
|
1599
1728
|
}, [showSettings, showResults]);
|
|
1600
|
-
const
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
}, [liveScanEnabled, enableLiveScan, disableLiveScan, showSettings]);
|
|
1609
|
-
const handleIssuesClick = useCallback2(() => {
|
|
1610
|
-
if (!liveScanEnabled) {
|
|
1611
|
-
enableLiveScan();
|
|
1612
|
-
return;
|
|
1613
|
-
}
|
|
1614
|
-
setShowResults((prev) => !prev);
|
|
1615
|
-
}, [liveScanEnabled, enableLiveScan]);
|
|
1729
|
+
const handleStartScan = useCallback2(() => {
|
|
1730
|
+
enableLiveScan();
|
|
1731
|
+
setShowSettings(false);
|
|
1732
|
+
}, [enableLiveScan]);
|
|
1733
|
+
const handleStopScan = useCallback2(() => {
|
|
1734
|
+
disableLiveScan();
|
|
1735
|
+
setShowResults(false);
|
|
1736
|
+
}, [disableLiveScan]);
|
|
1616
1737
|
const handleSettingsClick = useCallback2(() => {
|
|
1617
1738
|
if (showSettings) {
|
|
1618
1739
|
handleCloseSettings();
|
|
1619
1740
|
} else {
|
|
1620
1741
|
setShowSettings(true);
|
|
1621
|
-
setShowResults(false);
|
|
1622
1742
|
}
|
|
1623
1743
|
}, [showSettings]);
|
|
1624
1744
|
const handleCloseSettings = useCallback2(() => {
|
|
@@ -1628,125 +1748,77 @@ function UILintToolbar() {
|
|
|
1628
1748
|
setSettingsClosing(false);
|
|
1629
1749
|
}, 150);
|
|
1630
1750
|
}, []);
|
|
1751
|
+
const handleToggleResults = useCallback2(() => {
|
|
1752
|
+
setShowResults((prev) => !prev);
|
|
1753
|
+
}, []);
|
|
1754
|
+
const handleUILintInteraction = useCallback2(
|
|
1755
|
+
(e) => {
|
|
1756
|
+
e.stopPropagation();
|
|
1757
|
+
},
|
|
1758
|
+
[]
|
|
1759
|
+
);
|
|
1631
1760
|
if (!mounted) return null;
|
|
1632
|
-
const issueVariant = !liveScanEnabled ? "default" : hasIssues ? "warning" : isComplete ? "success" : "default";
|
|
1633
1761
|
const bottomPosition = nextjsOverlayVisible ? "80px" : "20px";
|
|
1762
|
+
const renderToolbar = () => {
|
|
1763
|
+
if (!wsConnected) {
|
|
1764
|
+
return /* @__PURE__ */ jsx5(
|
|
1765
|
+
DisconnectedToolbar,
|
|
1766
|
+
{
|
|
1767
|
+
onSettingsClick: handleSettingsClick,
|
|
1768
|
+
showSettings
|
|
1769
|
+
}
|
|
1770
|
+
);
|
|
1771
|
+
}
|
|
1772
|
+
if (!liveScanEnabled) {
|
|
1773
|
+
return /* @__PURE__ */ jsx5(
|
|
1774
|
+
IdleToolbar,
|
|
1775
|
+
{
|
|
1776
|
+
onStartScan: handleStartScan,
|
|
1777
|
+
onSettingsClick: handleSettingsClick,
|
|
1778
|
+
showSettings
|
|
1779
|
+
}
|
|
1780
|
+
);
|
|
1781
|
+
}
|
|
1782
|
+
return /* @__PURE__ */ jsx5(
|
|
1783
|
+
ScanningToolbar,
|
|
1784
|
+
{
|
|
1785
|
+
issueCount: totalIssues,
|
|
1786
|
+
isScanning,
|
|
1787
|
+
showResults,
|
|
1788
|
+
onToggleResults: handleToggleResults,
|
|
1789
|
+
onStopScan: handleStopScan
|
|
1790
|
+
}
|
|
1791
|
+
);
|
|
1792
|
+
};
|
|
1634
1793
|
const content = /* @__PURE__ */ jsxs4(
|
|
1635
1794
|
"div",
|
|
1636
1795
|
{
|
|
1637
1796
|
"data-ui-lint": true,
|
|
1797
|
+
onMouseDown: handleUILintInteraction,
|
|
1798
|
+
onClick: handleUILintInteraction,
|
|
1799
|
+
onKeyDown: handleUILintInteraction,
|
|
1638
1800
|
style: {
|
|
1639
1801
|
position: "fixed",
|
|
1640
1802
|
bottom: bottomPosition,
|
|
1641
1803
|
left: "20px",
|
|
1642
1804
|
zIndex: 99999,
|
|
1643
1805
|
fontFamily: TOKENS.fontFamily,
|
|
1644
|
-
transition: `bottom ${TOKENS.transitionSlow}
|
|
1806
|
+
transition: `bottom ${TOKENS.transitionSlow}`,
|
|
1807
|
+
pointerEvents: "none"
|
|
1645
1808
|
},
|
|
1646
1809
|
children: [
|
|
1647
1810
|
/* @__PURE__ */ jsx5("style", { children: globalStyles }),
|
|
1648
1811
|
/* @__PURE__ */ jsx5(
|
|
1649
|
-
"div",
|
|
1650
|
-
{
|
|
1651
|
-
className: `uilint-hint ${liveScanEnabled ? "uilint-hint--visible" : ""}`,
|
|
1652
|
-
style: {
|
|
1653
|
-
textAlign: "center",
|
|
1654
|
-
marginBottom: "10px",
|
|
1655
|
-
fontSize: "11px",
|
|
1656
|
-
color: TOKENS.textMuted,
|
|
1657
|
-
letterSpacing: "0.02em"
|
|
1658
|
-
},
|
|
1659
|
-
"aria-hidden": !liveScanEnabled,
|
|
1660
|
-
children: /* @__PURE__ */ jsx5(
|
|
1661
|
-
"kbd",
|
|
1662
|
-
{
|
|
1663
|
-
style: {
|
|
1664
|
-
display: "inline-block",
|
|
1665
|
-
padding: "2px 5px",
|
|
1666
|
-
marginRight: "4px",
|
|
1667
|
-
borderRadius: "4px",
|
|
1668
|
-
backgroundColor: TOKENS.bgElevated,
|
|
1669
|
-
border: `1px solid ${TOKENS.border}`,
|
|
1670
|
-
fontSize: "10px",
|
|
1671
|
-
fontFamily: TOKENS.fontMono,
|
|
1672
|
-
color: TOKENS.textSecondary,
|
|
1673
|
-
boxShadow: `0 1px 3px rgba(0, 0, 0, 0.5)`
|
|
1674
|
-
},
|
|
1675
|
-
children: "\u2325 + Click to inspect element"
|
|
1676
|
-
}
|
|
1677
|
-
)
|
|
1678
|
-
}
|
|
1679
|
-
),
|
|
1680
|
-
/* @__PURE__ */ jsxs4(
|
|
1681
1812
|
"div",
|
|
1682
1813
|
{
|
|
1683
1814
|
ref: toolbarRef,
|
|
1684
1815
|
role: "toolbar",
|
|
1685
1816
|
"aria-label": "UI Lint toolbar",
|
|
1686
|
-
style: {
|
|
1687
|
-
|
|
1688
|
-
display: "inline-flex",
|
|
1689
|
-
alignItems: "center",
|
|
1690
|
-
height: TOKENS.pillHeight,
|
|
1691
|
-
borderRadius: TOKENS.pillRadius,
|
|
1692
|
-
border: `1px solid ${TOKENS.border}`,
|
|
1693
|
-
backgroundColor: TOKENS.bgBase,
|
|
1694
|
-
backdropFilter: TOKENS.blur,
|
|
1695
|
-
WebkitBackdropFilter: TOKENS.blur,
|
|
1696
|
-
boxShadow: liveScanEnabled && hasIssues ? `${TOKENS.shadowMd}, ${TOKENS.shadowGlow(
|
|
1697
|
-
`${TOKENS.warning}30`
|
|
1698
|
-
)}` : TOKENS.shadowMd,
|
|
1699
|
-
overflow: "hidden",
|
|
1700
|
-
transition: `box-shadow ${TOKENS.transitionBase}`
|
|
1701
|
-
},
|
|
1702
|
-
children: [
|
|
1703
|
-
/* @__PURE__ */ jsx5(
|
|
1704
|
-
ToolbarButton,
|
|
1705
|
-
{
|
|
1706
|
-
onClick: handleToggleClick,
|
|
1707
|
-
active: liveScanEnabled,
|
|
1708
|
-
title: liveScanEnabled ? "Stop scanning (\u2325S)" : "Start scanning (\u2325S)",
|
|
1709
|
-
ariaLabel: liveScanEnabled ? "Stop live scanning" : "Start live scanning",
|
|
1710
|
-
width: "48px",
|
|
1711
|
-
children: liveScanEnabled ? /* @__PURE__ */ jsx5(Icons.Eye, {}) : /* @__PURE__ */ jsx5(Icons.EyeOff, {})
|
|
1712
|
-
}
|
|
1713
|
-
),
|
|
1714
|
-
/* @__PURE__ */ jsx5(Divider, {}),
|
|
1715
|
-
/* @__PURE__ */ jsx5(
|
|
1716
|
-
ToolbarButton,
|
|
1717
|
-
{
|
|
1718
|
-
onClick: handleIssuesClick,
|
|
1719
|
-
active: showResults && liveScanEnabled,
|
|
1720
|
-
variant: issueVariant,
|
|
1721
|
-
title: !liveScanEnabled ? "Click to enable scanning" : `${totalIssues} issue${totalIssues !== 1 ? "s" : ""} found`,
|
|
1722
|
-
ariaLabel: !liveScanEnabled ? "Enable scanning to see issues" : `View ${totalIssues} issues`,
|
|
1723
|
-
width: "auto",
|
|
1724
|
-
children: /* @__PURE__ */ jsx5("span", { style: { padding: "0 12px" }, children: /* @__PURE__ */ jsx5(
|
|
1725
|
-
ScanStatus,
|
|
1726
|
-
{
|
|
1727
|
-
status: autoScanState.status,
|
|
1728
|
-
issueCount: totalIssues,
|
|
1729
|
-
enabled: liveScanEnabled
|
|
1730
|
-
}
|
|
1731
|
-
) })
|
|
1732
|
-
}
|
|
1733
|
-
),
|
|
1734
|
-
/* @__PURE__ */ jsx5(Divider, {}),
|
|
1735
|
-
/* @__PURE__ */ jsx5(
|
|
1736
|
-
ToolbarButton,
|
|
1737
|
-
{
|
|
1738
|
-
onClick: handleSettingsClick,
|
|
1739
|
-
active: showSettings,
|
|
1740
|
-
title: "Settings",
|
|
1741
|
-
ariaLabel: "Open settings",
|
|
1742
|
-
width: "44px",
|
|
1743
|
-
children: /* @__PURE__ */ jsx5(Icons.Settings, {})
|
|
1744
|
-
}
|
|
1745
|
-
)
|
|
1746
|
-
]
|
|
1817
|
+
style: { pointerEvents: "auto" },
|
|
1818
|
+
children: renderToolbar()
|
|
1747
1819
|
}
|
|
1748
1820
|
),
|
|
1749
|
-
showSettings && /* @__PURE__ */ jsx5(
|
|
1821
|
+
showSettings && !liveScanEnabled && /* @__PURE__ */ jsx5(
|
|
1750
1822
|
"div",
|
|
1751
1823
|
{
|
|
1752
1824
|
ref: settingsRef,
|
|
@@ -1755,7 +1827,8 @@ function UILintToolbar() {
|
|
|
1755
1827
|
position: "absolute",
|
|
1756
1828
|
bottom: "100%",
|
|
1757
1829
|
left: 0,
|
|
1758
|
-
marginBottom: "8px"
|
|
1830
|
+
marginBottom: "8px",
|
|
1831
|
+
pointerEvents: "auto"
|
|
1759
1832
|
},
|
|
1760
1833
|
children: /* @__PURE__ */ jsx5(SettingsPopover, { settings })
|
|
1761
1834
|
}
|