@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,406 @@
1
+ /**
2
+ * Enhanced Flexbox System for ProteusJS
3
+ * Container query integration with intelligent flex calculations
4
+ */
5
+
6
+ export interface FlexboxConfig {
7
+ direction: 'row' | 'column' | 'row-reverse' | 'column-reverse';
8
+ wrap: 'nowrap' | 'wrap' | 'wrap-reverse' | 'auto';
9
+ justify: 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly';
10
+ align: 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline';
11
+ gap: number | 'fluid';
12
+ responsive: boolean;
13
+ autoWrap: boolean;
14
+ minItemWidth?: number;
15
+ maxItemWidth?: number;
16
+ itemGrowRatio?: number;
17
+ itemShrinkRatio?: number;
18
+ breakpoints?: Record<string, Partial<FlexboxConfig>>;
19
+ }
20
+
21
+ export interface FlexItemConfig {
22
+ grow: number;
23
+ shrink: number;
24
+ basis: string | number;
25
+ order?: number;
26
+ alignSelf?: 'auto' | 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline';
27
+ responsive?: boolean;
28
+ }
29
+
30
+ export interface FlexboxState {
31
+ containerWidth: number;
32
+ containerHeight: number;
33
+ itemCount: number;
34
+ wrappedLines: number;
35
+ optimalItemWidth: number;
36
+ actualGap: number;
37
+ overflow: boolean;
38
+ }
39
+
40
+ export class FlexboxEnhancer {
41
+ private element: Element;
42
+ private config: Required<FlexboxConfig>;
43
+ private state: FlexboxState;
44
+ private resizeObserver: ResizeObserver | null = null;
45
+ private mutationObserver: MutationObserver | null = null;
46
+
47
+ constructor(element: Element, config: Partial<FlexboxConfig> = {}) {
48
+ this.element = element;
49
+ this.config = {
50
+ direction: 'row',
51
+ wrap: 'auto',
52
+ justify: 'flex-start',
53
+ align: 'stretch',
54
+ gap: 16,
55
+ responsive: true,
56
+ autoWrap: true,
57
+ minItemWidth: 200,
58
+ maxItemWidth: 800,
59
+ itemGrowRatio: 1,
60
+ itemShrinkRatio: 1,
61
+ breakpoints: {},
62
+ ...config
63
+ };
64
+
65
+ this.state = this.createInitialState();
66
+ this.setupFlexbox();
67
+ }
68
+
69
+ /**
70
+ * Activate the enhanced flexbox
71
+ */
72
+ public activate(): void {
73
+ this.updateFlexbox();
74
+ this.setupObservers();
75
+ }
76
+
77
+ /**
78
+ * Deactivate and clean up
79
+ */
80
+ public deactivate(): void {
81
+ this.cleanupObservers();
82
+ this.removeFlexboxStyles();
83
+ }
84
+
85
+ /**
86
+ * Update flexbox configuration
87
+ */
88
+ public updateConfig(newConfig: Partial<FlexboxConfig>): void {
89
+ this.config = { ...this.config, ...newConfig };
90
+ this.updateFlexbox();
91
+ }
92
+
93
+ /**
94
+ * Get current flexbox state
95
+ */
96
+ public getState(): FlexboxState {
97
+ return { ...this.state };
98
+ }
99
+
100
+ /**
101
+ * Configure individual flex item
102
+ */
103
+ public configureItem(item: Element, config: FlexItemConfig): void {
104
+ const htmlItem = item as HTMLElement;
105
+
106
+ htmlItem.style.flexGrow = config.grow.toString();
107
+ htmlItem.style.flexShrink = config.shrink.toString();
108
+ htmlItem.style.flexBasis = typeof config.basis === 'number'
109
+ ? `${config.basis}px`
110
+ : config.basis;
111
+
112
+ if (config.order !== undefined) {
113
+ htmlItem.style.order = config.order.toString();
114
+ }
115
+
116
+ if (config.alignSelf) {
117
+ htmlItem.style.alignSelf = config.alignSelf;
118
+ }
119
+ }
120
+
121
+ /**
122
+ * Auto-configure all flex items
123
+ */
124
+ public autoConfigureItems(): void {
125
+ const items = Array.from(this.element.children) as HTMLElement[];
126
+ const optimalConfig = this.calculateOptimalItemConfig();
127
+
128
+ items.forEach(item => {
129
+ this.configureItem(item, optimalConfig);
130
+ });
131
+ }
132
+
133
+ /**
134
+ * Detect if wrapping is needed
135
+ */
136
+ public shouldWrap(): boolean {
137
+ if (!this.config.autoWrap) return this.config.wrap === 'wrap';
138
+
139
+ const containerWidth = this.element.getBoundingClientRect().width;
140
+ const itemCount = this.element.children.length;
141
+ const gap = this.getGapValue();
142
+ const minItemWidth = this.config.minItemWidth || 200;
143
+
144
+ const totalMinWidth = (itemCount * minItemWidth) + (gap * (itemCount - 1));
145
+ return totalMinWidth > containerWidth;
146
+ }
147
+
148
+ /**
149
+ * Calculate optimal space distribution
150
+ */
151
+ public calculateSpaceDistribution(): {
152
+ itemWidth: number;
153
+ gap: number;
154
+ remainingSpace: number;
155
+ } {
156
+ const containerWidth = this.element.getBoundingClientRect().width;
157
+ const itemCount = this.element.children.length;
158
+ const gap = this.getGapValue();
159
+
160
+ if (this.shouldWrap()) {
161
+ // Calculate for wrapped layout
162
+ const itemsPerLine = this.calculateItemsPerLine();
163
+ const availableWidth = containerWidth - (gap * (itemsPerLine - 1));
164
+ const itemWidth = availableWidth / itemsPerLine;
165
+
166
+ return {
167
+ itemWidth,
168
+ gap,
169
+ remainingSpace: 0
170
+ };
171
+ } else {
172
+ // Calculate for single line
173
+ const totalGapSpace = gap * (itemCount - 1);
174
+ const availableWidth = containerWidth - totalGapSpace;
175
+ const itemWidth = availableWidth / itemCount;
176
+
177
+ return {
178
+ itemWidth,
179
+ gap,
180
+ remainingSpace: Math.max(0, containerWidth - (itemCount * itemWidth + totalGapSpace))
181
+ };
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Calculate items per line for wrapped layout
187
+ */
188
+ public calculateItemsPerLine(): number {
189
+ const containerWidth = this.element.getBoundingClientRect().width;
190
+ const minItemWidth = this.config.minItemWidth || 200;
191
+ const gap = this.getGapValue();
192
+
193
+ // Binary search for optimal items per line
194
+ let min = 1;
195
+ let max = this.element.children.length;
196
+ let optimal = 1;
197
+
198
+ while (min <= max) {
199
+ const mid = Math.floor((min + max) / 2);
200
+ const totalWidth = (mid * minItemWidth) + (gap * (mid - 1));
201
+
202
+ if (totalWidth <= containerWidth) {
203
+ optimal = mid;
204
+ min = mid + 1;
205
+ } else {
206
+ max = mid - 1;
207
+ }
208
+ }
209
+
210
+ return optimal;
211
+ }
212
+
213
+ /**
214
+ * Setup initial flexbox styles
215
+ */
216
+ private setupFlexbox(): void {
217
+ const htmlElement = this.element as HTMLElement;
218
+ htmlElement.style.display = 'flex';
219
+ this.applyFlexboxStyles();
220
+ }
221
+
222
+ /**
223
+ * Update flexbox layout
224
+ */
225
+ private updateFlexbox(): void {
226
+ const containerRect = this.element.getBoundingClientRect();
227
+ const activeConfig = this.getActiveConfig(containerRect.width);
228
+
229
+ // Update state
230
+ this.state = {
231
+ containerWidth: containerRect.width,
232
+ containerHeight: containerRect.height,
233
+ itemCount: this.element.children.length,
234
+ wrappedLines: this.calculateWrappedLines(),
235
+ optimalItemWidth: this.calculateSpaceDistribution().itemWidth,
236
+ actualGap: this.getGapValue(),
237
+ overflow: this.checkOverflow()
238
+ };
239
+
240
+ // Apply styles with active config
241
+ this.applyFlexboxStyles(activeConfig);
242
+
243
+ // Auto-configure items if enabled
244
+ if (this.config.autoWrap) {
245
+ this.autoConfigureItems();
246
+ }
247
+ }
248
+
249
+ /**
250
+ * Apply flexbox styles
251
+ */
252
+ private applyFlexboxStyles(config: Required<FlexboxConfig> = this.config): void {
253
+ const htmlElement = this.element as HTMLElement;
254
+
255
+ htmlElement.style.flexDirection = config.direction;
256
+ htmlElement.style.flexWrap = config.wrap === 'auto'
257
+ ? (this.shouldWrap() ? 'wrap' : 'nowrap')
258
+ : config.wrap;
259
+ htmlElement.style.justifyContent = config.justify;
260
+ htmlElement.style.alignItems = config.align;
261
+ htmlElement.style.gap = `${this.getGapValue()}px`;
262
+ }
263
+
264
+ /**
265
+ * Calculate optimal item configuration
266
+ */
267
+ private calculateOptimalItemConfig(): FlexItemConfig {
268
+ const spaceDistribution = this.calculateSpaceDistribution();
269
+ const isWrapped = this.shouldWrap();
270
+
271
+ return {
272
+ grow: isWrapped ? 0 : this.config.itemGrowRatio,
273
+ shrink: this.config.itemShrinkRatio,
274
+ basis: isWrapped ? `${spaceDistribution.itemWidth}px` : 'auto',
275
+ alignSelf: 'auto'
276
+ };
277
+ }
278
+
279
+ /**
280
+ * Calculate number of wrapped lines
281
+ */
282
+ private calculateWrappedLines(): number {
283
+ if (!this.shouldWrap()) return 1;
284
+
285
+ const itemsPerLine = this.calculateItemsPerLine();
286
+ return Math.ceil(this.element.children.length / itemsPerLine);
287
+ }
288
+
289
+ /**
290
+ * Check if content overflows
291
+ */
292
+ private checkOverflow(): boolean {
293
+ const containerWidth = this.element.getBoundingClientRect().width;
294
+ const spaceDistribution = this.calculateSpaceDistribution();
295
+ const totalRequiredWidth = this.element.children.length * spaceDistribution.itemWidth +
296
+ (this.element.children.length - 1) * spaceDistribution.gap;
297
+
298
+ return totalRequiredWidth > containerWidth && !this.shouldWrap();
299
+ }
300
+
301
+ /**
302
+ * Get active configuration based on container width
303
+ */
304
+ private getActiveConfig(containerWidth: number): Required<FlexboxConfig> {
305
+ let activeConfig = { ...this.config };
306
+
307
+ if (this.config.breakpoints) {
308
+ const sortedBreakpoints = Object.entries(this.config.breakpoints)
309
+ .map(([name, config]) => ({ name, width: parseInt(name), config }))
310
+ .sort((a, b) => a.width - b.width);
311
+
312
+ for (const breakpoint of sortedBreakpoints) {
313
+ if (containerWidth >= breakpoint.width) {
314
+ activeConfig = { ...activeConfig, ...breakpoint.config };
315
+ }
316
+ }
317
+ }
318
+
319
+ return activeConfig;
320
+ }
321
+
322
+ /**
323
+ * Get gap value in pixels
324
+ */
325
+ private getGapValue(): number {
326
+ if (this.config.gap === 'fluid') {
327
+ const containerWidth = this.element.getBoundingClientRect().width;
328
+ return Math.max(8, Math.min(32, containerWidth * 0.02));
329
+ }
330
+ return this.config.gap as number;
331
+ }
332
+
333
+ /**
334
+ * Setup observers for responsive behavior
335
+ */
336
+ private setupObservers(): void {
337
+ if (!this.config.responsive) return;
338
+
339
+ this.resizeObserver = new ResizeObserver(() => {
340
+ this.updateFlexbox();
341
+ });
342
+ this.resizeObserver.observe(this.element);
343
+
344
+ this.mutationObserver = new MutationObserver(() => {
345
+ this.updateFlexbox();
346
+ });
347
+ this.mutationObserver.observe(this.element, {
348
+ childList: true,
349
+ subtree: false
350
+ });
351
+ }
352
+
353
+ /**
354
+ * Clean up observers
355
+ */
356
+ private cleanupObservers(): void {
357
+ if (this.resizeObserver) {
358
+ this.resizeObserver.disconnect();
359
+ this.resizeObserver = null;
360
+ }
361
+
362
+ if (this.mutationObserver) {
363
+ this.mutationObserver.disconnect();
364
+ this.mutationObserver = null;
365
+ }
366
+ }
367
+
368
+ /**
369
+ * Remove flexbox styles
370
+ */
371
+ private removeFlexboxStyles(): void {
372
+ const htmlElement = this.element as HTMLElement;
373
+
374
+ htmlElement.style.removeProperty('display');
375
+ htmlElement.style.removeProperty('flex-direction');
376
+ htmlElement.style.removeProperty('flex-wrap');
377
+ htmlElement.style.removeProperty('justify-content');
378
+ htmlElement.style.removeProperty('align-items');
379
+ htmlElement.style.removeProperty('gap');
380
+
381
+ // Remove item styles
382
+ Array.from(this.element.children).forEach(child => {
383
+ const htmlChild = child as HTMLElement;
384
+ htmlChild.style.removeProperty('flex-grow');
385
+ htmlChild.style.removeProperty('flex-shrink');
386
+ htmlChild.style.removeProperty('flex-basis');
387
+ htmlChild.style.removeProperty('order');
388
+ htmlChild.style.removeProperty('align-self');
389
+ });
390
+ }
391
+
392
+ /**
393
+ * Create initial state
394
+ */
395
+ private createInitialState(): FlexboxState {
396
+ return {
397
+ containerWidth: 0,
398
+ containerHeight: 0,
399
+ itemCount: 0,
400
+ wrappedLines: 1,
401
+ optimalItemWidth: 0,
402
+ actualGap: 16,
403
+ overflow: false
404
+ };
405
+ }
406
+ }