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.
@@ -1,595 +0,0 @@
1
- "use client";
2
- import {
3
- useUILintContext
4
- } from "./chunk-7WYVWDRU.js";
5
-
6
- // src/components/ui-lint/UILintToolbar.tsx
7
- import { useState, useRef, useEffect } from "react";
8
- import { createPortal } from "react-dom";
9
- import { Fragment, 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
- var MODES = [
24
- { id: "off", label: "Off", icon: "\u25CB" },
25
- { id: "sources", label: "Sources", icon: "\u25C9" },
26
- { id: "inspect", label: "Inspect", icon: "\u25CE" }
27
- ];
28
- function UILintToolbar() {
29
- const {
30
- mode,
31
- setMode,
32
- scannedElements,
33
- sourceFiles,
34
- settings,
35
- updateSettings,
36
- rescan,
37
- isScanning
38
- } = useUILintContext();
39
- const [isExpanded, setIsExpanded] = useState(false);
40
- const [showSettings, setShowSettings] = useState(false);
41
- const [mounted, setMounted] = useState(false);
42
- const settingsRef = useRef(null);
43
- useEffect(() => {
44
- setMounted(true);
45
- }, []);
46
- useEffect(() => {
47
- const handleClickOutside = (e) => {
48
- if (settingsRef.current && !settingsRef.current.contains(e.target)) {
49
- setShowSettings(false);
50
- }
51
- };
52
- if (showSettings) {
53
- document.addEventListener("mousedown", handleClickOutside);
54
- return () => document.removeEventListener("mousedown", handleClickOutside);
55
- }
56
- }, [showSettings]);
57
- if (!mounted) return null;
58
- const content = /* @__PURE__ */ jsxs(
59
- "div",
60
- {
61
- "data-ui-lint": true,
62
- style: {
63
- position: "fixed",
64
- bottom: "24px",
65
- left: "50%",
66
- transform: "translateX(-50%)",
67
- zIndex: 99999,
68
- fontFamily: STYLES.font
69
- },
70
- children: [
71
- !isExpanded && /* @__PURE__ */ jsx(
72
- "button",
73
- {
74
- onClick: () => setIsExpanded(true),
75
- style: {
76
- display: "flex",
77
- alignItems: "center",
78
- justifyContent: "center",
79
- width: "48px",
80
- height: "48px",
81
- borderRadius: "50%",
82
- border: `1px solid ${STYLES.border}`,
83
- backgroundColor: STYLES.bg,
84
- backdropFilter: STYLES.blur,
85
- WebkitBackdropFilter: STYLES.blur,
86
- boxShadow: STYLES.shadow,
87
- cursor: "pointer",
88
- transition: "all 0.2s ease-out",
89
- color: mode === "off" ? STYLES.textMuted : STYLES.accent,
90
- fontSize: "20px"
91
- },
92
- onMouseEnter: (e) => {
93
- e.currentTarget.style.transform = "scale(1.1)";
94
- e.currentTarget.style.boxShadow = "0 12px 40px rgba(0, 0, 0, 0.5)";
95
- },
96
- onMouseLeave: (e) => {
97
- e.currentTarget.style.transform = "scale(1)";
98
- e.currentTarget.style.boxShadow = STYLES.shadow;
99
- },
100
- title: "UILint (\u2318+Shift+D)",
101
- children: isScanning ? /* @__PURE__ */ jsx(SpinnerIcon, {}) : /* @__PURE__ */ jsx(UILintIcon, { active: mode !== "off" })
102
- }
103
- ),
104
- isExpanded && /* @__PURE__ */ jsxs(
105
- "div",
106
- {
107
- style: {
108
- display: "flex",
109
- alignItems: "center",
110
- gap: "4px",
111
- padding: "6px",
112
- borderRadius: "28px",
113
- border: `1px solid ${STYLES.border}`,
114
- backgroundColor: STYLES.bg,
115
- backdropFilter: STYLES.blur,
116
- WebkitBackdropFilter: STYLES.blur,
117
- boxShadow: STYLES.shadow,
118
- animation: "uilint-fade-in 0.2s ease-out",
119
- minWidth: "380px"
120
- },
121
- children: [
122
- /* @__PURE__ */ jsx("style", { children: `
123
- @keyframes uilint-fade-in {
124
- from { opacity: 0; transform: scale(0.95); }
125
- to { opacity: 1; transform: scale(1); }
126
- }
127
- @keyframes uilint-spin {
128
- from { transform: rotate(0deg); }
129
- to { transform: rotate(360deg); }
130
- }
131
- ` }),
132
- MODES.map((m) => /* @__PURE__ */ jsx(
133
- ModeButton,
134
- {
135
- mode: m,
136
- isActive: mode === m.id,
137
- onClick: () => setMode(m.id)
138
- },
139
- m.id
140
- )),
141
- /* @__PURE__ */ jsx(
142
- "div",
143
- {
144
- style: {
145
- width: "1px",
146
- height: "24px",
147
- backgroundColor: STYLES.border,
148
- margin: "0 4px"
149
- }
150
- }
151
- ),
152
- mode !== "off" && /* @__PURE__ */ jsx(
153
- "div",
154
- {
155
- style: {
156
- display: "flex",
157
- alignItems: "center",
158
- justifyContent: "center",
159
- gap: "6px",
160
- padding: "6px 10px",
161
- borderRadius: "16px",
162
- backgroundColor: "rgba(59, 130, 246, 0.15)",
163
- fontSize: "12px",
164
- color: STYLES.accent,
165
- fontWeight: 500,
166
- minWidth: "120px"
167
- },
168
- children: isScanning ? /* @__PURE__ */ jsxs(Fragment, { children: [
169
- /* @__PURE__ */ jsx(SpinnerIcon, { size: 12 }),
170
- /* @__PURE__ */ jsx("span", { children: "Scanning..." })
171
- ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
172
- /* @__PURE__ */ jsxs("span", { children: [
173
- sourceFiles.length,
174
- " files"
175
- ] }),
176
- /* @__PURE__ */ jsx("span", { style: { color: STYLES.textMuted }, children: "\u2022" }),
177
- /* @__PURE__ */ jsxs("span", { children: [
178
- scannedElements.length,
179
- " elements"
180
- ] })
181
- ] })
182
- }
183
- ),
184
- mode !== "off" && /* @__PURE__ */ jsx(
185
- "button",
186
- {
187
- onClick: rescan,
188
- disabled: isScanning,
189
- style: {
190
- display: "flex",
191
- alignItems: "center",
192
- justifyContent: "center",
193
- width: "32px",
194
- height: "32px",
195
- borderRadius: "50%",
196
- border: "none",
197
- backgroundColor: "transparent",
198
- color: STYLES.textMuted,
199
- cursor: isScanning ? "not-allowed" : "pointer",
200
- opacity: isScanning ? 0.5 : 1,
201
- transition: "all 0.15s"
202
- },
203
- onMouseEnter: (e) => {
204
- if (!isScanning) {
205
- e.currentTarget.style.backgroundColor = STYLES.bgHover;
206
- e.currentTarget.style.color = STYLES.text;
207
- }
208
- },
209
- onMouseLeave: (e) => {
210
- e.currentTarget.style.backgroundColor = "transparent";
211
- e.currentTarget.style.color = STYLES.textMuted;
212
- },
213
- title: "Rescan page",
214
- children: /* @__PURE__ */ jsx(RefreshIcon, {})
215
- }
216
- ),
217
- /* @__PURE__ */ jsxs("div", { style: { position: "relative" }, ref: settingsRef, children: [
218
- /* @__PURE__ */ jsx(
219
- "button",
220
- {
221
- onClick: () => setShowSettings(!showSettings),
222
- style: {
223
- display: "flex",
224
- alignItems: "center",
225
- justifyContent: "center",
226
- width: "32px",
227
- height: "32px",
228
- borderRadius: "50%",
229
- border: "none",
230
- backgroundColor: showSettings ? STYLES.bgHover : "transparent",
231
- color: showSettings ? STYLES.text : STYLES.textMuted,
232
- cursor: "pointer",
233
- transition: "all 0.15s"
234
- },
235
- onMouseEnter: (e) => {
236
- e.currentTarget.style.backgroundColor = STYLES.bgHover;
237
- e.currentTarget.style.color = STYLES.text;
238
- },
239
- onMouseLeave: (e) => {
240
- if (!showSettings) {
241
- e.currentTarget.style.backgroundColor = "transparent";
242
- e.currentTarget.style.color = STYLES.textMuted;
243
- }
244
- },
245
- title: "Settings",
246
- children: /* @__PURE__ */ jsx(SettingsIcon, {})
247
- }
248
- ),
249
- showSettings && /* @__PURE__ */ jsx(
250
- SettingsPopover,
251
- {
252
- settings,
253
- onUpdate: updateSettings
254
- }
255
- )
256
- ] }),
257
- /* @__PURE__ */ jsx(
258
- "button",
259
- {
260
- onClick: () => setIsExpanded(false),
261
- style: {
262
- display: "flex",
263
- alignItems: "center",
264
- justifyContent: "center",
265
- width: "32px",
266
- height: "32px",
267
- borderRadius: "50%",
268
- border: "none",
269
- backgroundColor: "transparent",
270
- color: STYLES.textMuted,
271
- cursor: "pointer",
272
- transition: "all 0.15s"
273
- },
274
- onMouseEnter: (e) => {
275
- e.currentTarget.style.backgroundColor = STYLES.bgHover;
276
- e.currentTarget.style.color = STYLES.text;
277
- },
278
- onMouseLeave: (e) => {
279
- e.currentTarget.style.backgroundColor = "transparent";
280
- e.currentTarget.style.color = STYLES.textMuted;
281
- },
282
- title: "Collapse",
283
- children: /* @__PURE__ */ jsx(ChevronDownIcon, {})
284
- }
285
- )
286
- ]
287
- }
288
- ),
289
- !isExpanded && mode === "off" && /* @__PURE__ */ jsx(
290
- "div",
291
- {
292
- style: {
293
- position: "absolute",
294
- top: "100%",
295
- left: "50%",
296
- transform: "translateX(-50%)",
297
- marginTop: "8px",
298
- padding: "4px 8px",
299
- borderRadius: "4px",
300
- backgroundColor: STYLES.bg,
301
- border: `1px solid ${STYLES.border}`,
302
- fontSize: "11px",
303
- color: STYLES.textMuted,
304
- whiteSpace: "nowrap",
305
- opacity: 0,
306
- transition: "opacity 0.2s",
307
- pointerEvents: "none"
308
- },
309
- className: "uilint-hint",
310
- children: "\u2318+Shift+D"
311
- }
312
- )
313
- ]
314
- }
315
- );
316
- return createPortal(content, document.body);
317
- }
318
- function ModeButton({
319
- mode,
320
- isActive,
321
- onClick
322
- }) {
323
- return /* @__PURE__ */ jsxs(
324
- "button",
325
- {
326
- onClick,
327
- style: {
328
- display: "flex",
329
- alignItems: "center",
330
- gap: "6px",
331
- padding: "8px 14px",
332
- borderRadius: "20px",
333
- border: "none",
334
- backgroundColor: isActive ? STYLES.accent : "transparent",
335
- color: isActive ? "#FFFFFF" : STYLES.textMuted,
336
- fontSize: "13px",
337
- fontWeight: 500,
338
- cursor: "pointer",
339
- transition: "all 0.15s ease-out",
340
- fontFamily: STYLES.font
341
- },
342
- onMouseEnter: (e) => {
343
- if (!isActive) {
344
- e.currentTarget.style.backgroundColor = STYLES.bgHover;
345
- e.currentTarget.style.color = STYLES.text;
346
- }
347
- },
348
- onMouseLeave: (e) => {
349
- if (!isActive) {
350
- e.currentTarget.style.backgroundColor = "transparent";
351
- e.currentTarget.style.color = STYLES.textMuted;
352
- }
353
- },
354
- children: [
355
- /* @__PURE__ */ jsx("span", { style: { fontSize: "14px" }, children: mode.icon }),
356
- /* @__PURE__ */ jsx("span", { children: mode.label })
357
- ]
358
- }
359
- );
360
- }
361
- function SettingsPopover({
362
- settings,
363
- onUpdate
364
- }) {
365
- return /* @__PURE__ */ jsxs(
366
- "div",
367
- {
368
- style: {
369
- position: "absolute",
370
- bottom: "100%",
371
- right: 0,
372
- marginBottom: "8px",
373
- width: "280px",
374
- padding: "16px",
375
- borderRadius: "12px",
376
- border: `1px solid ${STYLES.border}`,
377
- backgroundColor: STYLES.bg,
378
- backdropFilter: STYLES.blur,
379
- WebkitBackdropFilter: STYLES.blur,
380
- boxShadow: STYLES.shadow,
381
- animation: "uilint-fade-in 0.15s ease-out"
382
- },
383
- children: [
384
- /* @__PURE__ */ jsx("div", { style: { fontSize: "13px", fontWeight: 600, color: STYLES.text, marginBottom: "12px" }, children: "Settings" }),
385
- /* @__PURE__ */ jsx(
386
- SettingToggle,
387
- {
388
- label: "Show file labels",
389
- checked: settings.showLabels,
390
- onChange: (checked) => onUpdate({ showLabels: checked })
391
- }
392
- ),
393
- /* @__PURE__ */ jsx(
394
- SettingToggle,
395
- {
396
- label: "Hide node_modules",
397
- checked: settings.hideNodeModules,
398
- onChange: (checked) => onUpdate({ hideNodeModules: checked })
399
- }
400
- ),
401
- /* @__PURE__ */ jsxs("div", { style: { marginTop: "12px" }, children: [
402
- /* @__PURE__ */ jsx(
403
- "div",
404
- {
405
- style: {
406
- fontSize: "12px",
407
- color: STYLES.textMuted,
408
- marginBottom: "6px"
409
- },
410
- children: "Label position"
411
- }
412
- ),
413
- /* @__PURE__ */ jsxs(
414
- "select",
415
- {
416
- value: settings.labelPosition,
417
- onChange: (e) => onUpdate({ labelPosition: e.target.value }),
418
- style: {
419
- width: "100%",
420
- padding: "6px 8px",
421
- borderRadius: "6px",
422
- border: `1px solid ${STYLES.border}`,
423
- backgroundColor: STYLES.bgHover,
424
- color: STYLES.text,
425
- fontSize: "12px",
426
- cursor: "pointer"
427
- },
428
- children: [
429
- /* @__PURE__ */ jsx("option", { value: "top-left", children: "Top Left" }),
430
- /* @__PURE__ */ jsx("option", { value: "top-right", children: "Top Right" }),
431
- /* @__PURE__ */ jsx("option", { value: "bottom-left", children: "Bottom Left" }),
432
- /* @__PURE__ */ jsx("option", { value: "bottom-right", children: "Bottom Right" })
433
- ]
434
- }
435
- )
436
- ] })
437
- ]
438
- }
439
- );
440
- }
441
- function SettingToggle({
442
- label,
443
- checked,
444
- onChange
445
- }) {
446
- return /* @__PURE__ */ jsxs(
447
- "label",
448
- {
449
- style: {
450
- display: "flex",
451
- alignItems: "center",
452
- justifyContent: "space-between",
453
- padding: "8px 0",
454
- cursor: "pointer"
455
- },
456
- children: [
457
- /* @__PURE__ */ jsx("span", { style: { fontSize: "12px", color: STYLES.textMuted }, children: label }),
458
- /* @__PURE__ */ jsx(
459
- "div",
460
- {
461
- onClick: () => onChange(!checked),
462
- style: {
463
- width: "36px",
464
- height: "20px",
465
- borderRadius: "10px",
466
- backgroundColor: checked ? STYLES.accent : "rgba(75, 85, 99, 0.5)",
467
- position: "relative",
468
- transition: "background-color 0.2s"
469
- },
470
- children: /* @__PURE__ */ jsx(
471
- "div",
472
- {
473
- style: {
474
- position: "absolute",
475
- top: "2px",
476
- left: checked ? "18px" : "2px",
477
- width: "16px",
478
- height: "16px",
479
- borderRadius: "50%",
480
- backgroundColor: "#FFFFFF",
481
- transition: "left 0.2s",
482
- boxShadow: "0 1px 3px rgba(0, 0, 0, 0.2)"
483
- }
484
- }
485
- )
486
- }
487
- )
488
- ]
489
- }
490
- );
491
- }
492
- function UILintIcon({ active }) {
493
- return /* @__PURE__ */ jsxs("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", children: [
494
- /* @__PURE__ */ jsx(
495
- "rect",
496
- {
497
- x: "3",
498
- y: "3",
499
- width: "18",
500
- height: "18",
501
- rx: "3",
502
- stroke: active ? STYLES.accent : "currentColor",
503
- strokeWidth: "2"
504
- }
505
- ),
506
- /* @__PURE__ */ jsx(
507
- "path",
508
- {
509
- d: "M7 12h10M12 7v10",
510
- stroke: active ? STYLES.accent : "currentColor",
511
- strokeWidth: "2",
512
- strokeLinecap: "round"
513
- }
514
- )
515
- ] });
516
- }
517
- function SpinnerIcon({ size = 16 }) {
518
- return /* @__PURE__ */ jsx(
519
- "svg",
520
- {
521
- width: size,
522
- height: size,
523
- viewBox: "0 0 24 24",
524
- fill: "none",
525
- style: { animation: "uilint-spin 1s linear infinite" },
526
- children: /* @__PURE__ */ jsx(
527
- "circle",
528
- {
529
- cx: "12",
530
- cy: "12",
531
- r: "10",
532
- stroke: "currentColor",
533
- strokeWidth: "3",
534
- strokeLinecap: "round",
535
- strokeDasharray: "31.4 31.4",
536
- fill: "none"
537
- }
538
- )
539
- }
540
- );
541
- }
542
- function RefreshIcon() {
543
- return /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: [
544
- /* @__PURE__ */ jsx(
545
- "path",
546
- {
547
- d: "M21 12a9 9 0 11-9-9c2.52 0 4.93 1 6.74 2.74L21 8",
548
- stroke: "currentColor",
549
- strokeWidth: "2",
550
- strokeLinecap: "round",
551
- strokeLinejoin: "round"
552
- }
553
- ),
554
- /* @__PURE__ */ jsx(
555
- "path",
556
- {
557
- d: "M21 3v5h-5",
558
- stroke: "currentColor",
559
- strokeWidth: "2",
560
- strokeLinecap: "round",
561
- strokeLinejoin: "round"
562
- }
563
- )
564
- ] });
565
- }
566
- function SettingsIcon() {
567
- return /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: [
568
- /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "3", stroke: "currentColor", strokeWidth: "2" }),
569
- /* @__PURE__ */ jsx(
570
- "path",
571
- {
572
- d: "M12 1v2m0 18v2M4.22 4.22l1.42 1.42m12.72 12.72l1.42 1.42M1 12h2m18 0h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42",
573
- stroke: "currentColor",
574
- strokeWidth: "2",
575
- strokeLinecap: "round"
576
- }
577
- )
578
- ] });
579
- }
580
- function ChevronDownIcon() {
581
- return /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx(
582
- "path",
583
- {
584
- d: "M6 9l6 6 6-6",
585
- stroke: "currentColor",
586
- strokeWidth: "2",
587
- strokeLinecap: "round",
588
- strokeLinejoin: "round"
589
- }
590
- ) });
591
- }
592
-
593
- export {
594
- UILintToolbar
595
- };