@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,593 @@
|
|
1
|
+
/**
|
2
|
+
* Zero-Config Setup System for ProteusJS
|
3
|
+
* Automatic container detection, intelligent defaults, and optimization
|
4
|
+
*/
|
5
|
+
|
6
|
+
export interface ZeroConfigOptions {
|
7
|
+
autoDetectContainers: boolean;
|
8
|
+
intelligentBreakpoints: boolean;
|
9
|
+
autoTypographyScaling: boolean;
|
10
|
+
performanceOptimization: boolean;
|
11
|
+
accessibilityOptimization: boolean;
|
12
|
+
autoThemeDetection: boolean;
|
13
|
+
responsiveImages: boolean;
|
14
|
+
lazyLoading: boolean;
|
15
|
+
}
|
16
|
+
|
17
|
+
export interface DetectedContainer {
|
18
|
+
element: Element;
|
19
|
+
type: 'grid' | 'flex' | 'block' | 'inline';
|
20
|
+
suggestedBreakpoints: Record<string, string>;
|
21
|
+
priority: 'high' | 'normal' | 'low';
|
22
|
+
confidence: number;
|
23
|
+
}
|
24
|
+
|
25
|
+
export interface AutoOptimization {
|
26
|
+
performance: string[];
|
27
|
+
accessibility: string[];
|
28
|
+
typography: string[];
|
29
|
+
layout: string[];
|
30
|
+
}
|
31
|
+
|
32
|
+
export class ZeroConfigSystem {
|
33
|
+
private config: Required<ZeroConfigOptions>;
|
34
|
+
private detectedContainers: Map<Element, DetectedContainer> = new Map();
|
35
|
+
private appliedOptimizations: AutoOptimization;
|
36
|
+
private observer: MutationObserver | null = null;
|
37
|
+
|
38
|
+
constructor(config: Partial<ZeroConfigOptions> = {}) {
|
39
|
+
this.config = {
|
40
|
+
autoDetectContainers: true,
|
41
|
+
intelligentBreakpoints: true,
|
42
|
+
autoTypographyScaling: true,
|
43
|
+
performanceOptimization: true,
|
44
|
+
accessibilityOptimization: true,
|
45
|
+
autoThemeDetection: true,
|
46
|
+
responsiveImages: true,
|
47
|
+
lazyLoading: true,
|
48
|
+
...config
|
49
|
+
};
|
50
|
+
|
51
|
+
this.appliedOptimizations = {
|
52
|
+
performance: [],
|
53
|
+
accessibility: [],
|
54
|
+
typography: [],
|
55
|
+
layout: []
|
56
|
+
};
|
57
|
+
}
|
58
|
+
|
59
|
+
/**
|
60
|
+
* Initialize zero-config setup
|
61
|
+
*/
|
62
|
+
public async initialize(): Promise<void> {
|
63
|
+
console.log('🚀 ProteusJS Zero-Config Setup Starting...');
|
64
|
+
|
65
|
+
if (this.config.autoDetectContainers) {
|
66
|
+
await this.detectContainers();
|
67
|
+
}
|
68
|
+
|
69
|
+
if (this.config.intelligentBreakpoints) {
|
70
|
+
await this.setupIntelligentBreakpoints();
|
71
|
+
}
|
72
|
+
|
73
|
+
if (this.config.autoTypographyScaling) {
|
74
|
+
await this.setupTypographyScaling();
|
75
|
+
}
|
76
|
+
|
77
|
+
if (this.config.performanceOptimization) {
|
78
|
+
await this.applyPerformanceOptimizations();
|
79
|
+
}
|
80
|
+
|
81
|
+
if (this.config.accessibilityOptimization) {
|
82
|
+
await this.applyAccessibilityOptimizations();
|
83
|
+
}
|
84
|
+
|
85
|
+
if (this.config.autoThemeDetection) {
|
86
|
+
await this.setupAutoTheme();
|
87
|
+
}
|
88
|
+
|
89
|
+
if (this.config.responsiveImages) {
|
90
|
+
await this.optimizeImages();
|
91
|
+
}
|
92
|
+
|
93
|
+
this.setupContinuousOptimization();
|
94
|
+
|
95
|
+
console.log('✅ ProteusJS Zero-Config Setup Complete!');
|
96
|
+
this.logOptimizations();
|
97
|
+
}
|
98
|
+
|
99
|
+
/**
|
100
|
+
* Automatically detect containers in the DOM
|
101
|
+
*/
|
102
|
+
private async detectContainers(): Promise<void> {
|
103
|
+
const candidates = document.querySelectorAll('*');
|
104
|
+
const containers: DetectedContainer[] = [];
|
105
|
+
|
106
|
+
candidates.forEach(element => {
|
107
|
+
const container = this.analyzeElement(element);
|
108
|
+
if (container) {
|
109
|
+
containers.push(container);
|
110
|
+
this.detectedContainers.set(element, container);
|
111
|
+
}
|
112
|
+
});
|
113
|
+
|
114
|
+
// Sort by priority and confidence
|
115
|
+
containers.sort((a, b) => {
|
116
|
+
const priorityOrder = { high: 3, normal: 2, low: 1 };
|
117
|
+
const priorityDiff = priorityOrder[b.priority] - priorityOrder[a.priority];
|
118
|
+
return priorityDiff !== 0 ? priorityDiff : b.confidence - a.confidence;
|
119
|
+
});
|
120
|
+
|
121
|
+
console.log(`🔍 Detected ${containers.length} potential containers`);
|
122
|
+
}
|
123
|
+
|
124
|
+
/**
|
125
|
+
* Analyze element to determine if it's a container
|
126
|
+
*/
|
127
|
+
private analyzeElement(element: Element): DetectedContainer | null {
|
128
|
+
const styles = window.getComputedStyle(element);
|
129
|
+
const children = element.children.length;
|
130
|
+
const rect = element.getBoundingClientRect();
|
131
|
+
|
132
|
+
// Skip if too small or no children
|
133
|
+
if (rect.width < 100 || rect.height < 50 || children === 0) {
|
134
|
+
return null;
|
135
|
+
}
|
136
|
+
|
137
|
+
let type: DetectedContainer['type'] = 'block';
|
138
|
+
let confidence = 0;
|
139
|
+
let priority: DetectedContainer['priority'] = 'normal';
|
140
|
+
|
141
|
+
// Detect container type
|
142
|
+
if (styles.display === 'grid') {
|
143
|
+
type = 'grid';
|
144
|
+
confidence += 0.4;
|
145
|
+
} else if (styles.display === 'flex') {
|
146
|
+
type = 'flex';
|
147
|
+
confidence += 0.3;
|
148
|
+
} else if (styles.display === 'inline-block' || styles.display === 'inline-flex') {
|
149
|
+
type = 'inline';
|
150
|
+
confidence += 0.2;
|
151
|
+
}
|
152
|
+
|
153
|
+
// Increase confidence based on characteristics
|
154
|
+
if (children >= 3) confidence += 0.2;
|
155
|
+
if (rect.width > 300) confidence += 0.1;
|
156
|
+
if (element.classList.length > 0) confidence += 0.1;
|
157
|
+
if (element.id) confidence += 0.1;
|
158
|
+
|
159
|
+
// Determine priority
|
160
|
+
if (element.matches('main, .main, #main, .container, .wrapper')) {
|
161
|
+
priority = 'high';
|
162
|
+
confidence += 0.2;
|
163
|
+
} else if (element.matches('section, article, aside, nav, header, footer')) {
|
164
|
+
priority = 'normal';
|
165
|
+
confidence += 0.1;
|
166
|
+
}
|
167
|
+
|
168
|
+
// Skip if confidence too low
|
169
|
+
if (confidence < 0.3) return null;
|
170
|
+
|
171
|
+
return {
|
172
|
+
element,
|
173
|
+
type,
|
174
|
+
suggestedBreakpoints: this.generateBreakpoints(rect.width),
|
175
|
+
priority,
|
176
|
+
confidence
|
177
|
+
};
|
178
|
+
}
|
179
|
+
|
180
|
+
/**
|
181
|
+
* Generate intelligent breakpoints based on content
|
182
|
+
*/
|
183
|
+
private generateBreakpoints(width: number): Record<string, string> {
|
184
|
+
const breakpoints: Record<string, string> = {};
|
185
|
+
|
186
|
+
// Base breakpoints on golden ratio and common device sizes
|
187
|
+
const ratios = [0.618, 0.8, 1.0, 1.2, 1.618];
|
188
|
+
const names = ['xs', 'sm', 'md', 'lg', 'xl'];
|
189
|
+
|
190
|
+
ratios.forEach((ratio, index) => {
|
191
|
+
const size = Math.round(width * ratio);
|
192
|
+
if (size >= 200 && size <= 1920) {
|
193
|
+
const name = names[index];
|
194
|
+
if (name) {
|
195
|
+
breakpoints[name] = `${size}px`;
|
196
|
+
}
|
197
|
+
}
|
198
|
+
});
|
199
|
+
|
200
|
+
return breakpoints;
|
201
|
+
}
|
202
|
+
|
203
|
+
/**
|
204
|
+
* Setup intelligent breakpoints for detected containers
|
205
|
+
*/
|
206
|
+
private async setupIntelligentBreakpoints(): Promise<void> {
|
207
|
+
this.detectedContainers.forEach((container, element) => {
|
208
|
+
// Apply container queries
|
209
|
+
const className = this.generateClassName(element);
|
210
|
+
element.classList.add(className);
|
211
|
+
|
212
|
+
// Generate CSS for breakpoints
|
213
|
+
this.generateBreakpointCSS(className, container.suggestedBreakpoints);
|
214
|
+
});
|
215
|
+
|
216
|
+
this.appliedOptimizations.layout.push('Intelligent breakpoints applied');
|
217
|
+
}
|
218
|
+
|
219
|
+
/**
|
220
|
+
* Setup automatic typography scaling
|
221
|
+
*/
|
222
|
+
private async setupTypographyScaling(): Promise<void> {
|
223
|
+
const textElements = document.querySelectorAll('h1, h2, h3, h4, h5, h6, p, span, div');
|
224
|
+
|
225
|
+
textElements.forEach(element => {
|
226
|
+
const container = this.findParentContainer(element);
|
227
|
+
if (container) {
|
228
|
+
this.applyFluidTypography(element, container);
|
229
|
+
}
|
230
|
+
});
|
231
|
+
|
232
|
+
this.appliedOptimizations.typography.push('Fluid typography scaling applied');
|
233
|
+
}
|
234
|
+
|
235
|
+
/**
|
236
|
+
* Apply performance optimizations
|
237
|
+
*/
|
238
|
+
private async applyPerformanceOptimizations(): Promise<void> {
|
239
|
+
// Enable passive event listeners
|
240
|
+
this.enablePassiveListeners();
|
241
|
+
|
242
|
+
// Optimize images
|
243
|
+
if (this.config.responsiveImages) {
|
244
|
+
this.optimizeImages();
|
245
|
+
}
|
246
|
+
|
247
|
+
// Enable lazy loading
|
248
|
+
if (this.config.lazyLoading) {
|
249
|
+
this.enableLazyLoading();
|
250
|
+
}
|
251
|
+
|
252
|
+
this.appliedOptimizations.performance.push(
|
253
|
+
'Passive event listeners',
|
254
|
+
'Image optimization',
|
255
|
+
'Lazy loading'
|
256
|
+
);
|
257
|
+
}
|
258
|
+
|
259
|
+
/**
|
260
|
+
* Apply accessibility optimizations
|
261
|
+
*/
|
262
|
+
private async applyAccessibilityOptimizations(): Promise<void> {
|
263
|
+
// Add missing ARIA labels
|
264
|
+
this.addMissingAriaLabels();
|
265
|
+
|
266
|
+
// Improve focus indicators
|
267
|
+
this.improveFocusIndicators();
|
268
|
+
|
269
|
+
// Ensure proper heading hierarchy
|
270
|
+
this.validateHeadingHierarchy();
|
271
|
+
|
272
|
+
// Add skip links
|
273
|
+
this.addSkipLinks();
|
274
|
+
|
275
|
+
this.appliedOptimizations.accessibility.push(
|
276
|
+
'ARIA labels added',
|
277
|
+
'Focus indicators improved',
|
278
|
+
'Heading hierarchy validated',
|
279
|
+
'Skip links added'
|
280
|
+
);
|
281
|
+
}
|
282
|
+
|
283
|
+
/**
|
284
|
+
* Setup automatic theme detection
|
285
|
+
*/
|
286
|
+
private async setupAutoTheme(): Promise<void> {
|
287
|
+
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
288
|
+
const prefersHighContrast = window.matchMedia('(prefers-contrast: high)').matches;
|
289
|
+
|
290
|
+
if (prefersDark) {
|
291
|
+
document.body.classList.add('proteus-dark');
|
292
|
+
}
|
293
|
+
|
294
|
+
if (prefersHighContrast) {
|
295
|
+
document.body.classList.add('proteus-high-contrast');
|
296
|
+
}
|
297
|
+
|
298
|
+
// Listen for changes
|
299
|
+
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
|
300
|
+
document.body.classList.toggle('proteus-dark', e.matches);
|
301
|
+
});
|
302
|
+
}
|
303
|
+
|
304
|
+
/**
|
305
|
+
* Optimize images automatically
|
306
|
+
*/
|
307
|
+
private async optimizeImages(): Promise<void> {
|
308
|
+
const images = document.querySelectorAll('img');
|
309
|
+
|
310
|
+
images.forEach(img => {
|
311
|
+
// Add loading="lazy" if not present
|
312
|
+
if (!img.hasAttribute('loading')) {
|
313
|
+
img.setAttribute('loading', 'lazy');
|
314
|
+
}
|
315
|
+
|
316
|
+
// Add decoding="async" for better performance
|
317
|
+
if (!img.hasAttribute('decoding')) {
|
318
|
+
img.setAttribute('decoding', 'async');
|
319
|
+
}
|
320
|
+
|
321
|
+
// Suggest responsive image attributes
|
322
|
+
if (!img.hasAttribute('sizes') && !img.hasAttribute('srcset')) {
|
323
|
+
const container = this.findParentContainer(img);
|
324
|
+
if (container) {
|
325
|
+
this.addResponsiveImageAttributes(img, container);
|
326
|
+
}
|
327
|
+
}
|
328
|
+
});
|
329
|
+
}
|
330
|
+
|
331
|
+
/**
|
332
|
+
* Enable lazy loading for various elements
|
333
|
+
*/
|
334
|
+
private enableLazyLoading(): Promise<void> {
|
335
|
+
return new Promise((resolve) => {
|
336
|
+
if ('IntersectionObserver' in window) {
|
337
|
+
const observer = new IntersectionObserver((entries) => {
|
338
|
+
entries.forEach(entry => {
|
339
|
+
if (entry.isIntersecting) {
|
340
|
+
const element = entry.target;
|
341
|
+
element.classList.add('proteus-loaded');
|
342
|
+
observer.unobserve(element);
|
343
|
+
}
|
344
|
+
});
|
345
|
+
});
|
346
|
+
|
347
|
+
// Observe images, videos, and iframes
|
348
|
+
document.querySelectorAll('img, video, iframe').forEach(element => {
|
349
|
+
observer.observe(element);
|
350
|
+
});
|
351
|
+
}
|
352
|
+
resolve();
|
353
|
+
});
|
354
|
+
}
|
355
|
+
|
356
|
+
/**
|
357
|
+
* Setup continuous optimization
|
358
|
+
*/
|
359
|
+
private setupContinuousOptimization(): void {
|
360
|
+
// Watch for DOM changes
|
361
|
+
this.observer = new MutationObserver((mutations) => {
|
362
|
+
mutations.forEach(mutation => {
|
363
|
+
if (mutation.type === 'childList') {
|
364
|
+
mutation.addedNodes.forEach(node => {
|
365
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
366
|
+
this.optimizeNewElement(node as Element);
|
367
|
+
}
|
368
|
+
});
|
369
|
+
}
|
370
|
+
});
|
371
|
+
});
|
372
|
+
|
373
|
+
this.observer.observe(document.body, {
|
374
|
+
childList: true,
|
375
|
+
subtree: true
|
376
|
+
});
|
377
|
+
}
|
378
|
+
|
379
|
+
/**
|
380
|
+
* Optimize newly added elements
|
381
|
+
*/
|
382
|
+
private optimizeNewElement(element: Element): void {
|
383
|
+
// Check if it's a potential container
|
384
|
+
const container = this.analyzeElement(element);
|
385
|
+
if (container) {
|
386
|
+
this.detectedContainers.set(element, container);
|
387
|
+
|
388
|
+
if (this.config.intelligentBreakpoints) {
|
389
|
+
const className = this.generateClassName(element);
|
390
|
+
element.classList.add(className);
|
391
|
+
this.generateBreakpointCSS(className, container.suggestedBreakpoints);
|
392
|
+
}
|
393
|
+
}
|
394
|
+
|
395
|
+
// Optimize images
|
396
|
+
if (this.config.responsiveImages) {
|
397
|
+
const images = element.querySelectorAll('img');
|
398
|
+
images.forEach(_img => this.optimizeImages());
|
399
|
+
}
|
400
|
+
|
401
|
+
// Apply accessibility improvements
|
402
|
+
if (this.config.accessibilityOptimization) {
|
403
|
+
this.addMissingAriaLabels(element);
|
404
|
+
}
|
405
|
+
}
|
406
|
+
|
407
|
+
/**
|
408
|
+
* Helper methods
|
409
|
+
*/
|
410
|
+
private generateClassName(element: Element): string {
|
411
|
+
const id = element.id || '';
|
412
|
+
const classes = Array.from(element.classList).join('-');
|
413
|
+
const tag = element.tagName.toLowerCase();
|
414
|
+
return `proteus-${tag}-${id || classes || Math.random().toString(36).substring(2, 11)}`;
|
415
|
+
}
|
416
|
+
|
417
|
+
private generateBreakpointCSS(className: string, breakpoints: Record<string, string>): void {
|
418
|
+
let css = '';
|
419
|
+
Object.entries(breakpoints).forEach(([name, size]) => {
|
420
|
+
css += `
|
421
|
+
.${className} {
|
422
|
+
container-type: inline-size;
|
423
|
+
}
|
424
|
+
@container (min-width: ${size}) {
|
425
|
+
.${className} {
|
426
|
+
--proteus-breakpoint: ${name};
|
427
|
+
}
|
428
|
+
}
|
429
|
+
`;
|
430
|
+
});
|
431
|
+
|
432
|
+
// Add CSS to document
|
433
|
+
const style = document.createElement('style');
|
434
|
+
style.textContent = css;
|
435
|
+
document.head.appendChild(style);
|
436
|
+
}
|
437
|
+
|
438
|
+
private findParentContainer(element: Element): DetectedContainer | null {
|
439
|
+
let parent = element.parentElement;
|
440
|
+
while (parent) {
|
441
|
+
const container = this.detectedContainers.get(parent);
|
442
|
+
if (container) return container;
|
443
|
+
parent = parent.parentElement;
|
444
|
+
}
|
445
|
+
return null;
|
446
|
+
}
|
447
|
+
|
448
|
+
private applyFluidTypography(element: Element, _container: DetectedContainer): void {
|
449
|
+
const htmlElement = element as HTMLElement;
|
450
|
+
const currentSize = parseFloat(window.getComputedStyle(element).fontSize);
|
451
|
+
|
452
|
+
// Calculate fluid typography based on container
|
453
|
+
const minSize = Math.max(currentSize * 0.8, 12);
|
454
|
+
const maxSize = currentSize * 1.5;
|
455
|
+
|
456
|
+
htmlElement.style.fontSize = `clamp(${minSize}px, 4cw, ${maxSize}px)`;
|
457
|
+
}
|
458
|
+
|
459
|
+
private enablePassiveListeners(): void {
|
460
|
+
// Override addEventListener to use passive listeners where appropriate
|
461
|
+
const originalAddEventListener = EventTarget.prototype.addEventListener;
|
462
|
+
EventTarget.prototype.addEventListener = function(type, listener, options) {
|
463
|
+
const passiveEvents = ['scroll', 'wheel', 'touchstart', 'touchmove'];
|
464
|
+
if (passiveEvents.includes(type) && typeof options !== 'object') {
|
465
|
+
options = { passive: true };
|
466
|
+
}
|
467
|
+
return originalAddEventListener.call(this, type, listener, options);
|
468
|
+
};
|
469
|
+
}
|
470
|
+
|
471
|
+
private addMissingAriaLabels(root: Element = document.body): void {
|
472
|
+
// Add labels to buttons without text
|
473
|
+
const buttons = root.querySelectorAll('button:not([aria-label]):not([aria-labelledby])');
|
474
|
+
buttons.forEach(button => {
|
475
|
+
if (!button.textContent?.trim()) {
|
476
|
+
button.setAttribute('aria-label', 'Button');
|
477
|
+
}
|
478
|
+
});
|
479
|
+
|
480
|
+
// Add labels to form inputs
|
481
|
+
const inputs = root.querySelectorAll('input:not([aria-label]):not([aria-labelledby])');
|
482
|
+
inputs.forEach(input => {
|
483
|
+
const type = input.getAttribute('type') || 'text';
|
484
|
+
input.setAttribute('aria-label', `${type} input`);
|
485
|
+
});
|
486
|
+
}
|
487
|
+
|
488
|
+
private improveFocusIndicators(): void {
|
489
|
+
const style = document.createElement('style');
|
490
|
+
style.textContent = `
|
491
|
+
*:focus {
|
492
|
+
outline: 2px solid #4A90E2 !important;
|
493
|
+
outline-offset: 2px !important;
|
494
|
+
}
|
495
|
+
.proteus-focus-visible:focus-visible {
|
496
|
+
outline: 3px solid #4A90E2 !important;
|
497
|
+
outline-offset: 2px !important;
|
498
|
+
}
|
499
|
+
`;
|
500
|
+
document.head.appendChild(style);
|
501
|
+
}
|
502
|
+
|
503
|
+
private validateHeadingHierarchy(): void {
|
504
|
+
const headings = document.querySelectorAll('h1, h2, h3, h4, h5, h6');
|
505
|
+
let lastLevel = 0;
|
506
|
+
|
507
|
+
headings.forEach(heading => {
|
508
|
+
const level = parseInt(heading.tagName.charAt(1));
|
509
|
+
if (level > lastLevel + 1) {
|
510
|
+
console.warn(`Heading hierarchy issue: ${heading.tagName} follows h${lastLevel}`);
|
511
|
+
}
|
512
|
+
lastLevel = level;
|
513
|
+
});
|
514
|
+
}
|
515
|
+
|
516
|
+
private addSkipLinks(): void {
|
517
|
+
const main = document.querySelector('main, [role="main"], #main');
|
518
|
+
if (main && !document.querySelector('.proteus-skip-link')) {
|
519
|
+
const skipLink = document.createElement('a');
|
520
|
+
skipLink.href = '#main';
|
521
|
+
skipLink.textContent = 'Skip to main content';
|
522
|
+
skipLink.className = 'proteus-skip-link';
|
523
|
+
skipLink.style.cssText = `
|
524
|
+
position: absolute;
|
525
|
+
top: -40px;
|
526
|
+
left: 6px;
|
527
|
+
background: #000;
|
528
|
+
color: #fff;
|
529
|
+
padding: 8px;
|
530
|
+
text-decoration: none;
|
531
|
+
z-index: 1000;
|
532
|
+
`;
|
533
|
+
|
534
|
+
skipLink.addEventListener('focus', () => {
|
535
|
+
skipLink.style.top = '6px';
|
536
|
+
});
|
537
|
+
|
538
|
+
skipLink.addEventListener('blur', () => {
|
539
|
+
skipLink.style.top = '-40px';
|
540
|
+
});
|
541
|
+
|
542
|
+
document.body.insertBefore(skipLink, document.body.firstChild);
|
543
|
+
}
|
544
|
+
}
|
545
|
+
|
546
|
+
private addResponsiveImageAttributes(img: HTMLImageElement, container: DetectedContainer): void {
|
547
|
+
const breakpoints = Object.values(container.suggestedBreakpoints);
|
548
|
+
const sizes = breakpoints.map((bp, index) => {
|
549
|
+
const width = parseInt(bp);
|
550
|
+
return index === breakpoints.length - 1 ? `${width}px` : `(max-width: ${width}px) ${width}px`;
|
551
|
+
}).join(', ');
|
552
|
+
|
553
|
+
img.setAttribute('sizes', sizes);
|
554
|
+
}
|
555
|
+
|
556
|
+
private logOptimizations(): void {
|
557
|
+
console.group('🎯 ProteusJS Auto-Optimizations Applied');
|
558
|
+
|
559
|
+
Object.entries(this.appliedOptimizations).forEach(([category, optimizations]) => {
|
560
|
+
if (optimizations.length > 0) {
|
561
|
+
console.group(`${category.charAt(0).toUpperCase() + category.slice(1)}:`);
|
562
|
+
optimizations.forEach((opt: string) => console.log(`✅ ${opt}`));
|
563
|
+
console.groupEnd();
|
564
|
+
}
|
565
|
+
});
|
566
|
+
|
567
|
+
console.log(`📊 Detected ${this.detectedContainers.size} containers`);
|
568
|
+
console.groupEnd();
|
569
|
+
}
|
570
|
+
|
571
|
+
/**
|
572
|
+
* Get optimization report
|
573
|
+
*/
|
574
|
+
public getOptimizationReport(): {
|
575
|
+
containers: number;
|
576
|
+
optimizations: AutoOptimization;
|
577
|
+
detectedContainers: DetectedContainer[];
|
578
|
+
} {
|
579
|
+
return {
|
580
|
+
containers: this.detectedContainers.size,
|
581
|
+
optimizations: this.appliedOptimizations,
|
582
|
+
detectedContainers: Array.from(this.detectedContainers.values())
|
583
|
+
};
|
584
|
+
}
|
585
|
+
|
586
|
+
/**
|
587
|
+
* Destroy zero-config system
|
588
|
+
*/
|
589
|
+
public destroy(): void {
|
590
|
+
this.observer?.disconnect();
|
591
|
+
this.detectedContainers.clear();
|
592
|
+
}
|
593
|
+
}
|
package/src/index.ts
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
/**
|
2
|
+
* ProteusJS - Dynamic Responsive Design Library
|
3
|
+
* Shape-shifting responsive design that adapts like the sea god himself
|
4
|
+
*
|
5
|
+
* @version 1.0.0
|
6
|
+
* @author ProteusJS Team
|
7
|
+
* @license MIT
|
8
|
+
*/
|
9
|
+
|
10
|
+
// Core exports
|
11
|
+
export { ProteusJS as default } from './core/ProteusJS';
|
12
|
+
export { ProteusJS } from './core/ProteusJS';
|
13
|
+
|
14
|
+
// Type exports
|
15
|
+
export type {
|
16
|
+
ProteusConfig,
|
17
|
+
ContainerConfig,
|
18
|
+
BreakpointConfig,
|
19
|
+
TypographyConfig,
|
20
|
+
LayoutConfig,
|
21
|
+
AnimationConfig,
|
22
|
+
AccessibilityConfig,
|
23
|
+
PerformanceConfig
|
24
|
+
} from './types';
|
25
|
+
|
26
|
+
// Utility exports
|
27
|
+
export { version } from './utils/version';
|
28
|
+
export { isSupported } from './utils/support';
|
29
|
+
|
30
|
+
// Plugin exports (for extensibility)
|
31
|
+
export type { ProteusPlugin } from './core/PluginSystem';
|
32
|
+
|
33
|
+
// Constants
|
34
|
+
export const VERSION = '1.0.0';
|
35
|
+
export const LIBRARY_NAME = 'ProteusJS';
|