uilint-react 0.1.21 → 0.1.23

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.
@@ -28,7 +28,14 @@ var FILE_COLORS = [
28
28
  // purple
29
29
  ];
30
30
  var DEFAULT_SETTINGS = {
31
- hideNodeModules: true
31
+ hideNodeModules: true,
32
+ autoScanEnabled: false
33
+ };
34
+ var DEFAULT_AUTO_SCAN_STATE = {
35
+ status: "idle",
36
+ currentIndex: 0,
37
+ totalElements: 0,
38
+ elements: []
32
39
  };
33
40
  var DATA_UILINT_ID = "data-ui-lint-id";
34
41
 
@@ -254,7 +261,8 @@ import {
254
261
  useState,
255
262
  useEffect,
256
263
  useCallback,
257
- useMemo
264
+ useMemo,
265
+ useRef
258
266
  } from "react";
259
267
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
260
268
  var UILintContext = createContext(null);
@@ -280,9 +288,185 @@ function UILintProvider({
280
288
  );
281
289
  const [locatorStackIndex, setLocatorStackIndex] = useState(0);
282
290
  const [inspectedElement, setInspectedElement] = useState(null);
291
+ const [autoScanState, setAutoScanState] = useState(
292
+ DEFAULT_AUTO_SCAN_STATE
293
+ );
294
+ const [elementIssuesCache, setElementIssuesCache] = useState(/* @__PURE__ */ new Map());
295
+ const scanPausedRef = useRef(false);
296
+ const scanAbortRef = useRef(false);
283
297
  const updateSettings = useCallback((partial) => {
284
298
  setSettings((prev) => ({ ...prev, ...partial }));
285
299
  }, []);
300
+ const scanElementForIssues = useCallback(
301
+ async (element) => {
302
+ if (!element.source) {
303
+ return {
304
+ elementId: element.id,
305
+ issues: [],
306
+ status: "complete"
307
+ };
308
+ }
309
+ try {
310
+ const sourceResponse = await fetch(
311
+ `/api/.uilint/source?path=${encodeURIComponent(
312
+ element.source.fileName
313
+ )}`
314
+ );
315
+ if (!sourceResponse.ok) {
316
+ return {
317
+ elementId: element.id,
318
+ issues: [],
319
+ status: "error"
320
+ };
321
+ }
322
+ const sourceData = await sourceResponse.json();
323
+ const analyzeResponse = await fetch("/api/.uilint/analyze", {
324
+ method: "POST",
325
+ headers: { "Content-Type": "application/json" },
326
+ body: JSON.stringify({
327
+ sourceCode: sourceData.content,
328
+ filePath: sourceData.relativePath || element.source.fileName,
329
+ componentName: element.componentStack[0]?.name || element.tagName,
330
+ componentLine: element.source.lineNumber
331
+ })
332
+ });
333
+ if (!analyzeResponse.ok) {
334
+ return {
335
+ elementId: element.id,
336
+ issues: [],
337
+ status: "error"
338
+ };
339
+ }
340
+ const result = await analyzeResponse.json();
341
+ return {
342
+ elementId: element.id,
343
+ issues: result.issues || [],
344
+ status: "complete"
345
+ };
346
+ } catch {
347
+ return {
348
+ elementId: element.id,
349
+ issues: [],
350
+ status: "error"
351
+ };
352
+ }
353
+ },
354
+ []
355
+ );
356
+ const runScanLoop = useCallback(
357
+ async (elements, startIndex) => {
358
+ const fileToElements = /* @__PURE__ */ new Map();
359
+ const scannedFiles = /* @__PURE__ */ new Set();
360
+ for (const el of elements) {
361
+ if (el.source) {
362
+ const file = el.source.fileName;
363
+ const existing = fileToElements.get(file) || [];
364
+ existing.push(el);
365
+ fileToElements.set(file, existing);
366
+ }
367
+ }
368
+ for (let i = startIndex; i < elements.length; i++) {
369
+ if (scanAbortRef.current) {
370
+ setAutoScanState((prev) => ({ ...prev, status: "idle" }));
371
+ return;
372
+ }
373
+ while (scanPausedRef.current) {
374
+ await new Promise((resolve) => setTimeout(resolve, 100));
375
+ if (scanAbortRef.current) {
376
+ setAutoScanState((prev) => ({ ...prev, status: "idle" }));
377
+ return;
378
+ }
379
+ }
380
+ const element = elements[i];
381
+ setAutoScanState((prev) => ({
382
+ ...prev,
383
+ currentIndex: i
384
+ }));
385
+ if (element.source && scannedFiles.has(element.source.fileName)) {
386
+ const existingElements = fileToElements.get(element.source.fileName);
387
+ if (existingElements && existingElements.length > 0) {
388
+ const firstId = existingElements[0].id;
389
+ setElementIssuesCache((prev) => {
390
+ const cached = prev.get(firstId);
391
+ if (cached) {
392
+ const newCache = new Map(prev);
393
+ newCache.set(element.id, { ...cached, elementId: element.id });
394
+ return newCache;
395
+ }
396
+ return prev;
397
+ });
398
+ }
399
+ continue;
400
+ }
401
+ setElementIssuesCache((prev) => {
402
+ const newCache = new Map(prev);
403
+ newCache.set(element.id, {
404
+ elementId: element.id,
405
+ issues: [],
406
+ status: "scanning"
407
+ });
408
+ return newCache;
409
+ });
410
+ const result = await scanElementForIssues(element);
411
+ setElementIssuesCache((prev) => {
412
+ const newCache = new Map(prev);
413
+ newCache.set(element.id, result);
414
+ return newCache;
415
+ });
416
+ if (element.source) {
417
+ scannedFiles.add(element.source.fileName);
418
+ }
419
+ await new Promise((resolve) => setTimeout(resolve, 100));
420
+ }
421
+ setAutoScanState((prev) => ({
422
+ ...prev,
423
+ status: "complete",
424
+ currentIndex: elements.length
425
+ }));
426
+ },
427
+ [scanElementForIssues]
428
+ );
429
+ const startAutoScan = useCallback(() => {
430
+ scanPausedRef.current = false;
431
+ scanAbortRef.current = false;
432
+ const elements = scanDOMForSources(document.body, settings.hideNodeModules);
433
+ const initialCache = /* @__PURE__ */ new Map();
434
+ for (const el of elements) {
435
+ initialCache.set(el.id, {
436
+ elementId: el.id,
437
+ issues: [],
438
+ status: "pending"
439
+ });
440
+ }
441
+ setElementIssuesCache(initialCache);
442
+ setAutoScanState({
443
+ status: "scanning",
444
+ currentIndex: 0,
445
+ totalElements: elements.length,
446
+ elements
447
+ });
448
+ runScanLoop(elements, 0);
449
+ }, [settings.hideNodeModules, runScanLoop]);
450
+ const pauseAutoScan = useCallback(() => {
451
+ scanPausedRef.current = true;
452
+ setAutoScanState((prev) => ({ ...prev, status: "paused" }));
453
+ }, []);
454
+ const resumeAutoScan = useCallback(() => {
455
+ scanPausedRef.current = false;
456
+ setAutoScanState((prev) => {
457
+ if (prev.status === "paused") {
458
+ runScanLoop(prev.elements, prev.currentIndex);
459
+ return { ...prev, status: "scanning" };
460
+ }
461
+ return prev;
462
+ });
463
+ }, [runScanLoop]);
464
+ const stopAutoScan = useCallback(() => {
465
+ scanAbortRef.current = true;
466
+ scanPausedRef.current = false;
467
+ setAutoScanState(DEFAULT_AUTO_SCAN_STATE);
468
+ setElementIssuesCache(/* @__PURE__ */ new Map());
469
+ }, []);
286
470
  const locatorGoUp = useCallback(() => {
287
471
  if (!locatorTarget) return;
288
472
  const maxIndex = locatorTarget.componentStack.length;
@@ -329,7 +513,7 @@ function UILintProvider({
329
513
  );
330
514
  const handleMouseMove = useCallback(
331
515
  (e) => {
332
- if (!altKeyHeld) return;
516
+ if (!altKeyHeld && !inspectedElement) return;
333
517
  const elementAtPoint = document.elementFromPoint(e.clientX, e.clientY);
334
518
  if (!elementAtPoint) {
335
519
  setLocatorTarget(null);
@@ -346,7 +530,7 @@ function UILintProvider({
346
530
  }
347
531
  setLocatorTarget(null);
348
532
  },
349
- [altKeyHeld, getLocatorTargetFromElement]
533
+ [altKeyHeld, inspectedElement, getLocatorTargetFromElement]
350
534
  );
351
535
  const handleLocatorClick = useCallback(
352
536
  (e) => {
@@ -402,14 +586,23 @@ function UILintProvider({
402
586
  };
403
587
  }, [enabled]);
404
588
  useEffect(() => {
405
- if (!isBrowser() || !enabled || !altKeyHeld) return;
589
+ if (!isBrowser() || !enabled) return;
590
+ if (!altKeyHeld && !inspectedElement) return;
406
591
  window.addEventListener("mousemove", handleMouseMove);
407
- window.addEventListener("click", handleLocatorClick, true);
592
+ if (altKeyHeld) {
593
+ window.addEventListener("click", handleLocatorClick, true);
594
+ }
408
595
  return () => {
409
596
  window.removeEventListener("mousemove", handleMouseMove);
410
597
  window.removeEventListener("click", handleLocatorClick, true);
411
598
  };
412
- }, [enabled, altKeyHeld, handleMouseMove, handleLocatorClick]);
599
+ }, [
600
+ enabled,
601
+ altKeyHeld,
602
+ inspectedElement,
603
+ handleMouseMove,
604
+ handleLocatorClick
605
+ ]);
413
606
  useEffect(() => {
414
607
  if (!isBrowser() || !enabled || !altKeyHeld) return;
415
608
  const handleWheel = (e) => {
@@ -453,7 +646,13 @@ function UILintProvider({
453
646
  locatorGoUp,
454
647
  locatorGoDown,
455
648
  inspectedElement,
456
- setInspectedElement
649
+ setInspectedElement,
650
+ autoScanState,
651
+ elementIssuesCache,
652
+ startAutoScan,
653
+ pauseAutoScan,
654
+ resumeAutoScan,
655
+ stopAutoScan
457
656
  }),
458
657
  [
459
658
  settings,
@@ -462,7 +661,13 @@ function UILintProvider({
462
661
  effectiveLocatorTarget,
463
662
  locatorGoUp,
464
663
  locatorGoDown,
465
- inspectedElement
664
+ inspectedElement,
665
+ autoScanState,
666
+ elementIssuesCache,
667
+ startAutoScan,
668
+ pauseAutoScan,
669
+ resumeAutoScan,
670
+ stopAutoScan
466
671
  ]
467
672
  );
468
673
  const shouldRenderUI = enabled && isMounted;
@@ -472,27 +677,31 @@ function UILintProvider({
472
677
  ] });
473
678
  }
474
679
  function UILintUI() {
475
- const { altKeyHeld, inspectedElement } = useUILintContext();
680
+ const { altKeyHeld, inspectedElement, autoScanState } = useUILintContext();
476
681
  const [components, setComponents] = useState(null);
477
682
  useEffect(() => {
478
683
  Promise.all([
479
- import("./UILintToolbar-C6HOAJA4.js"),
480
- import("./InspectionPanel-ZBDXQ2LU.js"),
481
- import("./LocatorOverlay-3H446RPO.js")
482
- ]).then(([toolbar, panel, locator]) => {
684
+ import("./UILintToolbar-7TFNXFZJ.js"),
685
+ import("./InspectionPanel-54HO4UI5.js"),
686
+ import("./LocatorOverlay-AXB5VERJ.js"),
687
+ import("./ElementBadges-64UOI6QT.js")
688
+ ]).then(([toolbar, panel, locator, badges]) => {
483
689
  setComponents({
484
690
  Toolbar: toolbar.UILintToolbar,
485
691
  Panel: panel.InspectionPanel,
486
692
  LocatorOverlay: locator.LocatorOverlay,
487
- InspectedHighlight: locator.InspectedElementHighlight
693
+ InspectedHighlight: locator.InspectedElementHighlight,
694
+ ElementBadges: badges.ElementBadges
488
695
  });
489
696
  });
490
697
  }, []);
491
698
  if (!components) return null;
492
- const { Toolbar, Panel, LocatorOverlay, InspectedHighlight } = components;
699
+ const { Toolbar, Panel, LocatorOverlay, InspectedHighlight, ElementBadges } = components;
700
+ const showBadges = autoScanState.status !== "idle";
493
701
  return /* @__PURE__ */ jsxs(Fragment, { children: [
494
702
  /* @__PURE__ */ jsx(Toolbar, {}),
495
- altKeyHeld && /* @__PURE__ */ jsx(LocatorOverlay, {}),
703
+ (altKeyHeld || inspectedElement) && /* @__PURE__ */ jsx(LocatorOverlay, {}),
704
+ showBadges && /* @__PURE__ */ jsx(ElementBadges, {}),
496
705
  inspectedElement && /* @__PURE__ */ jsxs(Fragment, { children: [
497
706
  /* @__PURE__ */ jsx(InspectedHighlight, {}),
498
707
  /* @__PURE__ */ jsx(Panel, {})
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import {
3
3
  useUILintContext
4
- } from "./chunk-EBU7YY73.js";
4
+ } from "./chunk-XPAUSE5Z.js";
5
5
 
6
6
  // src/components/ui-lint/LocatorOverlay.tsx
7
7
  import { useState, useEffect, useMemo } from "react";
package/dist/index.d.ts CHANGED
@@ -47,6 +47,27 @@ interface SourceFile {
47
47
  */
48
48
  interface UILintSettings {
49
49
  hideNodeModules: boolean;
50
+ autoScanEnabled: boolean;
51
+ }
52
+ /**
53
+ * State for the auto-scan feature
54
+ */
55
+ interface AutoScanState {
56
+ status: "idle" | "scanning" | "paused" | "complete";
57
+ currentIndex: number;
58
+ totalElements: number;
59
+ elements: ScannedElement[];
60
+ }
61
+ /**
62
+ * Cached issue data for a scanned element
63
+ */
64
+ interface ElementIssue {
65
+ elementId: string;
66
+ issues: Array<{
67
+ line?: number;
68
+ message: string;
69
+ }>;
70
+ status: "pending" | "scanning" | "complete" | "error";
50
71
  }
51
72
  /**
52
73
  * Element detected under the cursor during Alt-key locator mode
@@ -86,6 +107,18 @@ interface UILintContextValue {
86
107
  inspectedElement: InspectedElement | null;
87
108
  /** Set the element to inspect (opens sidebar) */
88
109
  setInspectedElement: (element: InspectedElement | null) => void;
110
+ /** Auto-scan state */
111
+ autoScanState: AutoScanState;
112
+ /** Cache of element issues from auto-scan */
113
+ elementIssuesCache: Map<string, ElementIssue>;
114
+ /** Start auto-scanning all page elements */
115
+ startAutoScan: () => void;
116
+ /** Pause the auto-scan */
117
+ pauseAutoScan: () => void;
118
+ /** Resume the auto-scan */
119
+ resumeAutoScan: () => void;
120
+ /** Stop and reset the auto-scan */
121
+ stopAutoScan: () => void;
89
122
  }
90
123
  /**
91
124
  * Props for the UILintProvider component
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import {
3
3
  UILintToolbar
4
- } from "./chunk-GUF36FGA.js";
4
+ } from "./chunk-7M2NF7HT.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-CWCKS753.js";
12
+ } from "./chunk-7BJIS7PI.js";
13
13
  import {
14
14
  LocatorOverlay
15
- } from "./chunk-3DNDKMZ4.js";
15
+ } from "./chunk-ZMGUWRAO.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-EBU7YY73.js";
34
+ } from "./chunk-XPAUSE5Z.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.21",
3
+ "version": "0.1.23",
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.21"
37
+ "uilint-core": "^0.1.23"
38
38
  },
39
39
  "peerDependencies": {
40
40
  "react": "^19.0.0",
@@ -1,276 +0,0 @@
1
- "use client";
2
- import {
3
- useUILintContext
4
- } from "./chunk-EBU7YY73.js";
5
-
6
- // src/components/ui-lint/UILintToolbar.tsx
7
- import { useState, useRef, useEffect } from "react";
8
- import { createPortal } from "react-dom";
9
- import { jsx, jsxs } from "react/jsx-runtime";
10
- var STYLES = {
11
- bg: "rgba(17, 24, 39, 0.9)",
12
- bgHover: "rgba(31, 41, 55, 0.95)",
13
- border: "rgba(75, 85, 99, 0.5)",
14
- text: "#F9FAFB",
15
- textMuted: "#9CA3AF",
16
- accent: "#3B82F6",
17
- accentHover: "#2563EB",
18
- shadow: "0 8px 32px rgba(0, 0, 0, 0.4)",
19
- blur: "blur(12px)",
20
- font: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
21
- fontMono: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace'
22
- };
23
- function UILintToolbar() {
24
- const { settings, updateSettings, inspectedElement } = useUILintContext();
25
- const [showSettings, setShowSettings] = useState(false);
26
- const [mounted, setMounted] = useState(false);
27
- const settingsRef = useRef(null);
28
- useEffect(() => {
29
- setMounted(true);
30
- }, []);
31
- useEffect(() => {
32
- const handleClickOutside = (e) => {
33
- if (settingsRef.current && !settingsRef.current.contains(e.target)) {
34
- setShowSettings(false);
35
- }
36
- };
37
- if (showSettings) {
38
- document.addEventListener("mousedown", handleClickOutside);
39
- return () => document.removeEventListener("mousedown", handleClickOutside);
40
- }
41
- }, [showSettings]);
42
- if (!mounted) return null;
43
- if (inspectedElement) return null;
44
- const content = /* @__PURE__ */ jsxs(
45
- "div",
46
- {
47
- "data-ui-lint": true,
48
- style: {
49
- position: "fixed",
50
- top: "24px",
51
- right: "24px",
52
- zIndex: 99999,
53
- fontFamily: STYLES.font
54
- },
55
- children: [
56
- /* @__PURE__ */ jsx("style", { children: `
57
- @keyframes uilint-fade-in {
58
- from { opacity: 0; transform: scale(0.95); }
59
- to { opacity: 1; transform: scale(1); }
60
- }
61
- ` }),
62
- /* @__PURE__ */ jsxs("div", { style: { position: "relative" }, ref: settingsRef, children: [
63
- /* @__PURE__ */ jsx(
64
- "button",
65
- {
66
- onClick: () => setShowSettings(!showSettings),
67
- style: {
68
- display: "flex",
69
- alignItems: "center",
70
- justifyContent: "center",
71
- width: "48px",
72
- height: "48px",
73
- borderRadius: "50%",
74
- border: `1px solid ${STYLES.border}`,
75
- backgroundColor: showSettings ? STYLES.bgHover : STYLES.bg,
76
- backdropFilter: STYLES.blur,
77
- WebkitBackdropFilter: STYLES.blur,
78
- boxShadow: STYLES.shadow,
79
- cursor: "pointer",
80
- transition: "all 0.2s ease-out",
81
- color: showSettings ? STYLES.text : STYLES.textMuted,
82
- fontSize: "20px"
83
- },
84
- onMouseEnter: (e) => {
85
- e.currentTarget.style.transform = "scale(1.05)";
86
- e.currentTarget.style.boxShadow = "0 12px 40px rgba(0, 0, 0, 0.5)";
87
- },
88
- onMouseLeave: (e) => {
89
- e.currentTarget.style.transform = "scale(1)";
90
- e.currentTarget.style.boxShadow = STYLES.shadow;
91
- },
92
- title: "UILint Settings (Alt+Click any element to inspect)",
93
- children: /* @__PURE__ */ jsx(UILintIcon, { active: showSettings })
94
- }
95
- ),
96
- showSettings && /* @__PURE__ */ jsx(SettingsPopover, { settings, onUpdate: updateSettings }),
97
- /* @__PURE__ */ jsxs(
98
- "div",
99
- {
100
- style: {
101
- position: "absolute",
102
- left: "100%",
103
- top: "50%",
104
- transform: "translateY(-50%)",
105
- marginLeft: "12px",
106
- padding: "8px 12px",
107
- borderRadius: "8px",
108
- backgroundColor: STYLES.bg,
109
- border: `1px solid ${STYLES.border}`,
110
- backdropFilter: STYLES.blur,
111
- WebkitBackdropFilter: STYLES.blur,
112
- boxShadow: STYLES.shadow,
113
- fontSize: "12px",
114
- color: STYLES.textMuted,
115
- whiteSpace: "nowrap",
116
- opacity: 0,
117
- transition: "opacity 0.2s",
118
- pointerEvents: "none"
119
- },
120
- className: "uilint-hint",
121
- children: [
122
- /* @__PURE__ */ jsx("span", { style: { color: STYLES.text }, children: "Alt+Click" }),
123
- " any element to inspect"
124
- ]
125
- }
126
- )
127
- ] })
128
- ]
129
- }
130
- );
131
- return createPortal(content, document.body);
132
- }
133
- function SettingsPopover({
134
- settings,
135
- onUpdate
136
- }) {
137
- return /* @__PURE__ */ jsxs(
138
- "div",
139
- {
140
- style: {
141
- position: "absolute",
142
- top: "100%",
143
- right: 0,
144
- marginTop: "8px",
145
- width: "280px",
146
- padding: "16px",
147
- borderRadius: "12px",
148
- border: `1px solid ${STYLES.border}`,
149
- backgroundColor: STYLES.bg,
150
- backdropFilter: STYLES.blur,
151
- WebkitBackdropFilter: STYLES.blur,
152
- boxShadow: STYLES.shadow,
153
- animation: "uilint-fade-in 0.15s ease-out"
154
- },
155
- children: [
156
- /* @__PURE__ */ jsx(
157
- "div",
158
- {
159
- style: {
160
- fontSize: "13px",
161
- fontWeight: 600,
162
- color: STYLES.text,
163
- marginBottom: "12px"
164
- },
165
- children: "UILint Settings"
166
- }
167
- ),
168
- /* @__PURE__ */ jsx(
169
- SettingToggle,
170
- {
171
- label: "Hide node_modules",
172
- checked: settings.hideNodeModules,
173
- onChange: (checked) => onUpdate({ hideNodeModules: checked })
174
- }
175
- ),
176
- /* @__PURE__ */ jsxs(
177
- "div",
178
- {
179
- style: {
180
- marginTop: "12px",
181
- paddingTop: "12px",
182
- borderTop: `1px solid ${STYLES.border}`,
183
- fontSize: "11px",
184
- color: STYLES.textMuted,
185
- lineHeight: 1.5
186
- },
187
- children: [
188
- /* @__PURE__ */ jsx("strong", { style: { color: STYLES.text }, children: "Alt+Click" }),
189
- " any element to open the inspector sidebar"
190
- ]
191
- }
192
- )
193
- ]
194
- }
195
- );
196
- }
197
- function SettingToggle({
198
- label,
199
- checked,
200
- onChange
201
- }) {
202
- return /* @__PURE__ */ jsxs(
203
- "label",
204
- {
205
- style: {
206
- display: "flex",
207
- alignItems: "center",
208
- justifyContent: "space-between",
209
- padding: "8px 0",
210
- cursor: "pointer"
211
- },
212
- children: [
213
- /* @__PURE__ */ jsx("span", { style: { fontSize: "12px", color: STYLES.textMuted }, children: label }),
214
- /* @__PURE__ */ jsx(
215
- "div",
216
- {
217
- onClick: () => onChange(!checked),
218
- style: {
219
- width: "36px",
220
- height: "20px",
221
- borderRadius: "10px",
222
- backgroundColor: checked ? STYLES.accent : "rgba(75, 85, 99, 0.5)",
223
- position: "relative",
224
- transition: "background-color 0.2s"
225
- },
226
- children: /* @__PURE__ */ jsx(
227
- "div",
228
- {
229
- style: {
230
- position: "absolute",
231
- top: "2px",
232
- left: checked ? "18px" : "2px",
233
- width: "16px",
234
- height: "16px",
235
- borderRadius: "50%",
236
- backgroundColor: "#FFFFFF",
237
- transition: "left 0.2s",
238
- boxShadow: "0 1px 3px rgba(0, 0, 0, 0.2)"
239
- }
240
- }
241
- )
242
- }
243
- )
244
- ]
245
- }
246
- );
247
- }
248
- function UILintIcon({ active }) {
249
- return /* @__PURE__ */ jsxs("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", children: [
250
- /* @__PURE__ */ jsx(
251
- "rect",
252
- {
253
- x: "3",
254
- y: "3",
255
- width: "18",
256
- height: "18",
257
- rx: "3",
258
- stroke: active ? STYLES.accent : "currentColor",
259
- strokeWidth: "2"
260
- }
261
- ),
262
- /* @__PURE__ */ jsx(
263
- "path",
264
- {
265
- d: "M7 12h10M12 7v10",
266
- stroke: active ? STYLES.accent : "currentColor",
267
- strokeWidth: "2",
268
- strokeLinecap: "round"
269
- }
270
- )
271
- ] });
272
- }
273
-
274
- export {
275
- UILintToolbar
276
- };