@ytspar/devbar 0.0.1 → 1.0.0-canary.2b99e1e

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,641 @@
1
+ /**
2
+ * DevBar Constants
3
+ *
4
+ * Shared constants used by the DevBar components.
5
+ */
6
+ // Re-export shared constants from sweetlink's browser modules to avoid pulling in Node.js-only code
7
+ export { MAX_CONSOLE_LOGS } from '@ytspar/sweetlink/browser/consoleCapture';
8
+ export { DEVBAR_SCREENSHOT_QUALITY } from '@ytspar/sweetlink/browser/screenshotUtils';
9
+ // ============================================================================
10
+ // Reconnection Settings
11
+ // ============================================================================
12
+ /** Maximum reconnection attempts before giving up */
13
+ export const MAX_RECONNECT_ATTEMPTS = 10;
14
+ /** Base delay for exponential backoff (ms) */
15
+ export const BASE_RECONNECT_DELAY_MS = 1000;
16
+ /** Maximum delay between reconnection attempts (ms) */
17
+ export const MAX_RECONNECT_DELAY_MS = 30000;
18
+ // ============================================================================
19
+ // WebSocket Settings
20
+ // ============================================================================
21
+ /** Default WebSocket port for Sweetlink connection (legacy fallback) */
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
+ // ============================================================================
32
+ // Notification Durations
33
+ // ============================================================================
34
+ /** Duration to show screenshot notification (ms) */
35
+ export const SCREENSHOT_NOTIFICATION_MS = 3000;
36
+ /** Duration to show clipboard notification (ms) */
37
+ export const CLIPBOARD_NOTIFICATION_MS = 2000;
38
+ /** Duration to show design review notification (ms) */
39
+ export const DESIGN_REVIEW_NOTIFICATION_MS = 5000;
40
+ // ============================================================================
41
+ // Screenshot Capture Settings
42
+ // ============================================================================
43
+ /** Delay after blur before capturing screenshot (ms) */
44
+ export const SCREENSHOT_BLUR_DELAY_MS = 50;
45
+ /** Scale factor for screenshots (0.75 = 75% of original) */
46
+ export const SCREENSHOT_SCALE = 0.75;
47
+ // ============================================================================
48
+ // Tailwind Breakpoints
49
+ // ============================================================================
50
+ /** Tailwind CSS breakpoint definitions */
51
+ export const TAILWIND_BREAKPOINTS = {
52
+ base: { min: 0, label: 'Tailwind base: <640px' },
53
+ sm: { min: 640, label: 'Tailwind sm: >=640px' },
54
+ md: { min: 768, label: 'Tailwind md: >=768px' },
55
+ lg: { min: 1024, label: 'Tailwind lg: >=1024px' },
56
+ xl: { min: 1280, label: 'Tailwind xl: >=1280px' },
57
+ '2xl': { min: 1536, label: 'Tailwind 2xl: >=1536px' },
58
+ };
59
+ // ============================================================================
60
+ // Base Color Palette (single source of truth)
61
+ // ============================================================================
62
+ /** Core color palette - all other color constants reference these */
63
+ const PALETTE = {
64
+ emerald: '#10b981',
65
+ emeraldHover: '#059669',
66
+ emeraldGlow: 'rgba(16, 185, 129, 0.4)',
67
+ red: '#ef4444',
68
+ amber: '#f59e0b',
69
+ blue: '#3b82f6',
70
+ purple: '#a855f7',
71
+ cyan: '#06b6d4',
72
+ pink: '#ec4899',
73
+ lime: '#84cc16',
74
+ gray: '#6b7280',
75
+ };
76
+ // ============================================================================
77
+ // Button Colors
78
+ // ============================================================================
79
+ /** Button colors for devbar toolbar buttons */
80
+ export const BUTTON_COLORS = {
81
+ screenshot: PALETTE.emerald,
82
+ review: PALETTE.purple,
83
+ outline: PALETTE.cyan,
84
+ schema: PALETTE.amber,
85
+ error: PALETTE.red,
86
+ warning: PALETTE.amber,
87
+ };
88
+ /** Category colors for outline display */
89
+ export const CATEGORY_COLORS = {
90
+ heading: PALETTE.emerald,
91
+ sectioning: PALETTE.blue,
92
+ landmark: PALETTE.purple,
93
+ grouping: PALETTE.cyan,
94
+ form: PALETTE.amber,
95
+ table: PALETTE.pink,
96
+ list: PALETTE.lime,
97
+ other: PALETTE.gray,
98
+ };
99
+ // ============================================================================
100
+ // Storage Keys
101
+ // ============================================================================
102
+ /** LocalStorage keys for DevBar persistence */
103
+ export const STORAGE_KEYS = {
104
+ /** Theme mode preference: 'dark' | 'light' | 'system' */
105
+ themeMode: 'devbar-theme-mode',
106
+ /** Compact mode preference: 'true' | 'false' */
107
+ compactMode: 'devbar-compact-mode',
108
+ };
109
+ // ============================================================================
110
+ // Design System Theme
111
+ // ============================================================================
112
+ /** Complete DevBar design system theme */
113
+ export const DEVBAR_THEME = {
114
+ colors: {
115
+ // Primary accent
116
+ primary: PALETTE.emerald,
117
+ primaryHover: PALETTE.emeraldHover,
118
+ primaryGlow: PALETTE.emeraldGlow,
119
+ // Semantic colors
120
+ error: PALETTE.red,
121
+ warning: PALETTE.amber,
122
+ info: PALETTE.blue,
123
+ // Extended palette
124
+ purple: PALETTE.purple,
125
+ cyan: PALETTE.cyan,
126
+ pink: PALETTE.pink,
127
+ lime: PALETTE.lime,
128
+ // Backgrounds
129
+ bg: '#0a0f1a',
130
+ bgCard: 'rgba(17, 24, 39, 0.95)',
131
+ bgElevated: 'rgba(17, 24, 39, 0.98)',
132
+ bgInput: 'rgba(10, 15, 26, 0.8)',
133
+ // Text
134
+ text: '#f1f5f9',
135
+ textSecondary: '#94a3b8',
136
+ textMuted: PALETTE.gray,
137
+ // Borders
138
+ border: 'rgba(16, 185, 129, 0.2)',
139
+ borderSubtle: 'rgba(255, 255, 255, 0.05)',
140
+ },
141
+ fonts: {
142
+ // Departure Mono - retro pixel terminal font (https://departuremono.com)
143
+ // Falls back to system monospace if not loaded
144
+ mono: "'Departure Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace",
145
+ },
146
+ // Typography scale (matches DevBar UI)
147
+ typography: {
148
+ // Font sizes
149
+ sizeXs: '0.625rem', // 10px - badges, tiny labels
150
+ sizeSm: '0.6875rem', // 11px - main devbar text
151
+ sizeBase: '0.75rem', // 12px - buttons, tooltips
152
+ sizeMd: '0.8125rem', // 13px - section headers
153
+ sizeLg: '0.875rem', // 14px - descriptions
154
+ sizeXl: '1rem', // 16px - modal titles
155
+ size2xl: '1.5rem', // 24px - page titles
156
+ // Line heights
157
+ leadingTight: '1rem',
158
+ leadingNormal: '1.5',
159
+ leadingRelaxed: '1.6',
160
+ // Font weights
161
+ weightNormal: '400',
162
+ weightMedium: '500',
163
+ weightSemibold: '600',
164
+ // Letter spacing
165
+ trackingTight: '-0.02em',
166
+ trackingNormal: '0',
167
+ trackingWide: '0.05em',
168
+ trackingWider: '0.1em',
169
+ },
170
+ radius: {
171
+ sm: '4px',
172
+ md: '6px',
173
+ lg: '12px',
174
+ },
175
+ shadows: {
176
+ sm: '0 1px 2px rgba(0, 0, 0, 0.4)',
177
+ md: '0 4px 12px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(16, 185, 129, 0.1)',
178
+ lg: '0 8px 32px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(16, 185, 129, 0.15)',
179
+ glow: '0 0 20px rgba(16, 185, 129, 0.15)',
180
+ },
181
+ transitions: {
182
+ fast: '150ms',
183
+ },
184
+ };
185
+ /** Light theme variant - terminal aesthetic with light green tones */
186
+ export const DEVBAR_THEME_LIGHT = {
187
+ colors: {
188
+ // Primary accent (darker emerald for contrast)
189
+ primary: '#047857', // darker emerald for better contrast
190
+ primaryHover: '#065f46',
191
+ primaryGlow: 'rgba(4, 120, 87, 0.25)',
192
+ // Semantic colors (adjusted for light bg)
193
+ error: '#dc2626',
194
+ warning: '#d97706',
195
+ info: '#2563eb',
196
+ // Extended palette (darker for light mode)
197
+ purple: '#7c3aed',
198
+ cyan: '#0891b2',
199
+ pink: '#db2777',
200
+ lime: '#65a30d',
201
+ // Backgrounds - terminal light green aesthetic
202
+ bg: '#ecfdf5', // very light mint/green
203
+ bgCard: 'rgba(255, 255, 255, 0.85)',
204
+ bgElevated: 'rgba(255, 255, 255, 0.95)',
205
+ bgInput: 'rgba(236, 253, 245, 0.9)', // light mint input
206
+ // Text (dark on light)
207
+ text: '#064e3b', // dark emerald text
208
+ textSecondary: '#065f46',
209
+ textMuted: '#047857',
210
+ // Borders (emerald-tinted)
211
+ border: 'rgba(4, 120, 87, 0.3)',
212
+ borderSubtle: 'rgba(4, 120, 87, 0.1)',
213
+ },
214
+ // Other properties same as dark theme
215
+ fonts: DEVBAR_THEME.fonts,
216
+ typography: DEVBAR_THEME.typography,
217
+ radius: DEVBAR_THEME.radius,
218
+ shadows: {
219
+ sm: '0 1px 2px rgba(4, 120, 87, 0.1)',
220
+ md: '0 4px 12px rgba(4, 120, 87, 0.12), 0 0 0 1px rgba(4, 120, 87, 0.15)',
221
+ lg: '0 8px 32px rgba(4, 120, 87, 0.15), 0 0 0 1px rgba(4, 120, 87, 0.2)',
222
+ glow: '0 0 20px rgba(4, 120, 87, 0.15)',
223
+ },
224
+ transitions: DEVBAR_THEME.transitions,
225
+ };
226
+ // ============================================================================
227
+ // Shorthand Exports (for cleaner imports)
228
+ // ============================================================================
229
+ /** Shorthand for common colors */
230
+ export const COLORS = DEVBAR_THEME.colors;
231
+ /** Shorthand for font stack */
232
+ export const FONT_MONO = DEVBAR_THEME.fonts.mono;
233
+ /**
234
+ * Get the stored theme mode preference
235
+ */
236
+ export function getStoredThemeMode() {
237
+ if (typeof localStorage === 'undefined')
238
+ return 'system';
239
+ const stored = localStorage.getItem(STORAGE_KEYS.themeMode);
240
+ if (stored === 'dark' || stored === 'light' || stored === 'system') {
241
+ return stored;
242
+ }
243
+ return 'system';
244
+ }
245
+ /**
246
+ * Store the theme mode preference
247
+ */
248
+ export function setStoredThemeMode(mode) {
249
+ if (typeof localStorage === 'undefined')
250
+ return;
251
+ localStorage.setItem(STORAGE_KEYS.themeMode, mode);
252
+ }
253
+ /**
254
+ * Get the effective theme (resolves 'system' to 'dark' or 'light')
255
+ */
256
+ export function getEffectiveTheme(mode) {
257
+ if (mode === 'system') {
258
+ if (typeof window === 'undefined')
259
+ return 'dark';
260
+ return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
261
+ }
262
+ return mode;
263
+ }
264
+ /**
265
+ * Get theme colors based on the current effective theme
266
+ */
267
+ export function getThemeColors(mode) {
268
+ const effectiveTheme = getEffectiveTheme(mode);
269
+ return effectiveTheme === 'light' ? DEVBAR_THEME_LIGHT.colors : DEVBAR_THEME.colors;
270
+ }
271
+ /**
272
+ * Get full theme based on the current effective theme
273
+ */
274
+ export function getTheme(mode) {
275
+ const effectiveTheme = getEffectiveTheme(mode);
276
+ return effectiveTheme === 'light' ? DEVBAR_THEME_LIGHT : DEVBAR_THEME;
277
+ }
278
+ /**
279
+ * Generate CSS custom properties from the theme
280
+ */
281
+ export function generateThemeCSSVars(theme = DEVBAR_THEME) {
282
+ return `
283
+ /* Departure Mono - retro pixel terminal font */
284
+ /* https://departuremono.com - SIL Open Font License */
285
+ @font-face {
286
+ font-family: 'Departure Mono';
287
+ src: url('/fonts/DepartureMono-Regular.woff2') format('woff2'),
288
+ url('/fonts/DepartureMono-Regular.woff') format('woff'),
289
+ url('https://github.com/rektdeckard/departure-mono/raw/main/fonts/DepartureMono-Regular.woff2') format('woff2');
290
+ font-weight: normal;
291
+ font-style: normal;
292
+ font-display: swap;
293
+ }
294
+
295
+ :root {
296
+ /* Colors - Primary */
297
+ --devbar-color-primary: ${theme.colors.primary};
298
+ --devbar-color-primary-hover: ${theme.colors.primaryHover};
299
+ --devbar-color-primary-glow: ${theme.colors.primaryGlow};
300
+
301
+ /* Colors - Semantic */
302
+ --devbar-color-error: ${theme.colors.error};
303
+ --devbar-color-warning: ${theme.colors.warning};
304
+ --devbar-color-info: ${theme.colors.info};
305
+
306
+ /* Colors - Extended */
307
+ --devbar-color-purple: ${theme.colors.purple};
308
+ --devbar-color-cyan: ${theme.colors.cyan};
309
+ --devbar-color-pink: ${theme.colors.pink};
310
+ --devbar-color-lime: ${theme.colors.lime};
311
+
312
+ /* Colors - Backgrounds */
313
+ --devbar-color-bg: ${theme.colors.bg};
314
+ --devbar-color-bg-card: ${theme.colors.bgCard};
315
+ --devbar-color-bg-elevated: ${theme.colors.bgElevated};
316
+ --devbar-color-bg-input: ${theme.colors.bgInput};
317
+
318
+ /* Colors - Text */
319
+ --devbar-color-text: ${theme.colors.text};
320
+ --devbar-color-text-secondary: ${theme.colors.textSecondary};
321
+ --devbar-color-text-muted: ${theme.colors.textMuted};
322
+
323
+ /* Colors - Borders */
324
+ --devbar-color-border: ${theme.colors.border};
325
+ --devbar-color-border-subtle: ${theme.colors.borderSubtle};
326
+
327
+ /* Typography - Font */
328
+ --devbar-font-mono: ${theme.fonts.mono};
329
+
330
+ /* Typography - Font Sizes */
331
+ --devbar-text-xs: ${theme.typography.sizeXs};
332
+ --devbar-text-sm: ${theme.typography.sizeSm};
333
+ --devbar-text-base: ${theme.typography.sizeBase};
334
+ --devbar-text-md: ${theme.typography.sizeMd};
335
+ --devbar-text-lg: ${theme.typography.sizeLg};
336
+ --devbar-text-xl: ${theme.typography.sizeXl};
337
+ --devbar-text-2xl: ${theme.typography.size2xl};
338
+
339
+ /* Typography - Line Heights */
340
+ --devbar-leading-tight: ${theme.typography.leadingTight};
341
+ --devbar-leading-normal: ${theme.typography.leadingNormal};
342
+ --devbar-leading-relaxed: ${theme.typography.leadingRelaxed};
343
+
344
+ /* Typography - Font Weights */
345
+ --devbar-font-normal: ${theme.typography.weightNormal};
346
+ --devbar-font-medium: ${theme.typography.weightMedium};
347
+ --devbar-font-semibold: ${theme.typography.weightSemibold};
348
+
349
+ /* Typography - Letter Spacing */
350
+ --devbar-tracking-tight: ${theme.typography.trackingTight};
351
+ --devbar-tracking-normal: ${theme.typography.trackingNormal};
352
+ --devbar-tracking-wide: ${theme.typography.trackingWide};
353
+ --devbar-tracking-wider: ${theme.typography.trackingWider};
354
+
355
+ /* Radius */
356
+ --devbar-radius-sm: ${theme.radius.sm};
357
+ --devbar-radius-md: ${theme.radius.md};
358
+ --devbar-radius-lg: ${theme.radius.lg};
359
+
360
+ /* Shadows */
361
+ --devbar-shadow-sm: ${theme.shadows.sm};
362
+ --devbar-shadow-md: ${theme.shadows.md};
363
+ --devbar-shadow-lg: ${theme.shadows.lg};
364
+ --devbar-shadow-glow: ${theme.shadows.glow};
365
+
366
+ /* Transitions */
367
+ --devbar-transition-fast: ${theme.transitions.fast};
368
+ }
369
+ `.trim();
370
+ }
371
+ /**
372
+ * Inject theme CSS variables into the document
373
+ */
374
+ export function injectThemeCSS(theme = DEVBAR_THEME) {
375
+ if (typeof document === 'undefined')
376
+ return;
377
+ const styleId = 'devbar-theme-vars';
378
+ let style = document.getElementById(styleId);
379
+ if (!style) {
380
+ style = document.createElement('style');
381
+ style.id = styleId;
382
+ document.head.appendChild(style);
383
+ }
384
+ style.textContent = generateThemeCSSVars(theme);
385
+ }
386
+ /**
387
+ * Generate CSS for breakpoint media queries
388
+ */
389
+ export function generateBreakpointCSS(selector, property, values) {
390
+ const breakpoints = Object.entries(TAILWIND_BREAKPOINTS);
391
+ return breakpoints
392
+ .map(([bp, { min }]) => {
393
+ const value = values[bp];
394
+ if (!value)
395
+ return '';
396
+ if (bp === 'base') {
397
+ return `${selector} { ${property}: ${value}; }`;
398
+ }
399
+ return `@media (min-width: ${min}px) { ${selector} { ${property}: ${value}; } }`;
400
+ })
401
+ .filter(Boolean)
402
+ .join('\n');
403
+ }
404
+ // ============================================================================
405
+ // Button Styles
406
+ // ============================================================================
407
+ /** Base styles for toolbar action buttons */
408
+ export const ACTION_BUTTON_BASE_STYLES = {
409
+ display: 'flex',
410
+ alignItems: 'center',
411
+ justifyContent: 'center',
412
+ width: '22px',
413
+ height: '22px',
414
+ minWidth: '22px',
415
+ minHeight: '22px',
416
+ flexShrink: '0',
417
+ borderRadius: '50%',
418
+ border: '1px solid',
419
+ transition: 'all 150ms',
420
+ };
421
+ // ============================================================================
422
+ // Modal Styles
423
+ // ============================================================================
424
+ /** Common modal overlay styles */
425
+ export const MODAL_OVERLAY_STYLES = {
426
+ position: 'fixed',
427
+ top: '0',
428
+ left: '0',
429
+ right: '0',
430
+ bottom: '0',
431
+ backgroundColor: 'rgba(0, 0, 0, 0.7)',
432
+ zIndex: '10002',
433
+ display: 'flex',
434
+ alignItems: 'center',
435
+ justifyContent: 'center',
436
+ };
437
+ /** Common modal box styles */
438
+ export const MODAL_BOX_BASE_STYLES = {
439
+ backgroundColor: COLORS.bgElevated,
440
+ borderRadius: '12px',
441
+ width: '90%',
442
+ maxWidth: '700px',
443
+ maxHeight: '80vh',
444
+ display: 'flex',
445
+ flexDirection: 'column',
446
+ fontFamily: FONT_MONO,
447
+ };
448
+ // ============================================================================
449
+ // CSS Styles
450
+ // ============================================================================
451
+ /** Tooltip and animation CSS styles */
452
+ export const TOOLTIP_STYLES = `
453
+ .devbar-tooltip {
454
+ position: relative;
455
+ }
456
+ /* Invisible bridge to keep tooltip open when moving mouse to it */
457
+ .devbar-tooltip::before {
458
+ content: '';
459
+ position: absolute;
460
+ bottom: 100%;
461
+ left: 0;
462
+ right: 0;
463
+ height: 16px;
464
+ pointer-events: none;
465
+ }
466
+ .devbar-tooltip:hover::before {
467
+ pointer-events: auto;
468
+ }
469
+ /* Extend bridge for right-aligned tooltips (tooltip extends left) */
470
+ .devbar-tooltip-right::before {
471
+ left: -400px;
472
+ right: 0;
473
+ }
474
+ /* Extend bridge for left-aligned tooltips (tooltip extends right) */
475
+ .devbar-tooltip-left::before {
476
+ left: 0;
477
+ right: -400px;
478
+ }
479
+ .devbar-tooltip::after {
480
+ content: attr(data-tooltip);
481
+ position: absolute;
482
+ bottom: calc(100% + 8px);
483
+ left: 50%;
484
+ transform: translateX(-50%) scale(0.95);
485
+ padding: 0.625rem 1rem;
486
+ background: ${COLORS.bgElevated};
487
+ color: ${COLORS.primary};
488
+ font-family: ${FONT_MONO};
489
+ font-size: 0.75rem;
490
+ line-height: 1.5;
491
+ border-radius: 6px;
492
+ border: 1px solid ${COLORS.border};
493
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(16, 185, 129, 0.1);
494
+ backdrop-filter: blur(8px);
495
+ -webkit-backdrop-filter: blur(8px);
496
+ min-width: min(200px, calc(100vw - 32px));
497
+ max-width: min(400px, calc(100vw - 32px));
498
+ white-space: pre-wrap;
499
+ z-index: 10001;
500
+ pointer-events: none;
501
+ opacity: 0;
502
+ visibility: hidden;
503
+ will-change: opacity, transform;
504
+ transition: opacity 150ms ease-out, transform 150ms ease-out, visibility 150ms;
505
+ user-select: text;
506
+ cursor: text;
507
+ }
508
+ .devbar-tooltip:hover::after {
509
+ opacity: 1;
510
+ visibility: visible;
511
+ transform: translateX(-50%) scale(1);
512
+ pointer-events: auto;
513
+ }
514
+ .devbar-tooltip-left::after {
515
+ left: 8px !important;
516
+ right: auto !important;
517
+ transform: translateX(0) scale(0.95) !important;
518
+ }
519
+ .devbar-tooltip-left:hover::after {
520
+ transform: translateX(0) scale(1) !important;
521
+ }
522
+ .devbar-tooltip-right::after {
523
+ left: auto !important;
524
+ right: 8px !important;
525
+ transform: translateX(0) scale(0.95) !important;
526
+ }
527
+ .devbar-tooltip-right:hover::after {
528
+ transform: translateX(0) scale(1) !important;
529
+ }
530
+ .devbar-capturing .devbar-tooltip::after,
531
+ .devbar-capturing .devbar-tooltip:hover::after {
532
+ display: none !important;
533
+ opacity: 0 !important;
534
+ visibility: hidden !important;
535
+ }
536
+ .devbar-item {
537
+ transition: opacity 150ms ease-out, color 150ms ease-out;
538
+ }
539
+ .devbar-item:hover {
540
+ opacity: 1 !important;
541
+ color: ${COLORS.primary};
542
+ }
543
+ .devbar-clickable {
544
+ transition: transform 150ms ease-out, background-color 150ms ease-out, box-shadow 150ms ease-out;
545
+ }
546
+ .devbar-clickable:hover {
547
+ transform: scale(1.1);
548
+ background-color: rgba(16, 185, 129, 0.15);
549
+ box-shadow: 0 0 8px ${COLORS.primaryGlow};
550
+ }
551
+ .devbar-badge {
552
+ transition: transform 150ms ease-out, box-shadow 150ms ease-out;
553
+ }
554
+ .devbar-badge:hover {
555
+ transform: scale(1.1);
556
+ box-shadow: 0 0 8px currentColor;
557
+ }
558
+ .devbar-collapse {
559
+ transition: transform 150ms ease-out, background-color 150ms ease-out, box-shadow 150ms ease-out, border-color 150ms ease-out;
560
+ }
561
+ .devbar-collapse:hover {
562
+ transform: scale(1.08);
563
+ background-color: rgba(16, 185, 129, 0.15);
564
+ box-shadow: 0 0 12px ${COLORS.primaryGlow};
565
+ border-color: ${COLORS.primary};
566
+ }
567
+ @keyframes pulse {
568
+ 0%, 100% { opacity: 1; }
569
+ 50% { opacity: 0.5; }
570
+ }
571
+ @keyframes devbar-collapse {
572
+ 0% { transform: scale(0.8); opacity: 0; }
573
+ 100% { transform: scale(1); opacity: 1; }
574
+ }
575
+ /* Main row - single row by default (SM, MD, LG, XL) */
576
+ .devbar-main {
577
+ flex-wrap: nowrap;
578
+ }
579
+ /* Info section - truncates if needed to fit single row */
580
+ .devbar-info {
581
+ white-space: nowrap;
582
+ }
583
+ .devbar-info > span {
584
+ flex-shrink: 0;
585
+ }
586
+ /* Actions container - stays on same row by default */
587
+ .devbar-actions {
588
+ display: flex;
589
+ align-items: center;
590
+ gap: 0.5rem;
591
+ flex-basis: auto;
592
+ flex-shrink: 0;
593
+ }
594
+ /* BASE only (< 640px): fit content, centered horizontally */
595
+ @media (max-width: 639px) {
596
+ /* Expanded state: center and constrain width */
597
+ [data-devbar]:not(.devbar-collapse) {
598
+ width: auto !important;
599
+ min-width: auto !important;
600
+ max-width: calc(100vw - 32px) !important;
601
+ left: 50% !important;
602
+ right: auto !important;
603
+ transform: translateX(-50%) !important;
604
+ }
605
+ /* Collapsed state: JS handles positioning based on captured dot location */
606
+ .devbar-main {
607
+ flex-wrap: wrap;
608
+ justify-content: center;
609
+ }
610
+ /* Keep status row (connection dot + info) on same line */
611
+ .devbar-status {
612
+ flex-wrap: nowrap !important;
613
+ justify-content: center;
614
+ }
615
+ .devbar-info {
616
+ justify-content: center;
617
+ flex-wrap: nowrap;
618
+ white-space: nowrap !important;
619
+ }
620
+ .devbar-actions {
621
+ justify-content: space-evenly;
622
+ margin-top: 0.25rem;
623
+ flex-wrap: nowrap;
624
+ width: 100%;
625
+ }
626
+ /* Constrain tooltips to viewport on mobile */
627
+ .devbar-tooltip::after {
628
+ left: auto !important;
629
+ right: 0 !important;
630
+ transform: translateX(0) scale(0.95) !important;
631
+ max-width: calc(100vw - 24px) !important;
632
+ }
633
+ .devbar-tooltip:hover::after {
634
+ transform: translateX(0) scale(1) !important;
635
+ }
636
+ .devbar-tooltip-left::after {
637
+ left: 0 !important;
638
+ right: auto !important;
639
+ }
640
+ }
641
+ `;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * DevBar Debug Utilities
3
+ *
4
+ * Debug logging system for DevBar lifecycle, state, and events.
5
+ */
6
+ import type { DebugConfig } from './types.js';
7
+ /**
8
+ * Normalize debug option to DebugConfig
9
+ */
10
+ export declare function normalizeDebugConfig(debug: boolean | DebugConfig | undefined): DebugConfig;
11
+ /**
12
+ * Debug logger for DevBar
13
+ */
14
+ export declare class DebugLogger {
15
+ private config;
16
+ private prefix;
17
+ constructor(config: DebugConfig);
18
+ /**
19
+ * Update debug configuration
20
+ */
21
+ setConfig(config: DebugConfig): void;
22
+ /**
23
+ * Log lifecycle events (init, destroy, etc.)
24
+ */
25
+ lifecycle(message: string, data?: unknown): void;
26
+ /**
27
+ * Log state changes (collapse, modal open/close, etc.)
28
+ */
29
+ state(message: string, data?: unknown): void;
30
+ /**
31
+ * Log WebSocket events (connect, disconnect, messages)
32
+ */
33
+ ws(message: string, data?: unknown): void;
34
+ /**
35
+ * Log performance measurements (FCP, LCP, CLS, INP)
36
+ */
37
+ perf(message: string, data?: unknown): void;
38
+ private log;
39
+ }