uilint-react 0.1.19 → 0.1.21
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 +50 -93
- package/dist/{InspectionPanel-6DBGEWWD.js → InspectionPanel-ZBDXQ2LU.js} +2 -2
- package/dist/LocatorOverlay-3H446RPO.js +11 -0
- package/dist/{UILintToolbar-7ZYCQC4M.js → UILintToolbar-C6HOAJA4.js} +2 -2
- package/dist/{chunk-KUFV22FO.js → chunk-3DNDKMZ4.js} +72 -2
- package/dist/{chunk-3TA6OKS6.js → chunk-CWCKS753.js} +417 -90
- package/dist/{chunk-7WYVWDRU.js → chunk-EBU7YY73.js} +53 -218
- package/dist/chunk-GUF36FGA.js +276 -0
- package/dist/index.d.ts +26 -65
- package/dist/index.js +33 -1097
- package/package.json +2 -2
- package/dist/LocatorOverlay-FQEYAMT6.js +0 -9
- package/dist/SourceOverlays-2SEINA2B.js +0 -9
- package/dist/chunk-MEP7WO7U.js +0 -210
- package/dist/chunk-OWX36QE3.js +0 -595
|
@@ -28,10 +28,7 @@ var FILE_COLORS = [
|
|
|
28
28
|
// purple
|
|
29
29
|
];
|
|
30
30
|
var DEFAULT_SETTINGS = {
|
|
31
|
-
|
|
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
|
|
372
|
-
useEffect
|
|
373
|
-
useCallback
|
|
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 [
|
|
394
|
-
const [
|
|
395
|
-
const [
|
|
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 [
|
|
399
|
-
|
|
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
|
|
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 =
|
|
291
|
+
const locatorGoDown = useCallback(() => {
|
|
435
292
|
setLocatorStackIndex((prev) => Math.max(prev - 1, 0));
|
|
436
293
|
}, []);
|
|
437
|
-
const getLocatorTargetFromElement =
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
507
|
-
|
|
508
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
427
|
+
useEffect(() => {
|
|
566
428
|
if (!isBrowser() || !enabled) return;
|
|
567
429
|
const handleKeyDown = (e) => {
|
|
568
|
-
if (
|
|
569
|
-
|
|
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,
|
|
581
|
-
|
|
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 {
|
|
638
|
-
const [components, setComponents] =
|
|
639
|
-
|
|
475
|
+
const { altKeyHeld, inspectedElement } = useUILintContext();
|
|
476
|
+
const [components, setComponents] = useState(null);
|
|
477
|
+
useEffect(() => {
|
|
640
478
|
Promise.all([
|
|
641
|
-
import("./UILintToolbar-
|
|
642
|
-
import("./
|
|
643
|
-
import("./
|
|
644
|
-
|
|
645
|
-
]).then(([toolbar, overlays, panel, locator]) => {
|
|
479
|
+
import("./UILintToolbar-C6HOAJA4.js"),
|
|
480
|
+
import("./InspectionPanel-ZBDXQ2LU.js"),
|
|
481
|
+
import("./LocatorOverlay-3H446RPO.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,
|
|
492
|
+
const { Toolbar, Panel, LocatorOverlay, InspectedHighlight } = components;
|
|
656
493
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
657
494
|
/* @__PURE__ */ jsx(Toolbar, {}),
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
/* @__PURE__ */ jsx(
|
|
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
|
};
|
|
@@ -0,0 +1,276 @@
|
|
|
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
|
+
};
|