@sc4rfurryx/proteusjs 1.0.0
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/API.md +438 -0
- package/FEATURES.md +286 -0
- package/LICENSE +21 -0
- package/README.md +645 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/proteus.cjs.js +16014 -0
- package/dist/proteus.cjs.js.map +1 -0
- package/dist/proteus.d.ts +3018 -0
- package/dist/proteus.esm.js +16005 -0
- package/dist/proteus.esm.js.map +1 -0
- package/dist/proteus.esm.min.js +8 -0
- package/dist/proteus.esm.min.js.map +1 -0
- package/dist/proteus.js +16020 -0
- package/dist/proteus.js.map +1 -0
- package/dist/proteus.min.js +8 -0
- package/dist/proteus.min.js.map +1 -0
- package/package.json +98 -0
- package/src/__tests__/mvp-integration.test.ts +518 -0
- package/src/accessibility/AccessibilityEngine.ts +2106 -0
- package/src/accessibility/ScreenReaderSupport.ts +444 -0
- package/src/accessibility/__tests__/ScreenReaderSupport.test.ts +435 -0
- package/src/animations/FLIPAnimationSystem.ts +491 -0
- package/src/compatibility/BrowserCompatibility.ts +1076 -0
- package/src/containers/BreakpointSystem.ts +347 -0
- package/src/containers/ContainerBreakpoints.ts +726 -0
- package/src/containers/ContainerManager.ts +370 -0
- package/src/containers/ContainerUnits.ts +336 -0
- package/src/containers/ContextIsolation.ts +394 -0
- package/src/containers/ElementQueries.ts +411 -0
- package/src/containers/SmartContainer.ts +536 -0
- package/src/containers/SmartContainers.ts +376 -0
- package/src/containers/__tests__/ContainerBreakpoints.test.ts +411 -0
- package/src/containers/__tests__/SmartContainers.test.ts +281 -0
- package/src/content/ResponsiveImages.ts +570 -0
- package/src/core/EventSystem.ts +147 -0
- package/src/core/MemoryManager.ts +321 -0
- package/src/core/PerformanceMonitor.ts +238 -0
- package/src/core/PluginSystem.ts +275 -0
- package/src/core/ProteusJS.test.ts +164 -0
- package/src/core/ProteusJS.ts +962 -0
- package/src/developer/PerformanceProfiler.ts +567 -0
- package/src/developer/VisualDebuggingTools.ts +656 -0
- package/src/developer/ZeroConfigSystem.ts +593 -0
- package/src/index.ts +35 -0
- package/src/integration.test.ts +227 -0
- package/src/layout/AdaptiveGrid.ts +429 -0
- package/src/layout/ContentReordering.ts +532 -0
- package/src/layout/FlexboxEnhancer.ts +406 -0
- package/src/layout/FlowLayout.ts +545 -0
- package/src/layout/SpacingSystem.ts +512 -0
- package/src/observers/IntersectionObserverPolyfill.ts +289 -0
- package/src/observers/ObserverManager.ts +299 -0
- package/src/observers/ResizeObserverPolyfill.ts +179 -0
- package/src/performance/BatchDOMOperations.ts +519 -0
- package/src/performance/CSSOptimizationEngine.ts +646 -0
- package/src/performance/CacheOptimizationSystem.ts +601 -0
- package/src/performance/EfficientEventHandler.ts +740 -0
- package/src/performance/LazyEvaluationSystem.ts +532 -0
- package/src/performance/MemoryManagementSystem.ts +497 -0
- package/src/performance/PerformanceMonitor.ts +931 -0
- package/src/performance/__tests__/BatchDOMOperations.test.ts +309 -0
- package/src/performance/__tests__/EfficientEventHandler.test.ts +268 -0
- package/src/performance/__tests__/PerformanceMonitor.test.ts +422 -0
- package/src/polyfills/BrowserPolyfills.ts +586 -0
- package/src/polyfills/__tests__/BrowserPolyfills.test.ts +328 -0
- package/src/test/setup.ts +115 -0
- package/src/theming/SmartThemeSystem.ts +591 -0
- package/src/types/index.ts +134 -0
- package/src/typography/ClampScaling.ts +356 -0
- package/src/typography/FluidTypography.ts +759 -0
- package/src/typography/LineHeightOptimization.ts +430 -0
- package/src/typography/LineHeightOptimizer.ts +326 -0
- package/src/typography/TextFitting.ts +355 -0
- package/src/typography/TypographicScale.ts +428 -0
- package/src/typography/VerticalRhythm.ts +369 -0
- package/src/typography/__tests__/FluidTypography.test.ts +432 -0
- package/src/typography/__tests__/LineHeightOptimization.test.ts +436 -0
- package/src/utils/Logger.ts +173 -0
- package/src/utils/debounce.ts +259 -0
- package/src/utils/performance.ts +371 -0
- package/src/utils/support.ts +106 -0
- package/src/utils/version.ts +24 -0
@@ -0,0 +1,656 @@
|
|
1
|
+
/**
|
2
|
+
* Visual Debugging Tools for ProteusJS
|
3
|
+
* Comprehensive debugging overlays with container visualization and performance metrics
|
4
|
+
*/
|
5
|
+
|
6
|
+
export interface DebugConfig {
|
7
|
+
showContainerBoundaries: boolean;
|
8
|
+
showBreakpointIndicators: boolean;
|
9
|
+
showTypographyScale: boolean;
|
10
|
+
showPerformanceMetrics: boolean;
|
11
|
+
showAccessibilityInfo: boolean;
|
12
|
+
showLayoutGrid: boolean;
|
13
|
+
overlayOpacity: number;
|
14
|
+
position: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
15
|
+
}
|
16
|
+
|
17
|
+
export interface DebugInfo {
|
18
|
+
containers: ContainerDebugInfo[];
|
19
|
+
performance: PerformanceDebugInfo;
|
20
|
+
accessibility: AccessibilityDebugInfo;
|
21
|
+
typography: TypographyDebugInfo;
|
22
|
+
}
|
23
|
+
|
24
|
+
export interface ContainerDebugInfo {
|
25
|
+
element: Element;
|
26
|
+
type: string;
|
27
|
+
dimensions: { width: number; height: number };
|
28
|
+
breakpoint: string;
|
29
|
+
queries: string[];
|
30
|
+
}
|
31
|
+
|
32
|
+
export interface PerformanceDebugInfo {
|
33
|
+
fps: number;
|
34
|
+
frameTime: number;
|
35
|
+
memoryUsage: number;
|
36
|
+
activeObservers: number;
|
37
|
+
queueSize: number;
|
38
|
+
}
|
39
|
+
|
40
|
+
export interface AccessibilityDebugInfo {
|
41
|
+
wcagLevel: string;
|
42
|
+
issues: string[];
|
43
|
+
score: number;
|
44
|
+
screenReaderCompatible: boolean;
|
45
|
+
}
|
46
|
+
|
47
|
+
export interface TypographyDebugInfo {
|
48
|
+
scale: string;
|
49
|
+
baseSize: number;
|
50
|
+
lineHeight: number;
|
51
|
+
rhythm: number;
|
52
|
+
}
|
53
|
+
|
54
|
+
export class VisualDebuggingTools {
|
55
|
+
private config: Required<DebugConfig>;
|
56
|
+
private overlay: HTMLElement | null = null;
|
57
|
+
private isActive: boolean = false;
|
58
|
+
private updateInterval: number | null = null;
|
59
|
+
private debugInfo: DebugInfo;
|
60
|
+
|
61
|
+
constructor(config: Partial<DebugConfig> = {}) {
|
62
|
+
this.config = {
|
63
|
+
showContainerBoundaries: true,
|
64
|
+
showBreakpointIndicators: true,
|
65
|
+
showTypographyScale: true,
|
66
|
+
showPerformanceMetrics: true,
|
67
|
+
showAccessibilityInfo: true,
|
68
|
+
showLayoutGrid: false,
|
69
|
+
overlayOpacity: 0.8,
|
70
|
+
position: 'top-right',
|
71
|
+
...config
|
72
|
+
};
|
73
|
+
|
74
|
+
this.debugInfo = this.createInitialDebugInfo();
|
75
|
+
this.setupKeyboardShortcuts();
|
76
|
+
}
|
77
|
+
|
78
|
+
/**
|
79
|
+
* Activate debugging tools
|
80
|
+
*/
|
81
|
+
public activate(): void {
|
82
|
+
if (this.isActive) return;
|
83
|
+
|
84
|
+
this.isActive = true;
|
85
|
+
this.createOverlay();
|
86
|
+
this.startUpdating();
|
87
|
+
this.highlightContainers();
|
88
|
+
this.showLayoutGrid();
|
89
|
+
|
90
|
+
console.log('🔍 ProteusJS Visual Debugging Tools Activated');
|
91
|
+
}
|
92
|
+
|
93
|
+
/**
|
94
|
+
* Deactivate debugging tools
|
95
|
+
*/
|
96
|
+
public deactivate(): void {
|
97
|
+
if (!this.isActive) return;
|
98
|
+
|
99
|
+
this.isActive = false;
|
100
|
+
this.removeOverlay();
|
101
|
+
this.stopUpdating();
|
102
|
+
this.removeHighlights();
|
103
|
+
this.hideLayoutGrid();
|
104
|
+
|
105
|
+
console.log('🔍 ProteusJS Visual Debugging Tools Deactivated');
|
106
|
+
}
|
107
|
+
|
108
|
+
/**
|
109
|
+
* Toggle debugging tools
|
110
|
+
*/
|
111
|
+
public toggle(): void {
|
112
|
+
if (this.isActive) {
|
113
|
+
this.deactivate();
|
114
|
+
} else {
|
115
|
+
this.activate();
|
116
|
+
}
|
117
|
+
}
|
118
|
+
|
119
|
+
/**
|
120
|
+
* Update debug information
|
121
|
+
*/
|
122
|
+
public updateDebugInfo(info: Partial<DebugInfo>): void {
|
123
|
+
this.debugInfo = { ...this.debugInfo, ...info };
|
124
|
+
if (this.isActive) {
|
125
|
+
this.updateOverlay();
|
126
|
+
}
|
127
|
+
}
|
128
|
+
|
129
|
+
/**
|
130
|
+
* Highlight specific container
|
131
|
+
*/
|
132
|
+
public highlightContainer(element: Element, color: string = '#ff6b6b'): void {
|
133
|
+
const highlight = document.createElement('div');
|
134
|
+
highlight.className = 'proteus-debug-highlight';
|
135
|
+
highlight.style.cssText = `
|
136
|
+
position: absolute;
|
137
|
+
pointer-events: none;
|
138
|
+
border: 2px solid ${color};
|
139
|
+
background: ${color}20;
|
140
|
+
z-index: 10000;
|
141
|
+
transition: all 0.3s ease;
|
142
|
+
`;
|
143
|
+
|
144
|
+
const rect = element.getBoundingClientRect();
|
145
|
+
highlight.style.left = `${rect.left + window.scrollX}px`;
|
146
|
+
highlight.style.top = `${rect.top + window.scrollY}px`;
|
147
|
+
highlight.style.width = `${rect.width}px`;
|
148
|
+
highlight.style.height = `${rect.height}px`;
|
149
|
+
|
150
|
+
document.body.appendChild(highlight);
|
151
|
+
|
152
|
+
// Auto-remove after 3 seconds
|
153
|
+
setTimeout(() => {
|
154
|
+
if (highlight.parentNode) {
|
155
|
+
highlight.parentNode.removeChild(highlight);
|
156
|
+
}
|
157
|
+
}, 3000);
|
158
|
+
}
|
159
|
+
|
160
|
+
/**
|
161
|
+
* Show performance bottlenecks
|
162
|
+
*/
|
163
|
+
public showBottlenecks(): void {
|
164
|
+
const bottlenecks = this.detectBottlenecks();
|
165
|
+
|
166
|
+
bottlenecks.forEach(bottleneck => {
|
167
|
+
this.highlightContainer(bottleneck.element, '#e53e3e');
|
168
|
+
|
169
|
+
// Show bottleneck info
|
170
|
+
const info = document.createElement('div');
|
171
|
+
info.className = 'proteus-debug-bottleneck-info';
|
172
|
+
info.style.cssText = `
|
173
|
+
position: absolute;
|
174
|
+
background: #e53e3e;
|
175
|
+
color: white;
|
176
|
+
padding: 8px;
|
177
|
+
border-radius: 4px;
|
178
|
+
font-size: 12px;
|
179
|
+
z-index: 10001;
|
180
|
+
pointer-events: none;
|
181
|
+
`;
|
182
|
+
info.textContent = bottleneck.issue;
|
183
|
+
|
184
|
+
const rect = bottleneck.element.getBoundingClientRect();
|
185
|
+
info.style.left = `${rect.left + window.scrollX}px`;
|
186
|
+
info.style.top = `${rect.top + window.scrollY - 30}px`;
|
187
|
+
|
188
|
+
document.body.appendChild(info);
|
189
|
+
|
190
|
+
setTimeout(() => {
|
191
|
+
if (info.parentNode) {
|
192
|
+
info.parentNode.removeChild(info);
|
193
|
+
}
|
194
|
+
}, 5000);
|
195
|
+
});
|
196
|
+
}
|
197
|
+
|
198
|
+
/**
|
199
|
+
* Export debug report
|
200
|
+
*/
|
201
|
+
public exportReport(): string {
|
202
|
+
const report = {
|
203
|
+
timestamp: new Date().toISOString(),
|
204
|
+
url: window.location.href,
|
205
|
+
userAgent: navigator.userAgent,
|
206
|
+
viewport: {
|
207
|
+
width: window.innerWidth,
|
208
|
+
height: window.innerHeight
|
209
|
+
},
|
210
|
+
debugInfo: this.debugInfo,
|
211
|
+
performance: this.getDetailedPerformanceInfo(),
|
212
|
+
accessibility: this.getDetailedAccessibilityInfo()
|
213
|
+
};
|
214
|
+
|
215
|
+
return JSON.stringify(report, null, 2);
|
216
|
+
}
|
217
|
+
|
218
|
+
/**
|
219
|
+
* Create debugging overlay
|
220
|
+
*/
|
221
|
+
private createOverlay(): void {
|
222
|
+
this.overlay = document.createElement('div');
|
223
|
+
this.overlay.className = 'proteus-debug-overlay';
|
224
|
+
this.overlay.style.cssText = this.getOverlayStyles();
|
225
|
+
|
226
|
+
this.updateOverlay();
|
227
|
+
document.body.appendChild(this.overlay);
|
228
|
+
}
|
229
|
+
|
230
|
+
/**
|
231
|
+
* Remove debugging overlay
|
232
|
+
*/
|
233
|
+
private removeOverlay(): void {
|
234
|
+
if (this.overlay && this.overlay.parentNode) {
|
235
|
+
this.overlay.parentNode.removeChild(this.overlay);
|
236
|
+
this.overlay = null;
|
237
|
+
}
|
238
|
+
}
|
239
|
+
|
240
|
+
/**
|
241
|
+
* Update overlay content
|
242
|
+
*/
|
243
|
+
private updateOverlay(): void {
|
244
|
+
if (!this.overlay) return;
|
245
|
+
|
246
|
+
this.overlay.innerHTML = `
|
247
|
+
<div class="proteus-debug-header">
|
248
|
+
<h3>🔍 ProteusJS Debug</h3>
|
249
|
+
<button onclick="this.parentElement.parentElement.style.display='none'">×</button>
|
250
|
+
</div>
|
251
|
+
|
252
|
+
${this.config.showPerformanceMetrics ? this.renderPerformanceSection() : ''}
|
253
|
+
${this.config.showContainerBoundaries ? this.renderContainerSection() : ''}
|
254
|
+
${this.config.showTypographyScale ? this.renderTypographySection() : ''}
|
255
|
+
${this.config.showAccessibilityInfo ? this.renderAccessibilitySection() : ''}
|
256
|
+
|
257
|
+
<div class="proteus-debug-actions">
|
258
|
+
<button onclick="proteusDebugTools.showBottlenecks()">Find Bottlenecks</button>
|
259
|
+
<button onclick="proteusDebugTools.exportReport()">Export Report</button>
|
260
|
+
</div>
|
261
|
+
`;
|
262
|
+
}
|
263
|
+
|
264
|
+
/**
|
265
|
+
* Render performance section
|
266
|
+
*/
|
267
|
+
private renderPerformanceSection(): string {
|
268
|
+
const perf = this.debugInfo.performance;
|
269
|
+
return `
|
270
|
+
<div class="proteus-debug-section">
|
271
|
+
<h4>⚡ Performance</h4>
|
272
|
+
<div class="proteus-debug-metrics">
|
273
|
+
<div class="metric">
|
274
|
+
<span class="label">FPS:</span>
|
275
|
+
<span class="value ${perf.fps < 50 ? 'warning' : ''}">${perf.fps}</span>
|
276
|
+
</div>
|
277
|
+
<div class="metric">
|
278
|
+
<span class="label">Frame Time:</span>
|
279
|
+
<span class="value ${perf.frameTime > 20 ? 'warning' : ''}">${perf.frameTime.toFixed(2)}ms</span>
|
280
|
+
</div>
|
281
|
+
<div class="metric">
|
282
|
+
<span class="label">Memory:</span>
|
283
|
+
<span class="value">${(perf.memoryUsage / 1024 / 1024).toFixed(1)}MB</span>
|
284
|
+
</div>
|
285
|
+
<div class="metric">
|
286
|
+
<span class="label">Observers:</span>
|
287
|
+
<span class="value">${perf.activeObservers}</span>
|
288
|
+
</div>
|
289
|
+
</div>
|
290
|
+
</div>
|
291
|
+
`;
|
292
|
+
}
|
293
|
+
|
294
|
+
/**
|
295
|
+
* Render container section
|
296
|
+
*/
|
297
|
+
private renderContainerSection(): string {
|
298
|
+
const containers = this.debugInfo.containers;
|
299
|
+
return `
|
300
|
+
<div class="proteus-debug-section">
|
301
|
+
<h4>📦 Containers (${containers.length})</h4>
|
302
|
+
<div class="proteus-debug-containers">
|
303
|
+
${containers.map(container => `
|
304
|
+
<div class="container-item">
|
305
|
+
<span class="container-type">${container.type}</span>
|
306
|
+
<span class="container-size">${container.dimensions.width}×${container.dimensions.height}</span>
|
307
|
+
<span class="container-breakpoint">${container.breakpoint}</span>
|
308
|
+
</div>
|
309
|
+
`).join('')}
|
310
|
+
</div>
|
311
|
+
</div>
|
312
|
+
`;
|
313
|
+
}
|
314
|
+
|
315
|
+
/**
|
316
|
+
* Render typography section
|
317
|
+
*/
|
318
|
+
private renderTypographySection(): string {
|
319
|
+
const typo = this.debugInfo.typography;
|
320
|
+
return `
|
321
|
+
<div class="proteus-debug-section">
|
322
|
+
<h4>📝 Typography</h4>
|
323
|
+
<div class="proteus-debug-typography">
|
324
|
+
<div class="typo-item">Scale: ${typo.scale}</div>
|
325
|
+
<div class="typo-item">Base: ${typo.baseSize}px</div>
|
326
|
+
<div class="typo-item">Line Height: ${typo.lineHeight}</div>
|
327
|
+
<div class="typo-item">Rhythm: ${typo.rhythm}px</div>
|
328
|
+
</div>
|
329
|
+
</div>
|
330
|
+
`;
|
331
|
+
}
|
332
|
+
|
333
|
+
/**
|
334
|
+
* Render accessibility section
|
335
|
+
*/
|
336
|
+
private renderAccessibilitySection(): string {
|
337
|
+
const a11y = this.debugInfo.accessibility;
|
338
|
+
return `
|
339
|
+
<div class="proteus-debug-section">
|
340
|
+
<h4>♿ Accessibility</h4>
|
341
|
+
<div class="proteus-debug-accessibility">
|
342
|
+
<div class="a11y-score ${a11y.score < 80 ? 'warning' : ''}">
|
343
|
+
Score: ${a11y.score}/100
|
344
|
+
</div>
|
345
|
+
<div class="a11y-level">WCAG: ${a11y.wcagLevel}</div>
|
346
|
+
<div class="a11y-issues">
|
347
|
+
Issues: ${a11y.issues.length}
|
348
|
+
${a11y.issues.length > 0 ? `
|
349
|
+
<ul>
|
350
|
+
${a11y.issues.slice(0, 3).map(issue => `<li>${issue}</li>`).join('')}
|
351
|
+
</ul>
|
352
|
+
` : ''}
|
353
|
+
</div>
|
354
|
+
</div>
|
355
|
+
</div>
|
356
|
+
`;
|
357
|
+
}
|
358
|
+
|
359
|
+
/**
|
360
|
+
* Highlight all containers
|
361
|
+
*/
|
362
|
+
private highlightContainers(): void {
|
363
|
+
if (!this.config.showContainerBoundaries) return;
|
364
|
+
|
365
|
+
this.debugInfo.containers.forEach(container => {
|
366
|
+
const highlight = document.createElement('div');
|
367
|
+
highlight.className = 'proteus-debug-container-highlight';
|
368
|
+
highlight.style.cssText = `
|
369
|
+
position: absolute;
|
370
|
+
pointer-events: none;
|
371
|
+
border: 1px dashed #667eea;
|
372
|
+
background: rgba(102, 126, 234, 0.1);
|
373
|
+
z-index: 9999;
|
374
|
+
`;
|
375
|
+
|
376
|
+
const rect = container.element.getBoundingClientRect();
|
377
|
+
highlight.style.left = `${rect.left + window.scrollX}px`;
|
378
|
+
highlight.style.top = `${rect.top + window.scrollY}px`;
|
379
|
+
highlight.style.width = `${rect.width}px`;
|
380
|
+
highlight.style.height = `${rect.height}px`;
|
381
|
+
|
382
|
+
// Add breakpoint indicator
|
383
|
+
if (this.config.showBreakpointIndicators) {
|
384
|
+
const indicator = document.createElement('div');
|
385
|
+
indicator.style.cssText = `
|
386
|
+
position: absolute;
|
387
|
+
top: 2px;
|
388
|
+
left: 2px;
|
389
|
+
background: #667eea;
|
390
|
+
color: white;
|
391
|
+
padding: 2px 6px;
|
392
|
+
font-size: 10px;
|
393
|
+
border-radius: 2px;
|
394
|
+
`;
|
395
|
+
indicator.textContent = container.breakpoint;
|
396
|
+
highlight.appendChild(indicator);
|
397
|
+
}
|
398
|
+
|
399
|
+
document.body.appendChild(highlight);
|
400
|
+
});
|
401
|
+
}
|
402
|
+
|
403
|
+
/**
|
404
|
+
* Remove container highlights
|
405
|
+
*/
|
406
|
+
private removeHighlights(): void {
|
407
|
+
const highlights = document.querySelectorAll('.proteus-debug-container-highlight, .proteus-debug-highlight');
|
408
|
+
highlights.forEach(highlight => {
|
409
|
+
if (highlight.parentNode) {
|
410
|
+
highlight.parentNode.removeChild(highlight);
|
411
|
+
}
|
412
|
+
});
|
413
|
+
}
|
414
|
+
|
415
|
+
/**
|
416
|
+
* Show layout grid
|
417
|
+
*/
|
418
|
+
private showLayoutGrid(): void {
|
419
|
+
if (!this.config.showLayoutGrid) return;
|
420
|
+
|
421
|
+
const grid = document.createElement('div');
|
422
|
+
grid.className = 'proteus-debug-grid';
|
423
|
+
grid.style.cssText = `
|
424
|
+
position: fixed;
|
425
|
+
top: 0;
|
426
|
+
left: 0;
|
427
|
+
width: 100vw;
|
428
|
+
height: 100vh;
|
429
|
+
pointer-events: none;
|
430
|
+
z-index: 9998;
|
431
|
+
background-image:
|
432
|
+
linear-gradient(rgba(102, 126, 234, 0.1) 1px, transparent 1px),
|
433
|
+
linear-gradient(90deg, rgba(102, 126, 234, 0.1) 1px, transparent 1px);
|
434
|
+
background-size: 20px 20px;
|
435
|
+
`;
|
436
|
+
|
437
|
+
document.body.appendChild(grid);
|
438
|
+
}
|
439
|
+
|
440
|
+
/**
|
441
|
+
* Hide layout grid
|
442
|
+
*/
|
443
|
+
private hideLayoutGrid(): void {
|
444
|
+
const grid = document.querySelector('.proteus-debug-grid');
|
445
|
+
if (grid && grid.parentNode) {
|
446
|
+
grid.parentNode.removeChild(grid);
|
447
|
+
}
|
448
|
+
}
|
449
|
+
|
450
|
+
/**
|
451
|
+
* Start updating debug info
|
452
|
+
*/
|
453
|
+
private startUpdating(): void {
|
454
|
+
this.updateInterval = window.setInterval(() => {
|
455
|
+
this.updateDebugInfo({
|
456
|
+
performance: this.getCurrentPerformanceInfo(),
|
457
|
+
containers: this.getCurrentContainerInfo()
|
458
|
+
});
|
459
|
+
}, 1000);
|
460
|
+
}
|
461
|
+
|
462
|
+
/**
|
463
|
+
* Stop updating debug info
|
464
|
+
*/
|
465
|
+
private stopUpdating(): void {
|
466
|
+
if (this.updateInterval) {
|
467
|
+
clearInterval(this.updateInterval);
|
468
|
+
this.updateInterval = null;
|
469
|
+
}
|
470
|
+
}
|
471
|
+
|
472
|
+
/**
|
473
|
+
* Setup keyboard shortcuts
|
474
|
+
*/
|
475
|
+
private setupKeyboardShortcuts(): void {
|
476
|
+
document.addEventListener('keydown', (e) => {
|
477
|
+
// Ctrl/Cmd + Shift + D to toggle debug tools
|
478
|
+
if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === 'D') {
|
479
|
+
e.preventDefault();
|
480
|
+
this.toggle();
|
481
|
+
}
|
482
|
+
});
|
483
|
+
}
|
484
|
+
|
485
|
+
/**
|
486
|
+
* Get overlay styles
|
487
|
+
*/
|
488
|
+
private getOverlayStyles(): string {
|
489
|
+
const positions = {
|
490
|
+
'top-left': 'top: 20px; left: 20px;',
|
491
|
+
'top-right': 'top: 20px; right: 20px;',
|
492
|
+
'bottom-left': 'bottom: 20px; left: 20px;',
|
493
|
+
'bottom-right': 'bottom: 20px; right: 20px;'
|
494
|
+
};
|
495
|
+
|
496
|
+
return `
|
497
|
+
position: fixed;
|
498
|
+
${positions[this.config.position]}
|
499
|
+
width: 300px;
|
500
|
+
max-height: 80vh;
|
501
|
+
background: rgba(0, 0, 0, ${this.config.overlayOpacity});
|
502
|
+
color: white;
|
503
|
+
font-family: monospace;
|
504
|
+
font-size: 12px;
|
505
|
+
border-radius: 8px;
|
506
|
+
padding: 15px;
|
507
|
+
z-index: 10000;
|
508
|
+
overflow-y: auto;
|
509
|
+
backdrop-filter: blur(10px);
|
510
|
+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
|
511
|
+
`;
|
512
|
+
}
|
513
|
+
|
514
|
+
/**
|
515
|
+
* Detect performance bottlenecks
|
516
|
+
*/
|
517
|
+
private detectBottlenecks(): Array<{ element: Element; issue: string }> {
|
518
|
+
const bottlenecks: Array<{ element: Element; issue: string }> = [];
|
519
|
+
|
520
|
+
// Check for elements with excessive reflows
|
521
|
+
const elements = document.querySelectorAll('*');
|
522
|
+
elements.forEach(element => {
|
523
|
+
const styles = window.getComputedStyle(element);
|
524
|
+
|
525
|
+
// Check for layout-triggering properties
|
526
|
+
if (styles.position === 'fixed' && styles.transform !== 'none') {
|
527
|
+
bottlenecks.push({
|
528
|
+
element,
|
529
|
+
issue: 'Fixed position with transform may cause performance issues'
|
530
|
+
});
|
531
|
+
}
|
532
|
+
|
533
|
+
// Check for large elements without will-change
|
534
|
+
const rect = element.getBoundingClientRect();
|
535
|
+
if (rect.width > 1000 && rect.height > 1000 && styles.willChange === 'auto') {
|
536
|
+
bottlenecks.push({
|
537
|
+
element,
|
538
|
+
issue: 'Large element without will-change optimization'
|
539
|
+
});
|
540
|
+
}
|
541
|
+
});
|
542
|
+
|
543
|
+
return bottlenecks;
|
544
|
+
}
|
545
|
+
|
546
|
+
/**
|
547
|
+
* Get current performance info
|
548
|
+
*/
|
549
|
+
private getCurrentPerformanceInfo(): PerformanceDebugInfo {
|
550
|
+
return {
|
551
|
+
fps: 60, // Would be calculated from actual frame timing
|
552
|
+
frameTime: 16.67,
|
553
|
+
memoryUsage: (performance as any).memory?.usedJSHeapSize || 0,
|
554
|
+
activeObservers: document.querySelectorAll('[data-proteus-observer]').length,
|
555
|
+
queueSize: 0
|
556
|
+
};
|
557
|
+
}
|
558
|
+
|
559
|
+
/**
|
560
|
+
* Get current container info
|
561
|
+
*/
|
562
|
+
private getCurrentContainerInfo(): ContainerDebugInfo[] {
|
563
|
+
const containers: ContainerDebugInfo[] = [];
|
564
|
+
|
565
|
+
document.querySelectorAll('[data-proteus-container]').forEach(element => {
|
566
|
+
const rect = element.getBoundingClientRect();
|
567
|
+
containers.push({
|
568
|
+
element,
|
569
|
+
type: element.getAttribute('data-proteus-type') || 'unknown',
|
570
|
+
dimensions: { width: rect.width, height: rect.height },
|
571
|
+
breakpoint: element.getAttribute('data-proteus-breakpoint') || 'none',
|
572
|
+
queries: (element.getAttribute('data-proteus-queries') || '').split(',')
|
573
|
+
});
|
574
|
+
});
|
575
|
+
|
576
|
+
return containers;
|
577
|
+
}
|
578
|
+
|
579
|
+
/**
|
580
|
+
* Get detailed performance info
|
581
|
+
*/
|
582
|
+
private getDetailedPerformanceInfo(): any {
|
583
|
+
return {
|
584
|
+
timing: performance.timing,
|
585
|
+
navigation: performance.navigation,
|
586
|
+
memory: (performance as any).memory,
|
587
|
+
entries: performance.getEntries().slice(-10)
|
588
|
+
};
|
589
|
+
}
|
590
|
+
|
591
|
+
/**
|
592
|
+
* Get detailed accessibility info
|
593
|
+
*/
|
594
|
+
private getDetailedAccessibilityInfo(): any {
|
595
|
+
const issues: string[] = [];
|
596
|
+
|
597
|
+
// Check for missing alt text
|
598
|
+
const images = document.querySelectorAll('img:not([alt])');
|
599
|
+
if (images.length > 0) {
|
600
|
+
issues.push(`${images.length} images missing alt text`);
|
601
|
+
}
|
602
|
+
|
603
|
+
// Check for missing form labels
|
604
|
+
const inputs = document.querySelectorAll('input:not([aria-label]):not([aria-labelledby])');
|
605
|
+
if (inputs.length > 0) {
|
606
|
+
issues.push(`${inputs.length} form inputs missing labels`);
|
607
|
+
}
|
608
|
+
|
609
|
+
return {
|
610
|
+
issues,
|
611
|
+
totalElements: document.querySelectorAll('*').length,
|
612
|
+
interactiveElements: document.querySelectorAll('button, a, input, select, textarea').length,
|
613
|
+
headingStructure: Array.from(document.querySelectorAll('h1, h2, h3, h4, h5, h6')).map(h => h.tagName)
|
614
|
+
};
|
615
|
+
}
|
616
|
+
|
617
|
+
/**
|
618
|
+
* Create initial debug info
|
619
|
+
*/
|
620
|
+
private createInitialDebugInfo(): DebugInfo {
|
621
|
+
return {
|
622
|
+
containers: [],
|
623
|
+
performance: {
|
624
|
+
fps: 60,
|
625
|
+
frameTime: 16.67,
|
626
|
+
memoryUsage: 0,
|
627
|
+
activeObservers: 0,
|
628
|
+
queueSize: 0
|
629
|
+
},
|
630
|
+
accessibility: {
|
631
|
+
wcagLevel: 'AA',
|
632
|
+
issues: [],
|
633
|
+
score: 100,
|
634
|
+
screenReaderCompatible: true
|
635
|
+
},
|
636
|
+
typography: {
|
637
|
+
scale: 'golden-ratio',
|
638
|
+
baseSize: 16,
|
639
|
+
lineHeight: 1.5,
|
640
|
+
rhythm: 24
|
641
|
+
}
|
642
|
+
};
|
643
|
+
}
|
644
|
+
}
|
645
|
+
|
646
|
+
// Global instance for easy access
|
647
|
+
declare global {
|
648
|
+
interface Window {
|
649
|
+
proteusDebugTools: VisualDebuggingTools;
|
650
|
+
}
|
651
|
+
}
|
652
|
+
|
653
|
+
// Auto-initialize if in development mode
|
654
|
+
if (typeof window !== 'undefined') {
|
655
|
+
window.proteusDebugTools = new VisualDebuggingTools();
|
656
|
+
}
|