@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.
Files changed (82) hide show
  1. package/API.md +438 -0
  2. package/FEATURES.md +286 -0
  3. package/LICENSE +21 -0
  4. package/README.md +645 -0
  5. package/dist/.tsbuildinfo +1 -0
  6. package/dist/proteus.cjs.js +16014 -0
  7. package/dist/proteus.cjs.js.map +1 -0
  8. package/dist/proteus.d.ts +3018 -0
  9. package/dist/proteus.esm.js +16005 -0
  10. package/dist/proteus.esm.js.map +1 -0
  11. package/dist/proteus.esm.min.js +8 -0
  12. package/dist/proteus.esm.min.js.map +1 -0
  13. package/dist/proteus.js +16020 -0
  14. package/dist/proteus.js.map +1 -0
  15. package/dist/proteus.min.js +8 -0
  16. package/dist/proteus.min.js.map +1 -0
  17. package/package.json +98 -0
  18. package/src/__tests__/mvp-integration.test.ts +518 -0
  19. package/src/accessibility/AccessibilityEngine.ts +2106 -0
  20. package/src/accessibility/ScreenReaderSupport.ts +444 -0
  21. package/src/accessibility/__tests__/ScreenReaderSupport.test.ts +435 -0
  22. package/src/animations/FLIPAnimationSystem.ts +491 -0
  23. package/src/compatibility/BrowserCompatibility.ts +1076 -0
  24. package/src/containers/BreakpointSystem.ts +347 -0
  25. package/src/containers/ContainerBreakpoints.ts +726 -0
  26. package/src/containers/ContainerManager.ts +370 -0
  27. package/src/containers/ContainerUnits.ts +336 -0
  28. package/src/containers/ContextIsolation.ts +394 -0
  29. package/src/containers/ElementQueries.ts +411 -0
  30. package/src/containers/SmartContainer.ts +536 -0
  31. package/src/containers/SmartContainers.ts +376 -0
  32. package/src/containers/__tests__/ContainerBreakpoints.test.ts +411 -0
  33. package/src/containers/__tests__/SmartContainers.test.ts +281 -0
  34. package/src/content/ResponsiveImages.ts +570 -0
  35. package/src/core/EventSystem.ts +147 -0
  36. package/src/core/MemoryManager.ts +321 -0
  37. package/src/core/PerformanceMonitor.ts +238 -0
  38. package/src/core/PluginSystem.ts +275 -0
  39. package/src/core/ProteusJS.test.ts +164 -0
  40. package/src/core/ProteusJS.ts +962 -0
  41. package/src/developer/PerformanceProfiler.ts +567 -0
  42. package/src/developer/VisualDebuggingTools.ts +656 -0
  43. package/src/developer/ZeroConfigSystem.ts +593 -0
  44. package/src/index.ts +35 -0
  45. package/src/integration.test.ts +227 -0
  46. package/src/layout/AdaptiveGrid.ts +429 -0
  47. package/src/layout/ContentReordering.ts +532 -0
  48. package/src/layout/FlexboxEnhancer.ts +406 -0
  49. package/src/layout/FlowLayout.ts +545 -0
  50. package/src/layout/SpacingSystem.ts +512 -0
  51. package/src/observers/IntersectionObserverPolyfill.ts +289 -0
  52. package/src/observers/ObserverManager.ts +299 -0
  53. package/src/observers/ResizeObserverPolyfill.ts +179 -0
  54. package/src/performance/BatchDOMOperations.ts +519 -0
  55. package/src/performance/CSSOptimizationEngine.ts +646 -0
  56. package/src/performance/CacheOptimizationSystem.ts +601 -0
  57. package/src/performance/EfficientEventHandler.ts +740 -0
  58. package/src/performance/LazyEvaluationSystem.ts +532 -0
  59. package/src/performance/MemoryManagementSystem.ts +497 -0
  60. package/src/performance/PerformanceMonitor.ts +931 -0
  61. package/src/performance/__tests__/BatchDOMOperations.test.ts +309 -0
  62. package/src/performance/__tests__/EfficientEventHandler.test.ts +268 -0
  63. package/src/performance/__tests__/PerformanceMonitor.test.ts +422 -0
  64. package/src/polyfills/BrowserPolyfills.ts +586 -0
  65. package/src/polyfills/__tests__/BrowserPolyfills.test.ts +328 -0
  66. package/src/test/setup.ts +115 -0
  67. package/src/theming/SmartThemeSystem.ts +591 -0
  68. package/src/types/index.ts +134 -0
  69. package/src/typography/ClampScaling.ts +356 -0
  70. package/src/typography/FluidTypography.ts +759 -0
  71. package/src/typography/LineHeightOptimization.ts +430 -0
  72. package/src/typography/LineHeightOptimizer.ts +326 -0
  73. package/src/typography/TextFitting.ts +355 -0
  74. package/src/typography/TypographicScale.ts +428 -0
  75. package/src/typography/VerticalRhythm.ts +369 -0
  76. package/src/typography/__tests__/FluidTypography.test.ts +432 -0
  77. package/src/typography/__tests__/LineHeightOptimization.test.ts +436 -0
  78. package/src/utils/Logger.ts +173 -0
  79. package/src/utils/debounce.ts +259 -0
  80. package/src/utils/performance.ts +371 -0
  81. package/src/utils/support.ts +106 -0
  82. package/src/utils/version.ts +24 -0
@@ -0,0 +1,394 @@
1
+ /**
2
+ * Context Isolation for ProteusJS
3
+ * Prevents interference between nested containers and manages cascade resolution
4
+ */
5
+
6
+ export interface ContainerContext {
7
+ element: Element;
8
+ level: number;
9
+ parent: ContainerContext | null;
10
+ children: Set<ContainerContext>;
11
+ isolated: boolean;
12
+ namespace: string;
13
+ }
14
+
15
+ export interface IsolationConfig {
16
+ autoIsolate: boolean;
17
+ maxNestingLevel: number;
18
+ conflictResolution: 'parent-wins' | 'child-wins' | 'explicit';
19
+ namespacePrefix: string;
20
+ }
21
+
22
+ export class ContextIsolation {
23
+ private contexts: Map<Element, ContainerContext> = new Map();
24
+ private namespaceCounter: number = 0;
25
+ private config: IsolationConfig;
26
+
27
+ constructor(config: Partial<IsolationConfig> = {}) {
28
+ this.config = {
29
+ autoIsolate: true,
30
+ maxNestingLevel: 10,
31
+ conflictResolution: 'child-wins',
32
+ namespacePrefix: 'proteus-ctx',
33
+ ...config
34
+ };
35
+ }
36
+
37
+ /**
38
+ * Create isolated context for container
39
+ */
40
+ public createContext(element: Element, isolated: boolean = true): ContainerContext {
41
+ // Check if context already exists
42
+ let context = this.contexts.get(element);
43
+ if (context) {
44
+ context.isolated = isolated;
45
+ return context;
46
+ }
47
+
48
+ // Find parent context
49
+ const parent = this.findParentContext(element);
50
+ const level = parent ? parent.level + 1 : 0;
51
+
52
+ // Check nesting level
53
+ if (level > this.config.maxNestingLevel) {
54
+ console.warn(
55
+ `ProteusJS: Maximum nesting level (${this.config.maxNestingLevel}) exceeded for container`
56
+ );
57
+ }
58
+
59
+ // Create new context
60
+ context = {
61
+ element,
62
+ level,
63
+ parent,
64
+ children: new Set(),
65
+ isolated: isolated || this.config.autoIsolate,
66
+ namespace: this.generateNamespace()
67
+ };
68
+
69
+ this.contexts.set(element, context);
70
+
71
+ // Update parent-child relationships
72
+ if (parent) {
73
+ parent.children.add(context);
74
+ }
75
+
76
+ // Apply isolation if needed
77
+ if (context.isolated) {
78
+ this.applyIsolation(context);
79
+ }
80
+
81
+ return context;
82
+ }
83
+
84
+ /**
85
+ * Remove context and clean up
86
+ */
87
+ public removeContext(element: Element): boolean {
88
+ const context = this.contexts.get(element);
89
+ if (!context) return false;
90
+
91
+ // Remove from parent's children
92
+ if (context.parent) {
93
+ context.parent.children.delete(context);
94
+ }
95
+
96
+ // Reparent children to this context's parent
97
+ context.children.forEach(child => {
98
+ child.parent = context.parent;
99
+ if (context.parent) {
100
+ context.parent.children.add(child);
101
+ }
102
+ });
103
+
104
+ // Remove isolation
105
+ this.removeIsolation(context);
106
+
107
+ this.contexts.delete(element);
108
+ return true;
109
+ }
110
+
111
+ /**
112
+ * Get context for element
113
+ */
114
+ public getContext(element: Element): ContainerContext | undefined {
115
+ return this.contexts.get(element);
116
+ }
117
+
118
+ /**
119
+ * Check if element has isolated context
120
+ */
121
+ public isIsolated(element: Element): boolean {
122
+ const context = this.contexts.get(element);
123
+ return context?.isolated || false;
124
+ }
125
+
126
+ /**
127
+ * Get all contexts at specific level
128
+ */
129
+ public getContextsAtLevel(level: number): ContainerContext[] {
130
+ return Array.from(this.contexts.values()).filter(ctx => ctx.level === level);
131
+ }
132
+
133
+ /**
134
+ * Get root contexts (level 0)
135
+ */
136
+ public getRootContexts(): ContainerContext[] {
137
+ return this.getContextsAtLevel(0);
138
+ }
139
+
140
+ /**
141
+ * Get context hierarchy for element
142
+ */
143
+ public getHierarchy(element: Element): ContainerContext[] {
144
+ const context = this.contexts.get(element);
145
+ if (!context) return [];
146
+
147
+ const hierarchy: ContainerContext[] = [];
148
+ let current: ContainerContext | null = context;
149
+
150
+ while (current) {
151
+ hierarchy.unshift(current);
152
+ current = current.parent;
153
+ }
154
+
155
+ return hierarchy;
156
+ }
157
+
158
+ /**
159
+ * Resolve conflicts between nested containers
160
+ */
161
+ public resolveConflicts(
162
+ element: Element,
163
+ property: string,
164
+ values: Map<ContainerContext, any>
165
+ ): any {
166
+ const context = this.contexts.get(element);
167
+ if (!context || values.size === 0) return undefined;
168
+
169
+ switch (this.config.conflictResolution) {
170
+ case 'parent-wins':
171
+ return this.resolveParentWins(context, values);
172
+ case 'child-wins':
173
+ return this.resolveChildWins(context, values);
174
+ case 'explicit':
175
+ return this.resolveExplicit(context, values);
176
+ default:
177
+ return values.values().next().value;
178
+ }
179
+ }
180
+
181
+ /**
182
+ * Generate scoped CSS selector for context
183
+ */
184
+ public getScopedSelector(context: ContainerContext, selector: string): string {
185
+ if (!context.isolated) return selector;
186
+
187
+ const namespace = `[data-${context.namespace}]`;
188
+
189
+ // If selector is a simple class or ID, scope it
190
+ if (selector.startsWith('.') || selector.startsWith('#')) {
191
+ return `${namespace} ${selector}`;
192
+ }
193
+
194
+ // For complex selectors, prepend namespace
195
+ return `${namespace} ${selector}`;
196
+ }
197
+
198
+ /**
199
+ * Generate scoped CSS rules for context
200
+ */
201
+ public generateScopedCSS(context: ContainerContext, css: string): string {
202
+ if (!context.isolated) return css;
203
+
204
+ const namespace = `[data-${context.namespace}]`;
205
+
206
+ // Simple CSS scoping - prepend namespace to selectors
207
+ return css.replace(/([^{}]+)\s*{/g, (match, selector) => {
208
+ const trimmedSelector = selector.trim();
209
+ if (trimmedSelector.startsWith('@')) {
210
+ // Don't scope at-rules
211
+ return match;
212
+ }
213
+ return `${namespace} ${trimmedSelector} {`;
214
+ });
215
+ }
216
+
217
+ /**
218
+ * Check for potential conflicts
219
+ */
220
+ public detectConflicts(): Array<{
221
+ elements: Element[];
222
+ property: string;
223
+ contexts: ContainerContext[];
224
+ }> {
225
+ const conflicts: Array<{
226
+ elements: Element[];
227
+ property: string;
228
+ contexts: ContainerContext[];
229
+ }> = [];
230
+
231
+ // This would need to be integrated with the actual style system
232
+ // For now, return empty array as placeholder
233
+ return conflicts;
234
+ }
235
+
236
+ /**
237
+ * Get isolation statistics
238
+ */
239
+ public getStats(): object {
240
+ const contexts = Array.from(this.contexts.values());
241
+ const isolated = contexts.filter(ctx => ctx.isolated);
242
+ const levels = new Map<number, number>();
243
+
244
+ contexts.forEach(ctx => {
245
+ levels.set(ctx.level, (levels.get(ctx.level) || 0) + 1);
246
+ });
247
+
248
+ return {
249
+ totalContexts: contexts.length,
250
+ isolatedContexts: isolated.length,
251
+ maxLevel: Math.max(...contexts.map(ctx => ctx.level), 0),
252
+ contextsByLevel: Object.fromEntries(levels),
253
+ averageChildren: contexts.length > 0
254
+ ? contexts.reduce((sum, ctx) => sum + ctx.children.size, 0) / contexts.length
255
+ : 0
256
+ };
257
+ }
258
+
259
+ /**
260
+ * Clear all contexts
261
+ */
262
+ public clear(): void {
263
+ // Remove isolation from all contexts
264
+ this.contexts.forEach(context => {
265
+ this.removeIsolation(context);
266
+ });
267
+
268
+ this.contexts.clear();
269
+ this.namespaceCounter = 0;
270
+ }
271
+
272
+ /**
273
+ * Find parent context by traversing DOM
274
+ */
275
+ private findParentContext(element: Element): ContainerContext | null {
276
+ let parent = element.parentElement;
277
+
278
+ while (parent) {
279
+ const context = this.contexts.get(parent);
280
+ if (context) return context;
281
+ parent = parent.parentElement;
282
+ }
283
+
284
+ return null;
285
+ }
286
+
287
+ /**
288
+ * Generate unique namespace
289
+ */
290
+ private generateNamespace(): string {
291
+ return `${this.config.namespacePrefix}-${++this.namespaceCounter}`;
292
+ }
293
+
294
+ /**
295
+ * Apply isolation to context
296
+ */
297
+ private applyIsolation(context: ContainerContext): void {
298
+ const element = context.element as HTMLElement;
299
+
300
+ // Add namespace data attribute
301
+ element.setAttribute(`data-${context.namespace}`, '');
302
+
303
+ // Add CSS containment if supported
304
+ if (typeof CSS !== 'undefined' && CSS.supports && CSS.supports('contain', 'layout style')) {
305
+ element.style.contain = 'layout style';
306
+ }
307
+
308
+ // Create isolated stacking context
309
+ if (getComputedStyle(element).position === 'static') {
310
+ element.style.position = 'relative';
311
+ }
312
+ }
313
+
314
+ /**
315
+ * Remove isolation from context
316
+ */
317
+ private removeIsolation(context: ContainerContext): void {
318
+ const element = context.element as HTMLElement;
319
+
320
+ // Remove namespace data attribute
321
+ element.removeAttribute(`data-${context.namespace}`);
322
+
323
+ // Remove CSS containment
324
+ element.style.removeProperty('contain');
325
+
326
+ // Note: We don't remove position as it might have been set by user
327
+ }
328
+
329
+ /**
330
+ * Resolve conflicts with parent-wins strategy
331
+ */
332
+ private resolveParentWins(
333
+ context: ContainerContext,
334
+ values: Map<ContainerContext, any>
335
+ ): any {
336
+ // Find the highest level (closest to root) context with a value
337
+ let winner: ContainerContext | null = null;
338
+ let minLevel = Infinity;
339
+
340
+ values.forEach((value, ctx) => {
341
+ if (ctx.level < minLevel) {
342
+ minLevel = ctx.level;
343
+ winner = ctx;
344
+ }
345
+ });
346
+
347
+ return winner ? values.get(winner) : undefined;
348
+ }
349
+
350
+ /**
351
+ * Resolve conflicts with child-wins strategy
352
+ */
353
+ private resolveChildWins(
354
+ context: ContainerContext,
355
+ values: Map<ContainerContext, any>
356
+ ): any {
357
+ // Find the lowest level (furthest from root) context with a value
358
+ let winner: ContainerContext | null = null;
359
+ let maxLevel = -1;
360
+
361
+ values.forEach((value, ctx) => {
362
+ if (ctx.level > maxLevel) {
363
+ maxLevel = ctx.level;
364
+ winner = ctx;
365
+ }
366
+ });
367
+
368
+ return winner ? values.get(winner) : undefined;
369
+ }
370
+
371
+ /**
372
+ * Resolve conflicts with explicit strategy
373
+ */
374
+ private resolveExplicit(
375
+ context: ContainerContext,
376
+ values: Map<ContainerContext, any>
377
+ ): any {
378
+ // Only use values from isolated contexts
379
+ const isolatedValues = new Map<ContainerContext, any>();
380
+
381
+ values.forEach((value, ctx) => {
382
+ if (ctx.isolated) {
383
+ isolatedValues.set(ctx, value);
384
+ }
385
+ });
386
+
387
+ if (isolatedValues.size === 0) {
388
+ return values.values().next().value;
389
+ }
390
+
391
+ // Use child-wins for isolated contexts
392
+ return this.resolveChildWins(context, isolatedValues);
393
+ }
394
+ }