@ytspar/devbar 1.0.0-canary.3007fc6 → 1.0.0-canary.92db425
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/dist/GlobalDevBar.d.ts +2 -15
- package/dist/GlobalDevBar.js +100 -231
- package/dist/constants.js +6 -8
- package/package.json +1 -1
package/dist/GlobalDevBar.d.ts
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* This is a vanilla JS replacement for the React-based GlobalDevBar component
|
|
8
8
|
* to avoid React dependency conflicts in host applications.
|
|
9
9
|
*/
|
|
10
|
-
import type { ConsoleLog,
|
|
11
|
-
export type { ConsoleLog, SweetlinkCommand, OutlineNode, PageSchema, GlobalDevBarOptions, DevBarControl
|
|
10
|
+
import type { ConsoleLog, SweetlinkCommand, OutlineNode, PageSchema, GlobalDevBarOptions, DevBarControl } from './types.js';
|
|
11
|
+
export type { ConsoleLog, SweetlinkCommand, OutlineNode, PageSchema, GlobalDevBarOptions, DevBarControl };
|
|
12
12
|
interface EarlyConsoleCapture {
|
|
13
13
|
errorCount: number;
|
|
14
14
|
warningCount: number;
|
|
@@ -48,7 +48,6 @@ export declare class GlobalDevBar {
|
|
|
48
48
|
private perfStats;
|
|
49
49
|
private lcpValue;
|
|
50
50
|
private reconnectAttempts;
|
|
51
|
-
private lastDotPosition;
|
|
52
51
|
private reconnectTimeout;
|
|
53
52
|
private screenshotTimeout;
|
|
54
53
|
private copiedPathTimeout;
|
|
@@ -95,10 +94,6 @@ export declare class GlobalDevBar {
|
|
|
95
94
|
* Initialize and mount the devbar
|
|
96
95
|
*/
|
|
97
96
|
init(): void;
|
|
98
|
-
/**
|
|
99
|
-
* Get the current position
|
|
100
|
-
*/
|
|
101
|
-
getPosition(): string;
|
|
102
97
|
/**
|
|
103
98
|
* Destroy the devbar and cleanup
|
|
104
99
|
*/
|
|
@@ -184,14 +179,6 @@ export declare class GlobalDevBar {
|
|
|
184
179
|
*/
|
|
185
180
|
private createConsoleBadge;
|
|
186
181
|
private createScreenshotButton;
|
|
187
|
-
/**
|
|
188
|
-
* Get the tooltip text for the screenshot button based on current state
|
|
189
|
-
*/
|
|
190
|
-
private getScreenshotTooltip;
|
|
191
|
-
/**
|
|
192
|
-
* Get the tooltip text for the AI review button based on current state
|
|
193
|
-
*/
|
|
194
|
-
private getAIReviewTooltip;
|
|
195
182
|
private createAIReviewButton;
|
|
196
183
|
private createOutlineButton;
|
|
197
184
|
private createSchemaButton;
|
package/dist/GlobalDevBar.js
CHANGED
|
@@ -8,20 +8,19 @@
|
|
|
8
8
|
* to avoid React dependency conflicts in host applications.
|
|
9
9
|
*/
|
|
10
10
|
import * as html2canvasModule from 'html2canvas-pro';
|
|
11
|
-
import {
|
|
11
|
+
import { MAX_CONSOLE_LOGS, DEVBAR_SCREENSHOT_QUALITY, MAX_RECONNECT_ATTEMPTS, BASE_RECONNECT_DELAY_MS, MAX_RECONNECT_DELAY_MS, WS_PORT, SCREENSHOT_NOTIFICATION_MS, CLIPBOARD_NOTIFICATION_MS, DESIGN_REVIEW_NOTIFICATION_MS, SCREENSHOT_BLUR_DELAY_MS, SCREENSHOT_SCALE, TAILWIND_BREAKPOINTS, BUTTON_COLORS, CATEGORY_COLORS, TOOLTIP_STYLES, COLORS, FONT_MONO, } from './constants.js';
|
|
12
|
+
import { formatArgs, canvasToDataUrl, prepareForCapture, delay, copyCanvasToClipboard, } from './utils.js';
|
|
12
13
|
import { extractDocumentOutline, outlineToMarkdown } from './outline.js';
|
|
13
14
|
import { extractPageSchema, schemaToMarkdown } from './schema.js';
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
const html2canvas = (html2canvasModule.default ??
|
|
17
|
-
html2canvasModule);
|
|
15
|
+
import { createSvgIcon, getButtonStyles, createStyledButton, createModalOverlay, createModalBox, createModalHeader, createModalContent, createEmptyMessage, createInfoBox, } from './ui/index.js';
|
|
16
|
+
const html2canvas = (html2canvasModule.default ?? html2canvasModule);
|
|
18
17
|
const earlyConsoleCapture = (() => {
|
|
19
18
|
const ssrFallback = {
|
|
20
19
|
errorCount: 0,
|
|
21
20
|
warningCount: 0,
|
|
22
21
|
logs: [],
|
|
23
22
|
originalConsole: null,
|
|
24
|
-
isPatched: false
|
|
23
|
+
isPatched: false
|
|
25
24
|
};
|
|
26
25
|
// Skip on server-side rendering
|
|
27
26
|
if (typeof window === 'undefined')
|
|
@@ -34,9 +33,9 @@ const earlyConsoleCapture = (() => {
|
|
|
34
33
|
log: console.log,
|
|
35
34
|
error: console.error,
|
|
36
35
|
warn: console.warn,
|
|
37
|
-
info: console.info
|
|
36
|
+
info: console.info
|
|
38
37
|
},
|
|
39
|
-
isPatched: false
|
|
38
|
+
isPatched: false
|
|
40
39
|
};
|
|
41
40
|
const captureLog = (level, args) => {
|
|
42
41
|
capture.logs.push({ level, message: formatArgs(args), timestamp: Date.now() });
|
|
@@ -45,24 +44,10 @@ const earlyConsoleCapture = (() => {
|
|
|
45
44
|
};
|
|
46
45
|
// Patch console immediately
|
|
47
46
|
if (!capture.isPatched && capture.originalConsole) {
|
|
48
|
-
console.log = (...args) => {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
};
|
|
52
|
-
console.error = (...args) => {
|
|
53
|
-
captureLog('error', args);
|
|
54
|
-
capture.errorCount++;
|
|
55
|
-
capture.originalConsole.error(...args);
|
|
56
|
-
};
|
|
57
|
-
console.warn = (...args) => {
|
|
58
|
-
captureLog('warn', args);
|
|
59
|
-
capture.warningCount++;
|
|
60
|
-
capture.originalConsole.warn(...args);
|
|
61
|
-
};
|
|
62
|
-
console.info = (...args) => {
|
|
63
|
-
captureLog('info', args);
|
|
64
|
-
capture.originalConsole.info(...args);
|
|
65
|
-
};
|
|
47
|
+
console.log = (...args) => { captureLog('log', args); capture.originalConsole.log(...args); };
|
|
48
|
+
console.error = (...args) => { captureLog('error', args); capture.errorCount++; capture.originalConsole.error(...args); };
|
|
49
|
+
console.warn = (...args) => { captureLog('warn', args); capture.warningCount++; capture.originalConsole.warn(...args); };
|
|
50
|
+
console.info = (...args) => { captureLog('info', args); capture.originalConsole.info(...args); };
|
|
66
51
|
capture.isPatched = true;
|
|
67
52
|
}
|
|
68
53
|
return capture;
|
|
@@ -96,8 +81,6 @@ export class GlobalDevBar {
|
|
|
96
81
|
this.perfStats = null;
|
|
97
82
|
this.lcpValue = null;
|
|
98
83
|
this.reconnectAttempts = 0;
|
|
99
|
-
// Track the position of the connection indicator dot for smooth collapse
|
|
100
|
-
this.lastDotPosition = null;
|
|
101
84
|
this.reconnectTimeout = null;
|
|
102
85
|
this.screenshotTimeout = null;
|
|
103
86
|
this.copiedPathTimeout = null;
|
|
@@ -170,7 +153,7 @@ export class GlobalDevBar {
|
|
|
170
153
|
fontWeight: '600',
|
|
171
154
|
display: 'flex',
|
|
172
155
|
alignItems: 'center',
|
|
173
|
-
justifyContent: 'center'
|
|
156
|
+
justifyContent: 'center'
|
|
174
157
|
});
|
|
175
158
|
badge.textContent = count > 99 ? '!' : String(count);
|
|
176
159
|
return badge;
|
|
@@ -183,7 +166,7 @@ export class GlobalDevBar {
|
|
|
183
166
|
*/
|
|
184
167
|
static registerControl(control) {
|
|
185
168
|
// Remove existing control with same ID
|
|
186
|
-
GlobalDevBar.customControls = GlobalDevBar.customControls.filter(
|
|
169
|
+
GlobalDevBar.customControls = GlobalDevBar.customControls.filter(c => c.id !== control.id);
|
|
187
170
|
GlobalDevBar.customControls.push(control);
|
|
188
171
|
// Trigger re-render of all instances
|
|
189
172
|
const instance = getGlobalInstance();
|
|
@@ -195,7 +178,7 @@ export class GlobalDevBar {
|
|
|
195
178
|
* Unregister a custom control by ID
|
|
196
179
|
*/
|
|
197
180
|
static unregisterControl(id) {
|
|
198
|
-
GlobalDevBar.customControls = GlobalDevBar.customControls.filter(
|
|
181
|
+
GlobalDevBar.customControls = GlobalDevBar.customControls.filter(c => c.id !== id);
|
|
199
182
|
// Trigger re-render of all instances
|
|
200
183
|
const instance = getGlobalInstance();
|
|
201
184
|
if (instance) {
|
|
@@ -241,12 +224,6 @@ export class GlobalDevBar {
|
|
|
241
224
|
// Initial render
|
|
242
225
|
this.render();
|
|
243
226
|
}
|
|
244
|
-
/**
|
|
245
|
-
* Get the current position
|
|
246
|
-
*/
|
|
247
|
-
getPosition() {
|
|
248
|
-
return this.options.position;
|
|
249
|
-
}
|
|
250
227
|
/**
|
|
251
228
|
* Destroy the devbar and cleanup
|
|
252
229
|
*/
|
|
@@ -330,7 +307,7 @@ export class GlobalDevBar {
|
|
|
330
307
|
this.render();
|
|
331
308
|
// Auto-reconnect with exponential backoff
|
|
332
309
|
if (!this.destroyed && this.reconnectAttempts < MAX_RECONNECT_ATTEMPTS) {
|
|
333
|
-
const delayMs = BASE_RECONNECT_DELAY_MS * 2
|
|
310
|
+
const delayMs = BASE_RECONNECT_DELAY_MS * Math.pow(2, this.reconnectAttempts);
|
|
334
311
|
this.reconnectAttempts++;
|
|
335
312
|
this.reconnectTimeout = setTimeout(() => this.connectWebSocket(), Math.min(delayMs, MAX_RECONNECT_DELAY_MS));
|
|
336
313
|
}
|
|
@@ -348,20 +325,11 @@ export class GlobalDevBar {
|
|
|
348
325
|
const targetElement = command.selector
|
|
349
326
|
? document.querySelector(command.selector) || document.body
|
|
350
327
|
: document.body;
|
|
351
|
-
const canvas = await html2canvas(targetElement, {
|
|
352
|
-
logging: false,
|
|
353
|
-
useCORS: true,
|
|
354
|
-
allowTaint: true,
|
|
355
|
-
});
|
|
328
|
+
const canvas = await html2canvas(targetElement, { logging: false, useCORS: true, allowTaint: true });
|
|
356
329
|
ws.send(JSON.stringify({
|
|
357
330
|
success: true,
|
|
358
|
-
data: {
|
|
359
|
-
|
|
360
|
-
width: canvas.width,
|
|
361
|
-
height: canvas.height,
|
|
362
|
-
selector: command.selector || 'body',
|
|
363
|
-
},
|
|
364
|
-
timestamp: Date.now(),
|
|
331
|
+
data: { screenshot: canvas.toDataURL('image/png'), width: canvas.width, height: canvas.height, selector: command.selector || 'body' },
|
|
332
|
+
timestamp: Date.now()
|
|
365
333
|
}));
|
|
366
334
|
break;
|
|
367
335
|
}
|
|
@@ -369,7 +337,7 @@ export class GlobalDevBar {
|
|
|
369
337
|
let logs = this.consoleLogs;
|
|
370
338
|
if (command.filter) {
|
|
371
339
|
const filter = command.filter.toLowerCase();
|
|
372
|
-
logs = logs.filter(
|
|
340
|
+
logs = logs.filter(log => log.level.includes(filter) || log.message.toLowerCase().includes(filter));
|
|
373
341
|
}
|
|
374
342
|
ws.send(JSON.stringify({ success: true, data: logs, timestamp: Date.now() }));
|
|
375
343
|
break;
|
|
@@ -380,18 +348,9 @@ export class GlobalDevBar {
|
|
|
380
348
|
const results = elements.map((el) => {
|
|
381
349
|
if (command.property)
|
|
382
350
|
return el[command.property] ?? null;
|
|
383
|
-
return {
|
|
384
|
-
tagName: el.tagName,
|
|
385
|
-
className: el.className,
|
|
386
|
-
id: el.id,
|
|
387
|
-
textContent: el.textContent?.trim().slice(0, 100),
|
|
388
|
-
};
|
|
351
|
+
return { tagName: el.tagName, className: el.className, id: el.id, textContent: el.textContent?.trim().slice(0, 100) };
|
|
389
352
|
});
|
|
390
|
-
ws.send(JSON.stringify({
|
|
391
|
-
success: true,
|
|
392
|
-
data: { count: results.length, results },
|
|
393
|
-
timestamp: Date.now(),
|
|
394
|
-
}));
|
|
353
|
+
ws.send(JSON.stringify({ success: true, data: { count: results.length, results }, timestamp: Date.now() }));
|
|
395
354
|
}
|
|
396
355
|
break;
|
|
397
356
|
}
|
|
@@ -404,11 +363,7 @@ export class GlobalDevBar {
|
|
|
404
363
|
ws.send(JSON.stringify({ success: true, data: result, timestamp: Date.now() }));
|
|
405
364
|
}
|
|
406
365
|
catch (e) {
|
|
407
|
-
ws.send(JSON.stringify({
|
|
408
|
-
success: false,
|
|
409
|
-
error: e instanceof Error ? e.message : 'Execution failed',
|
|
410
|
-
timestamp: Date.now(),
|
|
411
|
-
}));
|
|
366
|
+
ws.send(JSON.stringify({ success: false, error: e instanceof Error ? e.message : 'Execution failed', timestamp: Date.now() }));
|
|
412
367
|
}
|
|
413
368
|
}
|
|
414
369
|
break;
|
|
@@ -472,37 +427,25 @@ export class GlobalDevBar {
|
|
|
472
427
|
this.lastScreenshot = path;
|
|
473
428
|
if (this.screenshotTimeout)
|
|
474
429
|
clearTimeout(this.screenshotTimeout);
|
|
475
|
-
this.screenshotTimeout = setTimeout(() => {
|
|
476
|
-
this.lastScreenshot = null;
|
|
477
|
-
this.render();
|
|
478
|
-
}, durationMs);
|
|
430
|
+
this.screenshotTimeout = setTimeout(() => { this.lastScreenshot = null; this.render(); }, durationMs);
|
|
479
431
|
break;
|
|
480
432
|
case 'designReview':
|
|
481
433
|
this.lastDesignReview = path;
|
|
482
434
|
if (this.designReviewTimeout)
|
|
483
435
|
clearTimeout(this.designReviewTimeout);
|
|
484
|
-
this.designReviewTimeout = setTimeout(() => {
|
|
485
|
-
this.lastDesignReview = null;
|
|
486
|
-
this.render();
|
|
487
|
-
}, durationMs);
|
|
436
|
+
this.designReviewTimeout = setTimeout(() => { this.lastDesignReview = null; this.render(); }, durationMs);
|
|
488
437
|
break;
|
|
489
438
|
case 'outline':
|
|
490
439
|
this.lastOutline = path;
|
|
491
440
|
if (this.outlineTimeout)
|
|
492
441
|
clearTimeout(this.outlineTimeout);
|
|
493
|
-
this.outlineTimeout = setTimeout(() => {
|
|
494
|
-
this.lastOutline = null;
|
|
495
|
-
this.render();
|
|
496
|
-
}, durationMs);
|
|
442
|
+
this.outlineTimeout = setTimeout(() => { this.lastOutline = null; this.render(); }, durationMs);
|
|
497
443
|
break;
|
|
498
444
|
case 'schema':
|
|
499
445
|
this.lastSchema = path;
|
|
500
446
|
if (this.schemaTimeout)
|
|
501
447
|
clearTimeout(this.schemaTimeout);
|
|
502
|
-
this.schemaTimeout = setTimeout(() => {
|
|
503
|
-
this.lastSchema = null;
|
|
504
|
-
this.render();
|
|
505
|
-
}, durationMs);
|
|
448
|
+
this.schemaTimeout = setTimeout(() => { this.lastSchema = null; this.render(); }, durationMs);
|
|
506
449
|
break;
|
|
507
450
|
}
|
|
508
451
|
this.render();
|
|
@@ -512,17 +455,20 @@ export class GlobalDevBar {
|
|
|
512
455
|
const width = window.innerWidth;
|
|
513
456
|
const height = window.innerHeight;
|
|
514
457
|
// Determine breakpoint by checking thresholds in descending order
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
'
|
|
518
|
-
|
|
519
|
-
'
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
458
|
+
let tailwindBreakpoint = 'base';
|
|
459
|
+
if (width >= TAILWIND_BREAKPOINTS['2xl'].min)
|
|
460
|
+
tailwindBreakpoint = '2xl';
|
|
461
|
+
else if (width >= TAILWIND_BREAKPOINTS.xl.min)
|
|
462
|
+
tailwindBreakpoint = 'xl';
|
|
463
|
+
else if (width >= TAILWIND_BREAKPOINTS.lg.min)
|
|
464
|
+
tailwindBreakpoint = 'lg';
|
|
465
|
+
else if (width >= TAILWIND_BREAKPOINTS.md.min)
|
|
466
|
+
tailwindBreakpoint = 'md';
|
|
467
|
+
else if (width >= TAILWIND_BREAKPOINTS.sm.min)
|
|
468
|
+
tailwindBreakpoint = 'sm';
|
|
523
469
|
this.breakpointInfo = {
|
|
524
470
|
tailwindBreakpoint,
|
|
525
|
-
dimensions: `${width}x${height}
|
|
471
|
+
dimensions: `${width}x${height}`
|
|
526
472
|
};
|
|
527
473
|
this.render();
|
|
528
474
|
};
|
|
@@ -534,7 +480,7 @@ export class GlobalDevBar {
|
|
|
534
480
|
const updatePerfStats = () => {
|
|
535
481
|
// FCP
|
|
536
482
|
const paintEntries = performance.getEntriesByType('paint');
|
|
537
|
-
const fcpEntry = paintEntries.find(
|
|
483
|
+
const fcpEntry = paintEntries.find(entry => entry.name === 'first-contentful-paint');
|
|
538
484
|
const fcp = fcpEntry ? `${Math.round(fcpEntry.startTime)}ms` : '-';
|
|
539
485
|
// LCP (from cached value, updated by observer)
|
|
540
486
|
const lcp = this.lcpValue !== null ? `${Math.round(this.lcpValue)}ms` : '-';
|
|
@@ -596,10 +542,7 @@ export class GlobalDevBar {
|
|
|
596
542
|
this.keydownHandler = (e) => {
|
|
597
543
|
// Close modals on Escape
|
|
598
544
|
if (e.key === 'Escape') {
|
|
599
|
-
if (this.consoleFilter ||
|
|
600
|
-
this.showOutlineModal ||
|
|
601
|
-
this.showSchemaModal ||
|
|
602
|
-
this.showDesignReviewConfirm) {
|
|
545
|
+
if (this.consoleFilter || this.showOutlineModal || this.showSchemaModal || this.showDesignReviewConfirm) {
|
|
603
546
|
this.consoleFilter = null;
|
|
604
547
|
this.showOutlineModal = false;
|
|
605
548
|
this.showSchemaModal = false;
|
|
@@ -661,7 +604,7 @@ export class GlobalDevBar {
|
|
|
661
604
|
allowTaint: true,
|
|
662
605
|
scale: SCREENSHOT_SCALE,
|
|
663
606
|
width: window.innerWidth,
|
|
664
|
-
windowWidth: window.innerWidth
|
|
607
|
+
windowWidth: window.innerWidth
|
|
665
608
|
});
|
|
666
609
|
// Restore page state
|
|
667
610
|
cleanup();
|
|
@@ -683,10 +626,7 @@ export class GlobalDevBar {
|
|
|
683
626
|
}
|
|
684
627
|
}
|
|
685
628
|
else {
|
|
686
|
-
const dataUrl = canvasToDataUrl(canvas, {
|
|
687
|
-
format: 'jpeg',
|
|
688
|
-
quality: DEVBAR_SCREENSHOT_QUALITY,
|
|
689
|
-
});
|
|
629
|
+
const dataUrl = canvasToDataUrl(canvas, { format: 'jpeg', quality: DEVBAR_SCREENSHOT_QUALITY });
|
|
690
630
|
if (this.ws?.readyState === WebSocket.OPEN) {
|
|
691
631
|
this.ws.send(JSON.stringify({
|
|
692
632
|
type: 'save-screenshot',
|
|
@@ -696,8 +636,8 @@ export class GlobalDevBar {
|
|
|
696
636
|
height: canvas.height,
|
|
697
637
|
logs: this.consoleLogs,
|
|
698
638
|
url: window.location.href,
|
|
699
|
-
timestamp: Date.now()
|
|
700
|
-
}
|
|
639
|
+
timestamp: Date.now()
|
|
640
|
+
}
|
|
701
641
|
}));
|
|
702
642
|
}
|
|
703
643
|
}
|
|
@@ -732,7 +672,7 @@ export class GlobalDevBar {
|
|
|
732
672
|
allowTaint: true,
|
|
733
673
|
scale: 1, // Full quality for design review
|
|
734
674
|
width: window.innerWidth,
|
|
735
|
-
windowWidth: window.innerWidth
|
|
675
|
+
windowWidth: window.innerWidth
|
|
736
676
|
});
|
|
737
677
|
// Restore page state
|
|
738
678
|
cleanup();
|
|
@@ -747,8 +687,8 @@ export class GlobalDevBar {
|
|
|
747
687
|
height: canvas.height,
|
|
748
688
|
logs: this.consoleLogs,
|
|
749
689
|
url: window.location.href,
|
|
750
|
-
timestamp: Date.now()
|
|
751
|
-
}
|
|
690
|
+
timestamp: Date.now()
|
|
691
|
+
}
|
|
752
692
|
}));
|
|
753
693
|
}
|
|
754
694
|
}
|
|
@@ -843,8 +783,8 @@ export class GlobalDevBar {
|
|
|
843
783
|
markdown,
|
|
844
784
|
url: window.location.href,
|
|
845
785
|
title: document.title,
|
|
846
|
-
timestamp: Date.now()
|
|
847
|
-
}
|
|
786
|
+
timestamp: Date.now()
|
|
787
|
+
}
|
|
848
788
|
}));
|
|
849
789
|
}
|
|
850
790
|
}
|
|
@@ -859,8 +799,8 @@ export class GlobalDevBar {
|
|
|
859
799
|
markdown,
|
|
860
800
|
url: window.location.href,
|
|
861
801
|
title: document.title,
|
|
862
|
-
timestamp: Date.now()
|
|
863
|
-
}
|
|
802
|
+
timestamp: Date.now()
|
|
803
|
+
}
|
|
864
804
|
}));
|
|
865
805
|
}
|
|
866
806
|
}
|
|
@@ -943,12 +883,7 @@ export class GlobalDevBar {
|
|
|
943
883
|
Object.assign(title.style, { color, fontSize: '0.875rem', fontWeight: '600' });
|
|
944
884
|
title.textContent = 'AI Design Review';
|
|
945
885
|
header.appendChild(title);
|
|
946
|
-
const closeBtn = createStyledButton({
|
|
947
|
-
color: COLORS.textMuted,
|
|
948
|
-
text: '×',
|
|
949
|
-
padding: '0',
|
|
950
|
-
fontSize: '1.25rem',
|
|
951
|
-
});
|
|
886
|
+
const closeBtn = createStyledButton({ color: COLORS.textMuted, text: '×', padding: '0', fontSize: '1.25rem' });
|
|
952
887
|
closeBtn.style.border = 'none';
|
|
953
888
|
closeBtn.onclick = closeModal;
|
|
954
889
|
header.appendChild(closeBtn);
|
|
@@ -980,11 +915,7 @@ export class GlobalDevBar {
|
|
|
980
915
|
padding: '14px 18px',
|
|
981
916
|
borderTop: `1px solid ${COLORS.border}`,
|
|
982
917
|
});
|
|
983
|
-
const cancelBtn = createStyledButton({
|
|
984
|
-
color: COLORS.textMuted,
|
|
985
|
-
text: 'Cancel',
|
|
986
|
-
padding: '8px 16px',
|
|
987
|
-
});
|
|
918
|
+
const cancelBtn = createStyledButton({ color: COLORS.textMuted, text: 'Cancel', padding: '8px 16px' });
|
|
988
919
|
cancelBtn.onclick = closeModal;
|
|
989
920
|
footer.appendChild(cancelBtn);
|
|
990
921
|
if (this.apiKeyStatus?.configured) {
|
|
@@ -1007,11 +938,7 @@ export class GlobalDevBar {
|
|
|
1007
938
|
const instructions = document.createElement('div');
|
|
1008
939
|
Object.assign(instructions.style, { marginBottom: '12px' });
|
|
1009
940
|
const instructTitle = document.createElement('div');
|
|
1010
|
-
Object.assign(instructTitle.style, {
|
|
1011
|
-
color: COLORS.textSecondary,
|
|
1012
|
-
fontWeight: '600',
|
|
1013
|
-
marginBottom: '8px',
|
|
1014
|
-
});
|
|
941
|
+
Object.assign(instructTitle.style, { color: COLORS.textSecondary, fontWeight: '600', marginBottom: '8px' });
|
|
1015
942
|
instructTitle.textContent = 'To configure:';
|
|
1016
943
|
instructions.appendChild(instructTitle);
|
|
1017
944
|
const steps = [
|
|
@@ -1071,11 +998,7 @@ export class GlobalDevBar {
|
|
|
1071
998
|
// Model info
|
|
1072
999
|
if (this.apiKeyStatus?.model) {
|
|
1073
1000
|
const modelDiv = document.createElement('div');
|
|
1074
|
-
Object.assign(modelDiv.style, {
|
|
1075
|
-
color: COLORS.textMuted,
|
|
1076
|
-
fontSize: '0.6875rem',
|
|
1077
|
-
marginTop: '12px',
|
|
1078
|
-
});
|
|
1001
|
+
Object.assign(modelDiv.style, { color: COLORS.textMuted, fontSize: '0.6875rem', marginTop: '12px' });
|
|
1079
1002
|
modelDiv.textContent = `Model: ${this.apiKeyStatus.model}`;
|
|
1080
1003
|
if (this.apiKeyStatus.maskedKey) {
|
|
1081
1004
|
modelDiv.textContent += ` | Key: ${this.apiKeyStatus.maskedKey}`;
|
|
@@ -1088,7 +1011,7 @@ export class GlobalDevBar {
|
|
|
1088
1011
|
const filterType = this.consoleFilter;
|
|
1089
1012
|
if (!filterType)
|
|
1090
1013
|
return;
|
|
1091
|
-
const logs = earlyConsoleCapture.logs.filter(
|
|
1014
|
+
const logs = earlyConsoleCapture.logs.filter(log => log.level === filterType);
|
|
1092
1015
|
const color = filterType === 'error' ? BUTTON_COLORS.error : BUTTON_COLORS.warning;
|
|
1093
1016
|
const label = filterType === 'error' ? 'Errors' : 'Warnings';
|
|
1094
1017
|
const popup = document.createElement('div');
|
|
@@ -1197,8 +1120,7 @@ export class GlobalDevBar {
|
|
|
1197
1120
|
wordBreak: 'break-word',
|
|
1198
1121
|
whiteSpace: 'pre-wrap',
|
|
1199
1122
|
});
|
|
1200
|
-
message.textContent =
|
|
1201
|
-
log.message.length > 500 ? `${log.message.slice(0, 500)}...` : log.message;
|
|
1123
|
+
message.textContent = log.message.length > 500 ? log.message.slice(0, 500) + '...' : log.message;
|
|
1202
1124
|
logItem.appendChild(message);
|
|
1203
1125
|
container.appendChild(logItem);
|
|
1204
1126
|
});
|
|
@@ -1270,7 +1192,7 @@ export class GlobalDevBar {
|
|
|
1270
1192
|
fontSize: '0.6875rem',
|
|
1271
1193
|
marginLeft: '8px',
|
|
1272
1194
|
});
|
|
1273
|
-
const truncatedText = node.text.length > 60 ?
|
|
1195
|
+
const truncatedText = node.text.length > 60 ? node.text.slice(0, 60) + '...' : node.text;
|
|
1274
1196
|
textSpan.textContent = truncatedText;
|
|
1275
1197
|
nodeEl.appendChild(textSpan);
|
|
1276
1198
|
if (node.id) {
|
|
@@ -1403,7 +1325,7 @@ export class GlobalDevBar {
|
|
|
1403
1325
|
punct: COLORS.textMuted, // gray
|
|
1404
1326
|
};
|
|
1405
1327
|
// Simple tokenizer for JSON using matchAll for safety
|
|
1406
|
-
const tokenPattern = /("(?:\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*")(\s*:)?|(\btrue\b|\bfalse\b)|(\bnull\b)|(-?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?)|([{}[\],])|(\s+)/g;
|
|
1328
|
+
const tokenPattern = /("(?:\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*")(\s*:)?|(\btrue\b|\bfalse\b)|(\bnull\b)|(-?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?)|([{}\[\],])|(\s+)/g;
|
|
1407
1329
|
for (const match of json.matchAll(tokenPattern)) {
|
|
1408
1330
|
const [, str, colon, bool, nullToken, num, punct, whitespace] = match;
|
|
1409
1331
|
if (whitespace) {
|
|
@@ -1495,27 +1417,18 @@ export class GlobalDevBar {
|
|
|
1495
1417
|
return;
|
|
1496
1418
|
const { position, accentColor } = this.options;
|
|
1497
1419
|
const { errorCount, warningCount } = this.getLogCounts();
|
|
1498
|
-
//
|
|
1499
|
-
//
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
const collapsedPositions = {
|
|
1511
|
-
'bottom-left': { bottom: '27px', left: '86px' },
|
|
1512
|
-
'bottom-right': { bottom: '27px', right: '29px' },
|
|
1513
|
-
'top-left': { top: '27px', left: '86px' },
|
|
1514
|
-
'top-right': { top: '27px', right: '29px' },
|
|
1515
|
-
'bottom-center': { bottom: '19px', left: '50%', transform: 'translateX(-50%)' },
|
|
1516
|
-
};
|
|
1517
|
-
posStyle = collapsedPositions[position] ?? collapsedPositions['bottom-left'];
|
|
1518
|
-
}
|
|
1420
|
+
// Calculate position so the collapsed dot aligns with where it appears in expanded state
|
|
1421
|
+
// Expanded: left:80 + border:1 + padding:12 + half-indicator:6 = 99px horizontal center
|
|
1422
|
+
// Expanded: bottom:20 + border:1 + padding:8 + half-row-height:11 = 40px vertical center (approx)
|
|
1423
|
+
// Collapsed circle diameter: 26px, so offset by 13px from center
|
|
1424
|
+
const collapsedPositions = {
|
|
1425
|
+
'bottom-left': { bottom: '27px', left: '86px' },
|
|
1426
|
+
'bottom-right': { bottom: '27px', right: '29px' },
|
|
1427
|
+
'top-left': { top: '27px', left: '86px' },
|
|
1428
|
+
'top-right': { top: '27px', right: '29px' },
|
|
1429
|
+
'bottom-center': { bottom: '19px', left: '50%', transform: 'translateX(-50%)' },
|
|
1430
|
+
};
|
|
1431
|
+
const posStyle = collapsedPositions[position] ?? collapsedPositions['bottom-left'];
|
|
1519
1432
|
const wrapper = this.container;
|
|
1520
1433
|
wrapper.className = this.tooltipClass('left', 'devbar-collapse');
|
|
1521
1434
|
wrapper.setAttribute('data-tooltip', `Click to expand DevBar${this.sweetlinkConnected ? ' (Sweetlink connected)' : ' (Sweetlink not connected)'}${errorCount > 0 ? `\n${errorCount} console error${errorCount === 1 ? '' : 's'}` : ''}`);
|
|
@@ -1543,7 +1456,7 @@ export class GlobalDevBar {
|
|
|
1543
1456
|
width: '26px',
|
|
1544
1457
|
height: '26px',
|
|
1545
1458
|
boxSizing: 'border-box',
|
|
1546
|
-
animation: 'devbar-collapse 150ms ease-out'
|
|
1459
|
+
animation: 'devbar-collapse 150ms ease-out'
|
|
1547
1460
|
});
|
|
1548
1461
|
wrapper.onclick = () => {
|
|
1549
1462
|
this.collapsed = false;
|
|
@@ -1556,7 +1469,7 @@ export class GlobalDevBar {
|
|
|
1556
1469
|
height: '6px',
|
|
1557
1470
|
borderRadius: '50%',
|
|
1558
1471
|
backgroundColor: this.sweetlinkConnected ? COLORS.primary : COLORS.textMuted,
|
|
1559
|
-
boxShadow: this.sweetlinkConnected ? `0 0 6px ${COLORS.primary}` : 'none'
|
|
1472
|
+
boxShadow: this.sweetlinkConnected ? `0 0 6px ${COLORS.primary}` : 'none'
|
|
1560
1473
|
});
|
|
1561
1474
|
wrapper.appendChild(dot);
|
|
1562
1475
|
// Error badge (absolute, top-right of circle, shifted left if warning badge exists)
|
|
@@ -1611,19 +1524,9 @@ export class GlobalDevBar {
|
|
|
1611
1524
|
width: sizeOverrides?.width ?? defaultWidth,
|
|
1612
1525
|
maxWidth: sizeOverrides?.maxWidth ?? defaultMaxWidth,
|
|
1613
1526
|
minWidth: sizeOverrides?.minWidth ?? defaultMinWidth,
|
|
1614
|
-
cursor: 'default'
|
|
1527
|
+
cursor: 'default'
|
|
1615
1528
|
});
|
|
1616
1529
|
wrapper.ondblclick = () => {
|
|
1617
|
-
// Capture dot position before collapsing
|
|
1618
|
-
const dotEl = wrapper.querySelector('.devbar-status span span');
|
|
1619
|
-
if (dotEl) {
|
|
1620
|
-
const rect = dotEl.getBoundingClientRect();
|
|
1621
|
-
this.lastDotPosition = {
|
|
1622
|
-
left: rect.left + rect.width / 2,
|
|
1623
|
-
top: rect.top + rect.height / 2,
|
|
1624
|
-
bottom: window.innerHeight - (rect.top + rect.height / 2),
|
|
1625
|
-
};
|
|
1626
|
-
}
|
|
1627
1530
|
this.collapsed = true;
|
|
1628
1531
|
this.render();
|
|
1629
1532
|
};
|
|
@@ -1641,14 +1544,12 @@ export class GlobalDevBar {
|
|
|
1641
1544
|
boxSizing: 'border-box',
|
|
1642
1545
|
fontFamily: FONT_MONO,
|
|
1643
1546
|
fontSize: '0.6875rem',
|
|
1644
|
-
lineHeight: '1rem'
|
|
1547
|
+
lineHeight: '1rem'
|
|
1645
1548
|
});
|
|
1646
1549
|
// Connection indicator (click to collapse)
|
|
1647
1550
|
const connIndicator = document.createElement('span');
|
|
1648
1551
|
connIndicator.className = this.tooltipClass('left', 'devbar-clickable');
|
|
1649
|
-
connIndicator.setAttribute('data-tooltip', this.sweetlinkConnected
|
|
1650
|
-
? 'Sweetlink connected (click to minimize)'
|
|
1651
|
-
: 'Sweetlink disconnected (click to minimize)');
|
|
1552
|
+
connIndicator.setAttribute('data-tooltip', this.sweetlinkConnected ? 'Sweetlink connected (click to minimize)' : 'Sweetlink disconnected (click to minimize)');
|
|
1652
1553
|
Object.assign(connIndicator.style, {
|
|
1653
1554
|
width: '12px',
|
|
1654
1555
|
height: '12px',
|
|
@@ -1658,17 +1559,10 @@ export class GlobalDevBar {
|
|
|
1658
1559
|
alignItems: 'center',
|
|
1659
1560
|
justifyContent: 'center',
|
|
1660
1561
|
cursor: 'pointer',
|
|
1661
|
-
flexShrink: '0'
|
|
1562
|
+
flexShrink: '0'
|
|
1662
1563
|
});
|
|
1663
1564
|
connIndicator.onclick = (e) => {
|
|
1664
1565
|
e.stopPropagation();
|
|
1665
|
-
// Capture dot position before collapsing (connDot is the inner 6px dot)
|
|
1666
|
-
const rect = connIndicator.getBoundingClientRect();
|
|
1667
|
-
this.lastDotPosition = {
|
|
1668
|
-
left: rect.left + rect.width / 2,
|
|
1669
|
-
top: rect.top + rect.height / 2,
|
|
1670
|
-
bottom: window.innerHeight - (rect.top + rect.height / 2),
|
|
1671
|
-
};
|
|
1672
1566
|
this.collapsed = true;
|
|
1673
1567
|
this.render();
|
|
1674
1568
|
};
|
|
@@ -1679,7 +1573,7 @@ export class GlobalDevBar {
|
|
|
1679
1573
|
borderRadius: '50%',
|
|
1680
1574
|
backgroundColor: this.sweetlinkConnected ? COLORS.primary : COLORS.textMuted,
|
|
1681
1575
|
boxShadow: this.sweetlinkConnected ? `0 0 6px ${COLORS.primary}` : 'none',
|
|
1682
|
-
transition: 'all 300ms'
|
|
1576
|
+
transition: 'all 300ms'
|
|
1683
1577
|
});
|
|
1684
1578
|
connIndicator.appendChild(connDot);
|
|
1685
1579
|
// Status row wrapper - keeps connection dot, info, and badges together
|
|
@@ -1690,7 +1584,7 @@ export class GlobalDevBar {
|
|
|
1690
1584
|
alignItems: 'center',
|
|
1691
1585
|
gap: '0.5rem',
|
|
1692
1586
|
flexWrap: 'nowrap',
|
|
1693
|
-
flexShrink: '0'
|
|
1587
|
+
flexShrink: '0'
|
|
1694
1588
|
});
|
|
1695
1589
|
statusRow.appendChild(connIndicator);
|
|
1696
1590
|
// Info section
|
|
@@ -1704,7 +1598,7 @@ export class GlobalDevBar {
|
|
|
1704
1598
|
letterSpacing: '0.05em',
|
|
1705
1599
|
flexShrink: '1',
|
|
1706
1600
|
minWidth: '0',
|
|
1707
|
-
overflow: 'visible'
|
|
1601
|
+
overflow: 'visible'
|
|
1708
1602
|
});
|
|
1709
1603
|
// Breakpoint info
|
|
1710
1604
|
if (showMetrics.breakpoint && this.breakpointInfo) {
|
|
@@ -1716,10 +1610,9 @@ export class GlobalDevBar {
|
|
|
1716
1610
|
bpSpan.setAttribute('data-tooltip', `Tailwind Breakpoint: ${bp}\n${breakpointData?.label || ''}\n\nViewport: ${this.breakpointInfo.dimensions}\n\nBreakpoints:\nbase: <640px | sm: >=640px\nmd: >=768px | lg: >=1024px\nxl: >=1280px | 2xl: >=1536px`);
|
|
1717
1611
|
let bpText = bp;
|
|
1718
1612
|
if (bp !== 'base') {
|
|
1719
|
-
bpText =
|
|
1720
|
-
bp
|
|
1721
|
-
|
|
1722
|
-
: `${bp} - ${this.breakpointInfo.dimensions}`;
|
|
1613
|
+
bpText = bp === 'sm'
|
|
1614
|
+
? `${bp} - ${this.breakpointInfo.dimensions.split('x')[0]}`
|
|
1615
|
+
: `${bp} - ${this.breakpointInfo.dimensions}`;
|
|
1723
1616
|
}
|
|
1724
1617
|
bpSpan.textContent = bpText;
|
|
1725
1618
|
infoSection.appendChild(bpSpan);
|
|
@@ -1797,7 +1690,7 @@ export class GlobalDevBar {
|
|
|
1797
1690
|
fontFamily: FONT_MONO,
|
|
1798
1691
|
fontSize: '0.6875rem',
|
|
1799
1692
|
});
|
|
1800
|
-
GlobalDevBar.customControls.forEach(
|
|
1693
|
+
GlobalDevBar.customControls.forEach(control => {
|
|
1801
1694
|
const btn = document.createElement('button');
|
|
1802
1695
|
btn.type = 'button';
|
|
1803
1696
|
const color = control.variant === 'warning' ? BUTTON_COLORS.warning : accentColor;
|
|
@@ -1872,7 +1765,13 @@ export class GlobalDevBar {
|
|
|
1872
1765
|
btn.type = 'button';
|
|
1873
1766
|
btn.className = this.tooltipClass('right');
|
|
1874
1767
|
const hasSuccessState = this.copiedToClipboard || this.copiedPath || this.lastScreenshot;
|
|
1875
|
-
const tooltip = this.
|
|
1768
|
+
const tooltip = this.copiedToClipboard
|
|
1769
|
+
? 'Copied to clipboard!'
|
|
1770
|
+
: this.copiedPath
|
|
1771
|
+
? 'Path copied to clipboard!'
|
|
1772
|
+
: this.lastScreenshot
|
|
1773
|
+
? `Screenshot saved!\n${this.lastScreenshot}\n\nClick to copy path`
|
|
1774
|
+
: `Screenshot\n\nClick: Save to file\nShift+Click: Copy to clipboard\n\nKeyboard:\nCmd/Ctrl+Shift+S: Save\nCmd/Ctrl+Shift+C: Copy${!this.sweetlinkConnected ? '\n\nWarning: Sweetlink not connected' : ''}`;
|
|
1876
1775
|
btn.setAttribute('data-tooltip', tooltip);
|
|
1877
1776
|
Object.assign(btn.style, {
|
|
1878
1777
|
display: 'flex',
|
|
@@ -1890,7 +1789,7 @@ export class GlobalDevBar {
|
|
|
1890
1789
|
color: hasSuccessState ? accentColor : `${accentColor}99`,
|
|
1891
1790
|
cursor: !this.capturing ? 'pointer' : 'not-allowed',
|
|
1892
1791
|
opacity: '1',
|
|
1893
|
-
transition: 'all 150ms'
|
|
1792
|
+
transition: 'all 150ms'
|
|
1894
1793
|
});
|
|
1895
1794
|
btn.disabled = this.capturing;
|
|
1896
1795
|
btn.onclick = (e) => {
|
|
@@ -1936,47 +1835,17 @@ export class GlobalDevBar {
|
|
|
1936
1835
|
}
|
|
1937
1836
|
return btn;
|
|
1938
1837
|
}
|
|
1939
|
-
/**
|
|
1940
|
-
* Get the tooltip text for the screenshot button based on current state
|
|
1941
|
-
*/
|
|
1942
|
-
getScreenshotTooltip() {
|
|
1943
|
-
if (this.copiedToClipboard) {
|
|
1944
|
-
return 'Copied to clipboard!';
|
|
1945
|
-
}
|
|
1946
|
-
if (this.copiedPath) {
|
|
1947
|
-
return 'Path copied to clipboard!';
|
|
1948
|
-
}
|
|
1949
|
-
if (this.lastScreenshot) {
|
|
1950
|
-
return `Screenshot saved!\n${this.lastScreenshot}\n\nClick to copy path`;
|
|
1951
|
-
}
|
|
1952
|
-
const baseTooltip = `Screenshot\n\nClick: Save to file\nShift+Click: Copy to clipboard\n\nKeyboard:\nCmd/Ctrl+Shift+S: Save\nCmd/Ctrl+Shift+C: Copy`;
|
|
1953
|
-
return this.sweetlinkConnected
|
|
1954
|
-
? baseTooltip
|
|
1955
|
-
: `${baseTooltip}\n\nWarning: Sweetlink not connected`;
|
|
1956
|
-
}
|
|
1957
|
-
/**
|
|
1958
|
-
* Get the tooltip text for the AI review button based on current state
|
|
1959
|
-
*/
|
|
1960
|
-
getAIReviewTooltip() {
|
|
1961
|
-
if (this.designReviewInProgress) {
|
|
1962
|
-
return 'AI Design Review in progress...';
|
|
1963
|
-
}
|
|
1964
|
-
if (this.designReviewError) {
|
|
1965
|
-
return `Design review failed:\n${this.designReviewError}`;
|
|
1966
|
-
}
|
|
1967
|
-
if (this.lastDesignReview) {
|
|
1968
|
-
return `Design review saved to:\n${this.lastDesignReview}`;
|
|
1969
|
-
}
|
|
1970
|
-
const baseTooltip = `AI Design Review\n\nCaptures screenshot and sends to\nClaude for design analysis.\n\nRequires ANTHROPIC_API_KEY.`;
|
|
1971
|
-
return this.sweetlinkConnected
|
|
1972
|
-
? baseTooltip
|
|
1973
|
-
: `${baseTooltip}\n\nWarning: Sweetlink not connected`;
|
|
1974
|
-
}
|
|
1975
1838
|
createAIReviewButton() {
|
|
1976
1839
|
const btn = document.createElement('button');
|
|
1977
1840
|
btn.type = 'button';
|
|
1978
1841
|
btn.className = this.tooltipClass('right');
|
|
1979
|
-
const tooltip = this.
|
|
1842
|
+
const tooltip = this.designReviewInProgress
|
|
1843
|
+
? 'AI Design Review in progress...'
|
|
1844
|
+
: this.designReviewError
|
|
1845
|
+
? `Design review failed:\n${this.designReviewError}`
|
|
1846
|
+
: this.lastDesignReview
|
|
1847
|
+
? `Design review saved to:\n${this.lastDesignReview}`
|
|
1848
|
+
: `AI Design Review\n\nCaptures screenshot and sends to\nClaude for design analysis.\n\nRequires ANTHROPIC_API_KEY.${!this.sweetlinkConnected ? '\n\nWarning: Sweetlink not connected' : ''}`;
|
|
1980
1849
|
btn.setAttribute('data-tooltip', tooltip);
|
|
1981
1850
|
const hasError = !!this.designReviewError;
|
|
1982
1851
|
const isActive = this.designReviewInProgress || !!this.lastDesignReview || hasError;
|
|
@@ -2076,7 +1945,7 @@ export function initGlobalDevBar(options) {
|
|
|
2076
1945
|
const existing = getGlobalInstance();
|
|
2077
1946
|
if (existing) {
|
|
2078
1947
|
// Check if already initialized with same position - skip re-init during HMR
|
|
2079
|
-
const existingPosition = existing
|
|
1948
|
+
const existingPosition = existing['options']?.position ?? 'bottom-left';
|
|
2080
1949
|
const newPosition = options?.position ?? 'bottom-left';
|
|
2081
1950
|
if (existingPosition === newPosition) {
|
|
2082
1951
|
return existing;
|
package/dist/constants.js
CHANGED
|
@@ -41,11 +41,11 @@ export const SCREENSHOT_SCALE = 0.75;
|
|
|
41
41
|
// ============================================================================
|
|
42
42
|
/** Tailwind CSS breakpoint definitions */
|
|
43
43
|
export const TAILWIND_BREAKPOINTS = {
|
|
44
|
-
base: { min: 0, label: 'Tailwind base: <640px' },
|
|
45
|
-
sm: { min: 640, label: 'Tailwind sm: >=640px' },
|
|
46
|
-
md: { min: 768, label: 'Tailwind md: >=768px' },
|
|
47
|
-
lg: { min: 1024, label: 'Tailwind lg: >=1024px' },
|
|
48
|
-
xl: { min: 1280, label: 'Tailwind xl: >=1280px' },
|
|
44
|
+
'base': { min: 0, label: 'Tailwind base: <640px' },
|
|
45
|
+
'sm': { min: 640, label: 'Tailwind sm: >=640px' },
|
|
46
|
+
'md': { min: 768, label: 'Tailwind md: >=768px' },
|
|
47
|
+
'lg': { min: 1024, label: 'Tailwind lg: >=1024px' },
|
|
48
|
+
'xl': { min: 1280, label: 'Tailwind xl: >=1280px' },
|
|
49
49
|
'2xl': { min: 1536, label: 'Tailwind 2xl: >=1536px' },
|
|
50
50
|
};
|
|
51
51
|
// ============================================================================
|
|
@@ -489,8 +489,7 @@ export const TOOLTIP_STYLES = `
|
|
|
489
489
|
}
|
|
490
490
|
/* BASE only (< 640px): fit content, centered horizontally */
|
|
491
491
|
@media (max-width: 639px) {
|
|
492
|
-
|
|
493
|
-
[data-devbar]:not(.devbar-collapse) {
|
|
492
|
+
[data-devbar] {
|
|
494
493
|
width: auto !important;
|
|
495
494
|
min-width: auto !important;
|
|
496
495
|
max-width: calc(100vw - 32px) !important;
|
|
@@ -498,7 +497,6 @@ export const TOOLTIP_STYLES = `
|
|
|
498
497
|
right: auto !important;
|
|
499
498
|
transform: translateX(-50%) !important;
|
|
500
499
|
}
|
|
501
|
-
/* Collapsed state: JS handles positioning based on captured dot location */
|
|
502
500
|
.devbar-main {
|
|
503
501
|
flex-wrap: wrap;
|
|
504
502
|
justify-content: center;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ytspar/devbar",
|
|
3
|
-
"version": "1.0.0-canary.
|
|
3
|
+
"version": "1.0.0-canary.92db425",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "Development toolbar and utilities with Sweetlink integration - pure vanilla JS, no framework dependencies",
|