@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,275 @@
1
+ /**
2
+ * Plugin System for ProteusJS
3
+ * Enables extensibility and modular architecture
4
+ */
5
+
6
+ export interface ProteusPlugin {
7
+ name: string;
8
+ version: string;
9
+ dependencies?: string[];
10
+ install: (proteus: any) => void;
11
+ uninstall?: (proteus: any) => void;
12
+ config?: Record<string, any>;
13
+ }
14
+
15
+ export class PluginSystem {
16
+ private plugins: Map<string, ProteusPlugin> = new Map();
17
+ private installedPlugins: Set<string> = new Set();
18
+ private proteus: any;
19
+ private initialized: boolean = false;
20
+
21
+ constructor(proteus: any) {
22
+ this.proteus = proteus;
23
+ }
24
+
25
+ /**
26
+ * Initialize the plugin system
27
+ */
28
+ public init(): void {
29
+ if (this.initialized) return;
30
+ this.initialized = true;
31
+ }
32
+
33
+ /**
34
+ * Register a plugin
35
+ */
36
+ public register(plugin: ProteusPlugin): this {
37
+ if (this.plugins.has(plugin.name)) {
38
+ console.warn(`ProteusJS: Plugin "${plugin.name}" is already registered`);
39
+ return this;
40
+ }
41
+
42
+ // Validate plugin
43
+ if (!this.validatePlugin(plugin)) {
44
+ throw new Error(`ProteusJS: Invalid plugin "${plugin.name}"`);
45
+ }
46
+
47
+ this.plugins.set(plugin.name, plugin);
48
+ return this;
49
+ }
50
+
51
+ /**
52
+ * Install a plugin
53
+ */
54
+ public install(pluginName: string): this {
55
+ const plugin = this.plugins.get(pluginName);
56
+ if (!plugin) {
57
+ throw new Error(`ProteusJS: Plugin "${pluginName}" not found`);
58
+ }
59
+
60
+ if (this.installedPlugins.has(pluginName)) {
61
+ console.warn(`ProteusJS: Plugin "${pluginName}" is already installed`);
62
+ return this;
63
+ }
64
+
65
+ // Check dependencies
66
+ if (plugin.dependencies) {
67
+ for (const dep of plugin.dependencies) {
68
+ if (!this.installedPlugins.has(dep)) {
69
+ throw new Error(
70
+ `ProteusJS: Plugin "${pluginName}" requires dependency "${dep}" to be installed first`
71
+ );
72
+ }
73
+ }
74
+ }
75
+
76
+ try {
77
+ // Install the plugin
78
+ plugin.install(this.proteus);
79
+ this.installedPlugins.add(pluginName);
80
+
81
+ // Emit plugin installed event
82
+ this.proteus.getEventSystem().emit('pluginInstalled', {
83
+ plugin: pluginName,
84
+ version: plugin.version
85
+ });
86
+
87
+ console.log(`ProteusJS: Plugin "${pluginName}" v${plugin.version} installed`);
88
+ } catch (error) {
89
+ console.error(`ProteusJS: Failed to install plugin "${pluginName}":`, error);
90
+ throw error;
91
+ }
92
+
93
+ return this;
94
+ }
95
+
96
+ /**
97
+ * Uninstall a plugin
98
+ */
99
+ public uninstall(pluginName: string): this {
100
+ const plugin = this.plugins.get(pluginName);
101
+ if (!plugin) {
102
+ console.warn(`ProteusJS: Plugin "${pluginName}" not found`);
103
+ return this;
104
+ }
105
+
106
+ if (!this.installedPlugins.has(pluginName)) {
107
+ console.warn(`ProteusJS: Plugin "${pluginName}" is not installed`);
108
+ return this;
109
+ }
110
+
111
+ // Check if other plugins depend on this one
112
+ const dependents = this.getDependents(pluginName);
113
+ if (dependents.length > 0) {
114
+ throw new Error(
115
+ `ProteusJS: Cannot uninstall plugin "${pluginName}" because it's required by: ${dependents.join(', ')}`
116
+ );
117
+ }
118
+
119
+ try {
120
+ // Uninstall the plugin
121
+ if (plugin.uninstall) {
122
+ plugin.uninstall(this.proteus);
123
+ }
124
+ this.installedPlugins.delete(pluginName);
125
+
126
+ // Emit plugin uninstalled event
127
+ this.proteus.getEventSystem().emit('pluginUninstalled', {
128
+ plugin: pluginName,
129
+ version: plugin.version
130
+ });
131
+
132
+ console.log(`ProteusJS: Plugin "${pluginName}" uninstalled`);
133
+ } catch (error) {
134
+ console.error(`ProteusJS: Failed to uninstall plugin "${pluginName}":`, error);
135
+ throw error;
136
+ }
137
+
138
+ return this;
139
+ }
140
+
141
+ /**
142
+ * Check if a plugin is installed
143
+ */
144
+ public isInstalled(pluginName: string): boolean {
145
+ return this.installedPlugins.has(pluginName);
146
+ }
147
+
148
+ /**
149
+ * Get list of registered plugins
150
+ */
151
+ public getRegisteredPlugins(): string[] {
152
+ return Array.from(this.plugins.keys());
153
+ }
154
+
155
+ /**
156
+ * Get list of installed plugins
157
+ */
158
+ public getInstalledPlugins(): string[] {
159
+ return Array.from(this.installedPlugins);
160
+ }
161
+
162
+ /**
163
+ * Get plugin information
164
+ */
165
+ public getPluginInfo(pluginName: string): ProteusPlugin | undefined {
166
+ return this.plugins.get(pluginName);
167
+ }
168
+
169
+ /**
170
+ * Install multiple plugins in dependency order
171
+ */
172
+ public installMany(pluginNames: string[]): this {
173
+ const sortedPlugins = this.sortByDependencies(pluginNames);
174
+ for (const pluginName of sortedPlugins) {
175
+ this.install(pluginName);
176
+ }
177
+ return this;
178
+ }
179
+
180
+ /**
181
+ * Destroy the plugin system
182
+ */
183
+ public destroy(): void {
184
+ // Uninstall all plugins in reverse dependency order
185
+ const installedPlugins = Array.from(this.installedPlugins);
186
+ const sortedPlugins = this.sortByDependencies(installedPlugins).reverse();
187
+
188
+ for (const pluginName of sortedPlugins) {
189
+ try {
190
+ this.uninstall(pluginName);
191
+ } catch (error) {
192
+ console.error(`ProteusJS: Error uninstalling plugin "${pluginName}":`, error);
193
+ }
194
+ }
195
+
196
+ this.plugins.clear();
197
+ this.installedPlugins.clear();
198
+ this.initialized = false;
199
+ }
200
+
201
+ /**
202
+ * Validate plugin structure
203
+ */
204
+ private validatePlugin(plugin: ProteusPlugin): boolean {
205
+ if (!plugin.name || typeof plugin.name !== 'string') {
206
+ console.error('ProteusJS: Plugin must have a valid name');
207
+ return false;
208
+ }
209
+
210
+ if (!plugin.version || typeof plugin.version !== 'string') {
211
+ console.error('ProteusJS: Plugin must have a valid version');
212
+ return false;
213
+ }
214
+
215
+ if (!plugin.install || typeof plugin.install !== 'function') {
216
+ console.error('ProteusJS: Plugin must have an install function');
217
+ return false;
218
+ }
219
+
220
+ return true;
221
+ }
222
+
223
+ /**
224
+ * Get plugins that depend on the given plugin
225
+ */
226
+ private getDependents(pluginName: string): string[] {
227
+ const dependents: string[] = [];
228
+
229
+ for (const [name, plugin] of this.plugins) {
230
+ if (this.installedPlugins.has(name) && plugin.dependencies?.includes(pluginName)) {
231
+ dependents.push(name);
232
+ }
233
+ }
234
+
235
+ return dependents;
236
+ }
237
+
238
+ /**
239
+ * Sort plugins by dependency order
240
+ */
241
+ private sortByDependencies(pluginNames: string[]): string[] {
242
+ const sorted: string[] = [];
243
+ const visited = new Set<string>();
244
+ const visiting = new Set<string>();
245
+
246
+ const visit = (pluginName: string): void => {
247
+ if (visiting.has(pluginName)) {
248
+ throw new Error(`ProteusJS: Circular dependency detected involving plugin "${pluginName}"`);
249
+ }
250
+
251
+ if (visited.has(pluginName)) return;
252
+
253
+ visiting.add(pluginName);
254
+
255
+ const plugin = this.plugins.get(pluginName);
256
+ if (plugin?.dependencies) {
257
+ for (const dep of plugin.dependencies) {
258
+ if (pluginNames.includes(dep)) {
259
+ visit(dep);
260
+ }
261
+ }
262
+ }
263
+
264
+ visiting.delete(pluginName);
265
+ visited.add(pluginName);
266
+ sorted.push(pluginName);
267
+ };
268
+
269
+ for (const pluginName of pluginNames) {
270
+ visit(pluginName);
271
+ }
272
+
273
+ return sorted;
274
+ }
275
+ }
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Tests for ProteusJS core functionality
3
+ */
4
+
5
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
6
+ import { ProteusJS } from './ProteusJS';
7
+
8
+ describe('ProteusJS', () => {
9
+ let proteus: ProteusJS;
10
+
11
+ beforeEach(() => {
12
+ // Reset singleton instance
13
+ (ProteusJS as any).instance = null;
14
+ proteus = new ProteusJS({ debug: true, autoInit: false });
15
+ });
16
+
17
+ afterEach(() => {
18
+ if (proteus) {
19
+ proteus.destroy();
20
+ }
21
+ });
22
+
23
+ describe('Initialization', () => {
24
+ it('should create a singleton instance', () => {
25
+ const instance1 = new ProteusJS();
26
+ const instance2 = new ProteusJS();
27
+ expect(instance1).toBe(instance2);
28
+ });
29
+
30
+ it('should initialize with default config', () => {
31
+ const config = proteus.getConfig();
32
+ expect(config.debug).toBe(true);
33
+ expect(config.accessibility).toBe(true);
34
+ expect(config.performance).toBe('high');
35
+ });
36
+
37
+ it('should merge custom config with defaults', () => {
38
+ const customProteus = new ProteusJS({
39
+ debug: false,
40
+ performance: 'low',
41
+ containers: {
42
+ autoDetect: false
43
+ }
44
+ });
45
+
46
+ const config = customProteus.getConfig();
47
+ expect(config.debug).toBe(false);
48
+ expect(config.performance).toBe('low');
49
+ expect(config.containers.autoDetect).toBe(false);
50
+ expect(config.accessibility).toBe(true); // Should keep default
51
+
52
+ customProteus.destroy();
53
+ });
54
+
55
+ it('should initialize successfully', () => {
56
+ expect(proteus.isInitialized()).toBe(false);
57
+ proteus.init();
58
+ expect(proteus.isInitialized()).toBe(true);
59
+ });
60
+
61
+ it('should not initialize twice', () => {
62
+ const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
63
+
64
+ proteus.init();
65
+ proteus.init(); // Second call should warn
66
+
67
+ expect(consoleSpy).toHaveBeenCalledWith('ProteusJS: Already initialized');
68
+ consoleSpy.mockRestore();
69
+ });
70
+ });
71
+
72
+ describe('Configuration', () => {
73
+ it('should update configuration', () => {
74
+ proteus.updateConfig({ debug: false });
75
+ const config = proteus.getConfig();
76
+ expect(config.debug).toBe(false);
77
+ });
78
+
79
+ it('should emit config update event', () => {
80
+ const eventSystem = proteus.getEventSystem();
81
+ const mockCallback = vi.fn();
82
+
83
+ eventSystem.on('configUpdate', mockCallback);
84
+ proteus.updateConfig({ debug: false });
85
+
86
+ expect(mockCallback).toHaveBeenCalledWith(
87
+ expect.objectContaining({
88
+ type: 'configUpdate',
89
+ detail: expect.objectContaining({
90
+ config: expect.any(Object)
91
+ })
92
+ })
93
+ );
94
+ });
95
+ });
96
+
97
+ describe('Systems', () => {
98
+ it('should provide access to event system', () => {
99
+ const eventSystem = proteus.getEventSystem();
100
+ expect(eventSystem).toBeDefined();
101
+ expect(typeof eventSystem.on).toBe('function');
102
+ });
103
+
104
+ it('should provide access to plugin system', () => {
105
+ const pluginSystem = proteus.getPluginSystem();
106
+ expect(pluginSystem).toBeDefined();
107
+ expect(typeof pluginSystem.register).toBe('function');
108
+ });
109
+
110
+ it('should provide access to performance monitor', () => {
111
+ const performanceMonitor = proteus.getPerformanceMonitor();
112
+ expect(performanceMonitor).toBeDefined();
113
+ expect(typeof performanceMonitor.getMetrics).toBe('function');
114
+ });
115
+ });
116
+
117
+ describe('Static methods', () => {
118
+ it('should return version', () => {
119
+ const version = ProteusJS.getVersion();
120
+ expect(typeof version).toBe('string');
121
+ expect(version).toMatch(/^\d+\.\d+\.\d+$/);
122
+ });
123
+
124
+ it('should return support info', () => {
125
+ const support = ProteusJS.getSupportInfo();
126
+ expect(support).toBeDefined();
127
+ expect(typeof support.resizeObserver).toBe('boolean');
128
+ expect(typeof support.intersectionObserver).toBe('boolean');
129
+ });
130
+
131
+ it('should check browser support', () => {
132
+ const isSupported = ProteusJS.isSupported();
133
+ expect(typeof isSupported).toBe('boolean');
134
+ });
135
+
136
+ it('should get or create global instance', () => {
137
+ const instance1 = ProteusJS.getInstance();
138
+ const instance2 = ProteusJS.getInstance();
139
+ expect(instance1).toBe(instance2);
140
+
141
+ instance1.destroy();
142
+ });
143
+ });
144
+
145
+ describe('Cleanup', () => {
146
+ it('should destroy properly', () => {
147
+ proteus.init();
148
+ expect(proteus.isInitialized()).toBe(true);
149
+
150
+ proteus.destroy();
151
+ expect(proteus.isInitialized()).toBe(false);
152
+ });
153
+
154
+ it('should reset singleton on destroy', () => {
155
+ proteus.init();
156
+ proteus.destroy();
157
+
158
+ const newInstance = new ProteusJS();
159
+ expect(newInstance).not.toBe(proteus);
160
+
161
+ newInstance.destroy();
162
+ });
163
+ });
164
+ });