@ytspar/devbar 0.0.1 → 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/LICENSE +21 -0
- package/README.md +173 -28
- package/dist/GlobalDevBar.d.ts +201 -0
- package/dist/GlobalDevBar.js +1979 -0
- package/dist/constants.d.ts +202 -0
- package/dist/constants.js +535 -0
- package/dist/earlyConsoleCapture.d.ts +34 -0
- package/dist/earlyConsoleCapture.js +77 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +13 -0
- package/dist/outline.d.ts +14 -0
- package/dist/outline.js +215 -0
- package/dist/schema.d.ts +14 -0
- package/dist/schema.js +113 -0
- package/dist/types.d.ts +50 -0
- package/dist/types.js +8 -0
- package/dist/ui/buttons.d.ts +21 -0
- package/dist/ui/buttons.js +55 -0
- package/dist/ui/icons.d.ts +13 -0
- package/dist/ui/icons.js +25 -0
- package/dist/ui/index.d.ts +8 -0
- package/dist/ui/index.js +8 -0
- package/dist/ui/modals.d.ts +40 -0
- package/dist/ui/modals.js +144 -0
- package/dist/utils.d.ts +11 -0
- package/dist/utils.js +13 -0
- package/package.json +58 -6
|
@@ -0,0 +1,535 @@
|
|
|
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 */
|
|
22
|
+
export const WS_PORT = 9223;
|
|
23
|
+
// ============================================================================
|
|
24
|
+
// Notification Durations
|
|
25
|
+
// ============================================================================
|
|
26
|
+
/** Duration to show screenshot notification (ms) */
|
|
27
|
+
export const SCREENSHOT_NOTIFICATION_MS = 3000;
|
|
28
|
+
/** Duration to show clipboard notification (ms) */
|
|
29
|
+
export const CLIPBOARD_NOTIFICATION_MS = 2000;
|
|
30
|
+
/** Duration to show design review notification (ms) */
|
|
31
|
+
export const DESIGN_REVIEW_NOTIFICATION_MS = 5000;
|
|
32
|
+
// ============================================================================
|
|
33
|
+
// Screenshot Capture Settings
|
|
34
|
+
// ============================================================================
|
|
35
|
+
/** Delay after blur before capturing screenshot (ms) */
|
|
36
|
+
export const SCREENSHOT_BLUR_DELAY_MS = 50;
|
|
37
|
+
/** Scale factor for screenshots (0.75 = 75% of original) */
|
|
38
|
+
export const SCREENSHOT_SCALE = 0.75;
|
|
39
|
+
// ============================================================================
|
|
40
|
+
// Tailwind Breakpoints
|
|
41
|
+
// ============================================================================
|
|
42
|
+
/** Tailwind CSS breakpoint definitions */
|
|
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' },
|
|
49
|
+
'2xl': { min: 1536, label: 'Tailwind 2xl: >=1536px' },
|
|
50
|
+
};
|
|
51
|
+
// ============================================================================
|
|
52
|
+
// Base Color Palette (single source of truth)
|
|
53
|
+
// ============================================================================
|
|
54
|
+
/** Core color palette - all other color constants reference these */
|
|
55
|
+
const PALETTE = {
|
|
56
|
+
emerald: '#10b981',
|
|
57
|
+
emeraldHover: '#059669',
|
|
58
|
+
emeraldGlow: 'rgba(16, 185, 129, 0.4)',
|
|
59
|
+
red: '#ef4444',
|
|
60
|
+
amber: '#f59e0b',
|
|
61
|
+
blue: '#3b82f6',
|
|
62
|
+
purple: '#a855f7',
|
|
63
|
+
cyan: '#06b6d4',
|
|
64
|
+
pink: '#ec4899',
|
|
65
|
+
lime: '#84cc16',
|
|
66
|
+
gray: '#6b7280',
|
|
67
|
+
};
|
|
68
|
+
// ============================================================================
|
|
69
|
+
// Button Colors
|
|
70
|
+
// ============================================================================
|
|
71
|
+
/** Button colors for devbar toolbar buttons */
|
|
72
|
+
export const BUTTON_COLORS = {
|
|
73
|
+
screenshot: PALETTE.emerald,
|
|
74
|
+
review: PALETTE.purple,
|
|
75
|
+
outline: PALETTE.cyan,
|
|
76
|
+
schema: PALETTE.amber,
|
|
77
|
+
error: PALETTE.red,
|
|
78
|
+
warning: PALETTE.amber,
|
|
79
|
+
};
|
|
80
|
+
/** Category colors for outline display */
|
|
81
|
+
export const CATEGORY_COLORS = {
|
|
82
|
+
heading: PALETTE.emerald,
|
|
83
|
+
sectioning: PALETTE.blue,
|
|
84
|
+
landmark: PALETTE.purple,
|
|
85
|
+
grouping: PALETTE.cyan,
|
|
86
|
+
form: PALETTE.amber,
|
|
87
|
+
table: PALETTE.pink,
|
|
88
|
+
list: PALETTE.lime,
|
|
89
|
+
other: PALETTE.gray,
|
|
90
|
+
};
|
|
91
|
+
// ============================================================================
|
|
92
|
+
// Design System Theme
|
|
93
|
+
// ============================================================================
|
|
94
|
+
/** Complete DevBar design system theme */
|
|
95
|
+
export const DEVBAR_THEME = {
|
|
96
|
+
colors: {
|
|
97
|
+
// Primary accent
|
|
98
|
+
primary: PALETTE.emerald,
|
|
99
|
+
primaryHover: PALETTE.emeraldHover,
|
|
100
|
+
primaryGlow: PALETTE.emeraldGlow,
|
|
101
|
+
// Semantic colors
|
|
102
|
+
error: PALETTE.red,
|
|
103
|
+
warning: PALETTE.amber,
|
|
104
|
+
info: PALETTE.blue,
|
|
105
|
+
// Extended palette
|
|
106
|
+
purple: PALETTE.purple,
|
|
107
|
+
cyan: PALETTE.cyan,
|
|
108
|
+
pink: PALETTE.pink,
|
|
109
|
+
lime: PALETTE.lime,
|
|
110
|
+
// Backgrounds
|
|
111
|
+
bg: '#0a0f1a',
|
|
112
|
+
bgCard: 'rgba(17, 24, 39, 0.95)',
|
|
113
|
+
bgElevated: 'rgba(17, 24, 39, 0.98)',
|
|
114
|
+
bgInput: 'rgba(10, 15, 26, 0.8)',
|
|
115
|
+
// Text
|
|
116
|
+
text: '#f1f5f9',
|
|
117
|
+
textSecondary: '#94a3b8',
|
|
118
|
+
textMuted: PALETTE.gray,
|
|
119
|
+
// Borders
|
|
120
|
+
border: 'rgba(16, 185, 129, 0.2)',
|
|
121
|
+
borderSubtle: 'rgba(255, 255, 255, 0.05)',
|
|
122
|
+
},
|
|
123
|
+
fonts: {
|
|
124
|
+
// Departure Mono - retro pixel terminal font (https://departuremono.com)
|
|
125
|
+
// Falls back to system monospace if not loaded
|
|
126
|
+
mono: "'Departure Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace",
|
|
127
|
+
},
|
|
128
|
+
// Typography scale (matches DevBar UI)
|
|
129
|
+
typography: {
|
|
130
|
+
// Font sizes
|
|
131
|
+
sizeXs: '0.625rem', // 10px - badges, tiny labels
|
|
132
|
+
sizeSm: '0.6875rem', // 11px - main devbar text
|
|
133
|
+
sizeBase: '0.75rem', // 12px - buttons, tooltips
|
|
134
|
+
sizeMd: '0.8125rem', // 13px - section headers
|
|
135
|
+
sizeLg: '0.875rem', // 14px - descriptions
|
|
136
|
+
sizeXl: '1rem', // 16px - modal titles
|
|
137
|
+
size2xl: '1.5rem', // 24px - page titles
|
|
138
|
+
// Line heights
|
|
139
|
+
leadingTight: '1rem',
|
|
140
|
+
leadingNormal: '1.5',
|
|
141
|
+
leadingRelaxed: '1.6',
|
|
142
|
+
// Font weights
|
|
143
|
+
weightNormal: '400',
|
|
144
|
+
weightMedium: '500',
|
|
145
|
+
weightSemibold: '600',
|
|
146
|
+
// Letter spacing
|
|
147
|
+
trackingTight: '-0.02em',
|
|
148
|
+
trackingNormal: '0',
|
|
149
|
+
trackingWide: '0.05em',
|
|
150
|
+
trackingWider: '0.1em',
|
|
151
|
+
},
|
|
152
|
+
radius: {
|
|
153
|
+
sm: '4px',
|
|
154
|
+
md: '6px',
|
|
155
|
+
lg: '12px',
|
|
156
|
+
},
|
|
157
|
+
shadows: {
|
|
158
|
+
sm: '0 1px 2px rgba(0, 0, 0, 0.4)',
|
|
159
|
+
md: '0 4px 12px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(16, 185, 129, 0.1)',
|
|
160
|
+
lg: '0 8px 32px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(16, 185, 129, 0.15)',
|
|
161
|
+
glow: '0 0 20px rgba(16, 185, 129, 0.15)',
|
|
162
|
+
},
|
|
163
|
+
transitions: {
|
|
164
|
+
fast: '150ms',
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
// ============================================================================
|
|
168
|
+
// Shorthand Exports (for cleaner imports)
|
|
169
|
+
// ============================================================================
|
|
170
|
+
/** Shorthand for common colors */
|
|
171
|
+
export const COLORS = DEVBAR_THEME.colors;
|
|
172
|
+
/** Shorthand for font stack */
|
|
173
|
+
export const FONT_MONO = DEVBAR_THEME.fonts.mono;
|
|
174
|
+
/**
|
|
175
|
+
* Generate CSS custom properties from the theme
|
|
176
|
+
*/
|
|
177
|
+
export function generateThemeCSSVars(theme = DEVBAR_THEME) {
|
|
178
|
+
return `
|
|
179
|
+
/* Departure Mono - retro pixel terminal font */
|
|
180
|
+
/* https://departuremono.com - SIL Open Font License */
|
|
181
|
+
@font-face {
|
|
182
|
+
font-family: 'Departure Mono';
|
|
183
|
+
src: url('/fonts/DepartureMono-Regular.woff2') format('woff2'),
|
|
184
|
+
url('/fonts/DepartureMono-Regular.woff') format('woff'),
|
|
185
|
+
url('https://github.com/rektdeckard/departure-mono/raw/main/fonts/DepartureMono-Regular.woff2') format('woff2');
|
|
186
|
+
font-weight: normal;
|
|
187
|
+
font-style: normal;
|
|
188
|
+
font-display: swap;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
:root {
|
|
192
|
+
/* Colors - Primary */
|
|
193
|
+
--devbar-color-primary: ${theme.colors.primary};
|
|
194
|
+
--devbar-color-primary-hover: ${theme.colors.primaryHover};
|
|
195
|
+
--devbar-color-primary-glow: ${theme.colors.primaryGlow};
|
|
196
|
+
|
|
197
|
+
/* Colors - Semantic */
|
|
198
|
+
--devbar-color-error: ${theme.colors.error};
|
|
199
|
+
--devbar-color-warning: ${theme.colors.warning};
|
|
200
|
+
--devbar-color-info: ${theme.colors.info};
|
|
201
|
+
|
|
202
|
+
/* Colors - Extended */
|
|
203
|
+
--devbar-color-purple: ${theme.colors.purple};
|
|
204
|
+
--devbar-color-cyan: ${theme.colors.cyan};
|
|
205
|
+
--devbar-color-pink: ${theme.colors.pink};
|
|
206
|
+
--devbar-color-lime: ${theme.colors.lime};
|
|
207
|
+
|
|
208
|
+
/* Colors - Backgrounds */
|
|
209
|
+
--devbar-color-bg: ${theme.colors.bg};
|
|
210
|
+
--devbar-color-bg-card: ${theme.colors.bgCard};
|
|
211
|
+
--devbar-color-bg-elevated: ${theme.colors.bgElevated};
|
|
212
|
+
--devbar-color-bg-input: ${theme.colors.bgInput};
|
|
213
|
+
|
|
214
|
+
/* Colors - Text */
|
|
215
|
+
--devbar-color-text: ${theme.colors.text};
|
|
216
|
+
--devbar-color-text-secondary: ${theme.colors.textSecondary};
|
|
217
|
+
--devbar-color-text-muted: ${theme.colors.textMuted};
|
|
218
|
+
|
|
219
|
+
/* Colors - Borders */
|
|
220
|
+
--devbar-color-border: ${theme.colors.border};
|
|
221
|
+
--devbar-color-border-subtle: ${theme.colors.borderSubtle};
|
|
222
|
+
|
|
223
|
+
/* Typography - Font */
|
|
224
|
+
--devbar-font-mono: ${theme.fonts.mono};
|
|
225
|
+
|
|
226
|
+
/* Typography - Font Sizes */
|
|
227
|
+
--devbar-text-xs: ${theme.typography.sizeXs};
|
|
228
|
+
--devbar-text-sm: ${theme.typography.sizeSm};
|
|
229
|
+
--devbar-text-base: ${theme.typography.sizeBase};
|
|
230
|
+
--devbar-text-md: ${theme.typography.sizeMd};
|
|
231
|
+
--devbar-text-lg: ${theme.typography.sizeLg};
|
|
232
|
+
--devbar-text-xl: ${theme.typography.sizeXl};
|
|
233
|
+
--devbar-text-2xl: ${theme.typography.size2xl};
|
|
234
|
+
|
|
235
|
+
/* Typography - Line Heights */
|
|
236
|
+
--devbar-leading-tight: ${theme.typography.leadingTight};
|
|
237
|
+
--devbar-leading-normal: ${theme.typography.leadingNormal};
|
|
238
|
+
--devbar-leading-relaxed: ${theme.typography.leadingRelaxed};
|
|
239
|
+
|
|
240
|
+
/* Typography - Font Weights */
|
|
241
|
+
--devbar-font-normal: ${theme.typography.weightNormal};
|
|
242
|
+
--devbar-font-medium: ${theme.typography.weightMedium};
|
|
243
|
+
--devbar-font-semibold: ${theme.typography.weightSemibold};
|
|
244
|
+
|
|
245
|
+
/* Typography - Letter Spacing */
|
|
246
|
+
--devbar-tracking-tight: ${theme.typography.trackingTight};
|
|
247
|
+
--devbar-tracking-normal: ${theme.typography.trackingNormal};
|
|
248
|
+
--devbar-tracking-wide: ${theme.typography.trackingWide};
|
|
249
|
+
--devbar-tracking-wider: ${theme.typography.trackingWider};
|
|
250
|
+
|
|
251
|
+
/* Radius */
|
|
252
|
+
--devbar-radius-sm: ${theme.radius.sm};
|
|
253
|
+
--devbar-radius-md: ${theme.radius.md};
|
|
254
|
+
--devbar-radius-lg: ${theme.radius.lg};
|
|
255
|
+
|
|
256
|
+
/* Shadows */
|
|
257
|
+
--devbar-shadow-sm: ${theme.shadows.sm};
|
|
258
|
+
--devbar-shadow-md: ${theme.shadows.md};
|
|
259
|
+
--devbar-shadow-lg: ${theme.shadows.lg};
|
|
260
|
+
--devbar-shadow-glow: ${theme.shadows.glow};
|
|
261
|
+
|
|
262
|
+
/* Transitions */
|
|
263
|
+
--devbar-transition-fast: ${theme.transitions.fast};
|
|
264
|
+
}
|
|
265
|
+
`.trim();
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Inject theme CSS variables into the document
|
|
269
|
+
*/
|
|
270
|
+
export function injectThemeCSS(theme = DEVBAR_THEME) {
|
|
271
|
+
if (typeof document === 'undefined')
|
|
272
|
+
return;
|
|
273
|
+
const styleId = 'devbar-theme-vars';
|
|
274
|
+
let style = document.getElementById(styleId);
|
|
275
|
+
if (!style) {
|
|
276
|
+
style = document.createElement('style');
|
|
277
|
+
style.id = styleId;
|
|
278
|
+
document.head.appendChild(style);
|
|
279
|
+
}
|
|
280
|
+
style.textContent = generateThemeCSSVars(theme);
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Generate CSS for breakpoint media queries
|
|
284
|
+
*/
|
|
285
|
+
export function generateBreakpointCSS(selector, property, values) {
|
|
286
|
+
const breakpoints = Object.entries(TAILWIND_BREAKPOINTS);
|
|
287
|
+
return breakpoints
|
|
288
|
+
.map(([bp, { min }]) => {
|
|
289
|
+
const value = values[bp];
|
|
290
|
+
if (!value)
|
|
291
|
+
return '';
|
|
292
|
+
if (bp === 'base') {
|
|
293
|
+
return `${selector} { ${property}: ${value}; }`;
|
|
294
|
+
}
|
|
295
|
+
return `@media (min-width: ${min}px) { ${selector} { ${property}: ${value}; } }`;
|
|
296
|
+
})
|
|
297
|
+
.filter(Boolean)
|
|
298
|
+
.join('\n');
|
|
299
|
+
}
|
|
300
|
+
// ============================================================================
|
|
301
|
+
// Button Styles
|
|
302
|
+
// ============================================================================
|
|
303
|
+
/** Base styles for toolbar action buttons */
|
|
304
|
+
export const ACTION_BUTTON_BASE_STYLES = {
|
|
305
|
+
display: 'flex',
|
|
306
|
+
alignItems: 'center',
|
|
307
|
+
justifyContent: 'center',
|
|
308
|
+
width: '22px',
|
|
309
|
+
height: '22px',
|
|
310
|
+
minWidth: '22px',
|
|
311
|
+
minHeight: '22px',
|
|
312
|
+
flexShrink: '0',
|
|
313
|
+
borderRadius: '50%',
|
|
314
|
+
border: '1px solid',
|
|
315
|
+
transition: 'all 150ms',
|
|
316
|
+
};
|
|
317
|
+
// ============================================================================
|
|
318
|
+
// Modal Styles
|
|
319
|
+
// ============================================================================
|
|
320
|
+
/** Common modal overlay styles */
|
|
321
|
+
export const MODAL_OVERLAY_STYLES = {
|
|
322
|
+
position: 'fixed',
|
|
323
|
+
top: '0',
|
|
324
|
+
left: '0',
|
|
325
|
+
right: '0',
|
|
326
|
+
bottom: '0',
|
|
327
|
+
backgroundColor: 'rgba(0, 0, 0, 0.7)',
|
|
328
|
+
zIndex: '10002',
|
|
329
|
+
display: 'flex',
|
|
330
|
+
alignItems: 'center',
|
|
331
|
+
justifyContent: 'center',
|
|
332
|
+
};
|
|
333
|
+
/** Common modal box styles */
|
|
334
|
+
export const MODAL_BOX_BASE_STYLES = {
|
|
335
|
+
backgroundColor: COLORS.bgElevated,
|
|
336
|
+
borderRadius: '12px',
|
|
337
|
+
width: '90%',
|
|
338
|
+
maxWidth: '700px',
|
|
339
|
+
maxHeight: '80vh',
|
|
340
|
+
display: 'flex',
|
|
341
|
+
flexDirection: 'column',
|
|
342
|
+
fontFamily: FONT_MONO,
|
|
343
|
+
};
|
|
344
|
+
// ============================================================================
|
|
345
|
+
// CSS Styles
|
|
346
|
+
// ============================================================================
|
|
347
|
+
/** Tooltip and animation CSS styles */
|
|
348
|
+
export const TOOLTIP_STYLES = `
|
|
349
|
+
.devbar-tooltip {
|
|
350
|
+
position: relative;
|
|
351
|
+
}
|
|
352
|
+
/* Invisible bridge to keep tooltip open when moving mouse to it */
|
|
353
|
+
.devbar-tooltip::before {
|
|
354
|
+
content: '';
|
|
355
|
+
position: absolute;
|
|
356
|
+
bottom: 100%;
|
|
357
|
+
left: 0;
|
|
358
|
+
right: 0;
|
|
359
|
+
height: 16px;
|
|
360
|
+
pointer-events: none;
|
|
361
|
+
}
|
|
362
|
+
.devbar-tooltip:hover::before {
|
|
363
|
+
pointer-events: auto;
|
|
364
|
+
}
|
|
365
|
+
/* Extend bridge for right-aligned tooltips (tooltip extends left) */
|
|
366
|
+
.devbar-tooltip-right::before {
|
|
367
|
+
left: -400px;
|
|
368
|
+
right: 0;
|
|
369
|
+
}
|
|
370
|
+
/* Extend bridge for left-aligned tooltips (tooltip extends right) */
|
|
371
|
+
.devbar-tooltip-left::before {
|
|
372
|
+
left: 0;
|
|
373
|
+
right: -400px;
|
|
374
|
+
}
|
|
375
|
+
.devbar-tooltip::after {
|
|
376
|
+
content: attr(data-tooltip);
|
|
377
|
+
position: absolute;
|
|
378
|
+
bottom: calc(100% + 8px);
|
|
379
|
+
left: 50%;
|
|
380
|
+
transform: translateX(-50%) scale(0.95);
|
|
381
|
+
padding: 0.625rem 1rem;
|
|
382
|
+
background: ${COLORS.bgElevated};
|
|
383
|
+
color: ${COLORS.primary};
|
|
384
|
+
font-family: ${FONT_MONO};
|
|
385
|
+
font-size: 0.75rem;
|
|
386
|
+
line-height: 1.5;
|
|
387
|
+
border-radius: 6px;
|
|
388
|
+
border: 1px solid ${COLORS.border};
|
|
389
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(16, 185, 129, 0.1);
|
|
390
|
+
backdrop-filter: blur(8px);
|
|
391
|
+
-webkit-backdrop-filter: blur(8px);
|
|
392
|
+
min-width: min(200px, calc(100vw - 32px));
|
|
393
|
+
max-width: min(400px, calc(100vw - 32px));
|
|
394
|
+
white-space: pre-wrap;
|
|
395
|
+
z-index: 10001;
|
|
396
|
+
pointer-events: none;
|
|
397
|
+
opacity: 0;
|
|
398
|
+
visibility: hidden;
|
|
399
|
+
will-change: opacity, transform;
|
|
400
|
+
transition: opacity 150ms ease-out, transform 150ms ease-out, visibility 150ms;
|
|
401
|
+
user-select: text;
|
|
402
|
+
cursor: text;
|
|
403
|
+
}
|
|
404
|
+
.devbar-tooltip:hover::after {
|
|
405
|
+
opacity: 1;
|
|
406
|
+
visibility: visible;
|
|
407
|
+
transform: translateX(-50%) scale(1);
|
|
408
|
+
pointer-events: auto;
|
|
409
|
+
}
|
|
410
|
+
.devbar-tooltip-left::after {
|
|
411
|
+
left: 8px !important;
|
|
412
|
+
right: auto !important;
|
|
413
|
+
transform: translateX(0) scale(0.95) !important;
|
|
414
|
+
}
|
|
415
|
+
.devbar-tooltip-left:hover::after {
|
|
416
|
+
transform: translateX(0) scale(1) !important;
|
|
417
|
+
}
|
|
418
|
+
.devbar-tooltip-right::after {
|
|
419
|
+
left: auto !important;
|
|
420
|
+
right: 8px !important;
|
|
421
|
+
transform: translateX(0) scale(0.95) !important;
|
|
422
|
+
}
|
|
423
|
+
.devbar-tooltip-right:hover::after {
|
|
424
|
+
transform: translateX(0) scale(1) !important;
|
|
425
|
+
}
|
|
426
|
+
.devbar-capturing .devbar-tooltip::after,
|
|
427
|
+
.devbar-capturing .devbar-tooltip:hover::after {
|
|
428
|
+
display: none !important;
|
|
429
|
+
opacity: 0 !important;
|
|
430
|
+
visibility: hidden !important;
|
|
431
|
+
}
|
|
432
|
+
.devbar-item {
|
|
433
|
+
transition: opacity 150ms ease-out, color 150ms ease-out;
|
|
434
|
+
}
|
|
435
|
+
.devbar-item:hover {
|
|
436
|
+
opacity: 1 !important;
|
|
437
|
+
color: ${COLORS.primary};
|
|
438
|
+
}
|
|
439
|
+
.devbar-clickable {
|
|
440
|
+
transition: transform 150ms ease-out, background-color 150ms ease-out, box-shadow 150ms ease-out;
|
|
441
|
+
}
|
|
442
|
+
.devbar-clickable:hover {
|
|
443
|
+
transform: scale(1.1);
|
|
444
|
+
background-color: rgba(16, 185, 129, 0.15);
|
|
445
|
+
box-shadow: 0 0 8px ${COLORS.primaryGlow};
|
|
446
|
+
}
|
|
447
|
+
.devbar-badge {
|
|
448
|
+
transition: transform 150ms ease-out, box-shadow 150ms ease-out;
|
|
449
|
+
}
|
|
450
|
+
.devbar-badge:hover {
|
|
451
|
+
transform: scale(1.1);
|
|
452
|
+
box-shadow: 0 0 8px currentColor;
|
|
453
|
+
}
|
|
454
|
+
.devbar-collapse {
|
|
455
|
+
transition: transform 150ms ease-out, background-color 150ms ease-out, box-shadow 150ms ease-out, border-color 150ms ease-out;
|
|
456
|
+
}
|
|
457
|
+
.devbar-collapse:hover {
|
|
458
|
+
transform: scale(1.08);
|
|
459
|
+
background-color: rgba(16, 185, 129, 0.15);
|
|
460
|
+
box-shadow: 0 0 12px ${COLORS.primaryGlow};
|
|
461
|
+
border-color: ${COLORS.primary};
|
|
462
|
+
}
|
|
463
|
+
@keyframes pulse {
|
|
464
|
+
0%, 100% { opacity: 1; }
|
|
465
|
+
50% { opacity: 0.5; }
|
|
466
|
+
}
|
|
467
|
+
@keyframes devbar-collapse {
|
|
468
|
+
0% { transform: scale(0.8); opacity: 0; }
|
|
469
|
+
100% { transform: scale(1); opacity: 1; }
|
|
470
|
+
}
|
|
471
|
+
/* Main row - single row by default (SM, MD, LG, XL) */
|
|
472
|
+
.devbar-main {
|
|
473
|
+
flex-wrap: nowrap;
|
|
474
|
+
}
|
|
475
|
+
/* Info section - truncates if needed to fit single row */
|
|
476
|
+
.devbar-info {
|
|
477
|
+
white-space: nowrap;
|
|
478
|
+
}
|
|
479
|
+
.devbar-info > span {
|
|
480
|
+
flex-shrink: 0;
|
|
481
|
+
}
|
|
482
|
+
/* Actions container - stays on same row by default */
|
|
483
|
+
.devbar-actions {
|
|
484
|
+
display: flex;
|
|
485
|
+
align-items: center;
|
|
486
|
+
gap: 0.5rem;
|
|
487
|
+
flex-basis: auto;
|
|
488
|
+
flex-shrink: 0;
|
|
489
|
+
}
|
|
490
|
+
/* BASE only (< 640px): fit content, centered horizontally */
|
|
491
|
+
@media (max-width: 639px) {
|
|
492
|
+
[data-devbar] {
|
|
493
|
+
width: auto !important;
|
|
494
|
+
min-width: auto !important;
|
|
495
|
+
max-width: calc(100vw - 32px) !important;
|
|
496
|
+
left: 50% !important;
|
|
497
|
+
right: auto !important;
|
|
498
|
+
transform: translateX(-50%) !important;
|
|
499
|
+
}
|
|
500
|
+
.devbar-main {
|
|
501
|
+
flex-wrap: wrap;
|
|
502
|
+
justify-content: center;
|
|
503
|
+
}
|
|
504
|
+
/* Keep status row (connection dot + info) on same line */
|
|
505
|
+
.devbar-status {
|
|
506
|
+
flex-wrap: nowrap !important;
|
|
507
|
+
justify-content: center;
|
|
508
|
+
}
|
|
509
|
+
.devbar-info {
|
|
510
|
+
justify-content: center;
|
|
511
|
+
flex-wrap: nowrap;
|
|
512
|
+
white-space: nowrap !important;
|
|
513
|
+
}
|
|
514
|
+
.devbar-actions {
|
|
515
|
+
justify-content: space-evenly;
|
|
516
|
+
margin-top: 0.25rem;
|
|
517
|
+
flex-wrap: nowrap;
|
|
518
|
+
width: 100%;
|
|
519
|
+
}
|
|
520
|
+
/* Constrain tooltips to viewport on mobile */
|
|
521
|
+
.devbar-tooltip::after {
|
|
522
|
+
left: auto !important;
|
|
523
|
+
right: 0 !important;
|
|
524
|
+
transform: translateX(0) scale(0.95) !important;
|
|
525
|
+
max-width: calc(100vw - 24px) !important;
|
|
526
|
+
}
|
|
527
|
+
.devbar-tooltip:hover::after {
|
|
528
|
+
transform: translateX(0) scale(1) !important;
|
|
529
|
+
}
|
|
530
|
+
.devbar-tooltip-left::after {
|
|
531
|
+
left: 0 !important;
|
|
532
|
+
right: auto !important;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
`;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Early Console Capture Script
|
|
3
|
+
*
|
|
4
|
+
* This script captures console logs BEFORE React hydrates, which is critical for
|
|
5
|
+
* catching hydration errors and other early-stage issues. It must be injected
|
|
6
|
+
* into the HTML <head> as an inline script.
|
|
7
|
+
*
|
|
8
|
+
* The script creates `window.__sweetlinkEarlyLogs` which GlobalDevBar will pick up
|
|
9
|
+
* when it mounts, merging these early logs with subsequent console output.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* // In your Document component (Remix) or _document.tsx (Next.js)
|
|
14
|
+
* import { EARLY_CONSOLE_CAPTURE_SCRIPT } from '@ytspar/devbar';
|
|
15
|
+
*
|
|
16
|
+
* <head>
|
|
17
|
+
* <script dangerouslySetInnerHTML={{ __html: EARLY_CONSOLE_CAPTURE_SCRIPT }} />
|
|
18
|
+
* </head>
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare const EARLY_CONSOLE_CAPTURE_SCRIPT = "\n(function() {\n if (window.__sweetlinkEarlyLogs) return;\n window.__sweetlinkEarlyLogs = [];\n var orig = {\n log: console.log,\n error: console.error,\n warn: console.warn,\n info: console.info\n };\n function formatArg(a) {\n if (a instanceof Error) {\n return a.name + ': ' + a.message + (a.stack ? '\\n' + a.stack : '');\n }\n if (typeof a === 'object' && a !== null) {\n try {\n return JSON.stringify(a, function(key, val) {\n if (val instanceof Error) {\n return val.name + ': ' + val.message;\n }\n return val;\n });\n } catch(e) {\n return String(a);\n }\n }\n return String(a);\n }\n function capture(level, args) {\n window.__sweetlinkEarlyLogs.push({\n level: level,\n message: Array.from(args).map(formatArg).join(' '),\n timestamp: new Date().toISOString()\n });\n }\n console.log = function() { capture('log', arguments); orig.log.apply(console, arguments); };\n console.error = function() { capture('error', arguments); orig.error.apply(console, arguments); };\n console.warn = function() { capture('warn', arguments); orig.warn.apply(console, arguments); };\n console.info = function() { capture('info', arguments); orig.info.apply(console, arguments); };\n // Capture uncaught errors\n window.addEventListener('error', function(e) {\n window.__sweetlinkEarlyLogs.push({\n level: 'error',\n message: 'Uncaught ' + (e.error ? formatArg(e.error) : e.message) + ' at ' + e.filename + ':' + e.lineno + ':' + e.colno,\n timestamp: new Date().toISOString()\n });\n });\n // Capture unhandled promise rejections\n window.addEventListener('unhandledrejection', function(e) {\n window.__sweetlinkEarlyLogs.push({\n level: 'error',\n message: 'Unhandled Promise Rejection: ' + formatArg(e.reason),\n timestamp: new Date().toISOString()\n });\n });\n})();\n";
|
|
22
|
+
/**
|
|
23
|
+
* Type declaration for the window object with early logs
|
|
24
|
+
* Use this to type-check access to early logs in your app
|
|
25
|
+
*/
|
|
26
|
+
declare global {
|
|
27
|
+
interface Window {
|
|
28
|
+
__sweetlinkEarlyLogs?: Array<{
|
|
29
|
+
level: string;
|
|
30
|
+
message: string;
|
|
31
|
+
timestamp: string;
|
|
32
|
+
}>;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Early Console Capture Script
|
|
3
|
+
*
|
|
4
|
+
* This script captures console logs BEFORE React hydrates, which is critical for
|
|
5
|
+
* catching hydration errors and other early-stage issues. It must be injected
|
|
6
|
+
* into the HTML <head> as an inline script.
|
|
7
|
+
*
|
|
8
|
+
* The script creates `window.__sweetlinkEarlyLogs` which GlobalDevBar will pick up
|
|
9
|
+
* when it mounts, merging these early logs with subsequent console output.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* // In your Document component (Remix) or _document.tsx (Next.js)
|
|
14
|
+
* import { EARLY_CONSOLE_CAPTURE_SCRIPT } from '@ytspar/devbar';
|
|
15
|
+
*
|
|
16
|
+
* <head>
|
|
17
|
+
* <script dangerouslySetInnerHTML={{ __html: EARLY_CONSOLE_CAPTURE_SCRIPT }} />
|
|
18
|
+
* </head>
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export const EARLY_CONSOLE_CAPTURE_SCRIPT = `
|
|
22
|
+
(function() {
|
|
23
|
+
if (window.__sweetlinkEarlyLogs) return;
|
|
24
|
+
window.__sweetlinkEarlyLogs = [];
|
|
25
|
+
var orig = {
|
|
26
|
+
log: console.log,
|
|
27
|
+
error: console.error,
|
|
28
|
+
warn: console.warn,
|
|
29
|
+
info: console.info
|
|
30
|
+
};
|
|
31
|
+
function formatArg(a) {
|
|
32
|
+
if (a instanceof Error) {
|
|
33
|
+
return a.name + ': ' + a.message + (a.stack ? '\\n' + a.stack : '');
|
|
34
|
+
}
|
|
35
|
+
if (typeof a === 'object' && a !== null) {
|
|
36
|
+
try {
|
|
37
|
+
return JSON.stringify(a, function(key, val) {
|
|
38
|
+
if (val instanceof Error) {
|
|
39
|
+
return val.name + ': ' + val.message;
|
|
40
|
+
}
|
|
41
|
+
return val;
|
|
42
|
+
});
|
|
43
|
+
} catch(e) {
|
|
44
|
+
return String(a);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return String(a);
|
|
48
|
+
}
|
|
49
|
+
function capture(level, args) {
|
|
50
|
+
window.__sweetlinkEarlyLogs.push({
|
|
51
|
+
level: level,
|
|
52
|
+
message: Array.from(args).map(formatArg).join(' '),
|
|
53
|
+
timestamp: new Date().toISOString()
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
console.log = function() { capture('log', arguments); orig.log.apply(console, arguments); };
|
|
57
|
+
console.error = function() { capture('error', arguments); orig.error.apply(console, arguments); };
|
|
58
|
+
console.warn = function() { capture('warn', arguments); orig.warn.apply(console, arguments); };
|
|
59
|
+
console.info = function() { capture('info', arguments); orig.info.apply(console, arguments); };
|
|
60
|
+
// Capture uncaught errors
|
|
61
|
+
window.addEventListener('error', function(e) {
|
|
62
|
+
window.__sweetlinkEarlyLogs.push({
|
|
63
|
+
level: 'error',
|
|
64
|
+
message: 'Uncaught ' + (e.error ? formatArg(e.error) : e.message) + ' at ' + e.filename + ':' + e.lineno + ':' + e.colno,
|
|
65
|
+
timestamp: new Date().toISOString()
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
// Capture unhandled promise rejections
|
|
69
|
+
window.addEventListener('unhandledrejection', function(e) {
|
|
70
|
+
window.__sweetlinkEarlyLogs.push({
|
|
71
|
+
level: 'error',
|
|
72
|
+
message: 'Unhandled Promise Rejection: ' + formatArg(e.reason),
|
|
73
|
+
timestamp: new Date().toISOString()
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
})();
|
|
77
|
+
`;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { GlobalDevBar, initGlobalDevBar, getGlobalDevBar, destroyGlobalDevBar, earlyConsoleCapture, } from './GlobalDevBar.js';
|
|
2
|
+
export type { GlobalDevBarOptions, DevBarControl, ConsoleLog, SweetlinkCommand, OutlineNode, PageSchema, } from './types.js';
|
|
3
|
+
export { formatArg, formatArgs, canvasToDataUrl, prepareForCapture, delay, copyCanvasToClipboard, } from './utils.js';
|
|
4
|
+
export { extractDocumentOutline, outlineToMarkdown } from './outline.js';
|
|
5
|
+
export { extractPageSchema, schemaToMarkdown } from './schema.js';
|
|
6
|
+
export { TAILWIND_BREAKPOINTS, BUTTON_COLORS, CATEGORY_COLORS, DEVBAR_THEME, COLORS, FONT_MONO, generateThemeCSSVars, injectThemeCSS, generateBreakpointCSS, type TailwindBreakpoint, type DevBarTheme, type DevBarThemeInput, } from './constants.js';
|
|
7
|
+
export { EARLY_CONSOLE_CAPTURE_SCRIPT } from './earlyConsoleCapture.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// DevBar - Development toolbar and utilities
|
|
2
|
+
// Pure vanilla JavaScript - no framework dependencies
|
|
3
|
+
// Main vanilla JS devbar
|
|
4
|
+
export { GlobalDevBar, initGlobalDevBar, getGlobalDevBar, destroyGlobalDevBar, earlyConsoleCapture, } from './GlobalDevBar.js';
|
|
5
|
+
// Re-export utilities for external use
|
|
6
|
+
export { formatArg, formatArgs, canvasToDataUrl, prepareForCapture, delay, copyCanvasToClipboard, } from './utils.js';
|
|
7
|
+
// Re-export outline/schema functions
|
|
8
|
+
export { extractDocumentOutline, outlineToMarkdown } from './outline.js';
|
|
9
|
+
export { extractPageSchema, schemaToMarkdown } from './schema.js';
|
|
10
|
+
// Re-export constants and theme utilities
|
|
11
|
+
export { TAILWIND_BREAKPOINTS, BUTTON_COLORS, CATEGORY_COLORS, DEVBAR_THEME, COLORS, FONT_MONO, generateThemeCSSVars, injectThemeCSS, generateBreakpointCSS, } from './constants.js';
|
|
12
|
+
// Early console capture script for injection
|
|
13
|
+
export { EARLY_CONSOLE_CAPTURE_SCRIPT } from './earlyConsoleCapture.js';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Document Outline Extraction
|
|
3
|
+
*
|
|
4
|
+
* Functions for extracting and formatting the semantic document outline.
|
|
5
|
+
*/
|
|
6
|
+
import type { OutlineNode } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Extract the document outline from the page
|
|
9
|
+
*/
|
|
10
|
+
export declare function extractDocumentOutline(): OutlineNode[];
|
|
11
|
+
/**
|
|
12
|
+
* Convert an outline to markdown format
|
|
13
|
+
*/
|
|
14
|
+
export declare function outlineToMarkdown(outline: OutlineNode[], indent?: number): string;
|