@ytspar/devbar 1.0.0-canary.2b99e1e → 1.0.0-canary.3c85c90
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 -36
- package/dist/GlobalDevBar.js +86 -491
- package/dist/constants.d.ts +20 -28
- package/dist/constants.js +27 -35
- package/dist/index.d.ts +5 -5
- package/dist/index.js +7 -7
- package/dist/presets.d.ts +1 -1
- package/dist/ui/modals.d.ts +0 -4
- package/dist/ui/modals.js +4 -48
- package/package.json +1 -1
package/dist/GlobalDevBar.d.ts
CHANGED
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
import { getThemeColors } from './constants.js';
|
|
11
11
|
import type { ConsoleLog, DebugConfig, DevBarControl, GlobalDevBarOptions, OutlineNode, PageSchema, SweetlinkCommand, ThemeMode } from './types.js';
|
|
12
12
|
export type { ConsoleLog, DebugConfig, SweetlinkCommand, OutlineNode, PageSchema, GlobalDevBarOptions, DevBarControl, ThemeMode, };
|
|
13
|
-
export type {
|
|
14
|
-
export {
|
|
13
|
+
export type { DevBarSettings, DevBarPosition, MetricsVisibility } from './settings.js';
|
|
14
|
+
export { DEFAULT_SETTINGS, ACCENT_COLOR_PRESETS, getSettingsManager } from './settings.js';
|
|
15
15
|
interface EarlyConsoleCapture {
|
|
16
16
|
errorCount: number;
|
|
17
17
|
warningCount: number;
|
|
@@ -46,8 +46,6 @@ export declare class GlobalDevBar {
|
|
|
46
46
|
private apiKeyStatus;
|
|
47
47
|
private lastOutline;
|
|
48
48
|
private lastSchema;
|
|
49
|
-
private savingOutline;
|
|
50
|
-
private savingSchema;
|
|
51
49
|
private consoleFilter;
|
|
52
50
|
private showOutlineModal;
|
|
53
51
|
private showSchemaModal;
|
|
@@ -57,10 +55,6 @@ export declare class GlobalDevBar {
|
|
|
57
55
|
private clsValue;
|
|
58
56
|
private inpValue;
|
|
59
57
|
private reconnectAttempts;
|
|
60
|
-
private readonly currentAppPort;
|
|
61
|
-
private readonly baseWsPort;
|
|
62
|
-
private wsVerified;
|
|
63
|
-
private serverProjectDir;
|
|
64
58
|
private lastDotPosition;
|
|
65
59
|
private reconnectTimeout;
|
|
66
60
|
private screenshotTimeout;
|
|
@@ -237,10 +231,6 @@ export declare class GlobalDevBar {
|
|
|
237
231
|
* Create the settings gear button
|
|
238
232
|
*/
|
|
239
233
|
private createSettingsButton;
|
|
240
|
-
/**
|
|
241
|
-
* Create the compact mode toggle button with chevron icon
|
|
242
|
-
*/
|
|
243
|
-
private createCompactToggleButton;
|
|
244
234
|
/**
|
|
245
235
|
* Create a settings section with title
|
|
246
236
|
*/
|
|
@@ -259,30 +249,6 @@ export declare class GlobalDevBar {
|
|
|
259
249
|
private resetToDefaults;
|
|
260
250
|
private renderCollapsed;
|
|
261
251
|
private renderExpanded;
|
|
262
|
-
/** Base styles for tooltip containers */
|
|
263
|
-
private readonly TOOLTIP_BASE_STYLES;
|
|
264
|
-
/** Create a tooltip container element */
|
|
265
|
-
private createTooltipContainer;
|
|
266
|
-
/** Add a bold title to tooltip (metric name, feature name, etc.) */
|
|
267
|
-
private addTooltipTitle;
|
|
268
|
-
/** Add a description paragraph to tooltip */
|
|
269
|
-
private addTooltipDescription;
|
|
270
|
-
/** Add a muted uppercase section header to tooltip */
|
|
271
|
-
private addTooltipSectionHeader;
|
|
272
|
-
/** Add a colored row with dot + label + value (for thresholds) */
|
|
273
|
-
private addTooltipColoredRow;
|
|
274
|
-
/** Add an info row with label + value (for breakpoint details) */
|
|
275
|
-
private addTooltipInfoRow;
|
|
276
|
-
/** Position tooltip above the anchor element, adjusting for screen edges */
|
|
277
|
-
private positionTooltip;
|
|
278
|
-
/** Attach an HTML tooltip to an element with custom content builder */
|
|
279
|
-
private attachHtmlTooltip;
|
|
280
|
-
/** Attach a metric tooltip with title, description, and colored thresholds */
|
|
281
|
-
private attachMetricTooltip;
|
|
282
|
-
/** Attach a breakpoint tooltip showing current breakpoint and all breakpoint ranges */
|
|
283
|
-
private attachBreakpointTooltip;
|
|
284
|
-
/** Attach a simple info tooltip with title and description */
|
|
285
|
-
private attachInfoTooltip;
|
|
286
252
|
/**
|
|
287
253
|
* Create a console badge for error/warning counts
|
|
288
254
|
*/
|
package/dist/GlobalDevBar.js
CHANGED
|
@@ -8,14 +8,14 @@
|
|
|
8
8
|
* to avoid React dependency conflicts in host applications.
|
|
9
9
|
*/
|
|
10
10
|
import * as html2canvasModule from 'html2canvas-pro';
|
|
11
|
-
import { BASE_RECONNECT_DELAY_MS, BUTTON_COLORS, CATEGORY_COLORS, CLIPBOARD_NOTIFICATION_MS, COLORS, DESIGN_REVIEW_NOTIFICATION_MS, DEVBAR_SCREENSHOT_QUALITY, FONT_MONO, getEffectiveTheme,
|
|
11
|
+
import { BASE_RECONNECT_DELAY_MS, BUTTON_COLORS, CATEGORY_COLORS, CLIPBOARD_NOTIFICATION_MS, COLORS, DESIGN_REVIEW_NOTIFICATION_MS, DEVBAR_SCREENSHOT_QUALITY, FONT_MONO, getEffectiveTheme, getThemeColors, MAX_CONSOLE_LOGS, MAX_RECONNECT_ATTEMPTS, MAX_RECONNECT_DELAY_MS, SCREENSHOT_BLUR_DELAY_MS, SCREENSHOT_NOTIFICATION_MS, SCREENSHOT_SCALE, TAILWIND_BREAKPOINTS, TOOLTIP_STYLES, WS_PORT, } from './constants.js';
|
|
12
12
|
import { DebugLogger, normalizeDebugConfig } from './debug.js';
|
|
13
13
|
import { extractDocumentOutline, outlineToMarkdown } from './outline.js';
|
|
14
14
|
import { extractPageSchema, schemaToMarkdown } from './schema.js';
|
|
15
15
|
import { ACCENT_COLOR_PRESETS, DEFAULT_SETTINGS, getSettingsManager, } from './settings.js';
|
|
16
16
|
import { createEmptyMessage, createInfoBox, createModalBox, createModalContent, createModalHeader, createModalOverlay, createStyledButton, createSvgIcon, getButtonStyles, } from './ui/index.js';
|
|
17
17
|
import { canvasToDataUrl, copyCanvasToClipboard, delay, formatArgs, prepareForCapture, } from './utils.js';
|
|
18
|
-
export {
|
|
18
|
+
export { DEFAULT_SETTINGS, ACCENT_COLOR_PRESETS, getSettingsManager } from './settings.js';
|
|
19
19
|
const html2canvas = (html2canvasModule.default ??
|
|
20
20
|
html2canvasModule);
|
|
21
21
|
const earlyConsoleCapture = (() => {
|
|
@@ -91,8 +91,6 @@ export class GlobalDevBar {
|
|
|
91
91
|
this.apiKeyStatus = null;
|
|
92
92
|
this.lastOutline = null;
|
|
93
93
|
this.lastSchema = null;
|
|
94
|
-
this.savingOutline = false;
|
|
95
|
-
this.savingSchema = false;
|
|
96
94
|
this.consoleFilter = null;
|
|
97
95
|
// Modal states
|
|
98
96
|
this.showOutlineModal = false;
|
|
@@ -103,8 +101,6 @@ export class GlobalDevBar {
|
|
|
103
101
|
this.clsValue = 0;
|
|
104
102
|
this.inpValue = 0;
|
|
105
103
|
this.reconnectAttempts = 0;
|
|
106
|
-
this.wsVerified = false;
|
|
107
|
-
this.serverProjectDir = null;
|
|
108
104
|
// Track the position of the connection indicator dot for smooth collapse
|
|
109
105
|
this.lastDotPosition = null;
|
|
110
106
|
this.reconnectTimeout = null;
|
|
@@ -131,39 +127,11 @@ export class GlobalDevBar {
|
|
|
131
127
|
this.showSettingsPopover = false;
|
|
132
128
|
// Overlay element for modals
|
|
133
129
|
this.overlayElement = null;
|
|
134
|
-
// ============================================================================
|
|
135
|
-
// Tooltip Helpers (DRY system for HTML tooltips)
|
|
136
|
-
// ============================================================================
|
|
137
|
-
/** Base styles for tooltip containers */
|
|
138
|
-
this.TOOLTIP_BASE_STYLES = {
|
|
139
|
-
position: 'fixed',
|
|
140
|
-
zIndex: '10004',
|
|
141
|
-
backgroundColor: 'rgba(17, 24, 39, 0.98)',
|
|
142
|
-
border: `1px solid ${COLORS.border}`,
|
|
143
|
-
borderRadius: '6px',
|
|
144
|
-
padding: '10px 12px',
|
|
145
|
-
fontSize: '0.6875rem',
|
|
146
|
-
fontFamily: FONT_MONO,
|
|
147
|
-
maxWidth: '280px',
|
|
148
|
-
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.4)',
|
|
149
|
-
pointerEvents: 'none',
|
|
150
|
-
};
|
|
151
130
|
// Initialize debug config first so we can log during construction
|
|
152
131
|
this.debugConfig = normalizeDebugConfig(options.debug);
|
|
153
132
|
this.debug = new DebugLogger(this.debugConfig);
|
|
154
133
|
// Initialize settings manager
|
|
155
134
|
this.settingsManager = getSettingsManager();
|
|
156
|
-
// Calculate app port from URL for multi-instance support
|
|
157
|
-
if (typeof window !== 'undefined') {
|
|
158
|
-
this.currentAppPort =
|
|
159
|
-
parseInt(window.location.port, 10) || (window.location.protocol === 'https:' ? 443 : 80);
|
|
160
|
-
// Calculate expected WS port (appPort + port offset) like SweetlinkBridge does
|
|
161
|
-
this.baseWsPort = this.currentAppPort > 0 ? this.currentAppPort + WS_PORT_OFFSET : WS_PORT;
|
|
162
|
-
}
|
|
163
|
-
else {
|
|
164
|
-
this.currentAppPort = 0;
|
|
165
|
-
this.baseWsPort = WS_PORT;
|
|
166
|
-
}
|
|
167
135
|
this.options = {
|
|
168
136
|
position: options.position ?? 'bottom-left',
|
|
169
137
|
accentColor: options.accentColor ?? COLORS.primary,
|
|
@@ -377,64 +345,27 @@ export class GlobalDevBar {
|
|
|
377
345
|
document.head.appendChild(style);
|
|
378
346
|
}
|
|
379
347
|
}
|
|
380
|
-
connectWebSocket(
|
|
348
|
+
connectWebSocket() {
|
|
381
349
|
if (this.destroyed)
|
|
382
350
|
return;
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
const ws = new WebSocket(`ws://localhost:${targetPort}`);
|
|
351
|
+
this.debug.ws('Connecting to WebSocket', { port: WS_PORT });
|
|
352
|
+
const ws = new WebSocket(`ws://localhost:${WS_PORT}`);
|
|
386
353
|
this.ws = ws;
|
|
387
|
-
this.wsVerified = false;
|
|
388
354
|
ws.onopen = () => {
|
|
389
|
-
this.
|
|
355
|
+
this.sweetlinkConnected = true;
|
|
356
|
+
this.reconnectAttempts = 0;
|
|
357
|
+
this.debug.ws('WebSocket connected');
|
|
358
|
+
// Update settings manager with WebSocket connection
|
|
359
|
+
this.settingsManager.setWebSocket(ws);
|
|
360
|
+
this.settingsManager.setConnected(true);
|
|
390
361
|
ws.send(JSON.stringify({ type: 'browser-client-ready' }));
|
|
362
|
+
// Request settings from server
|
|
363
|
+
ws.send(JSON.stringify({ type: 'load-settings' }));
|
|
364
|
+
this.render();
|
|
391
365
|
};
|
|
392
366
|
ws.onmessage = async (event) => {
|
|
393
367
|
try {
|
|
394
|
-
const
|
|
395
|
-
// Handle server-info for port matching
|
|
396
|
-
if (message.type === 'server-info') {
|
|
397
|
-
const serverAppPort = message.appPort;
|
|
398
|
-
const serverMatchesApp = serverAppPort === null || serverAppPort === this.currentAppPort;
|
|
399
|
-
if (!serverMatchesApp) {
|
|
400
|
-
this.debug.ws('Server mismatch', {
|
|
401
|
-
serverAppPort,
|
|
402
|
-
currentAppPort: this.currentAppPort,
|
|
403
|
-
tryingNextPort: targetPort + 1,
|
|
404
|
-
});
|
|
405
|
-
ws.close();
|
|
406
|
-
// Try next port
|
|
407
|
-
const nextPort = targetPort + 1;
|
|
408
|
-
if (nextPort < this.baseWsPort + MAX_PORT_RETRIES) {
|
|
409
|
-
setTimeout(() => this.connectWebSocket(nextPort), PORT_RETRY_DELAY_MS);
|
|
410
|
-
}
|
|
411
|
-
else {
|
|
412
|
-
this.debug.ws('No matching server found, will retry from base port');
|
|
413
|
-
setTimeout(() => this.connectWebSocket(this.baseWsPort), PORT_SCAN_RESTART_DELAY_MS);
|
|
414
|
-
}
|
|
415
|
-
return;
|
|
416
|
-
}
|
|
417
|
-
// Server matches - mark as verified and connected
|
|
418
|
-
this.wsVerified = true;
|
|
419
|
-
this.sweetlinkConnected = true;
|
|
420
|
-
this.reconnectAttempts = 0;
|
|
421
|
-
this.serverProjectDir = message.projectDir ?? null;
|
|
422
|
-
this.debug.ws('Server verified', {
|
|
423
|
-
appPort: serverAppPort ?? 'any',
|
|
424
|
-
projectDir: this.serverProjectDir,
|
|
425
|
-
});
|
|
426
|
-
this.settingsManager.setWebSocket(ws);
|
|
427
|
-
this.settingsManager.setConnected(true);
|
|
428
|
-
ws.send(JSON.stringify({ type: 'load-settings' }));
|
|
429
|
-
this.render();
|
|
430
|
-
return;
|
|
431
|
-
}
|
|
432
|
-
// Ignore other commands until verified
|
|
433
|
-
if (!this.wsVerified) {
|
|
434
|
-
this.debug.ws('Ignoring command before verification', { type: message.type });
|
|
435
|
-
return;
|
|
436
|
-
}
|
|
437
|
-
const command = message;
|
|
368
|
+
const command = JSON.parse(event.data);
|
|
438
369
|
this.debug.ws('Received command', { type: command.type });
|
|
439
370
|
await this.handleSweetlinkCommand(command);
|
|
440
371
|
}
|
|
@@ -443,21 +374,16 @@ export class GlobalDevBar {
|
|
|
443
374
|
}
|
|
444
375
|
};
|
|
445
376
|
ws.onclose = () => {
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
this.
|
|
453
|
-
this.
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
const delayMs = BASE_RECONNECT_DELAY_MS * 2 ** this.reconnectAttempts;
|
|
457
|
-
this.reconnectAttempts++;
|
|
458
|
-
this.debug.ws('Scheduling reconnect', { attempt: this.reconnectAttempts, delayMs });
|
|
459
|
-
this.reconnectTimeout = setTimeout(() => this.connectWebSocket(this.baseWsPort), Math.min(delayMs, MAX_RECONNECT_DELAY_MS));
|
|
460
|
-
}
|
|
377
|
+
this.sweetlinkConnected = false;
|
|
378
|
+
this.settingsManager.setConnected(false);
|
|
379
|
+
this.debug.ws('WebSocket disconnected');
|
|
380
|
+
this.render();
|
|
381
|
+
// Auto-reconnect with exponential backoff
|
|
382
|
+
if (!this.destroyed && this.reconnectAttempts < MAX_RECONNECT_ATTEMPTS) {
|
|
383
|
+
const delayMs = BASE_RECONNECT_DELAY_MS * 2 ** this.reconnectAttempts;
|
|
384
|
+
this.reconnectAttempts++;
|
|
385
|
+
this.debug.ws('Scheduling reconnect', { attempt: this.reconnectAttempts, delayMs });
|
|
386
|
+
this.reconnectTimeout = setTimeout(() => this.connectWebSocket(), Math.min(delayMs, MAX_RECONNECT_DELAY_MS));
|
|
461
387
|
}
|
|
462
388
|
};
|
|
463
389
|
ws.onerror = () => {
|
|
@@ -653,7 +579,6 @@ export class GlobalDevBar {
|
|
|
653
579
|
}, durationMs);
|
|
654
580
|
break;
|
|
655
581
|
case 'outline':
|
|
656
|
-
this.savingOutline = false;
|
|
657
582
|
this.lastOutline = path;
|
|
658
583
|
if (this.outlineTimeout)
|
|
659
584
|
clearTimeout(this.outlineTimeout);
|
|
@@ -663,7 +588,6 @@ export class GlobalDevBar {
|
|
|
663
588
|
}, durationMs);
|
|
664
589
|
break;
|
|
665
590
|
case 'schema':
|
|
666
|
-
this.savingSchema = false;
|
|
667
591
|
this.lastSchema = path;
|
|
668
592
|
if (this.schemaTimeout)
|
|
669
593
|
clearTimeout(this.schemaTimeout);
|
|
@@ -796,11 +720,7 @@ export class GlobalDevBar {
|
|
|
796
720
|
}
|
|
797
721
|
});
|
|
798
722
|
// durationThreshold filters out very short interactions
|
|
799
|
-
this.inpObserver.observe({
|
|
800
|
-
type: 'event',
|
|
801
|
-
buffered: true,
|
|
802
|
-
durationThreshold: 16,
|
|
803
|
-
});
|
|
723
|
+
this.inpObserver.observe({ type: 'event', buffered: true, durationThreshold: 16 });
|
|
804
724
|
}
|
|
805
725
|
catch (e) {
|
|
806
726
|
console.warn('[GlobalDevBar] INP PerformanceObserver not supported', e);
|
|
@@ -857,16 +777,12 @@ export class GlobalDevBar {
|
|
|
857
777
|
// Load stored theme preference from settings manager
|
|
858
778
|
const settings = this.settingsManager.getSettings();
|
|
859
779
|
this.themeMode = settings.themeMode;
|
|
860
|
-
// Inject the appropriate theme CSS variables on initial load
|
|
861
|
-
injectThemeCSS(getTheme(this.themeMode));
|
|
862
780
|
this.debug.state('Theme loaded', { mode: this.themeMode });
|
|
863
781
|
// Listen for system theme changes
|
|
864
782
|
if (typeof window !== 'undefined' && window.matchMedia) {
|
|
865
783
|
this.themeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
|
866
784
|
this.themeMediaHandler = () => {
|
|
867
785
|
if (this.themeMode === 'system') {
|
|
868
|
-
// Re-inject theme CSS when system preference changes
|
|
869
|
-
injectThemeCSS(getTheme(this.themeMode));
|
|
870
786
|
this.debug.state('System theme changed', {
|
|
871
787
|
effectiveTheme: getEffectiveTheme(this.themeMode),
|
|
872
788
|
});
|
|
@@ -893,8 +809,6 @@ export class GlobalDevBar {
|
|
|
893
809
|
setThemeMode(mode) {
|
|
894
810
|
this.themeMode = mode;
|
|
895
811
|
this.settingsManager.saveSettings({ themeMode: mode });
|
|
896
|
-
// Inject the appropriate theme CSS variables
|
|
897
|
-
injectThemeCSS(getTheme(mode));
|
|
898
812
|
this.debug.state('Theme mode changed', { mode, effectiveTheme: getEffectiveTheme(mode) });
|
|
899
813
|
this.render();
|
|
900
814
|
}
|
|
@@ -1148,13 +1062,9 @@ export class GlobalDevBar {
|
|
|
1148
1062
|
this.render();
|
|
1149
1063
|
}
|
|
1150
1064
|
handleSaveOutline() {
|
|
1151
|
-
if (this.savingOutline)
|
|
1152
|
-
return; // Prevent repeated clicks
|
|
1153
1065
|
const outline = extractDocumentOutline();
|
|
1154
1066
|
const markdown = outlineToMarkdown(outline);
|
|
1155
1067
|
if (this.ws?.readyState === WebSocket.OPEN) {
|
|
1156
|
-
this.savingOutline = true;
|
|
1157
|
-
this.render();
|
|
1158
1068
|
this.ws.send(JSON.stringify({
|
|
1159
1069
|
type: 'save-outline',
|
|
1160
1070
|
data: {
|
|
@@ -1168,13 +1078,9 @@ export class GlobalDevBar {
|
|
|
1168
1078
|
}
|
|
1169
1079
|
}
|
|
1170
1080
|
handleSaveSchema() {
|
|
1171
|
-
if (this.savingSchema)
|
|
1172
|
-
return; // Prevent repeated clicks
|
|
1173
1081
|
const schema = extractPageSchema();
|
|
1174
1082
|
const markdown = schemaToMarkdown(schema);
|
|
1175
1083
|
if (this.ws?.readyState === WebSocket.OPEN) {
|
|
1176
|
-
this.savingSchema = true;
|
|
1177
|
-
this.render();
|
|
1178
1084
|
this.ws.send(JSON.stringify({
|
|
1179
1085
|
type: 'save-schema',
|
|
1180
1086
|
data: {
|
|
@@ -1552,8 +1458,6 @@ export class GlobalDevBar {
|
|
|
1552
1458
|
},
|
|
1553
1459
|
onSave: () => this.handleSaveOutline(),
|
|
1554
1460
|
sweetlinkConnected: this.sweetlinkConnected,
|
|
1555
|
-
isSaving: this.savingOutline,
|
|
1556
|
-
savedPath: this.lastOutline,
|
|
1557
1461
|
});
|
|
1558
1462
|
modal.appendChild(header);
|
|
1559
1463
|
const content = createModalContent();
|
|
@@ -1640,8 +1544,6 @@ export class GlobalDevBar {
|
|
|
1640
1544
|
},
|
|
1641
1545
|
onSave: () => this.handleSaveSchema(),
|
|
1642
1546
|
sweetlinkConnected: this.sweetlinkConnected,
|
|
1643
|
-
isSaving: this.savingSchema,
|
|
1644
|
-
savedPath: this.lastSchema,
|
|
1645
1547
|
});
|
|
1646
1548
|
modal.appendChild(header);
|
|
1647
1549
|
const content = createModalContent();
|
|
@@ -1999,64 +1901,6 @@ export class GlobalDevBar {
|
|
|
1999
1901
|
btn.appendChild(svg);
|
|
2000
1902
|
return btn;
|
|
2001
1903
|
}
|
|
2002
|
-
/**
|
|
2003
|
-
* Create the compact mode toggle button with chevron icon
|
|
2004
|
-
*/
|
|
2005
|
-
createCompactToggleButton() {
|
|
2006
|
-
const btn = document.createElement('button');
|
|
2007
|
-
btn.type = 'button';
|
|
2008
|
-
btn.className = this.tooltipClass('right');
|
|
2009
|
-
const isCompact = this.compactMode;
|
|
2010
|
-
const tooltip = isCompact ? 'Expand (Cmd+Shift+M)' : 'Compact (Cmd+Shift+M)';
|
|
2011
|
-
btn.setAttribute('data-tooltip', tooltip);
|
|
2012
|
-
const { accentColor } = this.options;
|
|
2013
|
-
const iconColor = COLORS.textSecondary;
|
|
2014
|
-
Object.assign(btn.style, {
|
|
2015
|
-
display: 'flex',
|
|
2016
|
-
alignItems: 'center',
|
|
2017
|
-
justifyContent: 'center',
|
|
2018
|
-
width: '22px',
|
|
2019
|
-
height: '22px',
|
|
2020
|
-
minWidth: '22px',
|
|
2021
|
-
minHeight: '22px',
|
|
2022
|
-
flexShrink: '0',
|
|
2023
|
-
borderRadius: '50%',
|
|
2024
|
-
border: `1px solid ${accentColor}60`,
|
|
2025
|
-
backgroundColor: 'transparent',
|
|
2026
|
-
color: `${iconColor}99`,
|
|
2027
|
-
cursor: 'pointer',
|
|
2028
|
-
transition: 'all 150ms',
|
|
2029
|
-
});
|
|
2030
|
-
btn.onmouseenter = () => {
|
|
2031
|
-
btn.style.borderColor = accentColor;
|
|
2032
|
-
btn.style.backgroundColor = `${accentColor}20`;
|
|
2033
|
-
btn.style.color = iconColor;
|
|
2034
|
-
};
|
|
2035
|
-
btn.onmouseleave = () => {
|
|
2036
|
-
btn.style.borderColor = `${accentColor}60`;
|
|
2037
|
-
btn.style.backgroundColor = 'transparent';
|
|
2038
|
-
btn.style.color = `${iconColor}99`;
|
|
2039
|
-
};
|
|
2040
|
-
btn.onclick = () => {
|
|
2041
|
-
this.toggleCompactMode();
|
|
2042
|
-
};
|
|
2043
|
-
// Chevron icon SVG - points right when expanded, left when compact
|
|
2044
|
-
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
2045
|
-
svg.setAttribute('width', '12');
|
|
2046
|
-
svg.setAttribute('height', '12');
|
|
2047
|
-
svg.setAttribute('viewBox', '0 0 24 24');
|
|
2048
|
-
svg.setAttribute('fill', 'none');
|
|
2049
|
-
svg.setAttribute('stroke', 'currentColor');
|
|
2050
|
-
svg.setAttribute('stroke-width', '2');
|
|
2051
|
-
svg.setAttribute('stroke-linecap', 'round');
|
|
2052
|
-
svg.setAttribute('stroke-linejoin', 'round');
|
|
2053
|
-
const path = document.createElementNS('http://www.w3.org/2000/svg', 'polyline');
|
|
2054
|
-
// Left chevron (<) when expanded to shrink, right chevron (>) when compact to expand
|
|
2055
|
-
path.setAttribute('points', isCompact ? '9 18 15 12 9 6' : '15 18 9 12 15 6');
|
|
2056
|
-
svg.appendChild(path);
|
|
2057
|
-
btn.appendChild(svg);
|
|
2058
|
-
return btn;
|
|
2059
|
-
}
|
|
2060
1904
|
/**
|
|
2061
1905
|
* Create a settings section with title
|
|
2062
1906
|
*/
|
|
@@ -2210,78 +2054,49 @@ export class GlobalDevBar {
|
|
|
2210
2054
|
popover.appendChild(themeSection);
|
|
2211
2055
|
// ========== DISPLAY SECTION ==========
|
|
2212
2056
|
const displaySection = this.createSettingsSection('Display');
|
|
2213
|
-
// Position
|
|
2057
|
+
// Position dropdown
|
|
2214
2058
|
const positionRow = document.createElement('div');
|
|
2215
|
-
Object.assign(positionRow.style, {
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
marginBottom: '6px',
|
|
2059
|
+
Object.assign(positionRow.style, {
|
|
2060
|
+
display: 'flex',
|
|
2061
|
+
alignItems: 'center',
|
|
2062
|
+
justifyContent: 'space-between',
|
|
2063
|
+
marginBottom: '8px',
|
|
2221
2064
|
});
|
|
2065
|
+
const posLabel = document.createElement('span');
|
|
2066
|
+
Object.assign(posLabel.style, { color: COLORS.text, fontSize: '0.6875rem' });
|
|
2222
2067
|
posLabel.textContent = 'Position';
|
|
2223
2068
|
positionRow.appendChild(posLabel);
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
width: '100%',
|
|
2229
|
-
height: '50px',
|
|
2230
|
-
backgroundColor: 'rgba(10, 15, 26, 0.6)',
|
|
2231
|
-
border: `1px solid ${color}30`,
|
|
2069
|
+
const posSelect = document.createElement('select');
|
|
2070
|
+
Object.assign(posSelect.style, {
|
|
2071
|
+
backgroundColor: 'rgba(10, 15, 26, 0.8)',
|
|
2072
|
+
border: `1px solid ${color}40`,
|
|
2232
2073
|
borderRadius: '4px',
|
|
2074
|
+
color: COLORS.text,
|
|
2075
|
+
fontSize: '0.625rem',
|
|
2076
|
+
padding: '4px 6px',
|
|
2077
|
+
cursor: 'pointer',
|
|
2078
|
+
fontFamily: FONT_MONO,
|
|
2233
2079
|
});
|
|
2234
|
-
const
|
|
2235
|
-
{ value: '
|
|
2236
|
-
{ value: '
|
|
2237
|
-
{ value: 'bottom-
|
|
2238
|
-
{ value: '
|
|
2239
|
-
{
|
|
2240
|
-
value: 'bottom-center',
|
|
2241
|
-
style: { bottom: '6px', left: '50%', transform: 'translateX(-50%)' },
|
|
2242
|
-
title: 'Bottom Center',
|
|
2243
|
-
},
|
|
2080
|
+
const positions = [
|
|
2081
|
+
{ value: 'bottom-left', label: 'Bottom Left' },
|
|
2082
|
+
{ value: 'bottom-right', label: 'Bottom Right' },
|
|
2083
|
+
{ value: 'bottom-center', label: 'Bottom Center' },
|
|
2084
|
+
{ value: 'top-left', label: 'Top Left' },
|
|
2085
|
+
{ value: 'top-right', label: 'Top Right' },
|
|
2244
2086
|
];
|
|
2245
|
-
|
|
2246
|
-
const
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
height: '6px',
|
|
2252
|
-
backgroundColor: isActive ? accentColor : `${color}60`,
|
|
2253
|
-
border: `1px solid ${isActive ? accentColor : `${color}40`}`,
|
|
2254
|
-
borderRadius: '2px',
|
|
2255
|
-
cursor: 'pointer',
|
|
2256
|
-
padding: '0',
|
|
2257
|
-
transition: 'all 150ms',
|
|
2258
|
-
boxShadow: isActive ? `0 0 8px ${accentColor}60` : 'none',
|
|
2259
|
-
...style,
|
|
2260
|
-
});
|
|
2261
|
-
indicator.title = title;
|
|
2262
|
-
indicator.onclick = () => {
|
|
2263
|
-
this.options.position = value;
|
|
2264
|
-
this.settingsManager.saveSettings({ position: value });
|
|
2265
|
-
this.render();
|
|
2266
|
-
};
|
|
2267
|
-
// Hover effect
|
|
2268
|
-
indicator.onmouseenter = () => {
|
|
2269
|
-
if (!isActive) {
|
|
2270
|
-
indicator.style.backgroundColor = accentColor;
|
|
2271
|
-
indicator.style.borderColor = accentColor;
|
|
2272
|
-
indicator.style.boxShadow = `0 0 6px ${accentColor}40`;
|
|
2273
|
-
}
|
|
2274
|
-
};
|
|
2275
|
-
indicator.onmouseleave = () => {
|
|
2276
|
-
if (!isActive) {
|
|
2277
|
-
indicator.style.backgroundColor = `${color}60`;
|
|
2278
|
-
indicator.style.borderColor = `${color}40`;
|
|
2279
|
-
indicator.style.boxShadow = 'none';
|
|
2280
|
-
}
|
|
2281
|
-
};
|
|
2282
|
-
miniMap.appendChild(indicator);
|
|
2087
|
+
positions.forEach(({ value, label }) => {
|
|
2088
|
+
const option = document.createElement('option');
|
|
2089
|
+
option.value = value;
|
|
2090
|
+
option.textContent = label;
|
|
2091
|
+
option.selected = this.options.position === value;
|
|
2092
|
+
posSelect.appendChild(option);
|
|
2283
2093
|
});
|
|
2284
|
-
|
|
2094
|
+
posSelect.onchange = () => {
|
|
2095
|
+
this.options.position = posSelect.value;
|
|
2096
|
+
this.settingsManager.saveSettings({ position: this.options.position });
|
|
2097
|
+
this.render();
|
|
2098
|
+
};
|
|
2099
|
+
positionRow.appendChild(posSelect);
|
|
2285
2100
|
displaySection.appendChild(positionRow);
|
|
2286
2101
|
// Compact mode toggle
|
|
2287
2102
|
displaySection.appendChild(this.createToggleRow('Compact Mode', this.compactMode, accentColor, () => {
|
|
@@ -2643,10 +2458,9 @@ export class GlobalDevBar {
|
|
|
2643
2458
|
const bp = this.breakpointInfo.tailwindBreakpoint;
|
|
2644
2459
|
const breakpointData = TAILWIND_BREAKPOINTS[bp];
|
|
2645
2460
|
const bpSpan = document.createElement('span');
|
|
2646
|
-
bpSpan.className = 'devbar-item';
|
|
2461
|
+
bpSpan.className = this.tooltipClass('left', 'devbar-item');
|
|
2647
2462
|
Object.assign(bpSpan.style, { opacity: '0.9', cursor: 'default' });
|
|
2648
|
-
|
|
2649
|
-
this.attachBreakpointTooltip(bpSpan, bp, this.breakpointInfo.dimensions, breakpointData?.label || '');
|
|
2463
|
+
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`);
|
|
2650
2464
|
let bpText = bp;
|
|
2651
2465
|
if (bp !== 'base') {
|
|
2652
2466
|
bpText =
|
|
@@ -2668,45 +2482,45 @@ export class GlobalDevBar {
|
|
|
2668
2482
|
if (showMetrics.fcp) {
|
|
2669
2483
|
addSeparator();
|
|
2670
2484
|
const fcpSpan = document.createElement('span');
|
|
2671
|
-
fcpSpan.className = 'devbar-item';
|
|
2485
|
+
fcpSpan.className = this.tooltipClass('left', 'devbar-item');
|
|
2672
2486
|
Object.assign(fcpSpan.style, { opacity: '0.85', cursor: 'default' });
|
|
2487
|
+
fcpSpan.setAttribute('data-tooltip', 'First Contentful Paint (FCP): Time until first text/image renders.\n\nGood: <1.8s\nNeeds work: 1.8-3s\nPoor: >3s');
|
|
2673
2488
|
fcpSpan.textContent = `FCP ${this.perfStats.fcp}`;
|
|
2674
|
-
this.attachMetricTooltip(fcpSpan, 'First Contentful Paint (FCP)', 'Time until the first text or image renders on screen.', { good: '<1.8s', needsWork: '1.8-3s', poor: '>3s' });
|
|
2675
2489
|
infoSection.appendChild(fcpSpan);
|
|
2676
2490
|
}
|
|
2677
2491
|
if (showMetrics.lcp) {
|
|
2678
2492
|
addSeparator();
|
|
2679
2493
|
const lcpSpan = document.createElement('span');
|
|
2680
|
-
lcpSpan.className = 'devbar-item';
|
|
2494
|
+
lcpSpan.className = this.tooltipClass('left', 'devbar-item');
|
|
2681
2495
|
Object.assign(lcpSpan.style, { opacity: '0.85', cursor: 'default' });
|
|
2496
|
+
lcpSpan.setAttribute('data-tooltip', 'Largest Contentful Paint (LCP): Time until largest visible element renders.\n\nGood: <2.5s\nNeeds work: 2.5-4s\nPoor: >4s');
|
|
2682
2497
|
lcpSpan.textContent = `LCP ${this.perfStats.lcp}`;
|
|
2683
|
-
this.attachMetricTooltip(lcpSpan, 'Largest Contentful Paint (LCP)', 'Time until the largest visible element renders on screen.', { good: '<2.5s', needsWork: '2.5-4s', poor: '>4s' });
|
|
2684
2498
|
infoSection.appendChild(lcpSpan);
|
|
2685
2499
|
}
|
|
2686
2500
|
if (showMetrics.cls) {
|
|
2687
2501
|
addSeparator();
|
|
2688
2502
|
const clsSpan = document.createElement('span');
|
|
2689
|
-
clsSpan.className = 'devbar-item';
|
|
2503
|
+
clsSpan.className = this.tooltipClass('left', 'devbar-item');
|
|
2690
2504
|
Object.assign(clsSpan.style, { opacity: '0.85', cursor: 'default' });
|
|
2505
|
+
clsSpan.setAttribute('data-tooltip', 'Cumulative Layout Shift (CLS): Visual stability score.\nHigher values mean more unexpected layout shifts.\n\nGood: <0.1\nNeeds work: 0.1-0.25\nPoor: >0.25');
|
|
2691
2506
|
clsSpan.textContent = `CLS ${this.perfStats.cls}`;
|
|
2692
|
-
this.attachMetricTooltip(clsSpan, 'Cumulative Layout Shift (CLS)', 'Visual stability score. Higher values mean more unexpected layout shifts.', { good: '<0.1', needsWork: '0.1-0.25', poor: '>0.25' });
|
|
2693
2507
|
infoSection.appendChild(clsSpan);
|
|
2694
2508
|
}
|
|
2695
2509
|
if (showMetrics.inp) {
|
|
2696
2510
|
addSeparator();
|
|
2697
2511
|
const inpSpan = document.createElement('span');
|
|
2698
|
-
inpSpan.className = 'devbar-item';
|
|
2512
|
+
inpSpan.className = this.tooltipClass('left', 'devbar-item');
|
|
2699
2513
|
Object.assign(inpSpan.style, { opacity: '0.85', cursor: 'default' });
|
|
2514
|
+
inpSpan.setAttribute('data-tooltip', 'Interaction to Next Paint (INP): Responsiveness to user input.\nMeasures the longest interaction delay.\n\nGood: <200ms\nNeeds work: 200-500ms\nPoor: >500ms');
|
|
2700
2515
|
inpSpan.textContent = `INP ${this.perfStats.inp}`;
|
|
2701
|
-
this.attachMetricTooltip(inpSpan, 'Interaction to Next Paint (INP)', 'Responsiveness to user input. Measures the longest interaction delay.', { good: '<200ms', needsWork: '200-500ms', poor: '>500ms' });
|
|
2702
2516
|
infoSection.appendChild(inpSpan);
|
|
2703
2517
|
}
|
|
2704
2518
|
if (showMetrics.pageSize) {
|
|
2705
2519
|
addSeparator();
|
|
2706
2520
|
const sizeSpan = document.createElement('span');
|
|
2707
|
-
sizeSpan.className = 'devbar-item';
|
|
2521
|
+
sizeSpan.className = this.tooltipClass('left', 'devbar-item');
|
|
2708
2522
|
Object.assign(sizeSpan.style, { opacity: '0.7', cursor: 'default' });
|
|
2709
|
-
|
|
2523
|
+
sizeSpan.setAttribute('data-tooltip', 'Total page size (compressed/transferred).\nIncludes HTML, CSS, JS, images, and other resources.');
|
|
2710
2524
|
sizeSpan.textContent = this.perfStats.totalSize;
|
|
2711
2525
|
infoSection.appendChild(sizeSpan);
|
|
2712
2526
|
}
|
|
@@ -2732,7 +2546,6 @@ export class GlobalDevBar {
|
|
|
2732
2546
|
actionsContainer.appendChild(this.createOutlineButton());
|
|
2733
2547
|
actionsContainer.appendChild(this.createSchemaButton());
|
|
2734
2548
|
actionsContainer.appendChild(this.createSettingsButton());
|
|
2735
|
-
actionsContainer.appendChild(this.createCompactToggleButton());
|
|
2736
2549
|
mainRow.appendChild(actionsContainer);
|
|
2737
2550
|
wrapper.appendChild(mainRow);
|
|
2738
2551
|
// Render custom controls row if there are any
|
|
@@ -2787,207 +2600,6 @@ export class GlobalDevBar {
|
|
|
2787
2600
|
wrapper.appendChild(customRow);
|
|
2788
2601
|
}
|
|
2789
2602
|
}
|
|
2790
|
-
/** Create a tooltip container element */
|
|
2791
|
-
createTooltipContainer() {
|
|
2792
|
-
const tooltip = document.createElement('div');
|
|
2793
|
-
tooltip.setAttribute('data-devbar', 'true');
|
|
2794
|
-
Object.assign(tooltip.style, this.TOOLTIP_BASE_STYLES);
|
|
2795
|
-
return tooltip;
|
|
2796
|
-
}
|
|
2797
|
-
/** Add a bold title to tooltip (metric name, feature name, etc.) */
|
|
2798
|
-
addTooltipTitle(container, title) {
|
|
2799
|
-
const titleEl = document.createElement('div');
|
|
2800
|
-
const accentColor = this.settingsManager.get('accentColor') || COLORS.primary;
|
|
2801
|
-
Object.assign(titleEl.style, {
|
|
2802
|
-
color: accentColor,
|
|
2803
|
-
fontWeight: '600',
|
|
2804
|
-
marginBottom: '4px',
|
|
2805
|
-
});
|
|
2806
|
-
titleEl.textContent = title;
|
|
2807
|
-
container.appendChild(titleEl);
|
|
2808
|
-
}
|
|
2809
|
-
/** Add a description paragraph to tooltip */
|
|
2810
|
-
addTooltipDescription(container, description) {
|
|
2811
|
-
const descEl = document.createElement('div');
|
|
2812
|
-
Object.assign(descEl.style, {
|
|
2813
|
-
color: COLORS.text,
|
|
2814
|
-
marginBottom: '10px',
|
|
2815
|
-
lineHeight: '1.4',
|
|
2816
|
-
});
|
|
2817
|
-
descEl.textContent = description;
|
|
2818
|
-
container.appendChild(descEl);
|
|
2819
|
-
}
|
|
2820
|
-
/** Add a muted uppercase section header to tooltip */
|
|
2821
|
-
addTooltipSectionHeader(container, header) {
|
|
2822
|
-
const headerEl = document.createElement('div');
|
|
2823
|
-
Object.assign(headerEl.style, {
|
|
2824
|
-
color: COLORS.textMuted,
|
|
2825
|
-
fontSize: '0.625rem',
|
|
2826
|
-
textTransform: 'uppercase',
|
|
2827
|
-
letterSpacing: '0.05em',
|
|
2828
|
-
marginBottom: '6px',
|
|
2829
|
-
});
|
|
2830
|
-
headerEl.textContent = header;
|
|
2831
|
-
container.appendChild(headerEl);
|
|
2832
|
-
}
|
|
2833
|
-
/** Add a colored row with dot + label + value (for thresholds) */
|
|
2834
|
-
addTooltipColoredRow(container, label, value, color, labelWidth = '70px') {
|
|
2835
|
-
const row = document.createElement('div');
|
|
2836
|
-
Object.assign(row.style, { display: 'flex', alignItems: 'center', gap: '8px' });
|
|
2837
|
-
const dot = document.createElement('span');
|
|
2838
|
-
Object.assign(dot.style, {
|
|
2839
|
-
width: '6px',
|
|
2840
|
-
height: '6px',
|
|
2841
|
-
borderRadius: '50%',
|
|
2842
|
-
backgroundColor: color,
|
|
2843
|
-
flexShrink: '0',
|
|
2844
|
-
});
|
|
2845
|
-
row.appendChild(dot);
|
|
2846
|
-
const labelSpan = document.createElement('span');
|
|
2847
|
-
Object.assign(labelSpan.style, {
|
|
2848
|
-
color,
|
|
2849
|
-
fontWeight: '500',
|
|
2850
|
-
minWidth: labelWidth,
|
|
2851
|
-
});
|
|
2852
|
-
labelSpan.textContent = label;
|
|
2853
|
-
row.appendChild(labelSpan);
|
|
2854
|
-
const valueSpan = document.createElement('span');
|
|
2855
|
-
Object.assign(valueSpan.style, { color: COLORS.textMuted });
|
|
2856
|
-
valueSpan.textContent = value;
|
|
2857
|
-
row.appendChild(valueSpan);
|
|
2858
|
-
container.appendChild(row);
|
|
2859
|
-
}
|
|
2860
|
-
/** Add an info row with label + value (for breakpoint details) */
|
|
2861
|
-
addTooltipInfoRow(container, label, value) {
|
|
2862
|
-
const row = document.createElement('div');
|
|
2863
|
-
Object.assign(row.style, {
|
|
2864
|
-
display: 'flex',
|
|
2865
|
-
gap: '8px',
|
|
2866
|
-
lineHeight: '1.4',
|
|
2867
|
-
});
|
|
2868
|
-
const labelSpan = document.createElement('span');
|
|
2869
|
-
Object.assign(labelSpan.style, { color: COLORS.textMuted });
|
|
2870
|
-
labelSpan.textContent = label;
|
|
2871
|
-
row.appendChild(labelSpan);
|
|
2872
|
-
const valueSpan = document.createElement('span');
|
|
2873
|
-
Object.assign(valueSpan.style, { color: COLORS.text });
|
|
2874
|
-
valueSpan.textContent = value;
|
|
2875
|
-
row.appendChild(valueSpan);
|
|
2876
|
-
container.appendChild(row);
|
|
2877
|
-
}
|
|
2878
|
-
/** Position tooltip above the anchor element, adjusting for screen edges */
|
|
2879
|
-
positionTooltip(tooltip, anchor) {
|
|
2880
|
-
const rect = anchor.getBoundingClientRect();
|
|
2881
|
-
tooltip.style.left = `${rect.left}px`;
|
|
2882
|
-
tooltip.style.bottom = `${window.innerHeight - rect.top + 8}px`;
|
|
2883
|
-
document.body.appendChild(tooltip);
|
|
2884
|
-
// Adjust if off-screen
|
|
2885
|
-
const tooltipRect = tooltip.getBoundingClientRect();
|
|
2886
|
-
if (tooltipRect.right > window.innerWidth - 10) {
|
|
2887
|
-
tooltip.style.left = `${window.innerWidth - tooltipRect.width - 10}px`;
|
|
2888
|
-
}
|
|
2889
|
-
if (tooltipRect.left < 10) {
|
|
2890
|
-
tooltip.style.left = '10px';
|
|
2891
|
-
}
|
|
2892
|
-
}
|
|
2893
|
-
/** Attach an HTML tooltip to an element with custom content builder */
|
|
2894
|
-
attachHtmlTooltip(element, buildContent) {
|
|
2895
|
-
let tooltipEl = null;
|
|
2896
|
-
element.onmouseenter = () => {
|
|
2897
|
-
tooltipEl = this.createTooltipContainer();
|
|
2898
|
-
buildContent(tooltipEl);
|
|
2899
|
-
this.positionTooltip(tooltipEl, element);
|
|
2900
|
-
};
|
|
2901
|
-
element.onmouseleave = () => {
|
|
2902
|
-
if (tooltipEl) {
|
|
2903
|
-
tooltipEl.remove();
|
|
2904
|
-
tooltipEl = null;
|
|
2905
|
-
}
|
|
2906
|
-
};
|
|
2907
|
-
}
|
|
2908
|
-
// ============================================================================
|
|
2909
|
-
// Tooltip Attachment Methods (specific tooltip types)
|
|
2910
|
-
// ============================================================================
|
|
2911
|
-
/** Attach a metric tooltip with title, description, and colored thresholds */
|
|
2912
|
-
attachMetricTooltip(element, title, description, thresholds) {
|
|
2913
|
-
this.attachHtmlTooltip(element, (tooltip) => {
|
|
2914
|
-
this.addTooltipTitle(tooltip, title);
|
|
2915
|
-
this.addTooltipDescription(tooltip, description);
|
|
2916
|
-
this.addTooltipSectionHeader(tooltip, 'Thresholds');
|
|
2917
|
-
const thresholdsContainer = document.createElement('div');
|
|
2918
|
-
Object.assign(thresholdsContainer.style, {
|
|
2919
|
-
display: 'flex',
|
|
2920
|
-
flexDirection: 'column',
|
|
2921
|
-
gap: '4px',
|
|
2922
|
-
});
|
|
2923
|
-
this.addTooltipColoredRow(thresholdsContainer, 'Good', thresholds.good, COLORS.primary);
|
|
2924
|
-
this.addTooltipColoredRow(thresholdsContainer, 'Needs work', thresholds.needsWork, COLORS.warning);
|
|
2925
|
-
this.addTooltipColoredRow(thresholdsContainer, 'Poor', thresholds.poor, COLORS.error);
|
|
2926
|
-
tooltip.appendChild(thresholdsContainer);
|
|
2927
|
-
});
|
|
2928
|
-
}
|
|
2929
|
-
/** Attach a breakpoint tooltip showing current breakpoint and all breakpoint ranges */
|
|
2930
|
-
attachBreakpointTooltip(element, breakpoint, dimensions, breakpointLabel) {
|
|
2931
|
-
this.attachHtmlTooltip(element, (tooltip) => {
|
|
2932
|
-
this.addTooltipTitle(tooltip, 'Tailwind Breakpoint');
|
|
2933
|
-
// Current breakpoint info
|
|
2934
|
-
const currentSection = document.createElement('div');
|
|
2935
|
-
Object.assign(currentSection.style, { marginBottom: '10px' });
|
|
2936
|
-
this.addTooltipInfoRow(currentSection, 'Current:', `${breakpoint} (${breakpointLabel})`);
|
|
2937
|
-
this.addTooltipInfoRow(currentSection, 'Viewport:', dimensions);
|
|
2938
|
-
tooltip.appendChild(currentSection);
|
|
2939
|
-
// Breakpoints reference
|
|
2940
|
-
this.addTooltipSectionHeader(tooltip, 'Breakpoints');
|
|
2941
|
-
const bpContainer = document.createElement('div');
|
|
2942
|
-
Object.assign(bpContainer.style, {
|
|
2943
|
-
display: 'flex',
|
|
2944
|
-
flexDirection: 'column',
|
|
2945
|
-
gap: '2px',
|
|
2946
|
-
fontSize: '0.625rem',
|
|
2947
|
-
});
|
|
2948
|
-
const breakpoints = [
|
|
2949
|
-
{ name: 'base', range: '<640px' },
|
|
2950
|
-
{ name: 'sm', range: '≥640px' },
|
|
2951
|
-
{ name: 'md', range: '≥768px' },
|
|
2952
|
-
{ name: 'lg', range: '≥1024px' },
|
|
2953
|
-
{ name: 'xl', range: '≥1280px' },
|
|
2954
|
-
{ name: '2xl', range: '≥1536px' },
|
|
2955
|
-
];
|
|
2956
|
-
for (const bp of breakpoints) {
|
|
2957
|
-
const row = document.createElement('div');
|
|
2958
|
-
Object.assign(row.style, { display: 'flex', gap: '8px' });
|
|
2959
|
-
const nameSpan = document.createElement('span');
|
|
2960
|
-
Object.assign(nameSpan.style, {
|
|
2961
|
-
color: bp.name === breakpoint ? COLORS.primary : COLORS.textMuted,
|
|
2962
|
-
fontWeight: bp.name === breakpoint ? '600' : '400',
|
|
2963
|
-
minWidth: '32px',
|
|
2964
|
-
});
|
|
2965
|
-
nameSpan.textContent = bp.name;
|
|
2966
|
-
row.appendChild(nameSpan);
|
|
2967
|
-
const rangeSpan = document.createElement('span');
|
|
2968
|
-
Object.assign(rangeSpan.style, {
|
|
2969
|
-
color: bp.name === breakpoint ? COLORS.text : COLORS.textMuted,
|
|
2970
|
-
});
|
|
2971
|
-
rangeSpan.textContent = bp.range;
|
|
2972
|
-
row.appendChild(rangeSpan);
|
|
2973
|
-
bpContainer.appendChild(row);
|
|
2974
|
-
}
|
|
2975
|
-
tooltip.appendChild(bpContainer);
|
|
2976
|
-
});
|
|
2977
|
-
}
|
|
2978
|
-
/** Attach a simple info tooltip with title and description */
|
|
2979
|
-
attachInfoTooltip(element, title, description) {
|
|
2980
|
-
this.attachHtmlTooltip(element, (tooltip) => {
|
|
2981
|
-
this.addTooltipTitle(tooltip, title);
|
|
2982
|
-
const descEl = document.createElement('div');
|
|
2983
|
-
Object.assign(descEl.style, {
|
|
2984
|
-
color: COLORS.text,
|
|
2985
|
-
lineHeight: '1.4',
|
|
2986
|
-
});
|
|
2987
|
-
descEl.textContent = description;
|
|
2988
|
-
tooltip.appendChild(descEl);
|
|
2989
|
-
});
|
|
2990
|
-
}
|
|
2991
2603
|
/**
|
|
2992
2604
|
* Create a console badge for error/warning counts
|
|
2993
2605
|
*/
|
|
@@ -3026,9 +2638,6 @@ export class GlobalDevBar {
|
|
|
3026
2638
|
btn.type = 'button';
|
|
3027
2639
|
btn.className = this.tooltipClass('right');
|
|
3028
2640
|
const hasSuccessState = this.copiedToClipboard || this.copiedPath || this.lastScreenshot;
|
|
3029
|
-
const isDisabled = this.capturing;
|
|
3030
|
-
// Grey out when not connected (save won't work, but clipboard still does)
|
|
3031
|
-
const isGreyedOut = !this.sweetlinkConnected && !hasSuccessState;
|
|
3032
2641
|
const tooltip = this.getScreenshotTooltip();
|
|
3033
2642
|
btn.setAttribute('data-tooltip', tooltip);
|
|
3034
2643
|
Object.assign(btn.style, {
|
|
@@ -3045,11 +2654,11 @@ export class GlobalDevBar {
|
|
|
3045
2654
|
borderColor: hasSuccessState ? accentColor : `${accentColor}80`,
|
|
3046
2655
|
backgroundColor: hasSuccessState ? `${accentColor}33` : 'transparent',
|
|
3047
2656
|
color: hasSuccessState ? accentColor : `${accentColor}99`,
|
|
3048
|
-
cursor: !
|
|
3049
|
-
opacity:
|
|
2657
|
+
cursor: !this.capturing ? 'pointer' : 'not-allowed',
|
|
2658
|
+
opacity: '1',
|
|
3050
2659
|
transition: 'all 150ms',
|
|
3051
2660
|
});
|
|
3052
|
-
btn.disabled =
|
|
2661
|
+
btn.disabled = this.capturing;
|
|
3053
2662
|
btn.onclick = (e) => {
|
|
3054
2663
|
// If we have a saved screenshot path, clicking copies the path
|
|
3055
2664
|
if (this.lastScreenshot && !e.shiftKey) {
|
|
@@ -3106,10 +2715,10 @@ export class GlobalDevBar {
|
|
|
3106
2715
|
if (this.lastScreenshot) {
|
|
3107
2716
|
return `Screenshot saved!\n${this.lastScreenshot}\n\nClick to copy path`;
|
|
3108
2717
|
}
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
2718
|
+
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`;
|
|
2719
|
+
return this.sweetlinkConnected
|
|
2720
|
+
? baseTooltip
|
|
2721
|
+
: `${baseTooltip}\n\nWarning: Sweetlink not connected`;
|
|
3113
2722
|
}
|
|
3114
2723
|
/**
|
|
3115
2724
|
* Get the tooltip text for the AI review button based on current state
|
|
@@ -3169,16 +2778,9 @@ export class GlobalDevBar {
|
|
|
3169
2778
|
const btn = document.createElement('button');
|
|
3170
2779
|
btn.type = 'button';
|
|
3171
2780
|
btn.className = this.tooltipClass('right');
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
}
|
|
3176
|
-
else if (!this.sweetlinkConnected) {
|
|
3177
|
-
tooltip = `Document Outline\n\nView page heading structure.\n\n⚠ Sweetlink not connected\nSave to file unavailable`;
|
|
3178
|
-
}
|
|
3179
|
-
else {
|
|
3180
|
-
tooltip = `Document Outline\n\nView page heading structure and\nsave as markdown.`;
|
|
3181
|
-
}
|
|
2781
|
+
const tooltip = this.lastOutline
|
|
2782
|
+
? `Outline saved to:\n${this.lastOutline}`
|
|
2783
|
+
: `Document Outline\n\nView page heading structure and\nsave as markdown.`;
|
|
3182
2784
|
btn.setAttribute('data-tooltip', tooltip);
|
|
3183
2785
|
const isActive = this.showOutlineModal || !!this.lastOutline;
|
|
3184
2786
|
Object.assign(btn.style, getButtonStyles(BUTTON_COLORS.outline, isActive, false));
|
|
@@ -3196,16 +2798,9 @@ export class GlobalDevBar {
|
|
|
3196
2798
|
const btn = document.createElement('button');
|
|
3197
2799
|
btn.type = 'button';
|
|
3198
2800
|
btn.className = this.tooltipClass('right');
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
}
|
|
3203
|
-
else if (!this.sweetlinkConnected) {
|
|
3204
|
-
tooltip = `Page Schema\n\nView JSON-LD, Open Graph, and\nother structured data.\n\n⚠ Sweetlink not connected\nSave to file unavailable`;
|
|
3205
|
-
}
|
|
3206
|
-
else {
|
|
3207
|
-
tooltip = `Page Schema\n\nView JSON-LD, Open Graph, and\nother structured data.`;
|
|
3208
|
-
}
|
|
2801
|
+
const tooltip = this.lastSchema
|
|
2802
|
+
? `Schema saved to:\n${this.lastSchema}`
|
|
2803
|
+
: `Page Schema\n\nView JSON-LD, Open Graph, and\nother structured data.`;
|
|
3209
2804
|
btn.setAttribute('data-tooltip', tooltip);
|
|
3210
2805
|
const isActive = this.showSchemaModal || !!this.lastSchema;
|
|
3211
2806
|
Object.assign(btn.style, getButtonStyles(BUTTON_COLORS.schema, isActive, false));
|
package/dist/constants.d.ts
CHANGED
|
@@ -11,16 +11,8 @@ export declare const MAX_RECONNECT_ATTEMPTS = 10;
|
|
|
11
11
|
export declare const BASE_RECONNECT_DELAY_MS = 1000;
|
|
12
12
|
/** Maximum delay between reconnection attempts (ms) */
|
|
13
13
|
export declare const MAX_RECONNECT_DELAY_MS = 30000;
|
|
14
|
-
/** Default WebSocket port for Sweetlink connection
|
|
14
|
+
/** Default WebSocket port for Sweetlink connection */
|
|
15
15
|
export declare const WS_PORT = 9223;
|
|
16
|
-
/** Port offset from app port to calculate WebSocket port (matches SweetlinkBridge) */
|
|
17
|
-
export declare const WS_PORT_OFFSET = 6223;
|
|
18
|
-
/** Maximum ports to try when scanning for matching server */
|
|
19
|
-
export declare const MAX_PORT_RETRIES = 10;
|
|
20
|
-
/** Delay between port scan attempts (ms) */
|
|
21
|
-
export declare const PORT_RETRY_DELAY_MS = 100;
|
|
22
|
-
/** Delay before restarting port scan from base after all ports fail (ms) */
|
|
23
|
-
export declare const PORT_SCAN_RESTART_DELAY_MS = 3000;
|
|
24
16
|
/** Duration to show screenshot notification (ms) */
|
|
25
17
|
export declare const SCREENSHOT_NOTIFICATION_MS = 3000;
|
|
26
18
|
/** Duration to show clipboard notification (ms) */
|
|
@@ -138,28 +130,28 @@ export declare const DEVBAR_THEME: {
|
|
|
138
130
|
};
|
|
139
131
|
};
|
|
140
132
|
export type DevBarTheme = typeof DEVBAR_THEME;
|
|
141
|
-
/** Light theme variant -
|
|
133
|
+
/** Light theme variant - same structure, different colors */
|
|
142
134
|
export declare const DEVBAR_THEME_LIGHT: {
|
|
143
135
|
readonly colors: {
|
|
144
|
-
readonly primary: "#
|
|
145
|
-
readonly primaryHover: "#
|
|
146
|
-
readonly primaryGlow: "rgba(
|
|
147
|
-
readonly error: "#
|
|
136
|
+
readonly primary: "#059669";
|
|
137
|
+
readonly primaryHover: "#047857";
|
|
138
|
+
readonly primaryGlow: "rgba(5, 150, 105, 0.2)";
|
|
139
|
+
readonly error: "#ef4444";
|
|
148
140
|
readonly warning: "#d97706";
|
|
149
141
|
readonly info: "#2563eb";
|
|
150
|
-
readonly purple: "#
|
|
142
|
+
readonly purple: "#9333ea";
|
|
151
143
|
readonly cyan: "#0891b2";
|
|
152
144
|
readonly pink: "#db2777";
|
|
153
145
|
readonly lime: "#65a30d";
|
|
154
|
-
readonly bg: "#
|
|
155
|
-
readonly bgCard: "rgba(255, 255, 255, 0.
|
|
156
|
-
readonly bgElevated: "rgba(255, 255, 255, 0.
|
|
157
|
-
readonly bgInput: "rgba(
|
|
158
|
-
readonly text: "#
|
|
159
|
-
readonly textSecondary: "#
|
|
160
|
-
readonly textMuted: "#
|
|
161
|
-
readonly border: "rgba(
|
|
162
|
-
readonly borderSubtle: "rgba(
|
|
146
|
+
readonly bg: "#f8fafc";
|
|
147
|
+
readonly bgCard: "rgba(255, 255, 255, 0.98)";
|
|
148
|
+
readonly bgElevated: "rgba(255, 255, 255, 0.99)";
|
|
149
|
+
readonly bgInput: "rgba(241, 245, 249, 0.9)";
|
|
150
|
+
readonly text: "#1e293b";
|
|
151
|
+
readonly textSecondary: "#475569";
|
|
152
|
+
readonly textMuted: "#64748b";
|
|
153
|
+
readonly border: "rgba(5, 150, 105, 0.25)";
|
|
154
|
+
readonly borderSubtle: "rgba(0, 0, 0, 0.06)";
|
|
163
155
|
};
|
|
164
156
|
readonly fonts: {
|
|
165
157
|
readonly mono: "'Departure Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace";
|
|
@@ -189,10 +181,10 @@ export declare const DEVBAR_THEME_LIGHT: {
|
|
|
189
181
|
readonly lg: "12px";
|
|
190
182
|
};
|
|
191
183
|
readonly shadows: {
|
|
192
|
-
readonly sm: "0 1px 2px rgba(
|
|
193
|
-
readonly md: "0 4px 12px rgba(
|
|
194
|
-
readonly lg: "0 8px 32px rgba(
|
|
195
|
-
readonly glow: "0 0 20px rgba(
|
|
184
|
+
readonly sm: "0 1px 2px rgba(0, 0, 0, 0.08)";
|
|
185
|
+
readonly md: "0 4px 12px rgba(0, 0, 0, 0.1), 0 0 0 1px rgba(5, 150, 105, 0.1)";
|
|
186
|
+
readonly lg: "0 8px 32px rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(5, 150, 105, 0.12)";
|
|
187
|
+
readonly glow: "0 0 20px rgba(5, 150, 105, 0.1)";
|
|
196
188
|
};
|
|
197
189
|
readonly transitions: {
|
|
198
190
|
readonly fast: "150ms";
|
package/dist/constants.js
CHANGED
|
@@ -18,16 +18,8 @@ export const MAX_RECONNECT_DELAY_MS = 30000;
|
|
|
18
18
|
// ============================================================================
|
|
19
19
|
// WebSocket Settings
|
|
20
20
|
// ============================================================================
|
|
21
|
-
/** Default WebSocket port for Sweetlink connection
|
|
21
|
+
/** Default WebSocket port for Sweetlink connection */
|
|
22
22
|
export const WS_PORT = 9223;
|
|
23
|
-
/** Port offset from app port to calculate WebSocket port (matches SweetlinkBridge) */
|
|
24
|
-
export const WS_PORT_OFFSET = 6223;
|
|
25
|
-
/** Maximum ports to try when scanning for matching server */
|
|
26
|
-
export const MAX_PORT_RETRIES = 10;
|
|
27
|
-
/** Delay between port scan attempts (ms) */
|
|
28
|
-
export const PORT_RETRY_DELAY_MS = 100;
|
|
29
|
-
/** Delay before restarting port scan from base after all ports fail (ms) */
|
|
30
|
-
export const PORT_SCAN_RESTART_DELAY_MS = 3000;
|
|
31
23
|
// ============================================================================
|
|
32
24
|
// Notification Durations
|
|
33
25
|
// ============================================================================
|
|
@@ -182,44 +174,44 @@ export const DEVBAR_THEME = {
|
|
|
182
174
|
fast: '150ms',
|
|
183
175
|
},
|
|
184
176
|
};
|
|
185
|
-
/** Light theme variant -
|
|
177
|
+
/** Light theme variant - same structure, different colors */
|
|
186
178
|
export const DEVBAR_THEME_LIGHT = {
|
|
187
179
|
colors: {
|
|
188
|
-
// Primary accent (darker
|
|
189
|
-
primary: '#
|
|
190
|
-
primaryHover: '#
|
|
191
|
-
primaryGlow: 'rgba(
|
|
192
|
-
// Semantic colors (
|
|
193
|
-
error:
|
|
194
|
-
warning: '#d97706',
|
|
195
|
-
info: '#2563eb',
|
|
196
|
-
// Extended palette (darker
|
|
197
|
-
purple: '#
|
|
180
|
+
// Primary accent (darker for light mode)
|
|
181
|
+
primary: '#059669', // darker emerald
|
|
182
|
+
primaryHover: '#047857',
|
|
183
|
+
primaryGlow: 'rgba(5, 150, 105, 0.2)',
|
|
184
|
+
// Semantic colors (same)
|
|
185
|
+
error: PALETTE.red,
|
|
186
|
+
warning: '#d97706', // darker amber
|
|
187
|
+
info: '#2563eb', // darker blue
|
|
188
|
+
// Extended palette (darker variants)
|
|
189
|
+
purple: '#9333ea',
|
|
198
190
|
cyan: '#0891b2',
|
|
199
191
|
pink: '#db2777',
|
|
200
192
|
lime: '#65a30d',
|
|
201
|
-
// Backgrounds
|
|
202
|
-
bg: '#
|
|
203
|
-
bgCard: 'rgba(255, 255, 255, 0.
|
|
204
|
-
bgElevated: 'rgba(255, 255, 255, 0.
|
|
205
|
-
bgInput: 'rgba(
|
|
193
|
+
// Backgrounds (light)
|
|
194
|
+
bg: '#f8fafc',
|
|
195
|
+
bgCard: 'rgba(255, 255, 255, 0.98)',
|
|
196
|
+
bgElevated: 'rgba(255, 255, 255, 0.99)',
|
|
197
|
+
bgInput: 'rgba(241, 245, 249, 0.9)',
|
|
206
198
|
// Text (dark on light)
|
|
207
|
-
text: '#
|
|
208
|
-
textSecondary: '#
|
|
209
|
-
textMuted: '#
|
|
210
|
-
// Borders (
|
|
211
|
-
border: 'rgba(
|
|
212
|
-
borderSubtle: 'rgba(
|
|
199
|
+
text: '#1e293b',
|
|
200
|
+
textSecondary: '#475569',
|
|
201
|
+
textMuted: '#64748b',
|
|
202
|
+
// Borders (green-tinted)
|
|
203
|
+
border: 'rgba(5, 150, 105, 0.25)',
|
|
204
|
+
borderSubtle: 'rgba(0, 0, 0, 0.06)',
|
|
213
205
|
},
|
|
214
206
|
// Other properties same as dark theme
|
|
215
207
|
fonts: DEVBAR_THEME.fonts,
|
|
216
208
|
typography: DEVBAR_THEME.typography,
|
|
217
209
|
radius: DEVBAR_THEME.radius,
|
|
218
210
|
shadows: {
|
|
219
|
-
sm: '0 1px 2px rgba(
|
|
220
|
-
md: '0 4px 12px rgba(
|
|
221
|
-
lg: '0 8px 32px rgba(
|
|
222
|
-
glow: '0 0 20px rgba(
|
|
211
|
+
sm: '0 1px 2px rgba(0, 0, 0, 0.08)',
|
|
212
|
+
md: '0 4px 12px rgba(0, 0, 0, 0.1), 0 0 0 1px rgba(5, 150, 105, 0.1)',
|
|
213
|
+
lg: '0 8px 32px rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(5, 150, 105, 0.12)',
|
|
214
|
+
glow: '0 0 20px rgba(5, 150, 105, 0.1)',
|
|
223
215
|
},
|
|
224
216
|
transitions: DEVBAR_THEME.transitions,
|
|
225
217
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export { BUTTON_COLORS, CATEGORY_COLORS, COLORS, DEVBAR_THEME, DEVBAR_THEME_LIGHT, type DevBarTheme, type DevBarThemeInput, FONT_MONO, generateBreakpointCSS, generateThemeCSSVars, getEffectiveTheme, getStoredThemeMode, getTheme, getThemeColors, injectThemeCSS, STORAGE_KEYS, setStoredThemeMode, TAILWIND_BREAKPOINTS, type TailwindBreakpoint, type ThemeColors, } from './constants.js';
|
|
1
|
+
export { BUTTON_COLORS, CATEGORY_COLORS, COLORS, DEVBAR_THEME, DEVBAR_THEME_LIGHT, type DevBarTheme, type DevBarThemeInput, FONT_MONO, generateBreakpointCSS, generateThemeCSSVars, getEffectiveTheme, getStoredThemeMode, getTheme, getThemeColors, injectThemeCSS, setStoredThemeMode, STORAGE_KEYS, TAILWIND_BREAKPOINTS, type TailwindBreakpoint, type ThemeColors, } from './constants.js';
|
|
3
2
|
export { DebugLogger, normalizeDebugConfig } from './debug.js';
|
|
4
3
|
export { EARLY_CONSOLE_CAPTURE_SCRIPT } from './earlyConsoleCapture.js';
|
|
5
4
|
export { destroyGlobalDevBar, earlyConsoleCapture, GlobalDevBar, getGlobalDevBar, initGlobalDevBar, } from './GlobalDevBar.js';
|
|
5
|
+
export { initDebug, initFull, initMinimal, initPerformance, initResponsive, PRESET_DEBUG, PRESET_FULL, PRESET_MINIMAL, PRESET_PERFORMANCE, PRESET_RESPONSIVE, } from './presets.js';
|
|
6
6
|
export { getHtml2Canvas, isHtml2CanvasLoaded, preloadHtml2Canvas } from './lazy/index.js';
|
|
7
|
-
export { formatBytes as formatNetworkBytes, formatDuration, getInitiatorColor, type NetworkEntry, NetworkMonitor, type NetworkState, } from './network.js';
|
|
8
7
|
export { extractDocumentOutline, outlineToMarkdown } from './outline.js';
|
|
9
|
-
export { initDebug, initFull, initMinimal, initPerformance, initResponsive, PRESET_DEBUG, PRESET_FULL, PRESET_MINIMAL, PRESET_PERFORMANCE, PRESET_RESPONSIVE, } from './presets.js';
|
|
10
8
|
export { extractPageSchema, schemaToMarkdown } from './schema.js';
|
|
11
|
-
export {
|
|
9
|
+
export { formatBytes as formatNetworkBytes, formatDuration, getInitiatorColor, NetworkMonitor, type NetworkEntry, type NetworkState, } from './network.js';
|
|
10
|
+
export { beautifyJson, clearLocalStorage, clearSessionStorage, deleteCookie, deleteLocalStorageItem, deleteSessionStorageItem, formatStorageSummary, getCookies, getLocalStorage, getSessionStorage, getStorageData, setLocalStorageItem, setSessionStorageItem, type CookieItem, type StorageData, type StorageItem, } from './storage.js';
|
|
11
|
+
export { clearA11yCache, formatViolation, getBadgeColor, getCachedResult, getImpactColor, getViolationCounts, groupViolationsByImpact, isAxeLoaded, preloadAxe, runA11yAudit, type A11yState, type AxeResult, type AxeViolation, } from './accessibility.js';
|
|
12
12
|
export type { ConsoleLog, DebugConfig, DevBarControl, GlobalDevBarOptions, OutlineNode, PageSchema, SweetlinkCommand, ThemeMode, } from './types.js';
|
|
13
13
|
export { canvasToDataUrl, copyCanvasToClipboard, delay, formatArg, formatArgs, prepareForCapture, } from './utils.js';
|
package/dist/index.js
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
// DevBar - Development toolbar and utilities
|
|
2
2
|
// Pure vanilla JavaScript - no framework dependencies
|
|
3
|
-
// Accessibility audit utilities
|
|
4
|
-
export { clearA11yCache, formatViolation, getBadgeColor, getCachedResult, getImpactColor, getViolationCounts, groupViolationsByImpact, isAxeLoaded, preloadAxe, runA11yAudit, } from './accessibility.js';
|
|
5
3
|
// Re-export constants and theme utilities
|
|
6
|
-
export { BUTTON_COLORS, CATEGORY_COLORS, COLORS, DEVBAR_THEME, DEVBAR_THEME_LIGHT, FONT_MONO, generateBreakpointCSS, generateThemeCSSVars, getEffectiveTheme, getStoredThemeMode, getTheme, getThemeColors, injectThemeCSS,
|
|
4
|
+
export { BUTTON_COLORS, CATEGORY_COLORS, COLORS, DEVBAR_THEME, DEVBAR_THEME_LIGHT, FONT_MONO, generateBreakpointCSS, generateThemeCSSVars, getEffectiveTheme, getStoredThemeMode, getTheme, getThemeColors, injectThemeCSS, setStoredThemeMode, STORAGE_KEYS, TAILWIND_BREAKPOINTS, } from './constants.js';
|
|
7
5
|
// Debug utilities
|
|
8
6
|
export { DebugLogger, normalizeDebugConfig } from './debug.js';
|
|
9
7
|
// Early console capture script for injection
|
|
10
8
|
export { EARLY_CONSOLE_CAPTURE_SCRIPT } from './earlyConsoleCapture.js';
|
|
11
9
|
// Main vanilla JS devbar
|
|
12
10
|
export { destroyGlobalDevBar, earlyConsoleCapture, GlobalDevBar, getGlobalDevBar, initGlobalDevBar, } from './GlobalDevBar.js';
|
|
11
|
+
// Configuration presets
|
|
12
|
+
export { initDebug, initFull, initMinimal, initPerformance, initResponsive, PRESET_DEBUG, PRESET_FULL, PRESET_MINIMAL, PRESET_PERFORMANCE, PRESET_RESPONSIVE, } from './presets.js';
|
|
13
13
|
// Lazy loading utilities
|
|
14
14
|
export { getHtml2Canvas, isHtml2CanvasLoaded, preloadHtml2Canvas } from './lazy/index.js';
|
|
15
|
-
// Network monitoring utilities
|
|
16
|
-
export { formatBytes as formatNetworkBytes, formatDuration, getInitiatorColor, NetworkMonitor, } from './network.js';
|
|
17
15
|
// Re-export outline/schema functions
|
|
18
16
|
export { extractDocumentOutline, outlineToMarkdown } from './outline.js';
|
|
19
|
-
// Configuration presets
|
|
20
|
-
export { initDebug, initFull, initMinimal, initPerformance, initResponsive, PRESET_DEBUG, PRESET_FULL, PRESET_MINIMAL, PRESET_PERFORMANCE, PRESET_RESPONSIVE, } from './presets.js';
|
|
21
17
|
export { extractPageSchema, schemaToMarkdown } from './schema.js';
|
|
18
|
+
// Network monitoring utilities
|
|
19
|
+
export { formatBytes as formatNetworkBytes, formatDuration, getInitiatorColor, NetworkMonitor, } from './network.js';
|
|
22
20
|
// Storage inspection utilities
|
|
23
21
|
export { beautifyJson, clearLocalStorage, clearSessionStorage, deleteCookie, deleteLocalStorageItem, deleteSessionStorageItem, formatStorageSummary, getCookies, getLocalStorage, getSessionStorage, getStorageData, setLocalStorageItem, setSessionStorageItem, } from './storage.js';
|
|
22
|
+
// Accessibility audit utilities
|
|
23
|
+
export { clearA11yCache, formatViolation, getBadgeColor, getCachedResult, getImpactColor, getViolationCounts, groupViolationsByImpact, isAxeLoaded, preloadAxe, runA11yAudit, } from './accessibility.js';
|
|
24
24
|
// Re-export utilities for external use
|
|
25
25
|
export { canvasToDataUrl, copyCanvasToClipboard, delay, formatArg, formatArgs, prepareForCapture, } from './utils.js';
|
package/dist/presets.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Pre-configured options for common DevBar use cases.
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
6
|
+
import { GlobalDevBar } from './GlobalDevBar.js';
|
|
7
7
|
import type { GlobalDevBarOptions } from './types.js';
|
|
8
8
|
/**
|
|
9
9
|
* Minimal preset - shows only essential features
|
package/dist/ui/modals.d.ts
CHANGED
|
@@ -13,10 +13,6 @@ export interface ModalConfig {
|
|
|
13
13
|
onCopyMd: () => Promise<void>;
|
|
14
14
|
onSave?: () => void;
|
|
15
15
|
sweetlinkConnected: boolean;
|
|
16
|
-
/** Whether a save operation is in progress */
|
|
17
|
-
isSaving?: boolean;
|
|
18
|
-
/** Path where data was saved (shows confirmation) */
|
|
19
|
-
savedPath?: string | null;
|
|
20
16
|
}
|
|
21
17
|
/**
|
|
22
18
|
* Create modal overlay with click-outside-to-close behavior
|
package/dist/ui/modals.js
CHANGED
|
@@ -34,7 +34,7 @@ export function createModalBox(color) {
|
|
|
34
34
|
* Create modal header with title, copy/save/close buttons
|
|
35
35
|
*/
|
|
36
36
|
export function createModalHeader(config) {
|
|
37
|
-
const { color, title, onClose, onCopyMd, onSave, sweetlinkConnected
|
|
37
|
+
const { color, title, onClose, onCopyMd, onSave, sweetlinkConnected } = config;
|
|
38
38
|
const header = document.createElement('div');
|
|
39
39
|
Object.assign(header.style, {
|
|
40
40
|
display: 'flex',
|
|
@@ -42,8 +42,6 @@ export function createModalHeader(config) {
|
|
|
42
42
|
justifyContent: 'space-between',
|
|
43
43
|
padding: '16px 20px',
|
|
44
44
|
borderBottom: `1px solid ${color}40`,
|
|
45
|
-
flexWrap: 'wrap',
|
|
46
|
-
gap: '8px',
|
|
47
45
|
});
|
|
48
46
|
const titleEl = document.createElement('h2');
|
|
49
47
|
Object.assign(titleEl.style, {
|
|
@@ -55,7 +53,7 @@ export function createModalHeader(config) {
|
|
|
55
53
|
titleEl.textContent = title;
|
|
56
54
|
header.appendChild(titleEl);
|
|
57
55
|
const headerButtons = document.createElement('div');
|
|
58
|
-
Object.assign(headerButtons.style, { display: 'flex', gap: '10px'
|
|
56
|
+
Object.assign(headerButtons.style, { display: 'flex', gap: '10px' });
|
|
59
57
|
// Copy MD button
|
|
60
58
|
const copyBtn = createStyledButton({ color, text: 'Copy MD' });
|
|
61
59
|
copyBtn.onclick = async () => {
|
|
@@ -73,17 +71,8 @@ export function createModalHeader(config) {
|
|
|
73
71
|
headerButtons.appendChild(copyBtn);
|
|
74
72
|
// Save button (if Sweetlink connected)
|
|
75
73
|
if (sweetlinkConnected && onSave) {
|
|
76
|
-
const saveBtn = createStyledButton({
|
|
77
|
-
|
|
78
|
-
text: isSaving ? 'Saving...' : 'Save',
|
|
79
|
-
});
|
|
80
|
-
if (isSaving) {
|
|
81
|
-
saveBtn.style.opacity = '0.6';
|
|
82
|
-
saveBtn.style.cursor = 'not-allowed';
|
|
83
|
-
}
|
|
84
|
-
else {
|
|
85
|
-
saveBtn.onclick = onSave;
|
|
86
|
-
}
|
|
74
|
+
const saveBtn = createStyledButton({ color, text: 'Save' });
|
|
75
|
+
saveBtn.onclick = onSave;
|
|
87
76
|
headerButtons.appendChild(saveBtn);
|
|
88
77
|
}
|
|
89
78
|
// Close button - use same padding as other buttons for consistent height
|
|
@@ -96,39 +85,6 @@ export function createModalHeader(config) {
|
|
|
96
85
|
closeBtn.onclick = onClose;
|
|
97
86
|
headerButtons.appendChild(closeBtn);
|
|
98
87
|
header.appendChild(headerButtons);
|
|
99
|
-
// Show saved path confirmation below buttons
|
|
100
|
-
if (savedPath) {
|
|
101
|
-
const savedConfirm = document.createElement('div');
|
|
102
|
-
Object.assign(savedConfirm.style, {
|
|
103
|
-
width: '100%',
|
|
104
|
-
marginTop: '4px',
|
|
105
|
-
padding: '8px 12px',
|
|
106
|
-
backgroundColor: `${color}15`,
|
|
107
|
-
border: `1px solid ${color}30`,
|
|
108
|
-
borderRadius: '6px',
|
|
109
|
-
fontSize: '0.75rem',
|
|
110
|
-
color: color,
|
|
111
|
-
display: 'flex',
|
|
112
|
-
alignItems: 'center',
|
|
113
|
-
gap: '6px',
|
|
114
|
-
});
|
|
115
|
-
// Checkmark icon
|
|
116
|
-
const checkmark = document.createElement('span');
|
|
117
|
-
checkmark.textContent = '✓';
|
|
118
|
-
Object.assign(checkmark.style, { fontWeight: '600' });
|
|
119
|
-
savedConfirm.appendChild(checkmark);
|
|
120
|
-
// Path text
|
|
121
|
-
const pathText = document.createElement('span');
|
|
122
|
-
Object.assign(pathText.style, {
|
|
123
|
-
color: '#9ca3af',
|
|
124
|
-
fontFamily: 'monospace',
|
|
125
|
-
fontSize: '0.6875rem',
|
|
126
|
-
wordBreak: 'break-all',
|
|
127
|
-
});
|
|
128
|
-
pathText.textContent = `Saved to ${savedPath}`;
|
|
129
|
-
savedConfirm.appendChild(pathText);
|
|
130
|
-
header.appendChild(savedConfirm);
|
|
131
|
-
}
|
|
132
88
|
return header;
|
|
133
89
|
}
|
|
134
90
|
/**
|
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.3c85c90",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "Development toolbar and utilities with Sweetlink integration - pure vanilla JS, no framework dependencies",
|