uilint-react 0.1.28 → 0.1.30
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-HFQNIIO2.js → ElementBadges-ZDGDJFQU.js} +264 -366
- package/dist/{InspectionPanel-4OWY4FVY.js → InspectionPanel-7K662MF5.js} +2 -2
- package/dist/{LocatorOverlay-JJDOKNOS.js → LocatorOverlay-C4IVDVBW.js} +2 -2
- package/dist/{UILintToolbar-GMZ6YSI2.js → UILintToolbar-AX67REOL.js} +2 -2
- package/dist/{chunk-QYRESGFG.js → chunk-5CWWYEQM.js} +74 -17
- package/dist/{chunk-5VJ2Q2QW.js → chunk-GJJH5B4Y.js} +4 -4
- package/dist/{chunk-XLIDEQXH.js → chunk-IMPRRMMY.js} +1 -1
- package/dist/{chunk-7X5HN55P.js → chunk-KBEQSZMW.js} +1 -60
- package/dist/index.js +4 -4
- package/package.json +2 -2
|
@@ -2,11 +2,133 @@
|
|
|
2
2
|
"use client";
|
|
3
3
|
import {
|
|
4
4
|
useUILintContext
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-GJJH5B4Y.js";
|
|
6
6
|
|
|
7
7
|
// src/components/ui-lint/ElementBadges.tsx
|
|
8
8
|
import React, { useState, useEffect, useCallback, useMemo } from "react";
|
|
9
9
|
import { createPortal } from "react-dom";
|
|
10
|
+
|
|
11
|
+
// src/components/ui-lint/badge-layout.ts
|
|
12
|
+
var DEFAULT_CONFIG = {
|
|
13
|
+
repulsionForce: 50,
|
|
14
|
+
anchorStrength: 0.3,
|
|
15
|
+
minDistance: 24,
|
|
16
|
+
iterations: 50,
|
|
17
|
+
damping: 0.9
|
|
18
|
+
};
|
|
19
|
+
function computeLayout(positions, config) {
|
|
20
|
+
if (positions.length === 0) return [];
|
|
21
|
+
if (positions.length === 1) {
|
|
22
|
+
return [
|
|
23
|
+
{ ...positions[0], nudgedX: positions[0].x, nudgedY: positions[0].y }
|
|
24
|
+
];
|
|
25
|
+
}
|
|
26
|
+
const nodes = positions.map((p) => ({
|
|
27
|
+
position: p,
|
|
28
|
+
nudgedX: p.x,
|
|
29
|
+
nudgedY: p.y,
|
|
30
|
+
velocityX: 0,
|
|
31
|
+
velocityY: 0
|
|
32
|
+
}));
|
|
33
|
+
for (let iter = 0; iter < config.iterations; iter++) {
|
|
34
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
35
|
+
let fx = 0;
|
|
36
|
+
let fy = 0;
|
|
37
|
+
for (let j = 0; j < nodes.length; j++) {
|
|
38
|
+
if (i === j) continue;
|
|
39
|
+
const dx = nodes[i].nudgedX - nodes[j].nudgedX;
|
|
40
|
+
const dy = nodes[i].nudgedY - nodes[j].nudgedY;
|
|
41
|
+
const dist = Math.max(Math.hypot(dx, dy), 1);
|
|
42
|
+
if (dist < config.minDistance) {
|
|
43
|
+
const force = config.repulsionForce / (dist * dist);
|
|
44
|
+
fx += dx / dist * force;
|
|
45
|
+
fy += dy / dist * force;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const anchorDx = positions[i].x - nodes[i].nudgedX;
|
|
49
|
+
const anchorDy = positions[i].y - nodes[i].nudgedY;
|
|
50
|
+
fx += anchorDx * config.anchorStrength;
|
|
51
|
+
fy += anchorDy * config.anchorStrength;
|
|
52
|
+
nodes[i].velocityX = (nodes[i].velocityX + fx) * config.damping;
|
|
53
|
+
nodes[i].velocityY = (nodes[i].velocityY + fy) * config.damping;
|
|
54
|
+
nodes[i].nudgedX += nodes[i].velocityX;
|
|
55
|
+
nodes[i].nudgedY += nodes[i].velocityY;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return nodes.map((node) => ({
|
|
59
|
+
...node.position,
|
|
60
|
+
nudgedX: node.nudgedX,
|
|
61
|
+
nudgedY: node.nudgedY
|
|
62
|
+
}));
|
|
63
|
+
}
|
|
64
|
+
var BadgeLayoutBuilder = class _BadgeLayoutBuilder {
|
|
65
|
+
config;
|
|
66
|
+
positions;
|
|
67
|
+
constructor(positions) {
|
|
68
|
+
this.positions = positions;
|
|
69
|
+
this.config = { ...DEFAULT_CONFIG };
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Create a new layout builder with badge positions
|
|
73
|
+
*/
|
|
74
|
+
static create(positions) {
|
|
75
|
+
return new _BadgeLayoutBuilder(positions);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Set the repulsion force (how strongly badges push apart)
|
|
79
|
+
* Higher values = badges spread more aggressively
|
|
80
|
+
*/
|
|
81
|
+
repulsion(force) {
|
|
82
|
+
this.config.repulsionForce = force;
|
|
83
|
+
return this;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Set the anchor strength (how strongly badges stay near origin)
|
|
87
|
+
* Higher values = badges stay closer to their original positions
|
|
88
|
+
*/
|
|
89
|
+
anchorStrength(strength) {
|
|
90
|
+
this.config.anchorStrength = strength;
|
|
91
|
+
return this;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Set the minimum distance between badge centers
|
|
95
|
+
* Badges closer than this will be pushed apart
|
|
96
|
+
*/
|
|
97
|
+
minDistance(distance) {
|
|
98
|
+
this.config.minDistance = distance;
|
|
99
|
+
return this;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Set the number of simulation iterations
|
|
103
|
+
* More iterations = more stable but slower
|
|
104
|
+
*/
|
|
105
|
+
iterations(count) {
|
|
106
|
+
this.config.iterations = count;
|
|
107
|
+
return this;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Set the damping factor (velocity decay per step)
|
|
111
|
+
* Lower values = system settles faster but may be less stable
|
|
112
|
+
*/
|
|
113
|
+
damping(factor) {
|
|
114
|
+
this.config.damping = factor;
|
|
115
|
+
return this;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Run the simulation and return nudged positions
|
|
119
|
+
*/
|
|
120
|
+
compute() {
|
|
121
|
+
return computeLayout(this.positions, this.config);
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
function findNearbyBadges(positions, x, y, threshold) {
|
|
125
|
+
return positions.filter((p) => {
|
|
126
|
+
const dist = Math.hypot(p.nudgedX - x, p.nudgedY - y);
|
|
127
|
+
return dist <= threshold;
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// src/components/ui-lint/ElementBadges.tsx
|
|
10
132
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
11
133
|
var STYLES = {
|
|
12
134
|
bg: "rgba(17, 24, 39, 0.95)",
|
|
@@ -29,260 +151,29 @@ function getScaleFromDistance(distance) {
|
|
|
29
151
|
const t = (distance - NEAR_DISTANCE) / (FAR_DISTANCE - NEAR_DISTANCE);
|
|
30
152
|
return MAX_SCALE - t * (MAX_SCALE - MIN_SCALE);
|
|
31
153
|
}
|
|
32
|
-
var CLUSTER_THRESHOLD = 24;
|
|
33
154
|
function getBadgeColor(issueCount) {
|
|
34
155
|
if (issueCount === 0) return STYLES.success;
|
|
35
156
|
if (issueCount <= 2) return STYLES.warning;
|
|
36
157
|
return STYLES.error;
|
|
37
158
|
}
|
|
38
|
-
function
|
|
39
|
-
element
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
const [rect, setRect] = useState(null);
|
|
45
|
-
const [isHovered, setIsHovered] = useState(false);
|
|
46
|
-
useEffect(() => {
|
|
47
|
-
const updateRect = () => {
|
|
48
|
-
if (element.element && document.contains(element.element)) {
|
|
49
|
-
setRect(element.element.getBoundingClientRect());
|
|
50
|
-
} else {
|
|
51
|
-
setRect(null);
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
updateRect();
|
|
55
|
-
let rafId;
|
|
56
|
-
const handleUpdate = () => {
|
|
57
|
-
updateRect();
|
|
58
|
-
rafId = requestAnimationFrame(handleUpdate);
|
|
59
|
-
};
|
|
60
|
-
rafId = requestAnimationFrame(handleUpdate);
|
|
61
|
-
return () => {
|
|
62
|
-
cancelAnimationFrame(rafId);
|
|
63
|
-
};
|
|
64
|
-
}, [element.element]);
|
|
65
|
-
const handleClick = useCallback(
|
|
66
|
-
(e) => {
|
|
67
|
-
e.preventDefault();
|
|
68
|
-
e.stopPropagation();
|
|
69
|
-
onSelect(element, issue);
|
|
70
|
-
},
|
|
71
|
-
[element, issue, onSelect]
|
|
72
|
-
);
|
|
73
|
-
if (!rect) return null;
|
|
74
|
-
if (rect.top < -50 || rect.top > window.innerHeight + 50) return null;
|
|
75
|
-
if (rect.left < -50 || rect.left > window.innerWidth + 50) return null;
|
|
76
|
-
const scale = isHovered ? 1.1 : getScaleFromDistance(distance);
|
|
77
|
-
const badgeStyle = {
|
|
78
|
-
position: "fixed",
|
|
79
|
-
top: rect.top - 8,
|
|
80
|
-
left: rect.right - 8,
|
|
81
|
-
zIndex: isHovered ? 99999 : 99995,
|
|
82
|
-
cursor: "pointer",
|
|
83
|
-
transition: "transform 0.1s ease-out",
|
|
84
|
-
transform: `scale(${scale})`,
|
|
85
|
-
transformOrigin: "center center"
|
|
86
|
-
};
|
|
87
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
88
|
-
isHovered && /* @__PURE__ */ jsx(
|
|
89
|
-
"div",
|
|
90
|
-
{
|
|
91
|
-
style: {
|
|
92
|
-
position: "fixed",
|
|
93
|
-
top: rect.top - 2,
|
|
94
|
-
left: rect.left - 2,
|
|
95
|
-
width: rect.width + 4,
|
|
96
|
-
height: rect.height + 4,
|
|
97
|
-
border: `2px solid ${STYLES.highlight}`,
|
|
98
|
-
borderRadius: "4px",
|
|
99
|
-
pointerEvents: "none",
|
|
100
|
-
zIndex: 99994,
|
|
101
|
-
boxShadow: `0 0 0 1px rgba(59, 130, 246, 0.3)`
|
|
102
|
-
},
|
|
103
|
-
"data-ui-lint": true
|
|
104
|
-
}
|
|
105
|
-
),
|
|
106
|
-
/* @__PURE__ */ jsxs(
|
|
107
|
-
"div",
|
|
108
|
-
{
|
|
109
|
-
style: badgeStyle,
|
|
110
|
-
"data-ui-lint": true,
|
|
111
|
-
onMouseEnter: () => setIsHovered(true),
|
|
112
|
-
onMouseLeave: () => setIsHovered(false),
|
|
113
|
-
onClick: handleClick,
|
|
114
|
-
children: [
|
|
115
|
-
issue.status === "scanning" && /* @__PURE__ */ jsx(ScanningBadge, {}),
|
|
116
|
-
issue.status === "complete" && /* @__PURE__ */ jsx(IssueBadge, { count: issue.issues.length }),
|
|
117
|
-
issue.status === "error" && /* @__PURE__ */ jsx(ErrorBadge, {}),
|
|
118
|
-
issue.status === "pending" && /* @__PURE__ */ jsx(PendingBadge, {})
|
|
119
|
-
]
|
|
120
|
-
}
|
|
121
|
-
)
|
|
122
|
-
] });
|
|
123
|
-
}
|
|
124
|
-
function IssueBadge({ count }) {
|
|
125
|
-
const color = getBadgeColor(count);
|
|
126
|
-
if (count === 0) {
|
|
127
|
-
return /* @__PURE__ */ jsx(
|
|
128
|
-
"div",
|
|
129
|
-
{
|
|
130
|
-
style: {
|
|
131
|
-
display: "flex",
|
|
132
|
-
alignItems: "center",
|
|
133
|
-
justifyContent: "center",
|
|
134
|
-
width: "18px",
|
|
135
|
-
height: "18px",
|
|
136
|
-
borderRadius: "50%",
|
|
137
|
-
backgroundColor: color,
|
|
138
|
-
boxShadow: STYLES.shadow,
|
|
139
|
-
border: `1px solid ${STYLES.border}`
|
|
140
|
-
},
|
|
141
|
-
children: /* @__PURE__ */ jsx(CheckIcon, {})
|
|
142
|
-
}
|
|
143
|
-
);
|
|
159
|
+
function formatElementLabel(element) {
|
|
160
|
+
const tag = element.tagName.toLowerCase();
|
|
161
|
+
const source = element.source;
|
|
162
|
+
if (source) {
|
|
163
|
+
const fileName = source.fileName.split("/").pop() || "Unknown";
|
|
164
|
+
return `${tag} > ${fileName}`;
|
|
144
165
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
{
|
|
148
|
-
style: {
|
|
149
|
-
display: "flex",
|
|
150
|
-
alignItems: "center",
|
|
151
|
-
justifyContent: "center",
|
|
152
|
-
minWidth: "18px",
|
|
153
|
-
height: "18px",
|
|
154
|
-
padding: "0 5px",
|
|
155
|
-
borderRadius: "9px",
|
|
156
|
-
backgroundColor: color,
|
|
157
|
-
color: STYLES.text,
|
|
158
|
-
fontSize: "10px",
|
|
159
|
-
fontWeight: 700,
|
|
160
|
-
fontFamily: STYLES.font,
|
|
161
|
-
boxShadow: STYLES.shadow,
|
|
162
|
-
border: `1px solid ${STYLES.border}`
|
|
163
|
-
},
|
|
164
|
-
children: count > 9 ? "9+" : count
|
|
165
|
-
}
|
|
166
|
-
);
|
|
166
|
+
const componentName = element.componentStack[0]?.name;
|
|
167
|
+
return componentName ? `${tag} > ${componentName}` : tag;
|
|
167
168
|
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
alignItems: "center",
|
|
175
|
-
justifyContent: "center",
|
|
176
|
-
width: "18px",
|
|
177
|
-
height: "18px",
|
|
178
|
-
borderRadius: "50%",
|
|
179
|
-
backgroundColor: STYLES.bg,
|
|
180
|
-
boxShadow: STYLES.shadow,
|
|
181
|
-
border: `1px solid ${STYLES.border}`
|
|
182
|
-
},
|
|
183
|
-
children: [
|
|
184
|
-
/* @__PURE__ */ jsx("style", { children: `
|
|
185
|
-
@keyframes uilint-badge-spin {
|
|
186
|
-
from { transform: rotate(0deg); }
|
|
187
|
-
to { transform: rotate(360deg); }
|
|
188
|
-
}
|
|
189
|
-
` }),
|
|
190
|
-
/* @__PURE__ */ jsx(
|
|
191
|
-
"div",
|
|
192
|
-
{
|
|
193
|
-
style: {
|
|
194
|
-
width: "10px",
|
|
195
|
-
height: "10px",
|
|
196
|
-
border: "2px solid rgba(59, 130, 246, 0.3)",
|
|
197
|
-
borderTopColor: "#3B82F6",
|
|
198
|
-
borderRadius: "50%",
|
|
199
|
-
animation: "uilint-badge-spin 0.8s linear infinite"
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
)
|
|
203
|
-
]
|
|
204
|
-
}
|
|
205
|
-
);
|
|
206
|
-
}
|
|
207
|
-
function PendingBadge() {
|
|
208
|
-
return /* @__PURE__ */ jsx(
|
|
209
|
-
"div",
|
|
210
|
-
{
|
|
211
|
-
style: {
|
|
212
|
-
width: "10px",
|
|
213
|
-
height: "10px",
|
|
214
|
-
borderRadius: "50%",
|
|
215
|
-
backgroundColor: "rgba(156, 163, 175, 0.5)",
|
|
216
|
-
boxShadow: STYLES.shadow
|
|
169
|
+
var NEARBY_THRESHOLD = 30;
|
|
170
|
+
function BadgeAnimationStyles() {
|
|
171
|
+
return /* @__PURE__ */ jsx("style", { children: `
|
|
172
|
+
@keyframes uilint-badge-spin {
|
|
173
|
+
from { transform: rotate(0deg); }
|
|
174
|
+
to { transform: rotate(360deg); }
|
|
217
175
|
}
|
|
218
|
-
}
|
|
219
|
-
);
|
|
220
|
-
}
|
|
221
|
-
function ErrorBadge() {
|
|
222
|
-
return /* @__PURE__ */ jsx(
|
|
223
|
-
"div",
|
|
224
|
-
{
|
|
225
|
-
style: {
|
|
226
|
-
display: "flex",
|
|
227
|
-
alignItems: "center",
|
|
228
|
-
justifyContent: "center",
|
|
229
|
-
width: "18px",
|
|
230
|
-
height: "18px",
|
|
231
|
-
borderRadius: "50%",
|
|
232
|
-
backgroundColor: STYLES.error,
|
|
233
|
-
boxShadow: STYLES.shadow,
|
|
234
|
-
border: `1px solid ${STYLES.border}`
|
|
235
|
-
},
|
|
236
|
-
children: /* @__PURE__ */ jsx(ExclamationIcon, {})
|
|
237
|
-
}
|
|
238
|
-
);
|
|
239
|
-
}
|
|
240
|
-
var UnionFind = class {
|
|
241
|
-
parent = /* @__PURE__ */ new Map();
|
|
242
|
-
find(x) {
|
|
243
|
-
if (!this.parent.has(x)) {
|
|
244
|
-
this.parent.set(x, x);
|
|
245
|
-
}
|
|
246
|
-
if (this.parent.get(x) !== x) {
|
|
247
|
-
this.parent.set(x, this.find(this.parent.get(x)));
|
|
248
|
-
}
|
|
249
|
-
return this.parent.get(x);
|
|
250
|
-
}
|
|
251
|
-
union(x, y) {
|
|
252
|
-
const px = this.find(x);
|
|
253
|
-
const py = this.find(y);
|
|
254
|
-
if (px !== py) {
|
|
255
|
-
this.parent.set(px, py);
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
};
|
|
259
|
-
function clusterBadges(positions, threshold) {
|
|
260
|
-
if (positions.length === 0) return [];
|
|
261
|
-
const uf = new UnionFind();
|
|
262
|
-
for (let i = 0; i < positions.length; i++) {
|
|
263
|
-
for (let j = i + 1; j < positions.length; j++) {
|
|
264
|
-
const dist = Math.hypot(
|
|
265
|
-
positions[i].x - positions[j].x,
|
|
266
|
-
positions[i].y - positions[j].y
|
|
267
|
-
);
|
|
268
|
-
if (dist <= threshold) {
|
|
269
|
-
uf.union(positions[i].element.id, positions[j].element.id);
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
const clusters = /* @__PURE__ */ new Map();
|
|
274
|
-
for (const pos of positions) {
|
|
275
|
-
const root = uf.find(pos.element.id);
|
|
276
|
-
if (!clusters.has(root)) {
|
|
277
|
-
clusters.set(root, []);
|
|
278
|
-
}
|
|
279
|
-
clusters.get(root).push(pos);
|
|
280
|
-
}
|
|
281
|
-
return Array.from(clusters.entries()).map(([id, badges]) => {
|
|
282
|
-
const centroidX = badges.reduce((sum, b) => sum + b.x, 0) / badges.length;
|
|
283
|
-
const centroidY = badges.reduce((sum, b) => sum + b.y, 0) / badges.length;
|
|
284
|
-
return { id, badges, centroidX, centroidY };
|
|
285
|
-
});
|
|
176
|
+
` });
|
|
286
177
|
}
|
|
287
178
|
function ElementBadges() {
|
|
288
179
|
const { autoScanState, elementIssuesCache, setInspectedElement } = useUILintContext();
|
|
@@ -341,66 +232,61 @@ function ElementBadges() {
|
|
|
341
232
|
},
|
|
342
233
|
[setInspectedElement]
|
|
343
234
|
);
|
|
344
|
-
const
|
|
345
|
-
() =>
|
|
235
|
+
const nudgedPositions = useMemo(
|
|
236
|
+
() => BadgeLayoutBuilder.create(badgePositions).minDistance(24).repulsion(50).anchorStrength(0.3).iterations(50).compute(),
|
|
346
237
|
[badgePositions]
|
|
347
238
|
);
|
|
348
239
|
if (!mounted) return null;
|
|
349
240
|
if (autoScanState.status === "idle") return null;
|
|
350
|
-
const content = /* @__PURE__ */
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
const distance = Math.hypot(x - cursorPos.x, y - cursorPos.y);
|
|
354
|
-
return /* @__PURE__ */ jsx(
|
|
355
|
-
ElementBadge,
|
|
356
|
-
{
|
|
357
|
-
element,
|
|
358
|
-
issue,
|
|
359
|
-
distance,
|
|
360
|
-
onSelect: handleSelect
|
|
361
|
-
},
|
|
362
|
-
element.id
|
|
363
|
-
);
|
|
364
|
-
} else {
|
|
241
|
+
const content = /* @__PURE__ */ jsxs("div", { "data-ui-lint": true, children: [
|
|
242
|
+
/* @__PURE__ */ jsx(BadgeAnimationStyles, {}),
|
|
243
|
+
nudgedPositions.map((nudgedPos) => {
|
|
365
244
|
const distance = Math.hypot(
|
|
366
|
-
|
|
367
|
-
|
|
245
|
+
nudgedPos.nudgedX - cursorPos.x,
|
|
246
|
+
nudgedPos.nudgedY - cursorPos.y
|
|
247
|
+
);
|
|
248
|
+
const nearbyBadges = findNearbyBadges(
|
|
249
|
+
nudgedPositions,
|
|
250
|
+
nudgedPos.nudgedX,
|
|
251
|
+
nudgedPos.nudgedY,
|
|
252
|
+
NEARBY_THRESHOLD
|
|
368
253
|
);
|
|
369
254
|
return /* @__PURE__ */ jsx(
|
|
370
|
-
|
|
255
|
+
NudgedBadge,
|
|
371
256
|
{
|
|
372
|
-
|
|
257
|
+
position: nudgedPos,
|
|
373
258
|
distance,
|
|
259
|
+
nearbyBadges,
|
|
260
|
+
cursorPos,
|
|
374
261
|
onSelect: handleSelect
|
|
375
262
|
},
|
|
376
|
-
|
|
263
|
+
nudgedPos.element.id
|
|
377
264
|
);
|
|
378
|
-
}
|
|
379
|
-
|
|
265
|
+
})
|
|
266
|
+
] });
|
|
380
267
|
return createPortal(content, document.body);
|
|
381
268
|
}
|
|
382
|
-
function
|
|
269
|
+
function NudgedBadge({
|
|
270
|
+
position,
|
|
271
|
+
distance,
|
|
272
|
+
nearbyBadges,
|
|
273
|
+
cursorPos,
|
|
274
|
+
onSelect
|
|
275
|
+
}) {
|
|
383
276
|
const [isExpanded, setIsExpanded] = useState(false);
|
|
384
277
|
const [hoveredIndex, setHoveredIndex] = useState(null);
|
|
385
278
|
const closeTimeoutRef = React.useRef(null);
|
|
386
|
-
const
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
} else if (issue.status === "scanning") {
|
|
398
|
-
return { type: "scanning", color: STYLES.highlight };
|
|
399
|
-
} else {
|
|
400
|
-
return { type: "pending", color: "rgba(156, 163, 175, 0.5)" };
|
|
401
|
-
}
|
|
402
|
-
});
|
|
403
|
-
}, [cluster.badges]);
|
|
279
|
+
const { element, issue, rect, nudgedX, nudgedY } = position;
|
|
280
|
+
const hasNearbyBadges = nearbyBadges.length > 1;
|
|
281
|
+
const badgeColor = useMemo(() => {
|
|
282
|
+
if (issue.status === "error") return STYLES.error;
|
|
283
|
+
if (issue.status === "scanning") return STYLES.highlight;
|
|
284
|
+
if (issue.status === "pending") return "rgba(156, 163, 175, 0.7)";
|
|
285
|
+
if (issue.status === "complete") {
|
|
286
|
+
return getBadgeColor(issue.issues.length);
|
|
287
|
+
}
|
|
288
|
+
return STYLES.success;
|
|
289
|
+
}, [issue]);
|
|
404
290
|
const handleMouseEnter = useCallback(() => {
|
|
405
291
|
if (closeTimeoutRef.current) {
|
|
406
292
|
clearTimeout(closeTimeoutRef.current);
|
|
@@ -414,27 +300,58 @@ function ClusteredBadge({ cluster, distance, onSelect }) {
|
|
|
414
300
|
setHoveredIndex(null);
|
|
415
301
|
}, 150);
|
|
416
302
|
}, []);
|
|
417
|
-
const
|
|
303
|
+
const handleClick = useCallback(
|
|
304
|
+
(e) => {
|
|
305
|
+
e.preventDefault();
|
|
306
|
+
e.stopPropagation();
|
|
307
|
+
onSelect(element, issue);
|
|
308
|
+
},
|
|
309
|
+
[element, issue, onSelect]
|
|
310
|
+
);
|
|
311
|
+
const hoveredBadge = useMemo(() => {
|
|
312
|
+
if (hoveredIndex === null) return null;
|
|
313
|
+
return nearbyBadges[hoveredIndex] ?? null;
|
|
314
|
+
}, [hoveredIndex, nearbyBadges]);
|
|
418
315
|
const dropdownStyle = useMemo(() => {
|
|
419
|
-
const preferRight =
|
|
420
|
-
const preferBelow =
|
|
316
|
+
const preferRight = nudgedX < window.innerWidth - 220;
|
|
317
|
+
const preferBelow = nudgedY < window.innerHeight - 200;
|
|
421
318
|
return {
|
|
422
319
|
position: "fixed",
|
|
423
|
-
top: preferBelow ?
|
|
424
|
-
bottom: preferBelow ? void 0 : window.innerHeight -
|
|
425
|
-
left: preferRight ?
|
|
426
|
-
right: preferRight ? void 0 : window.innerWidth -
|
|
320
|
+
top: preferBelow ? nudgedY + 12 : void 0,
|
|
321
|
+
bottom: preferBelow ? void 0 : window.innerHeight - nudgedY + 12,
|
|
322
|
+
left: preferRight ? nudgedX - 8 : void 0,
|
|
323
|
+
right: preferRight ? void 0 : window.innerWidth - nudgedX - 8,
|
|
427
324
|
zIndex: 1e5,
|
|
428
325
|
backgroundColor: STYLES.bg,
|
|
429
326
|
borderRadius: "8px",
|
|
430
327
|
border: `1px solid ${STYLES.border}`,
|
|
431
328
|
boxShadow: "0 4px 20px rgba(0, 0, 0, 0.4)",
|
|
432
329
|
padding: "4px 0",
|
|
433
|
-
minWidth: "
|
|
330
|
+
minWidth: "200px",
|
|
434
331
|
fontFamily: STYLES.font
|
|
435
332
|
};
|
|
436
|
-
}, [
|
|
333
|
+
}, [nudgedX, nudgedY]);
|
|
334
|
+
const scale = isExpanded ? 1.1 : getScaleFromDistance(distance);
|
|
335
|
+
const issueCount = issue.status === "complete" ? issue.issues.length : 0;
|
|
437
336
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
337
|
+
isExpanded && !hoveredBadge && /* @__PURE__ */ jsx(
|
|
338
|
+
"div",
|
|
339
|
+
{
|
|
340
|
+
style: {
|
|
341
|
+
position: "fixed",
|
|
342
|
+
top: rect.top - 2,
|
|
343
|
+
left: rect.left - 2,
|
|
344
|
+
width: rect.width + 4,
|
|
345
|
+
height: rect.height + 4,
|
|
346
|
+
border: `2px solid ${STYLES.highlight}`,
|
|
347
|
+
borderRadius: "4px",
|
|
348
|
+
pointerEvents: "none",
|
|
349
|
+
zIndex: 99994,
|
|
350
|
+
boxShadow: `0 0 0 1px rgba(59, 130, 246, 0.3)`
|
|
351
|
+
},
|
|
352
|
+
"data-ui-lint": true
|
|
353
|
+
}
|
|
354
|
+
),
|
|
438
355
|
hoveredBadge && /* @__PURE__ */ jsx(
|
|
439
356
|
"div",
|
|
440
357
|
{
|
|
@@ -458,98 +375,79 @@ function ClusteredBadge({ cluster, distance, onSelect }) {
|
|
|
458
375
|
{
|
|
459
376
|
style: {
|
|
460
377
|
position: "fixed",
|
|
461
|
-
top:
|
|
462
|
-
left:
|
|
378
|
+
top: nudgedY - 9,
|
|
379
|
+
left: nudgedX - 9,
|
|
463
380
|
zIndex: isExpanded ? 99999 : 99995,
|
|
464
381
|
cursor: "pointer",
|
|
465
|
-
transition: "transform 0.1s ease-out",
|
|
466
|
-
transform: `scale(${
|
|
382
|
+
transition: "transform 0.1s ease-out, top 0.15s ease-out, left 0.15s ease-out",
|
|
383
|
+
transform: `scale(${scale})`,
|
|
467
384
|
transformOrigin: "center center"
|
|
468
385
|
},
|
|
469
386
|
"data-ui-lint": true,
|
|
470
387
|
onMouseEnter: handleMouseEnter,
|
|
471
388
|
onMouseLeave: handleMouseLeave,
|
|
389
|
+
onClick: handleClick,
|
|
472
390
|
children: /* @__PURE__ */ jsx(
|
|
473
391
|
"div",
|
|
474
392
|
{
|
|
475
393
|
style: {
|
|
476
394
|
display: "flex",
|
|
477
395
|
alignItems: "center",
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
396
|
+
justifyContent: "center",
|
|
397
|
+
width: "18px",
|
|
398
|
+
height: "18px",
|
|
399
|
+
borderRadius: "50%",
|
|
400
|
+
backgroundColor: badgeColor,
|
|
481
401
|
boxShadow: STYLES.shadow,
|
|
482
|
-
border: `1px solid ${STYLES.border}
|
|
483
|
-
overflow: "hidden"
|
|
402
|
+
border: `1px solid ${STYLES.border}`
|
|
484
403
|
},
|
|
485
|
-
children:
|
|
404
|
+
children: issue.status === "scanning" ? /* @__PURE__ */ jsx(
|
|
405
|
+
"div",
|
|
406
|
+
{
|
|
407
|
+
style: {
|
|
408
|
+
width: "10px",
|
|
409
|
+
height: "10px",
|
|
410
|
+
border: "2px solid rgba(255, 255, 255, 0.3)",
|
|
411
|
+
borderTopColor: "#FFFFFF",
|
|
412
|
+
borderRadius: "50%",
|
|
413
|
+
animation: "uilint-badge-spin 0.8s linear infinite"
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
) : issue.status === "error" ? /* @__PURE__ */ jsx(ExclamationIconTiny, {}) : issue.status === "pending" ? /* @__PURE__ */ jsx(
|
|
486
417
|
"div",
|
|
487
418
|
{
|
|
488
419
|
style: {
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
420
|
+
width: "6px",
|
|
421
|
+
height: "6px",
|
|
422
|
+
borderRadius: "50%",
|
|
423
|
+
backgroundColor: "rgba(255, 255, 255, 0.4)"
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
) : issueCount === 0 ? /* @__PURE__ */ jsx(CheckIconTiny, {}) : /* @__PURE__ */ jsx(
|
|
427
|
+
"span",
|
|
428
|
+
{
|
|
429
|
+
style: {
|
|
430
|
+
color: STYLES.text,
|
|
431
|
+
fontSize: "10px",
|
|
432
|
+
fontWeight: 700,
|
|
433
|
+
fontFamily: STYLES.font
|
|
497
434
|
},
|
|
498
|
-
children:
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
{
|
|
502
|
-
style: {
|
|
503
|
-
color: STYLES.text,
|
|
504
|
-
fontSize: "10px",
|
|
505
|
-
fontWeight: 700,
|
|
506
|
-
fontFamily: STYLES.font
|
|
507
|
-
},
|
|
508
|
-
children: segment.count > 9 ? "9+" : segment.count
|
|
509
|
-
}
|
|
510
|
-
)),
|
|
511
|
-
segment.type === "error" && /* @__PURE__ */ jsx(ExclamationIconTiny, {}),
|
|
512
|
-
segment.type === "scanning" && /* @__PURE__ */ jsx(
|
|
513
|
-
"div",
|
|
514
|
-
{
|
|
515
|
-
style: {
|
|
516
|
-
width: "8px",
|
|
517
|
-
height: "8px",
|
|
518
|
-
border: "1.5px solid rgba(255, 255, 255, 0.3)",
|
|
519
|
-
borderTopColor: "#FFFFFF",
|
|
520
|
-
borderRadius: "50%",
|
|
521
|
-
animation: "uilint-badge-spin 0.8s linear infinite"
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
),
|
|
525
|
-
segment.type === "pending" && /* @__PURE__ */ jsx(
|
|
526
|
-
"div",
|
|
527
|
-
{
|
|
528
|
-
style: {
|
|
529
|
-
width: "6px",
|
|
530
|
-
height: "6px",
|
|
531
|
-
borderRadius: "50%",
|
|
532
|
-
backgroundColor: "rgba(255, 255, 255, 0.4)"
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
)
|
|
536
|
-
]
|
|
537
|
-
},
|
|
538
|
-
index
|
|
539
|
-
))
|
|
435
|
+
children: issueCount > 9 ? "9+" : issueCount
|
|
436
|
+
}
|
|
437
|
+
)
|
|
540
438
|
}
|
|
541
439
|
)
|
|
542
440
|
}
|
|
543
441
|
),
|
|
544
|
-
isExpanded && /* @__PURE__ */ jsx(
|
|
442
|
+
isExpanded && hasNearbyBadges && /* @__PURE__ */ jsx(
|
|
545
443
|
"div",
|
|
546
444
|
{
|
|
547
445
|
style: dropdownStyle,
|
|
548
446
|
"data-ui-lint": true,
|
|
549
447
|
onMouseEnter: handleMouseEnter,
|
|
550
448
|
onMouseLeave: handleMouseLeave,
|
|
551
|
-
children:
|
|
552
|
-
|
|
449
|
+
children: nearbyBadges.map((badge, index) => /* @__PURE__ */ jsx(
|
|
450
|
+
DropdownItem,
|
|
553
451
|
{
|
|
554
452
|
badge,
|
|
555
453
|
isHovered: hoveredIndex === index,
|
|
@@ -563,14 +461,14 @@ function ClusteredBadge({ cluster, distance, onSelect }) {
|
|
|
563
461
|
)
|
|
564
462
|
] });
|
|
565
463
|
}
|
|
566
|
-
function
|
|
464
|
+
function DropdownItem({
|
|
567
465
|
badge,
|
|
568
466
|
isHovered,
|
|
569
467
|
onMouseEnter,
|
|
570
468
|
onMouseLeave,
|
|
571
469
|
onClick
|
|
572
470
|
}) {
|
|
573
|
-
const
|
|
471
|
+
const elementLabel = formatElementLabel(badge.element);
|
|
574
472
|
const issueCount = badge.issue.status === "complete" ? badge.issue.issues.length : 0;
|
|
575
473
|
const color = getBadgeColor(issueCount);
|
|
576
474
|
return /* @__PURE__ */ jsxs(
|
|
@@ -607,12 +505,12 @@ function ClusterDropdownItem({
|
|
|
607
505
|
style: {
|
|
608
506
|
fontSize: "12px",
|
|
609
507
|
color: STYLES.text,
|
|
610
|
-
maxWidth: "
|
|
508
|
+
maxWidth: "160px",
|
|
611
509
|
overflow: "hidden",
|
|
612
510
|
textOverflow: "ellipsis",
|
|
613
511
|
whiteSpace: "nowrap"
|
|
614
512
|
},
|
|
615
|
-
children:
|
|
513
|
+
children: elementLabel
|
|
616
514
|
}
|
|
617
515
|
)
|
|
618
516
|
] }),
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
buildEditorUrl,
|
|
4
4
|
useUILintContext,
|
|
5
5
|
useUILintStore
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-GJJH5B4Y.js";
|
|
7
7
|
|
|
8
8
|
// src/components/ui-lint/InspectionPanel.tsx
|
|
9
9
|
import { useState, useEffect, useCallback, useMemo } from "react";
|
|
@@ -570,7 +570,10 @@ function ScanSection({ element }) {
|
|
|
570
570
|
const manualScan = useUILintStore(
|
|
571
571
|
(s) => s.manualScanCache.get(manualKey)
|
|
572
572
|
);
|
|
573
|
-
const upsertManualScan = useUILintStore(
|
|
573
|
+
const upsertManualScan = useUILintStore(
|
|
574
|
+
(s) => s.upsertManualScan
|
|
575
|
+
);
|
|
576
|
+
const includeChildren = manualScan?.includeChildren ?? false;
|
|
574
577
|
const componentName = element.componentStack[0]?.name || element.element.tagName.toLowerCase();
|
|
575
578
|
const componentLine = element.source?.lineNumber;
|
|
576
579
|
const cachedIssue = useMemo(() => {
|
|
@@ -626,6 +629,22 @@ Please update this component to match our styleguide.`;
|
|
|
626
629
|
});
|
|
627
630
|
return;
|
|
628
631
|
}
|
|
632
|
+
const MAX_DATALOCS = 80;
|
|
633
|
+
const selectedDataLoc = element.element.getAttribute("data-loc");
|
|
634
|
+
let dataLocList = [];
|
|
635
|
+
if (includeChildren) {
|
|
636
|
+
const nodes = [
|
|
637
|
+
element.element,
|
|
638
|
+
...Array.from(element.element.querySelectorAll("[data-loc]"))
|
|
639
|
+
];
|
|
640
|
+
for (const n of nodes) {
|
|
641
|
+
const v = n.getAttribute("data-loc");
|
|
642
|
+
if (v) dataLocList.push(v);
|
|
643
|
+
}
|
|
644
|
+
} else if (selectedDataLoc) {
|
|
645
|
+
dataLocList = [selectedDataLoc];
|
|
646
|
+
}
|
|
647
|
+
dataLocList = Array.from(new Set(dataLocList)).slice(0, MAX_DATALOCS);
|
|
629
648
|
upsertManualScan(manualKey, {
|
|
630
649
|
status: "scanning",
|
|
631
650
|
error: void 0,
|
|
@@ -645,7 +664,6 @@ Please update this component to match our styleguide.`;
|
|
|
645
664
|
const sourceData = await sourceResponse.json();
|
|
646
665
|
const sourceCode = sourceData.content;
|
|
647
666
|
const relativePath = sourceData.relativePath || element.source.fileName;
|
|
648
|
-
const dataLoc = element.element.getAttribute("data-loc");
|
|
649
667
|
const analyzeResponse = await fetch("/api/.uilint/analyze", {
|
|
650
668
|
method: "POST",
|
|
651
669
|
headers: { "Content-Type": "application/json" },
|
|
@@ -654,7 +672,8 @@ Please update this component to match our styleguide.`;
|
|
|
654
672
|
filePath: relativePath,
|
|
655
673
|
componentName,
|
|
656
674
|
componentLine,
|
|
657
|
-
|
|
675
|
+
includeChildren,
|
|
676
|
+
dataLocs: dataLocList.length > 0 ? dataLocList : void 0,
|
|
658
677
|
stream: true
|
|
659
678
|
})
|
|
660
679
|
});
|
|
@@ -732,20 +751,24 @@ Please update this component to match our styleguide.`;
|
|
|
732
751
|
componentLine,
|
|
733
752
|
generateFixPrompt,
|
|
734
753
|
manualKey,
|
|
735
|
-
upsertManualScan
|
|
754
|
+
upsertManualScan,
|
|
755
|
+
includeChildren
|
|
736
756
|
]);
|
|
737
|
-
const handleCopy = useCallback(
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
757
|
+
const handleCopy = useCallback(
|
|
758
|
+
async (text) => {
|
|
759
|
+
try {
|
|
760
|
+
await navigator.clipboard.writeText(text);
|
|
761
|
+
setCopied(true);
|
|
762
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
763
|
+
} catch {
|
|
764
|
+
upsertManualScan(manualKey, {
|
|
765
|
+
status: "error",
|
|
766
|
+
error: "Failed to copy to clipboard"
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
},
|
|
770
|
+
[manualKey, upsertManualScan]
|
|
771
|
+
);
|
|
749
772
|
const manualStatus = manualScan?.status ?? "idle";
|
|
750
773
|
const showCachedScanning = cachedIssue?.status === "scanning" && manualStatus === "idle";
|
|
751
774
|
const showCachedPending = cachedIssue?.status === "pending" && manualStatus === "idle";
|
|
@@ -757,6 +780,7 @@ Please update this component to match our styleguide.`;
|
|
|
757
780
|
const error = manualScan?.status === "error" ? manualScan.error : null;
|
|
758
781
|
const fixPrompt = manualScan?.fixPrompt ?? null;
|
|
759
782
|
const progressLine = manualScan?.progressLine ?? null;
|
|
783
|
+
const scopeLabel = includeChildren ? "Element + children" : "Element only";
|
|
760
784
|
return /* @__PURE__ */ jsx(
|
|
761
785
|
"div",
|
|
762
786
|
{
|
|
@@ -1025,6 +1049,39 @@ Please update this component to match our styleguide.`;
|
|
|
1025
1049
|
) })
|
|
1026
1050
|
] }),
|
|
1027
1051
|
showScanButton && /* @__PURE__ */ jsxs("div", { style: { textAlign: "center", padding: "16px 0" }, children: [
|
|
1052
|
+
/* @__PURE__ */ jsxs("div", { style: { marginBottom: "10px" }, children: [
|
|
1053
|
+
/* @__PURE__ */ jsxs(
|
|
1054
|
+
"label",
|
|
1055
|
+
{
|
|
1056
|
+
style: {
|
|
1057
|
+
display: "inline-flex",
|
|
1058
|
+
alignItems: "center",
|
|
1059
|
+
gap: "8px",
|
|
1060
|
+
fontSize: "12px",
|
|
1061
|
+
color: STYLES.textMuted,
|
|
1062
|
+
cursor: "pointer",
|
|
1063
|
+
userSelect: "none"
|
|
1064
|
+
},
|
|
1065
|
+
children: [
|
|
1066
|
+
/* @__PURE__ */ jsx(
|
|
1067
|
+
"input",
|
|
1068
|
+
{
|
|
1069
|
+
type: "checkbox",
|
|
1070
|
+
checked: includeChildren,
|
|
1071
|
+
onChange: (e) => upsertManualScan(manualKey, {
|
|
1072
|
+
includeChildren: e.currentTarget.checked
|
|
1073
|
+
})
|
|
1074
|
+
}
|
|
1075
|
+
),
|
|
1076
|
+
"Include children"
|
|
1077
|
+
]
|
|
1078
|
+
}
|
|
1079
|
+
),
|
|
1080
|
+
/* @__PURE__ */ jsxs("div", { style: { marginTop: "6px", fontSize: "11px", color: STYLES.textDim }, children: [
|
|
1081
|
+
"Scope: ",
|
|
1082
|
+
scopeLabel
|
|
1083
|
+
] })
|
|
1084
|
+
] }),
|
|
1028
1085
|
/* @__PURE__ */ jsxs(
|
|
1029
1086
|
"button",
|
|
1030
1087
|
{
|
|
@@ -796,10 +796,10 @@ function UILintUI() {
|
|
|
796
796
|
const [components, setComponents] = useState(null);
|
|
797
797
|
useEffect(() => {
|
|
798
798
|
Promise.all([
|
|
799
|
-
import("./UILintToolbar-
|
|
800
|
-
import("./InspectionPanel-
|
|
801
|
-
import("./LocatorOverlay-
|
|
802
|
-
import("./ElementBadges-
|
|
799
|
+
import("./UILintToolbar-AX67REOL.js"),
|
|
800
|
+
import("./InspectionPanel-7K662MF5.js"),
|
|
801
|
+
import("./LocatorOverlay-C4IVDVBW.js"),
|
|
802
|
+
import("./ElementBadges-ZDGDJFQU.js")
|
|
803
803
|
]).then(([toolbar, panel, locator, badges]) => {
|
|
804
804
|
setComponents({
|
|
805
805
|
Toolbar: toolbar.UILintToolbar,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import {
|
|
3
3
|
useUILintContext
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-GJJH5B4Y.js";
|
|
5
5
|
|
|
6
6
|
// src/components/ui-lint/UILintToolbar.tsx
|
|
7
7
|
import { useState, useRef, useEffect } from "react";
|
|
@@ -176,14 +176,6 @@ function SettingsPopover({
|
|
|
176
176
|
children: "UILint Settings"
|
|
177
177
|
}
|
|
178
178
|
),
|
|
179
|
-
/* @__PURE__ */ jsx(
|
|
180
|
-
SettingToggle,
|
|
181
|
-
{
|
|
182
|
-
label: "Hide node_modules",
|
|
183
|
-
checked: settings.hideNodeModules,
|
|
184
|
-
onChange: (checked) => onUpdate({ hideNodeModules: checked })
|
|
185
|
-
}
|
|
186
|
-
),
|
|
187
179
|
/* @__PURE__ */ jsxs(
|
|
188
180
|
"div",
|
|
189
181
|
{
|
|
@@ -432,57 +424,6 @@ function SettingsPopover({
|
|
|
432
424
|
}
|
|
433
425
|
);
|
|
434
426
|
}
|
|
435
|
-
function SettingToggle({
|
|
436
|
-
label,
|
|
437
|
-
checked,
|
|
438
|
-
onChange
|
|
439
|
-
}) {
|
|
440
|
-
return /* @__PURE__ */ jsxs(
|
|
441
|
-
"label",
|
|
442
|
-
{
|
|
443
|
-
style: {
|
|
444
|
-
display: "flex",
|
|
445
|
-
alignItems: "center",
|
|
446
|
-
justifyContent: "space-between",
|
|
447
|
-
padding: "8px 0",
|
|
448
|
-
cursor: "pointer"
|
|
449
|
-
},
|
|
450
|
-
children: [
|
|
451
|
-
/* @__PURE__ */ jsx("span", { style: { fontSize: "12px", color: STYLES.textMuted }, children: label }),
|
|
452
|
-
/* @__PURE__ */ jsx(
|
|
453
|
-
"div",
|
|
454
|
-
{
|
|
455
|
-
onClick: () => onChange(!checked),
|
|
456
|
-
style: {
|
|
457
|
-
width: "36px",
|
|
458
|
-
height: "20px",
|
|
459
|
-
borderRadius: "10px",
|
|
460
|
-
backgroundColor: checked ? STYLES.accent : "rgba(75, 85, 99, 0.5)",
|
|
461
|
-
position: "relative",
|
|
462
|
-
transition: "background-color 0.2s"
|
|
463
|
-
},
|
|
464
|
-
children: /* @__PURE__ */ jsx(
|
|
465
|
-
"div",
|
|
466
|
-
{
|
|
467
|
-
style: {
|
|
468
|
-
position: "absolute",
|
|
469
|
-
top: "2px",
|
|
470
|
-
left: checked ? "18px" : "2px",
|
|
471
|
-
width: "16px",
|
|
472
|
-
height: "16px",
|
|
473
|
-
borderRadius: "50%",
|
|
474
|
-
backgroundColor: "#FFFFFF",
|
|
475
|
-
transition: "left 0.2s",
|
|
476
|
-
boxShadow: "0 1px 3px rgba(0, 0, 0, 0.2)"
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
)
|
|
480
|
-
}
|
|
481
|
-
)
|
|
482
|
-
]
|
|
483
|
-
}
|
|
484
|
-
);
|
|
485
|
-
}
|
|
486
427
|
function UILintIcon({ active }) {
|
|
487
428
|
return /* @__PURE__ */ jsxs("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", children: [
|
|
488
429
|
/* @__PURE__ */ jsx(
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import {
|
|
3
3
|
UILintToolbar
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-KBEQSZMW.js";
|
|
5
5
|
import {
|
|
6
6
|
InspectionPanel,
|
|
7
7
|
clearSourceCache,
|
|
@@ -9,10 +9,10 @@ import {
|
|
|
9
9
|
fetchSourceWithContext,
|
|
10
10
|
getCachedSource,
|
|
11
11
|
prefetchSources
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-5CWWYEQM.js";
|
|
13
13
|
import {
|
|
14
14
|
LocatorOverlay
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-IMPRRMMY.js";
|
|
16
16
|
import {
|
|
17
17
|
DATA_UILINT_ID,
|
|
18
18
|
DEFAULT_SETTINGS,
|
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
scanDOMForSources,
|
|
32
32
|
updateElementRects,
|
|
33
33
|
useUILintContext
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-GJJH5B4Y.js";
|
|
35
35
|
|
|
36
36
|
// src/consistency/snapshot.ts
|
|
37
37
|
var DATA_ELEMENTS_ATTR = "data-elements";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uilint-react",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.30",
|
|
4
4
|
"description": "React component for AI-powered UI consistency checking",
|
|
5
5
|
"author": "Peter Suggate",
|
|
6
6
|
"repository": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"node": ">=20.0.0"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"uilint-core": "^0.1.
|
|
37
|
+
"uilint-core": "^0.1.30",
|
|
38
38
|
"zustand": "^5.0.5"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|