uilint-react 0.1.19 → 0.1.20

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/README.md CHANGED
@@ -4,7 +4,7 @@ React component for AI-powered UI consistency checking in running applications.
4
4
 
5
5
  ## Overview
6
6
 
7
- `uilint-react` provides React components and utilities for analyzing UI consistency at runtime and in tests. It includes a visual overlay for development and a JSDOM adapter for testing.
7
+ `uilint-react` provides the `UILintProvider` component that enables element inspection and LLM-powered code analysis in your React/Next.js application.
8
8
 
9
9
  ## Installation
10
10
 
@@ -12,127 +12,70 @@ React component for AI-powered UI consistency checking in running applications.
12
12
  npm install uilint-react uilint-core
13
13
  ```
14
14
 
15
+ Or use the CLI to install everything automatically:
16
+
17
+ ```bash
18
+ npx uilint-cli install
19
+ ```
20
+
15
21
  ## Usage in a Running App
16
22
 
17
- Wrap your app with the `<UILint>` component to get a visual overlay:
23
+ Wrap your app with the `UILintProvider` component:
18
24
 
19
25
  ### Next.js Setup
20
26
 
21
27
  ```tsx
22
28
  // app/layout.tsx
23
- import { UILint } from "uilint-react";
29
+ import { UILintProvider } from "uilint-react";
24
30
 
25
31
  export default function RootLayout({ children }) {
26
32
  return (
27
33
  <html>
28
34
  <body>
29
- <UILint
30
- enabled={process.env.NODE_ENV !== "production"}
31
- position="bottom-left"
32
- autoScan={false}
33
- >
35
+ <UILintProvider enabled={process.env.NODE_ENV !== "production"}>
34
36
  {children}
35
- </UILint>
37
+ </UILintProvider>
36
38
  </body>
37
39
  </html>
38
40
  );
39
41
  }
40
42
  ```
41
43
 
44
+ ### Features
45
+
46
+ - **Alt+Click** on any element to open the inspector sidebar
47
+ - View component source location and file path
48
+ - Navigate through the component stack (scroll while holding Alt)
49
+ - **Open in Cursor** - jump directly to the source file
50
+ - **Scan with LLM** - analyze the component for style issues
51
+ - **Copy fix prompt** - paste into Cursor agent for automatic fixes
52
+
42
53
  ### Props
43
54
 
44
- | Prop | Type | Default | Description |
45
- | ------------- | -------------------------------------------------------------- | ----------------------- | ------------------------------- |
46
- | `enabled` | `boolean` | `true` | Enable/disable UILint |
47
- | `position` | `'bottom-left' \| 'bottom-right' \| 'top-left' \| 'top-right'` | `'bottom-left'` | Overlay position |
48
- | `autoScan` | `boolean` | `false` | Automatically scan on page load |
49
- | `apiEndpoint` | `string` | `'/api/uilint/analyze'` | Custom API endpoint |
55
+ | Prop | Type | Default | Description |
56
+ | --------- | --------- | ------- | --------------------- |
57
+ | `enabled` | `boolean` | `true` | Enable/disable UILint |
50
58
 
51
59
  ### API Routes
52
60
 
53
- You'll need to add API routes for the React component:
61
+ The CLI installs these routes automatically, or you can add them manually:
54
62
 
55
63
  ```ts
56
64
  // app/api/uilint/analyze/route.ts
57
- import { NextRequest, NextResponse } from "next/server";
58
- import { OllamaClient, UILINT_DEFAULT_OLLAMA_MODEL } from "uilint-core";
59
-
60
- export async function POST(request: NextRequest) {
61
- const { styleSummary, styleGuide, generateGuide, model } =
62
- await request.json();
63
- const client = new OllamaClient({
64
- model: model || UILINT_DEFAULT_OLLAMA_MODEL,
65
- });
66
-
67
- if (generateGuide) {
68
- const styleGuideContent = await client.generateStyleGuide(styleSummary);
69
- return NextResponse.json({ styleGuide: styleGuideContent });
70
- } else {
71
- const result = await client.analyzeStyles(styleSummary, styleGuide);
72
- return NextResponse.json({ issues: result.issues });
73
- }
74
- }
75
- ```
76
-
77
- ```ts
78
- // app/api/uilint/styleguide/route.ts
79
- import { NextRequest, NextResponse } from "next/server";
80
- import {
81
- readStyleGuideFromProject,
82
- writeStyleGuide,
83
- styleGuideExists,
84
- getDefaultStyleGuidePath,
85
- } from "uilint-core/node";
86
-
87
- export async function GET() {
88
- const projectPath = process.cwd();
89
- if (!styleGuideExists(projectPath)) {
90
- return NextResponse.json({ exists: false, content: null });
91
- }
92
- const content = await readStyleGuideFromProject(projectPath);
93
- return NextResponse.json({ exists: true, content });
94
- }
65
+ // Handles LLM analysis of source code
95
66
 
96
- export async function POST(request: NextRequest) {
97
- const { content } = await request.json();
98
- const projectPath = process.cwd();
99
- const stylePath = getDefaultStyleGuidePath(projectPath);
100
- await writeStyleGuide(stylePath, content);
101
- return NextResponse.json({ success: true });
102
- }
67
+ // app/api/dev/source/route.ts
68
+ // Dev-only route for fetching source files
103
69
  ```
104
70
 
105
71
  ## Usage in Tests
106
72
 
107
73
  UILint can run in Vitest/Jest tests with JSDOM:
108
74
 
109
- ### Basic Test
110
-
111
- ```tsx
112
- import { render, screen } from "@testing-library/react";
113
- import { UILint } from "uilint-react";
114
- import { MyComponent } from "./MyComponent";
115
-
116
- test("MyComponent has consistent styles", async () => {
117
- render(
118
- <UILint enabled={true}>
119
- <MyComponent />
120
- </UILint>
121
- );
122
-
123
- expect(screen.getByRole("button")).toBeInTheDocument();
124
-
125
- // UILint automatically outputs warnings to console:
126
- // ⚠️ [UILint] Button uses #3B82F6 but style guide specifies #2563EB
127
- });
128
- ```
129
-
130
75
  ### Direct JSDOM Adapter
131
76
 
132
- For more control, use the `JSDOMAdapter`:
133
-
134
77
  ```tsx
135
- import { JSDOMAdapter, runUILintInTest } from "uilint-react";
78
+ import { JSDOMAdapter, runUILintInTest } from "uilint-react/node";
136
79
  import { render } from "@testing-library/react";
137
80
 
138
81
  test("detect style inconsistencies", async () => {
@@ -160,23 +103,37 @@ test("custom adapter usage", async () => {
160
103
 
161
104
  ## API
162
105
 
163
- ### UILint Component
106
+ ### UILintProvider
164
107
 
165
108
  ```tsx
166
- interface UILintProps {
109
+ interface UILintProviderProps {
167
110
  enabled?: boolean;
168
- position?: "bottom-left" | "bottom-right" | "top-left" | "top-right";
169
- autoScan?: boolean;
170
- apiEndpoint?: string;
171
111
  children: React.ReactNode;
172
112
  }
173
113
 
174
- function UILint(props: UILintProps): JSX.Element;
114
+ function UILintProvider(props: UILintProviderProps): JSX.Element;
115
+ ```
116
+
117
+ ### useUILintContext
118
+
119
+ ```tsx
120
+ function useUILintContext(): UILintContextValue;
121
+
122
+ interface UILintContextValue {
123
+ settings: UILintSettings;
124
+ updateSettings: (settings: Partial<UILintSettings>) => void;
125
+ altKeyHeld: boolean;
126
+ locatorTarget: LocatorTarget | null;
127
+ inspectedElement: InspectedElement | null;
128
+ setInspectedElement: (element: InspectedElement | null) => void;
129
+ // ... additional context values
130
+ }
175
131
  ```
176
132
 
177
- ### JSDOM Adapter
133
+ ### JSDOM Adapter (Node.js)
178
134
 
179
135
  ```typescript
136
+ // Import from "uilint-react/node" for test environments
180
137
  class JSDOMAdapter {
181
138
  constructor(styleGuidePath?: string);
182
139
 
@@ -2,8 +2,8 @@
2
2
  "use client";
3
3
  import {
4
4
  InspectionPanel
5
- } from "./chunk-3TA6OKS6.js";
6
- import "./chunk-7WYVWDRU.js";
5
+ } from "./chunk-NOISZ3XP.js";
6
+ import "./chunk-DAFFOBEU.js";
7
7
  export {
8
8
  InspectionPanel
9
9
  };
@@ -0,0 +1,11 @@
1
+ "use client";
2
+ "use client";
3
+ import {
4
+ InspectedElementHighlight,
5
+ LocatorOverlay
6
+ } from "./chunk-VYCIUDU7.js";
7
+ import "./chunk-DAFFOBEU.js";
8
+ export {
9
+ InspectedElementHighlight,
10
+ LocatorOverlay
11
+ };
@@ -2,8 +2,8 @@
2
2
  "use client";
3
3
  import {
4
4
  UILintToolbar
5
- } from "./chunk-OWX36QE3.js";
6
- import "./chunk-7WYVWDRU.js";
5
+ } from "./chunk-PBC3J267.js";
6
+ import "./chunk-DAFFOBEU.js";
7
7
  export {
8
8
  UILintToolbar
9
9
  };
@@ -28,10 +28,7 @@ var FILE_COLORS = [
28
28
  // purple
29
29
  ];
30
30
  var DEFAULT_SETTINGS = {
31
- showLabels: true,
32
- hideNodeModules: true,
33
- overlayOpacity: 0.2,
34
- labelPosition: "top-left"
31
+ hideNodeModules: true
35
32
  };
36
33
  var DATA_UILINT_ID = "data-ui-lint-id";
37
34
 
@@ -250,127 +247,13 @@ function buildEditorUrl(source, editor = "cursor") {
250
247
  )}:${lineNumber}:${column}`;
251
248
  }
252
249
 
253
- // src/components/ui-lint/use-element-scan.ts
254
- import { useState, useEffect, useCallback, useRef } from "react";
255
- function debounce(fn, delay) {
256
- let timeoutId;
257
- return (...args) => {
258
- clearTimeout(timeoutId);
259
- timeoutId = setTimeout(() => fn(...args), delay);
260
- };
261
- }
262
- function useElementScan({
263
- enabled,
264
- settings
265
- }) {
266
- const [elements, setElements] = useState([]);
267
- const [sourceFiles, setSourceFiles] = useState([]);
268
- const [isScanning, setIsScanning] = useState(false);
269
- const mutationObserverRef = useRef(null);
270
- const resizeObserverRef = useRef(null);
271
- const performScan = useCallback(() => {
272
- if (!enabled || typeof window === "undefined") return;
273
- setIsScanning(true);
274
- const scan = () => {
275
- try {
276
- const scannedElements = scanDOMForSources(
277
- document.body,
278
- settings.hideNodeModules
279
- );
280
- const files = groupBySourceFile(scannedElements);
281
- setElements(scannedElements);
282
- setSourceFiles(files);
283
- } catch (error) {
284
- console.error("[UILint] Scan error:", error);
285
- } finally {
286
- setIsScanning(false);
287
- }
288
- };
289
- if ("requestIdleCallback" in window) {
290
- window.requestIdleCallback(scan, { timeout: 1e3 });
291
- } else {
292
- setTimeout(scan, 0);
293
- }
294
- }, [enabled, settings.hideNodeModules]);
295
- const updatePositions = useCallback(() => {
296
- if (elements.length === 0) return;
297
- setElements((prev) => updateElementRects(prev));
298
- }, [elements.length]);
299
- const debouncedRescan = useCallback(
300
- debounce(() => {
301
- performScan();
302
- }, 500),
303
- [performScan]
304
- );
305
- const handleScroll = useCallback(
306
- debounce(() => {
307
- updatePositions();
308
- }, 16),
309
- // ~60fps
310
- [updatePositions]
311
- );
312
- const handleResize = useCallback(
313
- debounce(() => {
314
- updatePositions();
315
- }, 100),
316
- [updatePositions]
317
- );
318
- useEffect(() => {
319
- if (!enabled) {
320
- cleanupDataAttributes();
321
- setElements([]);
322
- setSourceFiles([]);
323
- return;
324
- }
325
- const initialScanTimer = setTimeout(performScan, 100);
326
- mutationObserverRef.current = new MutationObserver((mutations) => {
327
- const hasRelevantMutation = mutations.some((mutation) => {
328
- if (mutation.type === "attributes") {
329
- return !mutation.attributeName?.startsWith("data-ui-lint");
330
- }
331
- return true;
332
- });
333
- if (hasRelevantMutation) {
334
- debouncedRescan();
335
- }
336
- });
337
- mutationObserverRef.current.observe(document.body, {
338
- childList: true,
339
- subtree: true,
340
- attributes: true,
341
- attributeFilter: ["class", "style"]
342
- });
343
- window.addEventListener("scroll", handleScroll, true);
344
- window.addEventListener("resize", handleResize);
345
- return () => {
346
- clearTimeout(initialScanTimer);
347
- mutationObserverRef.current?.disconnect();
348
- resizeObserverRef.current?.disconnect();
349
- window.removeEventListener("scroll", handleScroll, true);
350
- window.removeEventListener("resize", handleResize);
351
- cleanupDataAttributes();
352
- };
353
- }, [enabled, performScan, debouncedRescan, handleScroll, handleResize]);
354
- useEffect(() => {
355
- if (enabled && elements.length > 0) {
356
- performScan();
357
- }
358
- }, [settings.hideNodeModules]);
359
- return {
360
- elements,
361
- sourceFiles,
362
- isScanning,
363
- rescan: performScan
364
- };
365
- }
366
-
367
250
  // src/components/ui-lint/UILintProvider.tsx
368
251
  import {
369
252
  createContext,
370
253
  useContext,
371
- useState as useState2,
372
- useEffect as useEffect2,
373
- useCallback as useCallback2,
254
+ useState,
255
+ useEffect,
256
+ useCallback,
374
257
  useMemo
375
258
  } from "react";
376
259
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -387,54 +270,28 @@ function isBrowser() {
387
270
  }
388
271
  function UILintProvider({
389
272
  children,
390
- enabled = true,
391
- defaultMode = "off"
273
+ enabled = true
392
274
  }) {
393
- const [mode, setMode] = useState2(defaultMode);
394
- const [settings, setSettings] = useState2(DEFAULT_SETTINGS);
395
- const [selectedElement, setSelectedElement] = useState2(
275
+ const [settings, setSettings] = useState(DEFAULT_SETTINGS);
276
+ const [isMounted, setIsMounted] = useState(false);
277
+ const [altKeyHeld, setAltKeyHeld] = useState(false);
278
+ const [locatorTarget, setLocatorTarget] = useState(
396
279
  null
397
280
  );
398
- const [hoveredElement, setHoveredElement] = useState2(
399
- null
400
- );
401
- const [isMounted, setIsMounted] = useState2(false);
402
- const [altKeyHeld, setAltKeyHeld] = useState2(false);
403
- const [locatorTarget, setLocatorTarget] = useState2(
404
- null
405
- );
406
- const [locatorStackIndex, setLocatorStackIndex] = useState2(0);
407
- const isActive = enabled && mode !== "off";
408
- const { elements, sourceFiles, isScanning, rescan } = useElementScan({
409
- enabled: isActive,
410
- settings
411
- });
412
- const updateSettings = useCallback2((partial) => {
281
+ const [locatorStackIndex, setLocatorStackIndex] = useState(0);
282
+ const [inspectedElement, setInspectedElement] = useState(null);
283
+ const updateSettings = useCallback((partial) => {
413
284
  setSettings((prev) => ({ ...prev, ...partial }));
414
285
  }, []);
415
- const toggleMode = useCallback2(() => {
416
- setMode((prev) => {
417
- if (prev === "off") return "sources";
418
- if (prev === "sources") return "inspect";
419
- return "off";
420
- });
421
- }, []);
422
- const handleEscape = useCallback2(() => {
423
- if (selectedElement) {
424
- setSelectedElement(null);
425
- } else if (mode !== "off") {
426
- setMode("off");
427
- }
428
- }, [selectedElement, mode]);
429
- const locatorGoUp = useCallback2(() => {
286
+ const locatorGoUp = useCallback(() => {
430
287
  if (!locatorTarget) return;
431
288
  const maxIndex = locatorTarget.componentStack.length;
432
289
  setLocatorStackIndex((prev) => Math.min(prev + 1, maxIndex));
433
290
  }, [locatorTarget]);
434
- const locatorGoDown = useCallback2(() => {
291
+ const locatorGoDown = useCallback(() => {
435
292
  setLocatorStackIndex((prev) => Math.max(prev - 1, 0));
436
293
  }, []);
437
- const getLocatorTargetFromElement = useCallback2(
294
+ const getLocatorTargetFromElement = useCallback(
438
295
  (element) => {
439
296
  if (element.closest("[data-ui-lint]")) return null;
440
297
  let source = getSourceFromDataLoc(element);
@@ -470,7 +327,7 @@ function UILintProvider({
470
327
  },
471
328
  [settings.hideNodeModules]
472
329
  );
473
- const handleMouseMove = useCallback2(
330
+ const handleMouseMove = useCallback(
474
331
  (e) => {
475
332
  if (!altKeyHeld) return;
476
333
  const elementAtPoint = document.elementFromPoint(e.clientX, e.clientY);
@@ -491,7 +348,7 @@ function UILintProvider({
491
348
  },
492
349
  [altKeyHeld, getLocatorTargetFromElement]
493
350
  );
494
- const handleLocatorClick = useCallback2(
351
+ const handleLocatorClick = useCallback(
495
352
  (e) => {
496
353
  if (!altKeyHeld || !locatorTarget) return;
497
354
  e.preventDefault();
@@ -503,14 +360,19 @@ function UILintProvider({
503
360
  source = stackItem.source;
504
361
  }
505
362
  }
506
- if (source) {
507
- const url = buildEditorUrl(source, "cursor");
508
- window.open(url, "_blank");
509
- }
363
+ setInspectedElement({
364
+ element: locatorTarget.element,
365
+ source,
366
+ componentStack: locatorTarget.componentStack,
367
+ rect: locatorTarget.rect
368
+ });
369
+ setAltKeyHeld(false);
370
+ setLocatorTarget(null);
371
+ setLocatorStackIndex(0);
510
372
  },
511
373
  [altKeyHeld, locatorTarget, locatorStackIndex]
512
374
  );
513
- useEffect2(() => {
375
+ useEffect(() => {
514
376
  if (!isBrowser() || !enabled) return;
515
377
  const handleKeyDown = (e) => {
516
378
  if (e.key === "Alt") {
@@ -539,7 +401,7 @@ function UILintProvider({
539
401
  window.removeEventListener("blur", handleBlur);
540
402
  };
541
403
  }, [enabled]);
542
- useEffect2(() => {
404
+ useEffect(() => {
543
405
  if (!isBrowser() || !enabled || !altKeyHeld) return;
544
406
  window.addEventListener("mousemove", handleMouseMove);
545
407
  window.addEventListener("click", handleLocatorClick, true);
@@ -548,7 +410,7 @@ function UILintProvider({
548
410
  window.removeEventListener("click", handleLocatorClick, true);
549
411
  };
550
412
  }, [enabled, altKeyHeld, handleMouseMove, handleLocatorClick]);
551
- useEffect2(() => {
413
+ useEffect(() => {
552
414
  if (!isBrowser() || !enabled || !altKeyHeld) return;
553
415
  const handleWheel = (e) => {
554
416
  if (!locatorTarget) return;
@@ -562,29 +424,19 @@ function UILintProvider({
562
424
  window.addEventListener("wheel", handleWheel, { passive: false });
563
425
  return () => window.removeEventListener("wheel", handleWheel);
564
426
  }, [enabled, altKeyHeld, locatorTarget, locatorGoUp, locatorGoDown]);
565
- useEffect2(() => {
427
+ useEffect(() => {
566
428
  if (!isBrowser() || !enabled) return;
567
429
  const handleKeyDown = (e) => {
568
- if ((e.metaKey || e.ctrlKey) && e.shiftKey && e.key === "d") {
569
- e.preventDefault();
570
- toggleMode();
571
- return;
572
- }
573
- if (e.key === "Escape") {
574
- handleEscape();
575
- return;
430
+ if (e.key === "Escape" && inspectedElement) {
431
+ setInspectedElement(null);
576
432
  }
577
433
  };
578
434
  window.addEventListener("keydown", handleKeyDown);
579
435
  return () => window.removeEventListener("keydown", handleKeyDown);
580
- }, [enabled, toggleMode, handleEscape]);
581
- useEffect2(() => {
436
+ }, [enabled, inspectedElement]);
437
+ useEffect(() => {
582
438
  setIsMounted(true);
583
439
  }, []);
584
- useEffect2(() => {
585
- setSelectedElement(null);
586
- setHoveredElement(null);
587
- }, [mode]);
588
440
  const effectiveLocatorTarget = useMemo(() => {
589
441
  if (!locatorTarget) return null;
590
442
  return {
@@ -594,37 +446,23 @@ function UILintProvider({
594
446
  }, [locatorTarget, locatorStackIndex]);
595
447
  const contextValue = useMemo(
596
448
  () => ({
597
- mode,
598
- setMode,
599
- scannedElements: elements,
600
- sourceFiles,
601
- selectedElement,
602
- setSelectedElement,
603
- hoveredElement,
604
- setHoveredElement,
605
449
  settings,
606
450
  updateSettings,
607
- rescan,
608
- isScanning,
609
451
  altKeyHeld,
610
452
  locatorTarget: effectiveLocatorTarget,
611
453
  locatorGoUp,
612
- locatorGoDown
454
+ locatorGoDown,
455
+ inspectedElement,
456
+ setInspectedElement
613
457
  }),
614
458
  [
615
- mode,
616
- elements,
617
- sourceFiles,
618
- selectedElement,
619
- hoveredElement,
620
459
  settings,
621
460
  updateSettings,
622
- rescan,
623
- isScanning,
624
461
  altKeyHeld,
625
462
  effectiveLocatorTarget,
626
463
  locatorGoUp,
627
- locatorGoDown
464
+ locatorGoDown,
465
+ inspectedElement
628
466
  ]
629
467
  );
630
468
  const shouldRenderUI = enabled && isMounted;
@@ -634,33 +472,31 @@ function UILintProvider({
634
472
  ] });
635
473
  }
636
474
  function UILintUI() {
637
- const { mode, altKeyHeld } = useUILintContext();
638
- const [components, setComponents] = useState2(null);
639
- useEffect2(() => {
475
+ const { altKeyHeld, inspectedElement } = useUILintContext();
476
+ const [components, setComponents] = useState(null);
477
+ useEffect(() => {
640
478
  Promise.all([
641
- import("./UILintToolbar-7ZYCQC4M.js"),
642
- import("./SourceOverlays-2SEINA2B.js"),
643
- import("./InspectionPanel-6DBGEWWD.js"),
644
- import("./LocatorOverlay-FQEYAMT6.js")
645
- ]).then(([toolbar, overlays, panel, locator]) => {
479
+ import("./UILintToolbar-GAOYF7GY.js"),
480
+ import("./InspectionPanel-3ML64TAP.js"),
481
+ import("./LocatorOverlay-GTTWBRKH.js")
482
+ ]).then(([toolbar, panel, locator]) => {
646
483
  setComponents({
647
484
  Toolbar: toolbar.UILintToolbar,
648
- Overlays: overlays.SourceOverlays,
649
485
  Panel: panel.InspectionPanel,
650
- LocatorOverlay: locator.LocatorOverlay
486
+ LocatorOverlay: locator.LocatorOverlay,
487
+ InspectedHighlight: locator.InspectedElementHighlight
651
488
  });
652
489
  });
653
490
  }, []);
654
491
  if (!components) return null;
655
- const { Toolbar, Overlays, Panel, LocatorOverlay } = components;
492
+ const { Toolbar, Panel, LocatorOverlay, InspectedHighlight } = components;
656
493
  return /* @__PURE__ */ jsxs(Fragment, { children: [
657
494
  /* @__PURE__ */ jsx(Toolbar, {}),
658
- mode === "sources" && /* @__PURE__ */ jsx(Overlays, {}),
659
- mode === "inspect" && /* @__PURE__ */ jsxs(Fragment, { children: [
660
- /* @__PURE__ */ jsx(Overlays, {}),
495
+ altKeyHeld && /* @__PURE__ */ jsx(LocatorOverlay, {}),
496
+ inspectedElement && /* @__PURE__ */ jsxs(Fragment, { children: [
497
+ /* @__PURE__ */ jsx(InspectedHighlight, {}),
661
498
  /* @__PURE__ */ jsx(Panel, {})
662
- ] }),
663
- altKeyHeld && /* @__PURE__ */ jsx(LocatorOverlay, {})
499
+ ] })
664
500
  ] });
665
501
  }
666
502
 
@@ -680,7 +516,6 @@ export {
680
516
  getElementById,
681
517
  updateElementRects,
682
518
  buildEditorUrl,
683
- useElementScan,
684
519
  useUILintContext,
685
520
  UILintProvider
686
521
  };