uilint-react 0.1.17 → 0.1.19

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.
@@ -0,0 +1,686 @@
1
+ "use client";
2
+
3
+ // src/components/ui-lint/types.ts
4
+ var FILE_COLORS = [
5
+ "#3B82F6",
6
+ // blue
7
+ "#8B5CF6",
8
+ // violet
9
+ "#EC4899",
10
+ // pink
11
+ "#10B981",
12
+ // emerald
13
+ "#F59E0B",
14
+ // amber
15
+ "#06B6D4",
16
+ // cyan
17
+ "#EF4444",
18
+ // red
19
+ "#84CC16",
20
+ // lime
21
+ "#6366F1",
22
+ // indigo
23
+ "#F97316",
24
+ // orange
25
+ "#14B8A6",
26
+ // teal
27
+ "#A855F7"
28
+ // purple
29
+ ];
30
+ var DEFAULT_SETTINGS = {
31
+ showLabels: true,
32
+ hideNodeModules: true,
33
+ overlayOpacity: 0.2,
34
+ labelPosition: "top-left"
35
+ };
36
+ var DATA_UILINT_ID = "data-ui-lint-id";
37
+
38
+ // src/components/ui-lint/fiber-utils.ts
39
+ var DATA_ATTR = "data-ui-lint-id";
40
+ var COLORS = [
41
+ "#3B82F6",
42
+ "#8B5CF6",
43
+ "#EC4899",
44
+ "#10B981",
45
+ "#F59E0B",
46
+ "#06B6D4",
47
+ "#EF4444",
48
+ "#84CC16",
49
+ "#6366F1",
50
+ "#F97316",
51
+ "#14B8A6",
52
+ "#A855F7"
53
+ ];
54
+ var SKIP_TAGS = /* @__PURE__ */ new Set([
55
+ "SCRIPT",
56
+ "STYLE",
57
+ "SVG",
58
+ "NOSCRIPT",
59
+ "TEMPLATE",
60
+ "HEAD",
61
+ "META",
62
+ "LINK"
63
+ ]);
64
+ var elementCounter = 0;
65
+ function getFiberFromElement(element) {
66
+ const keys = Object.keys(element);
67
+ const fiberKey = keys.find((k) => k.startsWith("__reactFiber$"));
68
+ if (!fiberKey) return null;
69
+ return element[fiberKey];
70
+ }
71
+ function getDebugSource(fiber) {
72
+ if (!fiber._debugSource) return null;
73
+ return {
74
+ fileName: fiber._debugSource.fileName,
75
+ lineNumber: fiber._debugSource.lineNumber,
76
+ columnNumber: fiber._debugSource.columnNumber
77
+ };
78
+ }
79
+ function getSourceFromDataLoc(element) {
80
+ const loc = element.getAttribute("data-loc");
81
+ if (!loc) return null;
82
+ const parts = loc.split(":");
83
+ if (parts.length < 2) return null;
84
+ const lastPart = parts[parts.length - 1];
85
+ const secondLastPart = parts[parts.length - 2];
86
+ const lastIsNumber = /^\d+$/.test(lastPart);
87
+ const secondLastIsNumber = /^\d+$/.test(secondLastPart);
88
+ if (lastIsNumber && secondLastIsNumber) {
89
+ const columnNumber = parseInt(lastPart, 10);
90
+ const lineNumber = parseInt(secondLastPart, 10);
91
+ const fileName = parts.slice(0, -2).join(":");
92
+ if (isNaN(lineNumber) || isNaN(columnNumber) || !fileName) return null;
93
+ return { fileName, lineNumber, columnNumber };
94
+ } else if (lastIsNumber) {
95
+ const lineNumber = parseInt(lastPart, 10);
96
+ const fileName = parts.slice(0, -1).join(":");
97
+ if (isNaN(lineNumber) || !fileName) return null;
98
+ return { fileName, lineNumber };
99
+ }
100
+ return null;
101
+ }
102
+ function getDebugOwner(fiber) {
103
+ return fiber._debugOwner ?? null;
104
+ }
105
+ function getComponentName(fiber) {
106
+ if (!fiber.type) return "Unknown";
107
+ if (typeof fiber.type === "string") return fiber.type;
108
+ if (typeof fiber.type === "function") {
109
+ const fn = fiber.type;
110
+ return fn.displayName || fn.name || "Anonymous";
111
+ }
112
+ return "Unknown";
113
+ }
114
+ function getComponentStack(fiber) {
115
+ const stack = [];
116
+ let current = fiber._debugOwner ?? null;
117
+ while (current && stack.length < 20) {
118
+ const name = getComponentName(current);
119
+ const source = getDebugSource(current);
120
+ if (current.tag <= 2 && name !== "Unknown") {
121
+ stack.push({ name, source });
122
+ }
123
+ current = current._debugOwner ?? current.return;
124
+ }
125
+ return stack;
126
+ }
127
+ function isNodeModulesPath(path) {
128
+ return path.includes("node_modules");
129
+ }
130
+ function getDisplayName(path) {
131
+ const parts = path.split("/");
132
+ return parts[parts.length - 1] || path;
133
+ }
134
+ function shouldSkipElement(element) {
135
+ if (SKIP_TAGS.has(element.tagName.toUpperCase())) return true;
136
+ if (element.hasAttribute("data-ui-lint")) return true;
137
+ if (element.getAttribute("aria-hidden") === "true") return true;
138
+ const styles = window.getComputedStyle(element);
139
+ if (styles.display === "none" || styles.visibility === "hidden") return true;
140
+ const rect = element.getBoundingClientRect();
141
+ if (rect.width === 0 || rect.height === 0) return true;
142
+ return false;
143
+ }
144
+ function generateElementId() {
145
+ return `uilint-${++elementCounter}`;
146
+ }
147
+ function scanDOMForSources(root = document.body, hideNodeModules = true) {
148
+ const elements = [];
149
+ elementCounter = 0;
150
+ cleanupDataAttributes();
151
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, {
152
+ acceptNode: (node2) => {
153
+ const el = node2;
154
+ if (shouldSkipElement(el)) return NodeFilter.FILTER_REJECT;
155
+ return NodeFilter.FILTER_ACCEPT;
156
+ }
157
+ });
158
+ let node = walker.currentNode;
159
+ while (node) {
160
+ if (node instanceof Element) {
161
+ let source = getSourceFromDataLoc(node);
162
+ let componentStack = [];
163
+ if (!source) {
164
+ const fiber = getFiberFromElement(node);
165
+ if (fiber) {
166
+ source = getDebugSource(fiber);
167
+ if (!source && fiber._debugOwner) {
168
+ source = getDebugSource(fiber._debugOwner);
169
+ }
170
+ componentStack = getComponentStack(fiber);
171
+ }
172
+ }
173
+ if (hideNodeModules && source && isNodeModulesPath(source.fileName)) {
174
+ const appSource = componentStack.find(
175
+ (c) => c.source && !isNodeModulesPath(c.source.fileName)
176
+ );
177
+ if (appSource?.source) {
178
+ source = appSource.source;
179
+ } else {
180
+ node = walker.nextNode();
181
+ continue;
182
+ }
183
+ }
184
+ if (source) {
185
+ const id = generateElementId();
186
+ node.setAttribute(DATA_ATTR, id);
187
+ const scannedElement = {
188
+ id,
189
+ element: node,
190
+ tagName: node.tagName.toLowerCase(),
191
+ className: typeof node.className === "string" ? node.className : "",
192
+ source,
193
+ componentStack,
194
+ rect: node.getBoundingClientRect()
195
+ };
196
+ elements.push(scannedElement);
197
+ }
198
+ }
199
+ node = walker.nextNode();
200
+ }
201
+ return elements;
202
+ }
203
+ function groupBySourceFile(elements) {
204
+ const fileMap = /* @__PURE__ */ new Map();
205
+ for (const element of elements) {
206
+ if (!element.source) continue;
207
+ const path = element.source.fileName;
208
+ const existing = fileMap.get(path) || [];
209
+ existing.push(element);
210
+ fileMap.set(path, existing);
211
+ }
212
+ const sourceFiles = [];
213
+ let colorIndex = 0;
214
+ for (const [path, elements2] of fileMap) {
215
+ sourceFiles.push({
216
+ path,
217
+ displayName: getDisplayName(path),
218
+ color: COLORS[colorIndex % COLORS.length],
219
+ elements: elements2
220
+ });
221
+ colorIndex++;
222
+ }
223
+ sourceFiles.sort((a, b) => b.elements.length - a.elements.length);
224
+ return sourceFiles;
225
+ }
226
+ function cleanupDataAttributes() {
227
+ const elements = document.querySelectorAll(`[${DATA_ATTR}]`);
228
+ elements.forEach((el) => el.removeAttribute(DATA_ATTR));
229
+ elementCounter = 0;
230
+ }
231
+ function getElementById(id) {
232
+ return document.querySelector(`[${DATA_ATTR}="${id}"]`);
233
+ }
234
+ function updateElementRects(elements) {
235
+ return elements.map((el) => ({
236
+ ...el,
237
+ rect: el.element.getBoundingClientRect()
238
+ }));
239
+ }
240
+ function buildEditorUrl(source, editor = "cursor") {
241
+ const { fileName, lineNumber, columnNumber } = source;
242
+ const column = columnNumber ?? 1;
243
+ if (editor === "cursor") {
244
+ return `cursor://file/${encodeURIComponent(
245
+ fileName
246
+ )}:${lineNumber}:${column}`;
247
+ }
248
+ return `vscode://file/${encodeURIComponent(
249
+ fileName
250
+ )}:${lineNumber}:${column}`;
251
+ }
252
+
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
+ // src/components/ui-lint/UILintProvider.tsx
368
+ import {
369
+ createContext,
370
+ useContext,
371
+ useState as useState2,
372
+ useEffect as useEffect2,
373
+ useCallback as useCallback2,
374
+ useMemo
375
+ } from "react";
376
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
377
+ var UILintContext = createContext(null);
378
+ function useUILintContext() {
379
+ const context = useContext(UILintContext);
380
+ if (!context) {
381
+ throw new Error("useUILintContext must be used within a UILintProvider");
382
+ }
383
+ return context;
384
+ }
385
+ function isBrowser() {
386
+ return typeof window !== "undefined";
387
+ }
388
+ function UILintProvider({
389
+ children,
390
+ enabled = true,
391
+ defaultMode = "off"
392
+ }) {
393
+ const [mode, setMode] = useState2(defaultMode);
394
+ const [settings, setSettings] = useState2(DEFAULT_SETTINGS);
395
+ const [selectedElement, setSelectedElement] = useState2(
396
+ null
397
+ );
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) => {
413
+ setSettings((prev) => ({ ...prev, ...partial }));
414
+ }, []);
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(() => {
430
+ if (!locatorTarget) return;
431
+ const maxIndex = locatorTarget.componentStack.length;
432
+ setLocatorStackIndex((prev) => Math.min(prev + 1, maxIndex));
433
+ }, [locatorTarget]);
434
+ const locatorGoDown = useCallback2(() => {
435
+ setLocatorStackIndex((prev) => Math.max(prev - 1, 0));
436
+ }, []);
437
+ const getLocatorTargetFromElement = useCallback2(
438
+ (element) => {
439
+ if (element.closest("[data-ui-lint]")) return null;
440
+ let source = getSourceFromDataLoc(element);
441
+ let componentStack = [];
442
+ if (!source) {
443
+ const fiber = getFiberFromElement(element);
444
+ if (fiber) {
445
+ source = getDebugSource(fiber);
446
+ if (!source && fiber._debugOwner) {
447
+ source = getDebugSource(fiber._debugOwner);
448
+ }
449
+ componentStack = getComponentStack(fiber);
450
+ }
451
+ }
452
+ if (!source && componentStack.length === 0) return null;
453
+ if (settings.hideNodeModules && source && isNodeModulesPath(source.fileName)) {
454
+ const appSource = componentStack.find(
455
+ (c) => c.source && !isNodeModulesPath(c.source.fileName)
456
+ );
457
+ if (appSource?.source) {
458
+ source = appSource.source;
459
+ } else if (componentStack.length === 0) {
460
+ return null;
461
+ }
462
+ }
463
+ return {
464
+ element,
465
+ source,
466
+ componentStack,
467
+ rect: element.getBoundingClientRect(),
468
+ stackIndex: 0
469
+ };
470
+ },
471
+ [settings.hideNodeModules]
472
+ );
473
+ const handleMouseMove = useCallback2(
474
+ (e) => {
475
+ if (!altKeyHeld) return;
476
+ const elementAtPoint = document.elementFromPoint(e.clientX, e.clientY);
477
+ if (!elementAtPoint) {
478
+ setLocatorTarget(null);
479
+ return;
480
+ }
481
+ let current = elementAtPoint;
482
+ while (current) {
483
+ const target = getLocatorTargetFromElement(current);
484
+ if (target) {
485
+ setLocatorTarget(target);
486
+ return;
487
+ }
488
+ current = current.parentElement;
489
+ }
490
+ setLocatorTarget(null);
491
+ },
492
+ [altKeyHeld, getLocatorTargetFromElement]
493
+ );
494
+ const handleLocatorClick = useCallback2(
495
+ (e) => {
496
+ if (!altKeyHeld || !locatorTarget) return;
497
+ e.preventDefault();
498
+ e.stopPropagation();
499
+ let source = locatorTarget.source;
500
+ if (locatorStackIndex > 0 && locatorTarget.componentStack.length > 0) {
501
+ const stackItem = locatorTarget.componentStack[locatorStackIndex - 1];
502
+ if (stackItem?.source) {
503
+ source = stackItem.source;
504
+ }
505
+ }
506
+ if (source) {
507
+ const url = buildEditorUrl(source, "cursor");
508
+ window.open(url, "_blank");
509
+ }
510
+ },
511
+ [altKeyHeld, locatorTarget, locatorStackIndex]
512
+ );
513
+ useEffect2(() => {
514
+ if (!isBrowser() || !enabled) return;
515
+ const handleKeyDown = (e) => {
516
+ if (e.key === "Alt") {
517
+ setAltKeyHeld(true);
518
+ setLocatorStackIndex(0);
519
+ }
520
+ };
521
+ const handleKeyUp = (e) => {
522
+ if (e.key === "Alt") {
523
+ setAltKeyHeld(false);
524
+ setLocatorTarget(null);
525
+ setLocatorStackIndex(0);
526
+ }
527
+ };
528
+ const handleBlur = () => {
529
+ setAltKeyHeld(false);
530
+ setLocatorTarget(null);
531
+ setLocatorStackIndex(0);
532
+ };
533
+ window.addEventListener("keydown", handleKeyDown);
534
+ window.addEventListener("keyup", handleKeyUp);
535
+ window.addEventListener("blur", handleBlur);
536
+ return () => {
537
+ window.removeEventListener("keydown", handleKeyDown);
538
+ window.removeEventListener("keyup", handleKeyUp);
539
+ window.removeEventListener("blur", handleBlur);
540
+ };
541
+ }, [enabled]);
542
+ useEffect2(() => {
543
+ if (!isBrowser() || !enabled || !altKeyHeld) return;
544
+ window.addEventListener("mousemove", handleMouseMove);
545
+ window.addEventListener("click", handleLocatorClick, true);
546
+ return () => {
547
+ window.removeEventListener("mousemove", handleMouseMove);
548
+ window.removeEventListener("click", handleLocatorClick, true);
549
+ };
550
+ }, [enabled, altKeyHeld, handleMouseMove, handleLocatorClick]);
551
+ useEffect2(() => {
552
+ if (!isBrowser() || !enabled || !altKeyHeld) return;
553
+ const handleWheel = (e) => {
554
+ if (!locatorTarget) return;
555
+ e.preventDefault();
556
+ if (e.deltaY > 0) {
557
+ locatorGoUp();
558
+ } else {
559
+ locatorGoDown();
560
+ }
561
+ };
562
+ window.addEventListener("wheel", handleWheel, { passive: false });
563
+ return () => window.removeEventListener("wheel", handleWheel);
564
+ }, [enabled, altKeyHeld, locatorTarget, locatorGoUp, locatorGoDown]);
565
+ useEffect2(() => {
566
+ if (!isBrowser() || !enabled) return;
567
+ 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;
576
+ }
577
+ };
578
+ window.addEventListener("keydown", handleKeyDown);
579
+ return () => window.removeEventListener("keydown", handleKeyDown);
580
+ }, [enabled, toggleMode, handleEscape]);
581
+ useEffect2(() => {
582
+ setIsMounted(true);
583
+ }, []);
584
+ useEffect2(() => {
585
+ setSelectedElement(null);
586
+ setHoveredElement(null);
587
+ }, [mode]);
588
+ const effectiveLocatorTarget = useMemo(() => {
589
+ if (!locatorTarget) return null;
590
+ return {
591
+ ...locatorTarget,
592
+ stackIndex: locatorStackIndex
593
+ };
594
+ }, [locatorTarget, locatorStackIndex]);
595
+ const contextValue = useMemo(
596
+ () => ({
597
+ mode,
598
+ setMode,
599
+ scannedElements: elements,
600
+ sourceFiles,
601
+ selectedElement,
602
+ setSelectedElement,
603
+ hoveredElement,
604
+ setHoveredElement,
605
+ settings,
606
+ updateSettings,
607
+ rescan,
608
+ isScanning,
609
+ altKeyHeld,
610
+ locatorTarget: effectiveLocatorTarget,
611
+ locatorGoUp,
612
+ locatorGoDown
613
+ }),
614
+ [
615
+ mode,
616
+ elements,
617
+ sourceFiles,
618
+ selectedElement,
619
+ hoveredElement,
620
+ settings,
621
+ updateSettings,
622
+ rescan,
623
+ isScanning,
624
+ altKeyHeld,
625
+ effectiveLocatorTarget,
626
+ locatorGoUp,
627
+ locatorGoDown
628
+ ]
629
+ );
630
+ const shouldRenderUI = enabled && isMounted;
631
+ return /* @__PURE__ */ jsxs(UILintContext.Provider, { value: contextValue, children: [
632
+ children,
633
+ shouldRenderUI && /* @__PURE__ */ jsx(UILintUI, {})
634
+ ] });
635
+ }
636
+ function UILintUI() {
637
+ const { mode, altKeyHeld } = useUILintContext();
638
+ const [components, setComponents] = useState2(null);
639
+ useEffect2(() => {
640
+ 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]) => {
646
+ setComponents({
647
+ Toolbar: toolbar.UILintToolbar,
648
+ Overlays: overlays.SourceOverlays,
649
+ Panel: panel.InspectionPanel,
650
+ LocatorOverlay: locator.LocatorOverlay
651
+ });
652
+ });
653
+ }, []);
654
+ if (!components) return null;
655
+ const { Toolbar, Overlays, Panel, LocatorOverlay } = components;
656
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
657
+ /* @__PURE__ */ jsx(Toolbar, {}),
658
+ mode === "sources" && /* @__PURE__ */ jsx(Overlays, {}),
659
+ mode === "inspect" && /* @__PURE__ */ jsxs(Fragment, { children: [
660
+ /* @__PURE__ */ jsx(Overlays, {}),
661
+ /* @__PURE__ */ jsx(Panel, {})
662
+ ] }),
663
+ altKeyHeld && /* @__PURE__ */ jsx(LocatorOverlay, {})
664
+ ] });
665
+ }
666
+
667
+ export {
668
+ FILE_COLORS,
669
+ DEFAULT_SETTINGS,
670
+ DATA_UILINT_ID,
671
+ getFiberFromElement,
672
+ getDebugSource,
673
+ getDebugOwner,
674
+ getComponentStack,
675
+ isNodeModulesPath,
676
+ getDisplayName,
677
+ scanDOMForSources,
678
+ groupBySourceFile,
679
+ cleanupDataAttributes,
680
+ getElementById,
681
+ updateElementRects,
682
+ buildEditorUrl,
683
+ useElementScan,
684
+ useUILintContext,
685
+ UILintProvider
686
+ };