@coherent.js/core 1.0.0-beta.2

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 (116) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +130 -0
  3. package/dist/coherent.d.ts +472 -0
  4. package/dist/coherent.d.ts.map +1 -0
  5. package/dist/coherent.js +590 -0
  6. package/dist/coherent.js.map +1 -0
  7. package/dist/components/component-system.d.ts +1138 -0
  8. package/dist/components/component-system.d.ts.map +1 -0
  9. package/dist/components/component-system.js +2220 -0
  10. package/dist/components/component-system.js.map +1 -0
  11. package/dist/components/lifecycle.d.ts +212 -0
  12. package/dist/components/lifecycle.d.ts.map +1 -0
  13. package/dist/components/lifecycle.js +525 -0
  14. package/dist/components/lifecycle.js.map +1 -0
  15. package/dist/core/html-utils.d.ts +14 -0
  16. package/dist/core/html-utils.d.ts.map +1 -0
  17. package/dist/core/html-utils.js +166 -0
  18. package/dist/core/html-utils.js.map +1 -0
  19. package/dist/core/object-factory.d.ts +38 -0
  20. package/dist/core/object-factory.d.ts.map +1 -0
  21. package/dist/core/object-factory.js +63 -0
  22. package/dist/core/object-factory.js.map +1 -0
  23. package/dist/core/object-utils.d.ts +77 -0
  24. package/dist/core/object-utils.d.ts.map +1 -0
  25. package/dist/core/object-utils.js +502 -0
  26. package/dist/core/object-utils.js.map +1 -0
  27. package/dist/dev/dev-tools.d.ts +194 -0
  28. package/dist/dev/dev-tools.d.ts.map +1 -0
  29. package/dist/dev/dev-tools.js +846 -0
  30. package/dist/dev/dev-tools.js.map +1 -0
  31. package/dist/forms/validation.d.ts +271 -0
  32. package/dist/forms/validation.d.ts.map +1 -0
  33. package/dist/forms/validation.js +573 -0
  34. package/dist/forms/validation.js.map +1 -0
  35. package/dist/index.cjs +5281 -0
  36. package/dist/index.cjs.map +7 -0
  37. package/dist/index.js +5204 -0
  38. package/dist/index.js.map +7 -0
  39. package/dist/performance/bundle-optimizer.d.ts +95 -0
  40. package/dist/performance/bundle-optimizer.d.ts.map +1 -0
  41. package/dist/performance/bundle-optimizer.js +192 -0
  42. package/dist/performance/bundle-optimizer.js.map +1 -0
  43. package/dist/performance/cache-manager.d.ts +107 -0
  44. package/dist/performance/cache-manager.d.ts.map +1 -0
  45. package/dist/performance/cache-manager.js +314 -0
  46. package/dist/performance/cache-manager.js.map +1 -0
  47. package/dist/performance/component-cache.d.ts +120 -0
  48. package/dist/performance/component-cache.d.ts.map +1 -0
  49. package/dist/performance/component-cache.js +364 -0
  50. package/dist/performance/component-cache.js.map +1 -0
  51. package/dist/performance/monitor.d.ts +189 -0
  52. package/dist/performance/monitor.d.ts.map +1 -0
  53. package/dist/performance/monitor.js +347 -0
  54. package/dist/performance/monitor.js.map +1 -0
  55. package/dist/rendering/base-renderer.d.ts +140 -0
  56. package/dist/rendering/base-renderer.d.ts.map +1 -0
  57. package/dist/rendering/base-renderer.js +409 -0
  58. package/dist/rendering/base-renderer.js.map +1 -0
  59. package/dist/rendering/css-manager.d.ts +73 -0
  60. package/dist/rendering/css-manager.d.ts.map +1 -0
  61. package/dist/rendering/css-manager.js +176 -0
  62. package/dist/rendering/css-manager.js.map +1 -0
  63. package/dist/rendering/dom-renderer.d.ts +62 -0
  64. package/dist/rendering/dom-renderer.d.ts.map +1 -0
  65. package/dist/rendering/dom-renderer.js +252 -0
  66. package/dist/rendering/dom-renderer.js.map +1 -0
  67. package/dist/rendering/html-renderer.d.ts +67 -0
  68. package/dist/rendering/html-renderer.d.ts.map +1 -0
  69. package/dist/rendering/html-renderer.js +444 -0
  70. package/dist/rendering/html-renderer.js.map +1 -0
  71. package/dist/rendering/renderer-config.d.ts +282 -0
  72. package/dist/rendering/renderer-config.d.ts.map +1 -0
  73. package/dist/rendering/renderer-config.js +144 -0
  74. package/dist/rendering/renderer-config.js.map +1 -0
  75. package/dist/rendering/streaming-renderer.d.ts +117 -0
  76. package/dist/rendering/streaming-renderer.d.ts.map +1 -0
  77. package/dist/rendering/streaming-renderer.js +326 -0
  78. package/dist/rendering/streaming-renderer.js.map +1 -0
  79. package/dist/rendering/vdom-diff.d.ts +47 -0
  80. package/dist/rendering/vdom-diff.d.ts.map +1 -0
  81. package/dist/rendering/vdom-diff.js +416 -0
  82. package/dist/rendering/vdom-diff.js.map +1 -0
  83. package/dist/routing/router.d.ts +241 -0
  84. package/dist/routing/router.d.ts.map +1 -0
  85. package/dist/routing/router.js +648 -0
  86. package/dist/routing/router.js.map +1 -0
  87. package/dist/state/reactive-state.d.ts +166 -0
  88. package/dist/state/reactive-state.d.ts.map +1 -0
  89. package/dist/state/reactive-state.js +546 -0
  90. package/dist/state/reactive-state.js.map +1 -0
  91. package/dist/state/state-manager.d.ts +45 -0
  92. package/dist/state/state-manager.d.ts.map +1 -0
  93. package/dist/state/state-manager.js +151 -0
  94. package/dist/state/state-manager.js.map +1 -0
  95. package/dist/types/constants.d.ts +8 -0
  96. package/dist/types/constants.d.ts.map +1 -0
  97. package/dist/types/constants.js +36 -0
  98. package/dist/types/constants.js.map +1 -0
  99. package/dist/utils/dependency-utils.d.ts +43 -0
  100. package/dist/utils/dependency-utils.d.ts.map +1 -0
  101. package/dist/utils/dependency-utils.js +105 -0
  102. package/dist/utils/dependency-utils.js.map +1 -0
  103. package/dist/utils/error-handler.d.ts +148 -0
  104. package/dist/utils/error-handler.d.ts.map +1 -0
  105. package/dist/utils/error-handler.js +468 -0
  106. package/dist/utils/error-handler.js.map +1 -0
  107. package/dist/utils/normalization.d.ts +3 -0
  108. package/dist/utils/normalization.d.ts.map +1 -0
  109. package/dist/utils/normalization.js +24 -0
  110. package/dist/utils/normalization.js.map +1 -0
  111. package/dist/utils/validation.d.ts +10 -0
  112. package/dist/utils/validation.d.ts.map +1 -0
  113. package/dist/utils/validation.js +32 -0
  114. package/dist/utils/validation.js.map +1 -0
  115. package/package.json +44 -0
  116. package/types/index.d.ts +734 -0
@@ -0,0 +1,2220 @@
1
+ /**
2
+ * Component System for Coherent.js
3
+ * Provides component definition, lifecycle, composition, and state management
4
+ */
5
+ import { deepClone, validateComponent } from '../core/object-utils.js';
6
+ import { performanceMonitor } from '../performance/monitor.js';
7
+ /**
8
+ * Component registry for global component management
9
+ */
10
+ const COMPONENT_REGISTRY = new Map();
11
+ // eslint-disable-next-line no-unused-vars -- kept for future devtools/features
12
+ const COMPONENT_INSTANCES = new WeakMap();
13
+ const COMPONENT_METADATA = new WeakMap();
14
+ /**
15
+ * Component lifecycle hooks
16
+ */
17
+ // eslint-disable-next-line no-unused-vars -- lifecycle map kept for planned hooks
18
+ const LIFECYCLE_HOOKS = {
19
+ beforeCreate: 'beforeCreate',
20
+ created: 'created',
21
+ beforeMount: 'beforeMount',
22
+ mounted: 'mounted',
23
+ beforeUpdate: 'beforeUpdate',
24
+ updated: 'updated',
25
+ beforeDestroy: 'beforeDestroy',
26
+ destroyed: 'destroyed',
27
+ errorCaptured: 'errorCaptured'
28
+ };
29
+ /**
30
+ * Component state management class
31
+ *
32
+ * @class ComponentState
33
+ * @description Manages component state with reactive updates and listener notifications.
34
+ * Provides immutable state updates with change detection.
35
+ *
36
+ * @param {Object} [initialState={}] - Initial state object
37
+ *
38
+ * @example
39
+ * const state = new ComponentState({ count: 0 });
40
+ * state.set({ count: 1 });
41
+ * const count = state.get('count'); // 1
42
+ */
43
+ class ComponentState {
44
+ constructor(initialState = {}) {
45
+ this.state = { ...initialState };
46
+ this.listeners = new Set();
47
+ this.isUpdating = false;
48
+ }
49
+ /**
50
+ * Get state value by key or entire state
51
+ *
52
+ * @param {string} [key] - State key to retrieve
53
+ * @returns {*} State value or entire state object
54
+ */
55
+ get(key) {
56
+ return key ? this.state[key] : { ...this.state };
57
+ }
58
+ /**
59
+ * Update state with new values
60
+ *
61
+ * @param {Object} updates - State updates to apply
62
+ * @returns {ComponentState} This instance for chaining
63
+ */
64
+ set(updates) {
65
+ if (this.isUpdating)
66
+ return this;
67
+ const oldState = { ...this.state };
68
+ if (typeof updates === 'function') {
69
+ updates = updates(oldState);
70
+ }
71
+ this.state = { ...this.state, ...updates };
72
+ // Notify listeners
73
+ this.notifyListeners(oldState, this.state);
74
+ return this;
75
+ }
76
+ subscribe(listener) {
77
+ this.listeners.add(listener);
78
+ return () => this.listeners.delete(listener);
79
+ }
80
+ notifyListeners(oldState, newState) {
81
+ if (this.listeners.size === 0)
82
+ return;
83
+ this.isUpdating = true;
84
+ this.listeners.forEach(listener => {
85
+ try {
86
+ listener(newState, oldState);
87
+ }
88
+ catch (error) {
89
+ console.error('State listener error:', error);
90
+ }
91
+ });
92
+ this.isUpdating = false;
93
+ }
94
+ }
95
+ /**
96
+ * Base Component class
97
+ */
98
+ export class Component {
99
+ constructor(definition = {}) {
100
+ this.definition = definition;
101
+ this.name = definition.name || 'AnonymousComponent';
102
+ this.props = {};
103
+ this.state = new ComponentState(definition.state || {});
104
+ this.children = [];
105
+ this.parent = null;
106
+ this.rendered = null;
107
+ this.isMounted = false;
108
+ this.isDestroyed = false;
109
+ // Lifecycle hooks
110
+ this.hooks = {
111
+ beforeCreate: definition.beforeCreate || (() => {
112
+ }),
113
+ created: definition.created || (() => {
114
+ }),
115
+ beforeMount: definition.beforeMount || (() => {
116
+ }),
117
+ mounted: definition.mounted || (() => {
118
+ }),
119
+ beforeUpdate: definition.beforeUpdate || (() => {
120
+ }),
121
+ updated: definition.updated || (() => {
122
+ }),
123
+ beforeDestroy: definition.beforeDestroy || (() => {
124
+ }),
125
+ destroyed: definition.destroyed || (() => {
126
+ }),
127
+ errorCaptured: definition.errorCaptured || (() => {
128
+ })
129
+ };
130
+ // Methods
131
+ this.methods = definition.methods || {};
132
+ Object.keys(this.methods).forEach(methodName => {
133
+ if (typeof this.methods[methodName] === 'function') {
134
+ this[methodName] = this.methods[methodName].bind(this);
135
+ }
136
+ });
137
+ // Computed properties
138
+ this.computed = definition.computed || {};
139
+ this.computedCache = new Map();
140
+ // Watch properties
141
+ this.watchers = definition.watch || {};
142
+ this.setupWatchers();
143
+ // Store metadata
144
+ COMPONENT_METADATA.set(this, {
145
+ createdAt: Date.now(),
146
+ updateCount: 0,
147
+ renderCount: 0
148
+ });
149
+ // Initialize lifecycle
150
+ this.callHook('beforeCreate');
151
+ this.initialize();
152
+ this.callHook('created');
153
+ }
154
+ /**
155
+ * Initialize component
156
+ */
157
+ initialize() {
158
+ // Set up state subscription for re-rendering
159
+ this.unsubscribeState = this.state.subscribe((newState, oldState) => {
160
+ this.onStateChange(newState, oldState);
161
+ });
162
+ // Initialize computed properties
163
+ this.initializeComputed();
164
+ }
165
+ /**
166
+ * Set up watchers for reactive data
167
+ */
168
+ setupWatchers() {
169
+ Object.keys(this.watchers).forEach(key => {
170
+ const handler = this.watchers[key];
171
+ // Watch state changes
172
+ this.state.subscribe((newState, oldState) => {
173
+ if (newState[key] !== oldState[key]) {
174
+ handler.call(this, newState[key], oldState[key]);
175
+ }
176
+ });
177
+ });
178
+ }
179
+ /**
180
+ * Initialize computed properties
181
+ */
182
+ initializeComputed() {
183
+ Object.keys(this.computed).forEach(key => {
184
+ Object.defineProperty(this, key, {
185
+ get: () => {
186
+ if (!this.computedCache.has(key)) {
187
+ const value = this.computed[key].call(this);
188
+ this.computedCache.set(key, value);
189
+ }
190
+ return this.computedCache.get(key);
191
+ },
192
+ enumerable: true
193
+ });
194
+ });
195
+ }
196
+ /**
197
+ * Handle state changes
198
+ */
199
+ onStateChange() {
200
+ if (this.isDestroyed)
201
+ return;
202
+ // Clear computed cache
203
+ this.computedCache.clear();
204
+ // Trigger update if mounted
205
+ if (this.isMounted) {
206
+ this.update();
207
+ }
208
+ }
209
+ /**
210
+ * Call lifecycle hook
211
+ */
212
+ callHook(hookName, ...args) {
213
+ try {
214
+ if (this.hooks[hookName]) {
215
+ return this.hooks[hookName].call(this, ...args);
216
+ }
217
+ }
218
+ catch (error) {
219
+ this.handleError(error, `${hookName} hook`);
220
+ }
221
+ }
222
+ /**
223
+ * Handle component errors
224
+ */
225
+ handleError(error) {
226
+ console.error(`Component Error in ${this.name}:`, error);
227
+ // Call error hook
228
+ this.callHook('errorCaptured', error);
229
+ // Propagate to parent
230
+ if (this.parent && this.parent.handleError) {
231
+ this.parent.handleError(error, `${this.name} -> ${context}`);
232
+ }
233
+ }
234
+ /**
235
+ * Render the component
236
+ */
237
+ render(props = {}) {
238
+ if (this.isDestroyed) {
239
+ console.warn(`Attempting to render destroyed component: ${this.name}`);
240
+ return null;
241
+ }
242
+ try {
243
+ // Update metadata
244
+ const metadata = COMPONENT_METADATA.get(this);
245
+ if (metadata) {
246
+ metadata.renderCount++;
247
+ }
248
+ // Set props
249
+ this.props = { ...props };
250
+ // Call render method
251
+ if (typeof this.definition.render === 'function') {
252
+ this.rendered = this.definition.render.call(this, this.props, this.state.get());
253
+ }
254
+ else if (typeof this.definition.template !== 'undefined') {
255
+ this.rendered = this.processTemplate(this.definition.template, this.props, this.state.get());
256
+ }
257
+ else {
258
+ throw new Error(`Component ${this.name} must have either render method or template`);
259
+ }
260
+ // Validate rendered output
261
+ if (this.rendered !== null) {
262
+ validateComponent(this.rendered, this.name);
263
+ }
264
+ return this.rendered;
265
+ }
266
+ catch (error) {
267
+ this.handleError(error);
268
+ return { div: { className: 'component-error', text: `Error in ${this.name}` } };
269
+ }
270
+ }
271
+ /**
272
+ * Process template with data
273
+ */
274
+ processTemplate(template, props, state) {
275
+ if (typeof template === 'function') {
276
+ return template.call(this, props, state);
277
+ }
278
+ if (typeof template === 'string') {
279
+ // Simple string interpolation
280
+ return template.replace(/\{\{(\w+)\}\}/g, (match, key) => {
281
+ return props[key] || state[key] || '';
282
+ });
283
+ }
284
+ // Clone template object and process
285
+ const processed = deepClone(template);
286
+ this.interpolateObject(processed, { ...props, ...state });
287
+ return processed;
288
+ }
289
+ /**
290
+ * Interpolate object with data
291
+ */
292
+ interpolateObject(obj, data) {
293
+ if (typeof obj === 'string') {
294
+ return obj.replace(/\{\{(\w+)\}\}/g, (match, key) => data[key] || '');
295
+ }
296
+ if (Array.isArray(obj)) {
297
+ return obj.map(item => this.interpolateObject(item, data));
298
+ }
299
+ if (obj && typeof obj === 'object') {
300
+ Object.keys(obj).forEach(key => {
301
+ obj[key] = this.interpolateObject(obj[key], data);
302
+ });
303
+ }
304
+ return obj;
305
+ }
306
+ /**
307
+ * Mount the component
308
+ */
309
+ mount() {
310
+ if (this.isMounted || this.isDestroyed)
311
+ return this;
312
+ this.callHook('beforeMount');
313
+ this.isMounted = true;
314
+ this.callHook('mounted');
315
+ return this;
316
+ }
317
+ /**
318
+ * Update the component
319
+ */
320
+ update() {
321
+ if (!this.isMounted || this.isDestroyed)
322
+ return this;
323
+ const metadata = COMPONENT_METADATA.get(this);
324
+ if (metadata) {
325
+ metadata.updateCount++;
326
+ }
327
+ this.callHook('beforeUpdate');
328
+ // Re-render will happen automatically via state subscription
329
+ this.callHook('updated');
330
+ return this;
331
+ }
332
+ /**
333
+ * Destroy the component
334
+ */
335
+ destroy() {
336
+ if (this.isDestroyed)
337
+ return this;
338
+ this.callHook('beforeDestroy');
339
+ // Cleanup
340
+ if (this.unsubscribeState) {
341
+ this.unsubscribeState();
342
+ }
343
+ // Destroy children
344
+ this.children.forEach(child => {
345
+ if (child.destroy) {
346
+ child.destroy();
347
+ }
348
+ });
349
+ this.isMounted = false;
350
+ this.isDestroyed = true;
351
+ this.children = [];
352
+ this.parent = null;
353
+ this.callHook('destroyed');
354
+ return this;
355
+ }
356
+ /**
357
+ * Get component metadata
358
+ */
359
+ getMetadata() {
360
+ return COMPONENT_METADATA.get(this) || {};
361
+ }
362
+ /**
363
+ * Clone component with new props/state
364
+ */
365
+ clone(overrides = {}) {
366
+ const newDefinition = { ...this.definition, ...overrides };
367
+ return new Component(newDefinition);
368
+ }
369
+ }
370
+ /**
371
+ * Create a functional component
372
+ */
373
+ export function createComponent(definition) {
374
+ if (typeof definition === 'function') {
375
+ // Convert function to component definition
376
+ definition = {
377
+ name: definition.name || 'FunctionalComponent',
378
+ render: definition
379
+ };
380
+ }
381
+ return new Component(definition);
382
+ }
383
+ /**
384
+ * Create a component factory
385
+ */
386
+ export function defineComponent(definition) {
387
+ const componentFactory = (_props) => {
388
+ const component = new Component(definition);
389
+ return component.render(_props);
390
+ };
391
+ // Add static properties
392
+ componentFactory.componentName = definition.name || 'Component';
393
+ componentFactory.definition = definition;
394
+ return componentFactory;
395
+ }
396
+ /**
397
+ * Register a global component
398
+ */
399
+ export function registerComponent(name, definition) {
400
+ if (COMPONENT_REGISTRY.has(name)) {
401
+ console.warn(`Component ${name} is already registered. Overriding.`);
402
+ }
403
+ const component = typeof definition === 'function' ?
404
+ defineComponent({ name, render: definition }) :
405
+ defineComponent(definition);
406
+ COMPONENT_REGISTRY.set(name, component);
407
+ return component;
408
+ }
409
+ /**
410
+ * Get a registered component
411
+ */
412
+ export function getComponent(name) {
413
+ return COMPONENT_REGISTRY.get(name);
414
+ }
415
+ /**
416
+ * Get all registered components
417
+ */
418
+ export function getRegisteredComponents() {
419
+ return new Map(COMPONENT_REGISTRY);
420
+ }
421
+ /**
422
+ * Create a higher-order component
423
+ */
424
+ export function createHOC(enhancer) {
425
+ return (WrappedComponent) => {
426
+ return defineComponent({
427
+ name: `HOC(${WrappedComponent.componentName || 'Component'})`,
428
+ render(_props) {
429
+ return enhancer(WrappedComponent, _props);
430
+ }
431
+ });
432
+ };
433
+ }
434
+ /**
435
+ * Mixin functionality
436
+ */
437
+ export function createMixin(mixin) {
438
+ return (componentDefinition) => {
439
+ return {
440
+ ...mixin,
441
+ ...componentDefinition,
442
+ // Merge methods
443
+ methods: {
444
+ ...mixin.methods,
445
+ ...componentDefinition.methods
446
+ },
447
+ // Merge computed
448
+ computed: {
449
+ ...mixin.computed,
450
+ ...componentDefinition.computed
451
+ },
452
+ // Merge watchers
453
+ watch: {
454
+ ...mixin.watch,
455
+ ...componentDefinition.watch
456
+ },
457
+ // Merge state
458
+ state: {
459
+ ...mixin.state,
460
+ ...componentDefinition.state
461
+ }
462
+ };
463
+ };
464
+ }
465
+ /**
466
+ * Component composition utilities
467
+ */
468
+ export const compose = {
469
+ /**
470
+ * Combine multiple components
471
+ */
472
+ combine: (...components) => {
473
+ return defineComponent({
474
+ name: 'ComposedComponent',
475
+ render(_props) {
476
+ return components.map(comp => typeof comp === 'function' ? comp(_props) : comp);
477
+ }
478
+ });
479
+ },
480
+ /**
481
+ * Conditionally render components
482
+ */
483
+ conditional: (condition, trueComponent, falseComponent = null) => {
484
+ return defineComponent({
485
+ name: 'ConditionalComponent',
486
+ render(_props) {
487
+ const shouldRender = typeof condition === 'function' ?
488
+ condition(_props) : condition;
489
+ if (shouldRender) {
490
+ return typeof trueComponent === 'function' ?
491
+ trueComponent(_props) : trueComponent;
492
+ }
493
+ else if (falseComponent) {
494
+ return typeof falseComponent === 'function' ?
495
+ falseComponent(_props) : falseComponent;
496
+ }
497
+ return null;
498
+ }
499
+ });
500
+ },
501
+ /**
502
+ * Loop over data to render components
503
+ */
504
+ loop: (data, itemComponent, keyFn = (item, index) => index) => {
505
+ return defineComponent({
506
+ name: 'LoopComponent',
507
+ render(_props) {
508
+ const items = typeof data === 'function' ? data(_props) : data;
509
+ if (!Array.isArray(items)) {
510
+ console.warn('Loop component expects array data');
511
+ return null;
512
+ }
513
+ return items.map((item, index) => {
514
+ const key = keyFn(item, index);
515
+ const itemProps = { ...props, item, index, key };
516
+ return typeof itemComponent === 'function' ?
517
+ itemComponent(itemProps) : itemComponent;
518
+ });
519
+ }
520
+ });
521
+ }
522
+ };
523
+ /**
524
+ * Component utilities
525
+ */
526
+ export const componentUtils = {
527
+ /**
528
+ * Get component tree information
529
+ */
530
+ getComponentTree: (component) => {
531
+ const tree = {
532
+ name: component.name || 'Unknown',
533
+ props: component.props || {},
534
+ state: component.state ? component.state.get() : {},
535
+ children: [],
536
+ metadata: component.getMetadata ? component.getMetadata() : {}
537
+ };
538
+ if (component.children && component.children.length > 0) {
539
+ tree.children = component.children.map(child => componentUtils.getComponentTree(child));
540
+ }
541
+ return tree;
542
+ },
543
+ /**
544
+ * Find component by name in tree
545
+ */
546
+ findComponent: (component, name) => {
547
+ if (component.name === name) {
548
+ return component;
549
+ }
550
+ if (component.children) {
551
+ for (const child of component.children) {
552
+ const found = componentUtils.findComponent(child, name);
553
+ if (found)
554
+ return found;
555
+ }
556
+ }
557
+ return null;
558
+ },
559
+ /**
560
+ * Get component performance metrics
561
+ */
562
+ getPerformanceMetrics: (component) => {
563
+ const metadata = component.getMetadata ? component.getMetadata() : {};
564
+ return {
565
+ renderCount: metadata.renderCount || 0,
566
+ updateCount: metadata.updateCount || 0,
567
+ createdAt: metadata.createdAt || Date.now(),
568
+ age: Date.now() - (metadata.createdAt || Date.now())
569
+ };
570
+ },
571
+ /**
572
+ * Validate component definition
573
+ */
574
+ validateDefinition: (definition) => {
575
+ const errors = [];
576
+ if (!definition || typeof definition !== 'object') {
577
+ errors.push('Definition must be an object');
578
+ return errors;
579
+ }
580
+ if (!definition.render && !definition.template) {
581
+ errors.push('Component must have either render method or template');
582
+ }
583
+ if (definition.render && typeof definition.render !== 'function') {
584
+ errors.push('render must be a function');
585
+ }
586
+ if (definition.methods && typeof definition.methods !== 'object') {
587
+ errors.push('methods must be an object');
588
+ }
589
+ if (definition.computed && typeof definition.computed !== 'object') {
590
+ errors.push('computed must be an object');
591
+ }
592
+ if (definition.watch && typeof definition.watch !== 'object') {
593
+ errors.push('watch must be an object');
594
+ }
595
+ return errors;
596
+ }
597
+ };
598
+ /**
599
+ * Performance monitoring for components
600
+ */
601
+ if (performanceMonitor) {
602
+ const originalRender = Component.prototype.render;
603
+ Component.prototype.render = function (...args) {
604
+ const start = performance.now();
605
+ const result = originalRender.apply(this, args);
606
+ const duration = performance.now() - start;
607
+ performanceMonitor.recordRender('component', duration, {
608
+ name: this.name,
609
+ propsSize: JSON.stringify(this.props || {}).length,
610
+ hasState: Object.keys(this.state?.get() || {}).length > 0
611
+ });
612
+ return result;
613
+ };
614
+ }
615
+ /**
616
+ * Development helpers
617
+ */
618
+ export const dev = {
619
+ /**
620
+ * Get all component instances
621
+ */
622
+ getAllComponents: () => {
623
+ return Array.from(COMPONENT_REGISTRY.entries()).map(([name, factory]) => ({
624
+ name,
625
+ factory,
626
+ definition: factory.definition
627
+ }));
628
+ },
629
+ /**
630
+ * Clear component registry
631
+ */
632
+ clearRegistry: () => {
633
+ COMPONENT_REGISTRY.clear();
634
+ },
635
+ /**
636
+ * Get component registry stats
637
+ */
638
+ getRegistryStats: () => ({
639
+ totalComponents: COMPONENT_REGISTRY.size,
640
+ components: Array.from(COMPONENT_REGISTRY.keys())
641
+ })
642
+ };
643
+ /**
644
+ * Create lazy-evaluated properties and components
645
+ * Defers computation until actually needed, with optional caching
646
+ */
647
+ export function lazy(factory, options = {}) {
648
+ const { cache = true, // Cache the result after first evaluation
649
+ timeout = null, // Optional timeout for evaluation
650
+ fallback = null, // Fallback value if evaluation fails
651
+ onError = null, // Error handler
652
+ dependencies = [] // Dependencies that invalidate cache
653
+ } = options;
654
+ let cached = false;
655
+ let cachedValue = null;
656
+ let isEvaluating = false;
657
+ let lastDependencyHash = null;
658
+ const lazyWrapper = {
659
+ // Mark as lazy for identification
660
+ __isLazy: true,
661
+ __factory: factory,
662
+ __options: options,
663
+ // Evaluation method
664
+ evaluate(...args) {
665
+ // Prevent recursive evaluation
666
+ if (isEvaluating) {
667
+ console.warn('Lazy evaluation cycle detected, returning fallback');
668
+ return fallback;
669
+ }
670
+ // Check dependency changes
671
+ if (cache && dependencies.length > 0) {
672
+ const currentHash = hashDependencies(dependencies);
673
+ if (lastDependencyHash !== null && lastDependencyHash !== currentHash) {
674
+ cached = false;
675
+ cachedValue = null;
676
+ }
677
+ lastDependencyHash = currentHash;
678
+ }
679
+ // Return cached value if available
680
+ if (cache && cached) {
681
+ return cachedValue;
682
+ }
683
+ isEvaluating = true;
684
+ try {
685
+ let result;
686
+ // Handle timeout
687
+ if (timeout) {
688
+ result = evaluateWithTimeout(factory, timeout, args, fallback);
689
+ }
690
+ else {
691
+ result = typeof factory === 'function' ? factory(...args) : factory;
692
+ }
693
+ // Handle promises
694
+ if (result && typeof result.then === 'function') {
695
+ return result.catch(error => {
696
+ if (onError)
697
+ onError(error);
698
+ return fallback;
699
+ });
700
+ }
701
+ // Cache successful result
702
+ if (cache) {
703
+ cached = true;
704
+ cachedValue = result;
705
+ }
706
+ return result;
707
+ }
708
+ catch (error) {
709
+ if (onError) {
710
+ onError(error);
711
+ }
712
+ else {
713
+ console.error('Lazy evaluation error:', error);
714
+ }
715
+ return fallback;
716
+ }
717
+ finally {
718
+ isEvaluating = false;
719
+ }
720
+ },
721
+ // Force re-evaluation
722
+ invalidate() {
723
+ cached = false;
724
+ cachedValue = null;
725
+ lastDependencyHash = null;
726
+ return this;
727
+ },
728
+ // Check if evaluated
729
+ isEvaluated() {
730
+ return cached;
731
+ },
732
+ // Get cached value without evaluation
733
+ getCachedValue() {
734
+ return cachedValue;
735
+ },
736
+ // Transform the lazy value
737
+ map(transform) {
738
+ return lazy((...args) => {
739
+ const value = this.evaluate(...args);
740
+ return transform(value);
741
+ }, { ...options, cache: false }); // Don't double-cache
742
+ },
743
+ // Chain lazy evaluations
744
+ flatMap(transform) {
745
+ return lazy((...args) => {
746
+ const value = this.evaluate(...args);
747
+ const transformed = transform(value);
748
+ if (isLazy(transformed)) {
749
+ return transformed.evaluate(...args);
750
+ }
751
+ return transformed;
752
+ }, { ...options, cache: false });
753
+ },
754
+ // Convert to string for debugging
755
+ toString() {
756
+ return `[Lazy${cached ? ' (cached)' : ''}]`;
757
+ },
758
+ // JSON serialization
759
+ toJSON() {
760
+ return this.evaluate();
761
+ }
762
+ };
763
+ return lazyWrapper;
764
+ }
765
+ /**
766
+ * Check if value is lazy
767
+ */
768
+ export function isLazy(value) {
769
+ return value && typeof value === 'object' && value.__isLazy === true;
770
+ }
771
+ /**
772
+ * Evaluate lazy values recursively in an object
773
+ */
774
+ export function evaluateLazy(obj, ...args) {
775
+ if (isLazy(obj)) {
776
+ return obj.evaluate(...args);
777
+ }
778
+ if (Array.isArray(obj)) {
779
+ return obj.map(item => evaluateLazy(item, ...args));
780
+ }
781
+ if (obj && typeof obj === 'object') {
782
+ const result = {};
783
+ for (const [key, value] of Object.entries(obj)) {
784
+ result[key] = evaluateLazy(value, ...args);
785
+ }
786
+ return result;
787
+ }
788
+ return obj;
789
+ }
790
+ /**
791
+ * Create lazy component
792
+ */
793
+ export function lazyComponent(componentFactory, options = {}) {
794
+ return lazy(componentFactory, {
795
+ cache: true,
796
+ fallback: { div: { text: 'Loading component...' } },
797
+ ...options
798
+ });
799
+ }
800
+ /**
801
+ * Create lazy import for dynamic imports
802
+ */
803
+ export function lazyImport(importPromise, options = {}) {
804
+ return lazy(async () => {
805
+ const module = await importPromise;
806
+ return module.default || module;
807
+ }, {
808
+ cache: true,
809
+ fallback: { div: { text: 'Loading...' } },
810
+ ...options
811
+ });
812
+ }
813
+ /**
814
+ * Create lazy computed property
815
+ */
816
+ export function lazyComputed(computeFn, dependencies = [], options = {}) {
817
+ return lazy(computeFn, {
818
+ cache: true,
819
+ dependencies,
820
+ ...options
821
+ });
822
+ }
823
+ /**
824
+ * Batch evaluate multiple lazy values
825
+ */
826
+ export function batchEvaluate(lazyValues, ...args) {
827
+ const results = {};
828
+ const promises = [];
829
+ Object.entries(lazyValues).forEach(([key, lazyValue]) => {
830
+ if (isLazy(lazyValue)) {
831
+ const result = lazyValue.evaluate(...args);
832
+ if (result && typeof result.then === 'function') {
833
+ promises.push(result.then(value => ({ key, value }))
834
+ .catch(error => ({ key, error })));
835
+ }
836
+ else {
837
+ results[key] = result;
838
+ }
839
+ }
840
+ else {
841
+ results[key] = lazyValue;
842
+ }
843
+ });
844
+ if (promises.length === 0) {
845
+ return results;
846
+ }
847
+ return Promise.all(promises).then(asyncResults => {
848
+ asyncResults.forEach(({ key, value, error }) => {
849
+ if (error) {
850
+ console.error(`Batch evaluation error for ${key}:`, error);
851
+ results[key] = null;
852
+ }
853
+ else {
854
+ results[key] = value;
855
+ }
856
+ });
857
+ return results;
858
+ });
859
+ }
860
+ /**
861
+ * Helper function to hash dependencies
862
+ */
863
+ function hashDependencies(dependencies) {
864
+ return dependencies.map(dep => {
865
+ if (typeof dep === 'function') {
866
+ return dep.toString();
867
+ }
868
+ return JSON.stringify(dep);
869
+ }).join('|');
870
+ }
871
+ /**
872
+ * Helper function to evaluate with timeout
873
+ */
874
+ function evaluateWithTimeout(factory, timeout, args, fallback) {
875
+ return new Promise((resolve, reject) => {
876
+ const timer = setTimeout(() => {
877
+ reject(new Error(`Lazy evaluation timeout after ${timeout}ms`));
878
+ }, timeout);
879
+ try {
880
+ const result = factory(...args);
881
+ if (result && typeof result.then === 'function') {
882
+ result
883
+ .then(value => {
884
+ clearTimeout(timer);
885
+ resolve(value);
886
+ })
887
+ .catch(error => {
888
+ clearTimeout(timer);
889
+ reject(error);
890
+ });
891
+ }
892
+ else {
893
+ clearTimeout(timer);
894
+ resolve(result);
895
+ }
896
+ }
897
+ catch (error) {
898
+ clearTimeout(timer);
899
+ reject(error);
900
+ }
901
+ }).catch(() => fallback);
902
+ }
903
+ /**
904
+ * Lazy evaluation utilities
905
+ */
906
+ export const lazyUtils = {
907
+ /**
908
+ * Create a lazy chain of transformations
909
+ */
910
+ chain: (...transformations) => {
911
+ return lazy((initialValue) => {
912
+ return transformations.reduce((value, transform) => {
913
+ if (isLazy(value)) {
914
+ value = value.evaluate();
915
+ }
916
+ return transform(value);
917
+ }, initialValue);
918
+ });
919
+ },
920
+ /**
921
+ * Create conditional lazy evaluation
922
+ */
923
+ conditional: (condition, trueFactory, falseFactory) => {
924
+ return lazy((...args) => {
925
+ const shouldEvaluateTrue = typeof condition === 'function' ?
926
+ condition(...args) : condition;
927
+ const factory = shouldEvaluateTrue ? trueFactory : falseFactory;
928
+ return typeof factory === 'function' ? factory(...args) : factory;
929
+ });
930
+ },
931
+ /**
932
+ * Memoize a function with lazy evaluation
933
+ */
934
+ memoize: (fn, keyFn = (...args) => JSON.stringify(args)) => {
935
+ const cache = new Map();
936
+ return lazy((...args) => {
937
+ const key = keyFn(...args);
938
+ if (cache.has(key)) {
939
+ return cache.get(key);
940
+ }
941
+ const result = fn(...args);
942
+ cache.set(key, result);
943
+ return result;
944
+ }, { cache: false }); // Handle caching internally
945
+ },
946
+ /**
947
+ * Create lazy value from async function
948
+ */
949
+ async: (asyncFn, options = {}) => {
950
+ return lazy(asyncFn, {
951
+ cache: true,
952
+ fallback: options.loading || { div: { text: 'Loading...' } },
953
+ onError: options.onError,
954
+ ...options
955
+ });
956
+ },
957
+ /**
958
+ * Create lazy array with lazy items
959
+ */
960
+ array: (items = []) => {
961
+ return lazy(() => items.map(item => isLazy(item) ? item.evaluate() : item));
962
+ },
963
+ /**
964
+ * Create lazy object with lazy properties
965
+ */
966
+ object: (obj = {}) => {
967
+ return lazy(() => {
968
+ const result = {};
969
+ for (const [key, value] of Object.entries(obj)) {
970
+ result[key] = isLazy(value) ? value.evaluate() : value;
971
+ }
972
+ return result;
973
+ });
974
+ }
975
+ };
976
+ /**
977
+ * Memoization utilities for caching function results and component renders
978
+ */
979
+ /**
980
+ * Enhanced memoization with multiple caching strategies
981
+ */
982
+ export function memo(fn, options = {}) {
983
+ const {
984
+ // Caching strategy
985
+ strategy = 'lru', // 'lru', 'ttl', 'weak', 'simple'
986
+ maxSize = 100, // Maximum cache entries
987
+ ttl = null, // Time to live in milliseconds
988
+ // Key generation
989
+ keyFn = null, // Custom key function
990
+ keySerializer = JSON.stringify, // Default serialization
991
+ // Comparison
992
+ // eslint-disable-next-line no-unused-vars
993
+ compareFn = null, // Custom equality comparison
994
+ // eslint-disable-next-line no-unused-vars
995
+ shallow = false, // Shallow comparison for objects
996
+ // Lifecycle hooks
997
+ onHit = null, // Called on cache hit
998
+ onMiss = null, // Called on cache miss
999
+ onEvict = null, // Called when item evicted
1000
+ // Performance
1001
+ stats = false, // Track hit/miss statistics
1002
+ // Development
1003
+ debug = false // Debug logging
1004
+ } = options;
1005
+ // Choose cache implementation based on strategy
1006
+ let cache;
1007
+ const stats_data = stats ? { hits: 0, misses: 0, evictions: 0 } : null;
1008
+ switch (strategy) {
1009
+ case 'lru':
1010
+ cache = new LRUCache(maxSize, { onEvict: onEvict });
1011
+ break;
1012
+ case 'ttl':
1013
+ cache = new TTLCache(ttl, { onEvict: onEvict });
1014
+ break;
1015
+ case 'weak':
1016
+ cache = new WeakMap();
1017
+ break;
1018
+ default:
1019
+ cache = new Map();
1020
+ }
1021
+ // Generate cache key
1022
+ const generateKey = keyFn || ((...args) => {
1023
+ if (args.length === 0)
1024
+ return '__empty__';
1025
+ if (args.length === 1)
1026
+ return keySerializer(args[0]);
1027
+ return keySerializer(args);
1028
+ });
1029
+ // Compare values for equality (inline via compareFn or defaults where used)
1030
+ const memoizedFn = (...args) => {
1031
+ const key = generateKey(...args);
1032
+ // Check cache hit
1033
+ if (cache.has(key)) {
1034
+ const cached = cache.get(key);
1035
+ // For TTL cache or custom validation
1036
+ if (cached && (!cached.expires || Date.now() < cached.expires)) {
1037
+ if (debug)
1038
+ console.log(`Memo cache hit for key: ${key}`);
1039
+ if (onHit)
1040
+ onHit(key, cached.value, args);
1041
+ if (stats_data)
1042
+ stats_data.hits++;
1043
+ return cached.value || cached;
1044
+ }
1045
+ else {
1046
+ // Expired entry
1047
+ cache.delete(key);
1048
+ }
1049
+ }
1050
+ // Cache miss - compute result
1051
+ if (debug)
1052
+ console.log(`Memo cache miss for key: ${key}`);
1053
+ if (onMiss)
1054
+ onMiss(key, args);
1055
+ if (stats_data)
1056
+ stats_data.misses++;
1057
+ const result = fn(...args);
1058
+ // Store in cache
1059
+ const cacheEntry = ttl ?
1060
+ { value: result, expires: Date.now() + ttl } :
1061
+ result;
1062
+ cache.set(key, cacheEntry);
1063
+ return result;
1064
+ };
1065
+ // Attach utility methods
1066
+ memoizedFn.cache = cache;
1067
+ memoizedFn.clear = () => cache.clear();
1068
+ memoizedFn.delete = (key) => cache.delete(key);
1069
+ memoizedFn.has = (key) => cache.has(key);
1070
+ memoizedFn.size = () => cache.size;
1071
+ if (stats_data) {
1072
+ memoizedFn.stats = () => ({ ...stats_data });
1073
+ memoizedFn.resetStats = () => {
1074
+ stats_data.hits = 0;
1075
+ stats_data.misses = 0;
1076
+ stats_data.evictions = 0;
1077
+ };
1078
+ }
1079
+ // Force recomputation for specific args
1080
+ memoizedFn.refresh = (...args) => {
1081
+ const key = generateKey(...args);
1082
+ cache.delete(key);
1083
+ return memoizedFn(...args);
1084
+ };
1085
+ return memoizedFn;
1086
+ }
1087
+ /**
1088
+ * Component-specific memoization
1089
+ */
1090
+ export function memoComponent(component, options = {}) {
1091
+ const { propsEqual = shallowEqual, stateEqual = shallowEqual, name = component.name || 'AnonymousComponent' } = options;
1092
+ return memo((props = {}, state = {}, context = {}) => {
1093
+ return typeof component === 'function' ?
1094
+ component(props, state, _context) :
1095
+ component;
1096
+ }, {
1097
+ keyFn: (props, state) => {
1098
+ // Create key based on props and state
1099
+ return `${name}:${JSON.stringify(_props)}:${JSON.stringify(state)}`;
1100
+ },
1101
+ compareFn: (a, b) => {
1102
+ // Custom comparison for component args
1103
+ return propsEqual(a.props, b._props) &&
1104
+ stateEqual(a.state, b.state);
1105
+ },
1106
+ ...options
1107
+ });
1108
+ }
1109
+ /**
1110
+ * Async memoization with promise caching
1111
+ */
1112
+ export function memoAsync(asyncFn, options = {}) {
1113
+ const promiseCache = new Map();
1114
+ const memoized = memo((...args) => {
1115
+ const key = options.keyFn ?
1116
+ options.keyFn(...args) :
1117
+ JSON.stringify(args);
1118
+ // Check if promise is already running
1119
+ if (promiseCache.has(key)) {
1120
+ return promiseCache.get(key);
1121
+ }
1122
+ // Start new async operation
1123
+ const promise = asyncFn(...args).catch(error => {
1124
+ // Remove failed promise from cache
1125
+ promiseCache.delete(key);
1126
+ throw error;
1127
+ });
1128
+ promiseCache.set(key, promise);
1129
+ // Clean up resolved promise
1130
+ promise.finally(() => {
1131
+ setTimeout(() => promiseCache.delete(key), 0);
1132
+ });
1133
+ return promise;
1134
+ }, options);
1135
+ // Clear both caches
1136
+ const originalClear = memoized.clear;
1137
+ memoized.clear = () => {
1138
+ originalClear();
1139
+ promiseCache.clear();
1140
+ };
1141
+ return memoized;
1142
+ }
1143
+ /**
1144
+ * LRU Cache implementation
1145
+ */
1146
+ class LRUCache {
1147
+ constructor(maxSize = 100, options = {}) {
1148
+ this.maxSize = maxSize;
1149
+ this.cache = new Map();
1150
+ this.onEvict = options.onEvict;
1151
+ }
1152
+ get(key) {
1153
+ if (this.cache.has(key)) {
1154
+ // Move to end (most recently used)
1155
+ const value = this.cache.get(key);
1156
+ this.cache.delete(key);
1157
+ this.cache.set(key, value);
1158
+ return value;
1159
+ }
1160
+ return undefined;
1161
+ }
1162
+ set(key, value) {
1163
+ if (this.cache.has(key)) {
1164
+ // Update existing
1165
+ this.cache.delete(key);
1166
+ }
1167
+ else if (this.cache.size >= this.maxSize) {
1168
+ // Evict least recently used (first entry)
1169
+ const firstKey = this.cache.keys().next().value;
1170
+ const evicted = this.cache.get(firstKey);
1171
+ this.cache.delete(firstKey);
1172
+ if (this.onEvict) {
1173
+ this.onEvict(firstKey, evicted);
1174
+ }
1175
+ }
1176
+ this.cache.set(key, value);
1177
+ }
1178
+ has(key) {
1179
+ return this.cache.has(key);
1180
+ }
1181
+ delete(key) {
1182
+ return this.cache.delete(key);
1183
+ }
1184
+ clear() {
1185
+ this.cache.clear();
1186
+ }
1187
+ get size() {
1188
+ return this.cache.size;
1189
+ }
1190
+ }
1191
+ /**
1192
+ * TTL Cache implementation
1193
+ */
1194
+ class TTLCache {
1195
+ constructor(ttl, options = {}) {
1196
+ this.ttl = ttl;
1197
+ this.cache = new Map();
1198
+ this.timers = new Map();
1199
+ this.onEvict = options.onEvict;
1200
+ }
1201
+ get(key) {
1202
+ if (this.cache.has(key)) {
1203
+ const _entry = this.cache.get(key);
1204
+ if (Date.now() < entry.expires) {
1205
+ return entry.value;
1206
+ }
1207
+ else {
1208
+ // Expired
1209
+ this.delete(key);
1210
+ }
1211
+ }
1212
+ return undefined;
1213
+ }
1214
+ set(key, value) {
1215
+ // Clear existing timer
1216
+ if (this.timers.has(key)) {
1217
+ clearTimeout(this.timers.get(key));
1218
+ }
1219
+ const expires = Date.now() + this.ttl;
1220
+ this.cache.set(key, { value, expires });
1221
+ // Set expiration timer
1222
+ const timer = setTimeout(() => {
1223
+ this.delete(key);
1224
+ }, this.ttl);
1225
+ this.timers.set(key, timer);
1226
+ }
1227
+ has(key) {
1228
+ if (this.cache.has(key)) {
1229
+ const _entry = this.cache.get(key);
1230
+ return Date.now() < entry.expires;
1231
+ }
1232
+ return false;
1233
+ }
1234
+ delete(key) {
1235
+ const had = this.cache.has(key);
1236
+ if (had) {
1237
+ const _entry = this.cache.get(key);
1238
+ this.cache.delete(key);
1239
+ if (this.timers.has(key)) {
1240
+ clearTimeout(this.timers.get(key));
1241
+ this.timers.delete(key);
1242
+ }
1243
+ if (this.onEvict) {
1244
+ this.onEvict(key, entry.value);
1245
+ }
1246
+ }
1247
+ return had;
1248
+ }
1249
+ clear() {
1250
+ // Clear all timers
1251
+ this.timers.forEach(timer => clearTimeout(timer));
1252
+ this.timers.clear();
1253
+ this.cache.clear();
1254
+ }
1255
+ get size() {
1256
+ return this.cache.size;
1257
+ }
1258
+ }
1259
+ /**
1260
+ * Shallow equality check for objects
1261
+ */
1262
+ function shallowEqual(a, b) {
1263
+ if (a === b)
1264
+ return true;
1265
+ if (!a || !b)
1266
+ return false;
1267
+ if (typeof a !== typeof b)
1268
+ return false;
1269
+ if (Array.isArray(a) && Array.isArray(b)) {
1270
+ if (a.length !== b.length)
1271
+ return false;
1272
+ return a.every((item, index) => item === b[index]);
1273
+ }
1274
+ if (typeof a === 'object') {
1275
+ const keysA = Object.keys(a);
1276
+ const keysB = Object.keys(b);
1277
+ if (keysA.length !== keysB.length)
1278
+ return false;
1279
+ return keysA.every(key => a[key] === b[key]);
1280
+ }
1281
+ return false;
1282
+ }
1283
+ /**
1284
+ * Memoization utilities
1285
+ */
1286
+ export const memoUtils = {
1287
+ /**
1288
+ * Create a memo with automatic dependency tracking
1289
+ */
1290
+ auto: (fn, dependencies = []) => {
1291
+ let lastDeps = null;
1292
+ let cached = null;
1293
+ let hasCached = false;
1294
+ return (...args) => {
1295
+ const currentDeps = dependencies.map(dep => typeof dep === 'function' ? dep() : dep);
1296
+ if (!hasCached || !shallowEqual(lastDeps, currentDeps)) {
1297
+ cached = fn(...args);
1298
+ lastDeps = currentDeps;
1299
+ hasCached = true;
1300
+ }
1301
+ return cached;
1302
+ };
1303
+ },
1304
+ /**
1305
+ * Memo with size-based eviction
1306
+ */
1307
+ sized: (fn, maxSize = 50) => memo(fn, { strategy: 'lru', maxSize }),
1308
+ /**
1309
+ * Memo with time-based eviction
1310
+ */
1311
+ timed: (fn, ttl = 5000) => memo(fn, { strategy: 'ttl', ttl }),
1312
+ /**
1313
+ * Weak memo (garbage collected with keys)
1314
+ */
1315
+ weak: (fn) => memo(fn, { strategy: 'weak' }),
1316
+ /**
1317
+ * Create multiple memoized variants
1318
+ */
1319
+ variants: (fn, configs) => {
1320
+ const variants = {};
1321
+ Object.entries(configs).forEach(([name, config]) => {
1322
+ variants[name] = memo(fn, config);
1323
+ });
1324
+ return variants;
1325
+ },
1326
+ /**
1327
+ * Conditional memoization
1328
+ */
1329
+ conditional: (fn, shouldMemo = () => true) => {
1330
+ const memoized = memo(fn);
1331
+ return (...args) => {
1332
+ if (shouldMemo(...args)) {
1333
+ return memoized(...args);
1334
+ }
1335
+ return fn(...args);
1336
+ };
1337
+ },
1338
+ /**
1339
+ * Memo with custom storage
1340
+ */
1341
+ custom: (fn, storage) => {
1342
+ return (...args) => {
1343
+ const key = JSON.stringify(args);
1344
+ if (storage.has(key)) {
1345
+ return storage.get(key);
1346
+ }
1347
+ const result = fn(...args);
1348
+ storage.set(key, result);
1349
+ return result;
1350
+ };
1351
+ }
1352
+ };
1353
+ /**
1354
+ * Higher-order function utilities for component composition and prop manipulation
1355
+ */
1356
+ /**
1357
+ * Enhanced withProps utility for component prop transformation and injection
1358
+ */
1359
+ export function withProps(propsTransform, options = {}) {
1360
+ const {
1361
+ // Transformation options
1362
+ merge = true, // Merge with existing props vs replace
1363
+ override = false, // Allow overriding existing props
1364
+ validate = null, // Validation function for props
1365
+ // Caching and performance
1366
+ memoize = false, // Memoize the transformation
1367
+ memoOptions = {}, // Memoization options
1368
+ // Error handling
1369
+ onError = null, // Error handler for transformation
1370
+ fallbackProps = {}, // Fallback props on error
1371
+ // Development
1372
+ displayName = null, // Component name for debugging
1373
+ debug = false, // Debug logging
1374
+ // Lifecycle
1375
+ onPropsChange = null, // Called when props change
1376
+ shouldUpdate = null // Custom update logic
1377
+ } = options;
1378
+ return function withPropsHOC(WrappedComponent) {
1379
+ // Create the enhanced component
1380
+ function WithPropsComponent(originalProps = {}, state = {}, context = {}) {
1381
+ try {
1382
+ // Transform props
1383
+ let transformedProps;
1384
+ if (typeof propsTransform === 'function') {
1385
+ transformedProps = propsTransform(originalProps, state, _context);
1386
+ }
1387
+ else if (typeof propsTransform === 'object') {
1388
+ transformedProps = propsTransform;
1389
+ }
1390
+ else {
1391
+ transformedProps = {};
1392
+ }
1393
+ // Handle async transformations
1394
+ if (transformedProps && typeof transformedProps.then === 'function') {
1395
+ return transformedProps.then(resolved => {
1396
+ return processProps(resolved, originalProps, WrappedComponent, state, _context);
1397
+ }).catch(error => {
1398
+ if (onError)
1399
+ onError(error, originalProps);
1400
+ return processProps(fallbackProps, originalProps, WrappedComponent, state, _context);
1401
+ });
1402
+ }
1403
+ return processProps(transformedProps, originalProps, WrappedComponent, state, _context);
1404
+ }
1405
+ catch (error) {
1406
+ if (debug)
1407
+ console.error('withProps error:', error);
1408
+ if (onError)
1409
+ onError(error, originalProps);
1410
+ // Use fallback props
1411
+ return processProps(fallbackProps, originalProps, WrappedComponent, state, _context);
1412
+ }
1413
+ }
1414
+ // Process and merge props
1415
+ function processProps(transformed, original, component, state, _context) {
1416
+ let finalProps;
1417
+ if (merge) {
1418
+ if (override) {
1419
+ finalProps = { ...original, ...transformed };
1420
+ }
1421
+ else {
1422
+ // Don't override existing props
1423
+ finalProps = { ...transformed, ...original };
1424
+ }
1425
+ }
1426
+ else {
1427
+ finalProps = transformed;
1428
+ }
1429
+ // Validate final props
1430
+ if (validate && !validate(finalProps)) {
1431
+ if (debug)
1432
+ console.warn('Props validation failed:', finalProps);
1433
+ finalProps = { ...finalProps, ...fallbackProps };
1434
+ }
1435
+ // Check if should update
1436
+ if (shouldUpdate && !shouldUpdate(finalProps, original, state)) {
1437
+ return null; // Skip update
1438
+ }
1439
+ // Notify props change
1440
+ if (onPropsChange) {
1441
+ onPropsChange(finalProps, original, transformed);
1442
+ }
1443
+ if (debug) {
1444
+ console.log('withProps transformation:', {
1445
+ original,
1446
+ transformed,
1447
+ final: finalProps
1448
+ });
1449
+ }
1450
+ // Render wrapped component
1451
+ return typeof component === 'function' ?
1452
+ component(finalProps, state, _context) :
1453
+ component;
1454
+ }
1455
+ // Set display name for debugging
1456
+ WithPropsComponent.displayName = displayName ||
1457
+ `withProps(${WrappedComponent.displayName || WrappedComponent.name || 'Component'})`;
1458
+ // Add metadata
1459
+ WithPropsComponent.__isHOC = true;
1460
+ WithPropsComponent.__wrappedComponent = WrappedComponent;
1461
+ WithPropsComponent.__transform = propsTransform;
1462
+ // Apply memoization if requested
1463
+ if (memoize) {
1464
+ return memo(WithPropsComponent, {
1465
+ keyFn: (props, state) => JSON.stringify({ props, state }),
1466
+ ...memoOptions
1467
+ });
1468
+ }
1469
+ return WithPropsComponent;
1470
+ };
1471
+ }
1472
+ /**
1473
+ * Specialized withProps variants
1474
+ */
1475
+ export const withPropsUtils = {
1476
+ /**
1477
+ * Add static props to component
1478
+ */
1479
+ static: (staticProps) => withProps(() => staticProps),
1480
+ /**
1481
+ * Transform props based on conditions
1482
+ */
1483
+ conditional: (condition, trueProps, falseProps = {}) => withProps((props, state, _context) => {
1484
+ const shouldApply = typeof condition === 'function' ?
1485
+ condition(props, state, _context) :
1486
+ condition;
1487
+ return shouldApply ? trueProps : falseProps;
1488
+ }),
1489
+ /**
1490
+ * Map specific props to new names/values
1491
+ */
1492
+ map: (mapping) => withProps((_props) => {
1493
+ const result = {};
1494
+ Object.entries(mapping).forEach(([newKey, mapper]) => {
1495
+ if (typeof mapper === 'string') {
1496
+ // Simple property rename
1497
+ result[newKey] = props[mapper];
1498
+ }
1499
+ else if (typeof mapper === 'function') {
1500
+ // Transform function
1501
+ result[newKey] = mapper(_props);
1502
+ }
1503
+ else {
1504
+ // Static value
1505
+ result[newKey] = mapper;
1506
+ }
1507
+ });
1508
+ return result;
1509
+ }),
1510
+ /**
1511
+ * Pick only specific props
1512
+ */
1513
+ pick: (keys) => withProps((_props) => {
1514
+ const result = {};
1515
+ keys.forEach(key => {
1516
+ if (props.hasOwnProperty(key)) {
1517
+ result[key] = props[key];
1518
+ }
1519
+ });
1520
+ return result;
1521
+ }),
1522
+ /**
1523
+ * Omit specific props
1524
+ */
1525
+ omit: (keys) => withProps((_props) => {
1526
+ const result = { ...props };
1527
+ keys.forEach(key => delete result[key]);
1528
+ return result;
1529
+ }),
1530
+ /**
1531
+ * Default values for missing props
1532
+ */
1533
+ defaults: (defaultProps) => withProps((_props) => ({
1534
+ ...defaultProps,
1535
+ ...props
1536
+ }), { merge: false }),
1537
+ /**
1538
+ * Transform props with validation
1539
+ */
1540
+ validated: (transform, validator) => withProps(transform, {
1541
+ validate: validator,
1542
+ onError: (error) => console.warn('Prop validation failed:', error)
1543
+ }),
1544
+ /**
1545
+ * Async prop transformation
1546
+ */
1547
+ async: (asyncTransform, loadingProps = {}) => withProps(async (props, state, _context) => {
1548
+ try {
1549
+ return await asyncTransform(props, state, _context);
1550
+ }
1551
+ catch (error) {
1552
+ console.error('Async prop transform failed:', error);
1553
+ return loadingProps;
1554
+ }
1555
+ }, {
1556
+ fallbackProps: loadingProps
1557
+ }),
1558
+ /**
1559
+ * Computed props based on other props
1560
+ */
1561
+ computed: (computedProps) => withProps((_props) => {
1562
+ const computed = {};
1563
+ Object.entries(computedProps).forEach(([key, compute]) => {
1564
+ computed[key] = typeof compute === 'function' ?
1565
+ compute(_props) :
1566
+ compute;
1567
+ });
1568
+ return computed;
1569
+ }),
1570
+ /**
1571
+ * Props with context injection
1572
+ */
1573
+ withContext: (contextKeys) => withProps((props, state, _context) => {
1574
+ const contextProps = {};
1575
+ contextKeys.forEach(key => {
1576
+ if (context && context[key] !== undefined) {
1577
+ contextProps[key] = context[key];
1578
+ }
1579
+ });
1580
+ return contextProps;
1581
+ }),
1582
+ /**
1583
+ * Props with state injection
1584
+ */
1585
+ withState: (stateMapping) => withProps((props, state) => {
1586
+ if (typeof stateMapping === 'function') {
1587
+ return stateMapping(state, _props);
1588
+ }
1589
+ const stateProps = {};
1590
+ Object.entries(stateMapping).forEach(([propKey, stateKey]) => {
1591
+ stateProps[propKey] = state[stateKey];
1592
+ });
1593
+ return stateProps;
1594
+ }),
1595
+ /**
1596
+ * Memoized prop transformation
1597
+ */
1598
+ memoized: (transform, memoOptions = {}) => withProps(transform, {
1599
+ memoize: true,
1600
+ memoOptions: {
1601
+ maxSize: 50,
1602
+ ...memoOptions
1603
+ }
1604
+ }),
1605
+ /**
1606
+ * Props with performance measurement
1607
+ */
1608
+ timed: (transform, name = 'PropTransform') => withProps((props, state, _context) => {
1609
+ const start = performance.now();
1610
+ const result = transform(props, state, _context);
1611
+ const end = performance.now();
1612
+ if (end - start > 1) { // Log if > 1ms
1613
+ console.log(`${name} took ${(end - start).toFixed(2)}ms`);
1614
+ }
1615
+ return result;
1616
+ }),
1617
+ /**
1618
+ * Chain multiple prop transformations
1619
+ */
1620
+ chain: (...transforms) => withProps((props, state, _context) => {
1621
+ return transforms.reduce((acc, transform) => {
1622
+ if (typeof transform === 'function') {
1623
+ return { ...acc, ...transform(acc, state, _context) };
1624
+ }
1625
+ return { ...acc, ...transform };
1626
+ }, _props);
1627
+ })
1628
+ };
1629
+ /**
1630
+ * Create a reusable prop transformer
1631
+ */
1632
+ export function createPropTransformer(config) {
1633
+ const { transforms = [], validators = [], defaults = {}, options = {} } = config;
1634
+ return withProps((props, state, _context) => {
1635
+ let result = { ...defaults, ...props };
1636
+ // Apply transforms in sequence
1637
+ for (const transform of transforms) {
1638
+ if (typeof transform === 'function') {
1639
+ result = { ...result, ...transform(result, state, _context) };
1640
+ }
1641
+ else {
1642
+ result = { ...result, ...transform };
1643
+ }
1644
+ }
1645
+ // Run validators
1646
+ for (const validator of validators) {
1647
+ if (!validator(result)) {
1648
+ throw new Error('Prop validation failed');
1649
+ }
1650
+ }
1651
+ return result;
1652
+ }, options);
1653
+ }
1654
+ /**
1655
+ * Props debugging utility
1656
+ */
1657
+ export function withPropsDebug(component, debugOptions = {}) {
1658
+ const { logProps = true, logChanges = true, breakOnError = false } = debugOptions;
1659
+ return withProps((props, state, _context) => {
1660
+ if (logProps) {
1661
+ console.group(`Props Debug: ${component.name || 'Component'}`);
1662
+ console.log('Props:', _props);
1663
+ console.log('State:', state);
1664
+ console.log('Context:', _context);
1665
+ console.groupEnd();
1666
+ }
1667
+ return props;
1668
+ }, {
1669
+ debug: true,
1670
+ onError: breakOnError ? () => {
1671
+ // eslint-disable-next-line no-debugger
1672
+ debugger;
1673
+ } : undefined,
1674
+ onPropsChange: logChanges ? (finalProps, original) => {
1675
+ console.log('Props changed:', { from: original, to: finalProps });
1676
+ } : undefined
1677
+ })(component);
1678
+ }
1679
+ /**
1680
+ * State management utilities for component state injection and management
1681
+ */
1682
+ /**
1683
+ * Enhanced withState utility for component state management and injection
1684
+ */
1685
+ export function withState(initialState = {}, options = {}) {
1686
+ const {
1687
+ // State options
1688
+ persistent = false, // Persist state across component unmounts
1689
+ storageKey = null, // Key for persistent storage
1690
+ storage = typeof localStorage !== 'undefined' ? localStorage : {
1691
+ // Fallback storage for Node.js environments
1692
+ _data: new Map(),
1693
+ setItem(key, value) { this._data.set(key, value); },
1694
+ getItem(key) { return this._data.get(key) || null; },
1695
+ removeItem(key) { this._data.delete(key); },
1696
+ clear() { this._data.clear(); }
1697
+ }, // Storage mechanism
1698
+ // State transformation
1699
+ stateTransform = null, // Transform state before injection
1700
+ propName = 'state', // Prop name for state injection
1701
+ actionsName = 'actions', // Prop name for action injection
1702
+ // Reducers and actions
1703
+ reducer = null, // State reducer function
1704
+ actions = {}, // Action creators
1705
+ middleware = [], // State middleware
1706
+ // Performance
1707
+ memoizeState = false, // Memoize state transformations
1708
+ // eslint-disable-next-line no-unused-vars
1709
+ shallow = false, // Shallow state comparison
1710
+ // Development
1711
+ // eslint-disable-next-line no-unused-vars
1712
+ devTools = false, // Connect to dev tools
1713
+ debug = false, // Debug logging
1714
+ displayName = null, // Component name for debugging
1715
+ // Lifecycle hooks
1716
+ onStateChange = null, // Called when state changes
1717
+ onMount = null, // Called when component mounts
1718
+ onUnmount = null, // Called when component unmounts
1719
+ // Validation
1720
+ validator = null, // State validator function
1721
+ // Async state
1722
+ supportAsync = false // Support async state updates
1723
+ } = options;
1724
+ return function withStateHOC(WrappedComponent) {
1725
+ // Create state container
1726
+ const stateContainer = createStateContainer(initialState, {
1727
+ persistent,
1728
+ storageKey: storageKey || `${getComponentName(WrappedComponent)}_state`,
1729
+ storage,
1730
+ reducer,
1731
+ middleware,
1732
+ validator,
1733
+ onStateChange,
1734
+ debug
1735
+ });
1736
+ function WithStateComponent(props = {}, globalState = {}, context = {}) {
1737
+ // Initialize component state if not exists
1738
+ if (!stateContainer.initialized) {
1739
+ stateContainer.initialize();
1740
+ if (onMount) {
1741
+ onMount(stateContainer.getState(), props, _context);
1742
+ }
1743
+ }
1744
+ // Get current state
1745
+ const currentState = stateContainer.getState();
1746
+ // Transform state if needed
1747
+ let transformedState = currentState;
1748
+ if (stateTransform) {
1749
+ transformedState = stateTransform(currentState, props, _context);
1750
+ }
1751
+ // Create actions bound to this state container
1752
+ const boundActions = createBoundActions(actions, stateContainer, {
1753
+ props,
1754
+ context,
1755
+ supportAsync,
1756
+ debug
1757
+ });
1758
+ // Create state management utilities
1759
+ const stateUtils = {
1760
+ // Basic state operations
1761
+ setState: stateContainer.setState.bind(stateContainer),
1762
+ getState: stateContainer.getState.bind(stateContainer),
1763
+ resetState: () => stateContainer.setState(initialState),
1764
+ // Advanced operations
1765
+ updateState: (updater) => {
1766
+ const current = stateContainer.getState();
1767
+ const next = typeof updater === 'function' ? updater(current) : updater;
1768
+ stateContainer.setState(next);
1769
+ },
1770
+ // Batch updates
1771
+ batchUpdate: (updates) => {
1772
+ stateContainer.batch(() => {
1773
+ updates.forEach(update => {
1774
+ if (typeof update === 'function') {
1775
+ update(stateContainer);
1776
+ }
1777
+ else {
1778
+ stateContainer.setState(update);
1779
+ }
1780
+ });
1781
+ });
1782
+ },
1783
+ // Computed state
1784
+ computed: (computeFn) => {
1785
+ return memoizeState ?
1786
+ memo(computeFn)(transformedState) :
1787
+ computeFn(transformedState);
1788
+ },
1789
+ // State subscription
1790
+ subscribe: stateContainer.subscribe.bind(stateContainer),
1791
+ unsubscribe: stateContainer.unsubscribe.bind(stateContainer),
1792
+ // Async state operations
1793
+ ...(supportAsync && {
1794
+ setStateAsync: async (stateOrPromise) => {
1795
+ const resolved = await Promise.resolve(stateOrPromise);
1796
+ stateContainer.setState(resolved);
1797
+ },
1798
+ updateStateAsync: async (asyncUpdater) => {
1799
+ const current = stateContainer.getState();
1800
+ const next = await Promise.resolve(asyncUpdater(current));
1801
+ stateContainer.setState(next);
1802
+ }
1803
+ })
1804
+ };
1805
+ // Prepare enhanced props
1806
+ const enhancedProps = {
1807
+ ...props,
1808
+ [propName]: transformedState,
1809
+ [actionsName]: boundActions,
1810
+ stateUtils
1811
+ };
1812
+ if (debug) {
1813
+ console.log('withState render:', {
1814
+ component: getComponentName(WrappedComponent),
1815
+ state: transformedState,
1816
+ props: enhancedProps
1817
+ });
1818
+ }
1819
+ // Render wrapped component
1820
+ return typeof WrappedComponent === 'function' ?
1821
+ WrappedComponent(enhancedProps, globalState, _context) :
1822
+ WrappedComponent;
1823
+ }
1824
+ // Set display name
1825
+ WithStateComponent.displayName = displayName ||
1826
+ `withState(${getComponentName(WrappedComponent)})`;
1827
+ // Add metadata
1828
+ WithStateComponent.__isHOC = true;
1829
+ WithStateComponent.__hasState = true;
1830
+ WithStateComponent.__stateContainer = stateContainer;
1831
+ WithStateComponent.__wrappedComponent = WrappedComponent;
1832
+ // Cleanup on unmount
1833
+ WithStateComponent.cleanup = () => {
1834
+ if (onUnmount) {
1835
+ onUnmount(stateContainer.getState());
1836
+ }
1837
+ if (!persistent) {
1838
+ stateContainer.destroy();
1839
+ }
1840
+ };
1841
+ return WithStateComponent;
1842
+ };
1843
+ }
1844
+ /**
1845
+ * Create a centralized state container
1846
+ */
1847
+ function createStateContainer(initialState, options) {
1848
+ const { persistent, storageKey, storage, reducer, middleware, validator, onStateChange, debug } = options;
1849
+ let state = deepClone(initialState);
1850
+ let listeners = new Set();
1851
+ const middlewareStack = [...middleware];
1852
+ const container = {
1853
+ initialized: false,
1854
+ initialize() {
1855
+ // Load persisted state
1856
+ if (persistent && storageKey) {
1857
+ try {
1858
+ const saved = storage.getItem(storageKey);
1859
+ if (saved) {
1860
+ const parsed = JSON.parse(saved);
1861
+ state = { ...state, ...parsed };
1862
+ }
1863
+ }
1864
+ catch (error) {
1865
+ if (debug)
1866
+ console.warn('Failed to load persisted state:', error);
1867
+ }
1868
+ }
1869
+ container.initialized = true;
1870
+ },
1871
+ getState() {
1872
+ return deepClone(state);
1873
+ },
1874
+ setState(newState) {
1875
+ const prevState = state;
1876
+ // Apply reducer if provided
1877
+ if (reducer) {
1878
+ state = reducer(state, { type: 'SET_STATE', payload: newState });
1879
+ }
1880
+ else {
1881
+ state = typeof newState === 'function' ?
1882
+ newState(state) :
1883
+ { ...state, ...newState };
1884
+ }
1885
+ // Validate state
1886
+ if (validator && !validator(state)) {
1887
+ if (debug)
1888
+ console.warn('State validation failed, reverting:', state);
1889
+ state = prevState;
1890
+ return false;
1891
+ }
1892
+ // Apply middleware
1893
+ state = middlewareStack.reduce((acc, middleware) => middleware(acc, prevState) || acc, state);
1894
+ // Persist state
1895
+ if (persistent && storageKey) {
1896
+ try {
1897
+ storage.setItem(storageKey, JSON.stringify(state));
1898
+ }
1899
+ catch (error) {
1900
+ if (debug)
1901
+ console.warn('Failed to persist state:', error);
1902
+ }
1903
+ }
1904
+ // Notify listeners
1905
+ if (state !== prevState) {
1906
+ listeners.forEach(listener => {
1907
+ try {
1908
+ listener(state, prevState);
1909
+ }
1910
+ catch (error) {
1911
+ if (debug)
1912
+ console.error('State listener error:', error);
1913
+ }
1914
+ });
1915
+ if (onStateChange) {
1916
+ onStateChange(state, prevState);
1917
+ }
1918
+ }
1919
+ return true;
1920
+ },
1921
+ subscribe(listener) {
1922
+ listeners.add(listener);
1923
+ return () => listeners.delete(listener);
1924
+ },
1925
+ unsubscribe(listener) {
1926
+ return listeners.delete(listener);
1927
+ },
1928
+ batch(batchFn) {
1929
+ const originalListeners = listeners;
1930
+ listeners = new Set(); // Temporarily disable listeners
1931
+ try {
1932
+ batchFn();
1933
+ }
1934
+ finally {
1935
+ listeners = originalListeners;
1936
+ // Notify once after batch
1937
+ listeners.forEach(listener => listener(state));
1938
+ }
1939
+ },
1940
+ destroy() {
1941
+ listeners.clear();
1942
+ if (persistent && storageKey) {
1943
+ try {
1944
+ storage.removeItem(storageKey);
1945
+ }
1946
+ catch (error) {
1947
+ if (debug)
1948
+ console.warn('Failed to remove persisted state:', error);
1949
+ }
1950
+ }
1951
+ }
1952
+ };
1953
+ return container;
1954
+ }
1955
+ /**
1956
+ * Create bound action creators
1957
+ */
1958
+ function createBoundActions(actions, stateContainer, options) {
1959
+ const { props, context, supportAsync, debug } = options;
1960
+ const boundActions = {};
1961
+ Object.entries(actions).forEach(([actionName, actionCreator]) => {
1962
+ boundActions[actionName] = (...args) => {
1963
+ try {
1964
+ const result = actionCreator(stateContainer.getState(), stateContainer.setState.bind(stateContainer), { props, context, args });
1965
+ // Handle async actions
1966
+ if (supportAsync && result && typeof result.then === 'function') {
1967
+ return result.catch(error => {
1968
+ if (debug)
1969
+ console.error(`Async action ${actionName} failed:`, error);
1970
+ throw error;
1971
+ });
1972
+ }
1973
+ return result;
1974
+ }
1975
+ catch (error) {
1976
+ if (debug)
1977
+ console.error(`Action ${actionName} failed:`, error);
1978
+ throw error;
1979
+ }
1980
+ };
1981
+ });
1982
+ return boundActions;
1983
+ }
1984
+ /**
1985
+ * Specialized withState variants
1986
+ */
1987
+ export const withStateUtils = {
1988
+ /**
1989
+ * Simple local state
1990
+ */
1991
+ local: (initialState) => withState(initialState),
1992
+ /**
1993
+ * Persistent state with localStorage
1994
+ */
1995
+ persistent: (initialState, key) => withState(initialState, {
1996
+ persistent: true,
1997
+ storageKey: key
1998
+ }),
1999
+ /**
2000
+ * State with reducer pattern
2001
+ */
2002
+ reducer: (initialState, reducer, actions = {}) => withState(initialState, {
2003
+ reducer,
2004
+ actions
2005
+ }),
2006
+ /**
2007
+ * Async state management
2008
+ */
2009
+ async: (initialState, asyncActions = {}) => withState(initialState, {
2010
+ supportAsync: true,
2011
+ actions: asyncActions
2012
+ }),
2013
+ /**
2014
+ * State with validation
2015
+ */
2016
+ validated: (initialState, validator) => withState(initialState, {
2017
+ validator,
2018
+ debug: true
2019
+ }),
2020
+ /**
2021
+ * Shared state across components
2022
+ */
2023
+ shared: (initialState, sharedKey) => {
2024
+ const sharedStates = withStateUtils._shared || (withStateUtils._shared = new Map());
2025
+ if (!sharedStates.has(sharedKey)) {
2026
+ sharedStates.set(sharedKey, createStateContainer(initialState, {}));
2027
+ }
2028
+ return (WrappedComponent) => {
2029
+ const sharedContainer = sharedStates.get(sharedKey);
2030
+ function SharedStateComponent(props, globalState, _context) {
2031
+ const currentState = sharedContainer.getState();
2032
+ const enhancedProps = {
2033
+ ...props,
2034
+ state: currentState,
2035
+ setState: sharedContainer.setState.bind(sharedContainer),
2036
+ subscribe: sharedContainer.subscribe.bind(sharedContainer)
2037
+ };
2038
+ return typeof WrappedComponent === 'function' ?
2039
+ WrappedComponent(enhancedProps, globalState, _context) :
2040
+ WrappedComponent;
2041
+ }
2042
+ SharedStateComponent.displayName = `withSharedState(${getComponentName(WrappedComponent)})`;
2043
+ return SharedStateComponent;
2044
+ };
2045
+ },
2046
+ /**
2047
+ * State with form utilities
2048
+ */
2049
+ form: (initialFormState) => withState(initialFormState, {
2050
+ actions: {
2051
+ updateField: (state, setState, { args: [field, value] }) => {
2052
+ setState({ [field]: value });
2053
+ },
2054
+ updateMultiple: (state, setState, { args: [updates] }) => {
2055
+ setState(updates);
2056
+ },
2057
+ resetForm: (state, setState) => {
2058
+ setState(initialFormState);
2059
+ },
2060
+ validateForm: (state, setState, { args: [validator] }) => {
2061
+ const errors = validator(state);
2062
+ setState({ _errors: errors });
2063
+ return Object.keys(errors).length === 0;
2064
+ }
2065
+ }
2066
+ }),
2067
+ /**
2068
+ * State with loading/error handling
2069
+ */
2070
+ withLoading: async (initialState) => withState({
2071
+ ...initialState,
2072
+ _loading: false,
2073
+ _error: null
2074
+ }, {
2075
+ supportAsync: true,
2076
+ actions: {
2077
+ setLoading: (state, setState, { args: [loading] }) => {
2078
+ setState({ _loading: loading });
2079
+ },
2080
+ setError: (state, setState, { args: [error] }) => {
2081
+ setState({ _error: error, _loading: false });
2082
+ },
2083
+ clearError: (state, setState) => {
2084
+ setState({ _error: null });
2085
+ },
2086
+ asyncAction: async (state, setState, { args: [asyncFn] }) => {
2087
+ setState({ _loading: true, _error: null });
2088
+ try {
2089
+ const result = await asyncFn(state);
2090
+ setState({ _loading: false });
2091
+ return result;
2092
+ }
2093
+ catch (error) {
2094
+ setState({ _loading: false, _error: error });
2095
+ throw error;
2096
+ }
2097
+ }
2098
+ }
2099
+ }),
2100
+ /**
2101
+ * State with undo/redo functionality
2102
+ */
2103
+ withHistory: (initialState, maxHistory = 10) => {
2104
+ const historyState = {
2105
+ present: initialState,
2106
+ past: [],
2107
+ future: []
2108
+ };
2109
+ return withState(historyState, {
2110
+ actions: {
2111
+ undo: (state, setState) => {
2112
+ if (state.past.length === 0)
2113
+ return;
2114
+ const previous = state.past[state.past.length - 1];
2115
+ const newPast = state.past.slice(0, state.past.length - 1);
2116
+ setState({
2117
+ past: newPast,
2118
+ present: previous,
2119
+ future: [state.present, ...state.future]
2120
+ });
2121
+ },
2122
+ redo: (state, setState) => {
2123
+ if (state.future.length === 0)
2124
+ return;
2125
+ const next = state.future[0];
2126
+ const newFuture = state.future.slice(1);
2127
+ setState({
2128
+ past: [...state.past, state.present],
2129
+ present: next,
2130
+ future: newFuture
2131
+ });
2132
+ },
2133
+ updatePresent: (state, setState, { args: [newPresent] }) => {
2134
+ setState({
2135
+ past: [...state.past, state.present].slice(-maxHistory),
2136
+ present: newPresent,
2137
+ future: []
2138
+ });
2139
+ },
2140
+ canUndo: (state) => state.past.length > 0,
2141
+ canRedo: (state) => state.future.length > 0
2142
+ }
2143
+ });
2144
+ },
2145
+ /**
2146
+ * Computed state properties
2147
+ */
2148
+ computed: (initialState, computedProps) => withState(initialState, {
2149
+ stateTransform: (state) => {
2150
+ const computed = {};
2151
+ Object.entries(computedProps).forEach(([key, computeFn]) => {
2152
+ computed[key] = computeFn(state);
2153
+ });
2154
+ return { ...state, ...computed };
2155
+ },
2156
+ memoizeState: true
2157
+ })
2158
+ };
2159
+ /**
2160
+ * Create a compound state manager
2161
+ */
2162
+ export function createStateManager(config) {
2163
+ const { initialState = {}, reducers = {}, actions = {}, middleware = [], plugins = [] } = config;
2164
+ // Combine reducers
2165
+ const rootReducer = (state, action) => {
2166
+ let nextState = state;
2167
+ Object.entries(reducers).forEach(([key, reducer]) => {
2168
+ nextState = {
2169
+ ...nextState,
2170
+ [key]: reducer(nextState[key], action)
2171
+ };
2172
+ });
2173
+ return nextState;
2174
+ };
2175
+ // Apply plugins
2176
+ const enhancedConfig = plugins.reduce((acc, plugin) => plugin(acc), { initialState, reducer: rootReducer, actions, middleware });
2177
+ return withState(enhancedConfig.initialState, {
2178
+ reducer: enhancedConfig.reducer,
2179
+ actions: enhancedConfig.actions,
2180
+ middleware: enhancedConfig.middleware
2181
+ });
2182
+ }
2183
+ // Utility to get component name
2184
+ function getComponentName(component) {
2185
+ if (!component)
2186
+ return 'Component';
2187
+ return component.displayName ||
2188
+ component.name ||
2189
+ component.constructor?.name ||
2190
+ 'Component';
2191
+ }
2192
+ export default {
2193
+ Component,
2194
+ createComponent,
2195
+ defineComponent,
2196
+ registerComponent,
2197
+ getComponent,
2198
+ getRegisteredComponents,
2199
+ createHOC,
2200
+ createMixin,
2201
+ compose,
2202
+ componentUtils,
2203
+ dev,
2204
+ lazy,
2205
+ lazyUtils,
2206
+ evaluateLazy,
2207
+ evaluateWithTimeout,
2208
+ batchEvaluate,
2209
+ hashDependencies,
2210
+ memo,
2211
+ memoUtils,
2212
+ withProps,
2213
+ withPropsUtils,
2214
+ withPropsDebug,
2215
+ withState,
2216
+ createStateManager,
2217
+ getComponentName,
2218
+ withStateUtils
2219
+ };
2220
+ //# sourceMappingURL=component-system.js.map