@memberjunction/react-runtime 2.90.0 → 2.92.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 (83) hide show
  1. package/.turbo/turbo-build.log +29 -1
  2. package/CHANGELOG.md +31 -0
  3. package/dist/compiler/babel-config.js +1 -0
  4. package/dist/compiler/babel-config.js.map +1 -0
  5. package/dist/compiler/component-compiler.d.ts.map +1 -1
  6. package/dist/compiler/component-compiler.js +64 -14
  7. package/dist/compiler/component-compiler.js.map +1 -0
  8. package/dist/compiler/index.js +1 -0
  9. package/dist/compiler/index.js.map +1 -0
  10. package/dist/index.d.ts +1 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +4 -4
  13. package/dist/index.js.map +1 -0
  14. package/dist/registry/component-registry.d.ts +1 -0
  15. package/dist/registry/component-registry.d.ts.map +1 -1
  16. package/dist/registry/component-registry.js +10 -0
  17. package/dist/registry/component-registry.js.map +1 -0
  18. package/dist/registry/component-resolver.js +1 -0
  19. package/dist/registry/component-resolver.js.map +1 -0
  20. package/dist/registry/index.js +1 -0
  21. package/dist/registry/index.js.map +1 -0
  22. package/dist/runtime/component-hierarchy.d.ts +7 -4
  23. package/dist/runtime/component-hierarchy.d.ts.map +1 -1
  24. package/dist/runtime/component-hierarchy.js +20 -6
  25. package/dist/runtime/component-hierarchy.js.map +1 -0
  26. package/dist/runtime/error-boundary.js +1 -0
  27. package/dist/runtime/error-boundary.js.map +1 -0
  28. package/dist/runtime/index.js +1 -0
  29. package/dist/runtime/index.js.map +1 -0
  30. package/dist/runtime/prop-builder.d.ts +2 -1
  31. package/dist/runtime/prop-builder.d.ts.map +1 -1
  32. package/dist/runtime/prop-builder.js +1 -0
  33. package/dist/runtime/prop-builder.js.map +1 -0
  34. package/dist/runtime/react-root-manager.js +1 -0
  35. package/dist/runtime/react-root-manager.js.map +1 -0
  36. package/dist/runtime.umd.js +2 -0
  37. package/dist/runtime.umd.js.LICENSE.txt +10 -0
  38. package/dist/types/index.d.ts +8 -6
  39. package/dist/types/index.d.ts.map +1 -1
  40. package/dist/types/index.js +1 -0
  41. package/dist/types/index.js.map +1 -0
  42. package/dist/types/library-config.js +1 -0
  43. package/dist/types/library-config.js.map +1 -0
  44. package/dist/utilities/cache-manager.js +1 -0
  45. package/dist/utilities/cache-manager.js.map +1 -0
  46. package/dist/utilities/component-error-analyzer.js +1 -0
  47. package/dist/utilities/component-error-analyzer.js.map +1 -0
  48. package/dist/utilities/component-styles.js +1 -0
  49. package/dist/utilities/component-styles.js.map +1 -0
  50. package/dist/utilities/core-libraries.js +1 -0
  51. package/dist/utilities/core-libraries.js.map +1 -0
  52. package/dist/utilities/index.d.ts +0 -1
  53. package/dist/utilities/index.d.ts.map +1 -1
  54. package/dist/utilities/index.js +1 -1
  55. package/dist/utilities/index.js.map +1 -0
  56. package/dist/utilities/library-loader.d.ts.map +1 -1
  57. package/dist/utilities/library-loader.js +15 -0
  58. package/dist/utilities/library-loader.js.map +1 -0
  59. package/dist/utilities/library-registry.d.ts +3 -1
  60. package/dist/utilities/library-registry.d.ts.map +1 -1
  61. package/dist/utilities/library-registry.js +43 -518
  62. package/dist/utilities/library-registry.js.map +1 -0
  63. package/dist/utilities/resource-manager.js +1 -0
  64. package/dist/utilities/resource-manager.js.map +1 -0
  65. package/dist/utilities/standard-libraries.js +1 -0
  66. package/dist/utilities/standard-libraries.js.map +1 -0
  67. package/package.json +16 -6
  68. package/src/compiler/component-compiler.ts +84 -16
  69. package/src/index.ts +5 -4
  70. package/src/registry/component-registry.ts +18 -0
  71. package/src/runtime/component-hierarchy.ts +29 -8
  72. package/src/runtime/prop-builder.ts +3 -2
  73. package/src/types/index.ts +14 -12
  74. package/src/utilities/index.ts +0 -1
  75. package/src/utilities/library-loader.ts +18 -0
  76. package/src/utilities/library-registry.ts +57 -552
  77. package/tsconfig.json +1 -0
  78. package/tsconfig.tsbuildinfo +1 -1
  79. package/webpack.umd.config.js +76 -0
  80. package/dist/utilities/runtime-utilities.d.ts +0 -10
  81. package/dist/utilities/runtime-utilities.d.ts.map +0 -1
  82. package/dist/utilities/runtime-utilities.js +0 -92
  83. package/src/utilities/runtime-utilities.ts +0 -122
package/package.json CHANGED
@@ -1,11 +1,14 @@
1
1
  {
2
2
  "name": "@memberjunction/react-runtime",
3
- "version": "2.90.0",
3
+ "version": "2.92.0",
4
4
  "description": "Platform-agnostic React component runtime for MemberJunction. Provides core compilation, registry, and execution capabilities for React components in any JavaScript environment.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
+ "browser": "dist/runtime.umd.js",
7
8
  "scripts": {
8
- "build": "tsc",
9
+ "build": "npm run build:node && npm run build:umd",
10
+ "build:node": "tsc",
11
+ "build:umd": "webpack --config webpack.umd.config.js",
9
12
  "build:clean": "rimraf ./dist && npm run build",
10
13
  "watch": "tsc -w",
11
14
  "patchVersion": "npm version patch",
@@ -25,9 +28,10 @@
25
28
  },
26
29
  "homepage": "https://github.com/MemberJunction/MJ#readme",
27
30
  "dependencies": {
28
- "@memberjunction/core": "2.90.0",
29
- "@memberjunction/global": "2.90.0",
30
- "@memberjunction/interactive-component-types": "2.90.0",
31
+ "@memberjunction/core": "2.92.0",
32
+ "@memberjunction/global": "2.92.0",
33
+ "@memberjunction/interactive-component-types": "2.92.0",
34
+ "@memberjunction/core-entities": "2.92.0",
31
35
  "@babel/standalone": "^7.23.5",
32
36
  "rxjs": "^7.8.1"
33
37
  },
@@ -35,6 +39,12 @@
35
39
  "@types/node": "20.10.0",
36
40
  "jest": "^27.5.1",
37
41
  "rimraf": "^3.0.2",
38
- "typescript": "~5.3.3"
42
+ "typescript": "~5.3.3",
43
+ "webpack": "^5.89.0",
44
+ "webpack-cli": "^5.1.4",
45
+ "babel-loader": "^9.1.3",
46
+ "@babel/core": "^7.23.5",
47
+ "@babel/preset-env": "^7.23.5",
48
+ "path-browserify": "^1.0.1"
39
49
  }
40
50
  }
@@ -4,6 +4,7 @@
4
4
  * @module @memberjunction/react-runtime/compiler
5
5
  */
6
6
 
7
+ import { UserInfo } from '@memberjunction/core';
7
8
  import {
8
9
  CompileOptions,
9
10
  CompiledComponent,
@@ -13,6 +14,7 @@ import {
13
14
  RuntimeContext
14
15
  } from '../types';
15
16
  import { LibraryRegistry } from '../utilities/library-registry';
17
+ import { ComponentLibraryEntity } from '@memberjunction/core-entities';
16
18
 
17
19
  /**
18
20
  * Default compiler configuration
@@ -80,7 +82,7 @@ export class ComponentCompiler {
80
82
  this.validateCompileOptions(options);
81
83
 
82
84
  // Load required libraries if specified
83
- const loadedLibraries = await this.loadRequiredLibraries(options.libraries);
85
+ const loadedLibraries = await this.loadRequiredLibraries(options.libraries!, options.allLibraries);
84
86
 
85
87
  // Transpile the component code
86
88
  const transpiledCode = this.transpileComponent(
@@ -142,7 +144,7 @@ export class ComponentCompiler {
142
144
  throw new Error('Babel instance not set. Call setBabelInstance() first.');
143
145
  }
144
146
 
145
- const wrappedCode = this.wrapComponentCode(code, componentName, options.libraries);
147
+ const wrappedCode = this.wrapComponentCode(code, componentName, options.libraries, options.dependencies);
146
148
 
147
149
  try {
148
150
  const result = this.babelInstance.transform(wrappedCode, {
@@ -164,9 +166,10 @@ export class ComponentCompiler {
164
166
  * @param componentCode - Raw component code
165
167
  * @param componentName - Name of the component
166
168
  * @param libraries - Optional library dependencies
169
+ * @param dependencies - Optional child component dependencies
167
170
  * @returns Wrapped component code
168
171
  */
169
- private wrapComponentCode(componentCode: string, componentName: string, libraries?: any[]): string {
172
+ private wrapComponentCode(componentCode: string, componentName: string, libraries?: any[], dependencies?: Array<{ name: string }>): string {
170
173
  // Generate library declarations if libraries are provided
171
174
  const libraryDeclarations = libraries && libraries.length > 0
172
175
  ? libraries
@@ -174,14 +177,21 @@ export class ComponentCompiler {
174
177
  .map(lib => `const ${lib.globalVariable} = libraries['${lib.globalVariable}'];`)
175
178
  .join('\n ')
176
179
  : '';
180
+
181
+ // Generate component declarations if dependencies are provided
182
+ const componentDeclarations = dependencies && dependencies.length > 0
183
+ ? dependencies
184
+ .map(dep => `const ${dep.name} = components['${dep.name}'];`)
185
+ .join('\n ')
186
+ : '';
177
187
 
178
188
  return `
179
189
  function createComponent(
180
190
  React, ReactDOM,
181
191
  useState, useEffect, useCallback, useMemo, useRef, useContext, useReducer, useLayoutEffect,
182
- libraries, styles, console
192
+ libraries, styles, console, components
183
193
  ) {
184
- ${libraryDeclarations ? libraryDeclarations + '\n ' : ''}${componentCode}
194
+ ${libraryDeclarations ? libraryDeclarations + '\n ' : ''}${componentDeclarations ? componentDeclarations + '\n ' : ''}${componentCode}
185
195
 
186
196
  // Ensure the component exists
187
197
  if (typeof ${componentName} === 'undefined') {
@@ -207,12 +217,19 @@ export class ComponentCompiler {
207
217
  /**
208
218
  * Load required libraries from the registry
209
219
  * @param libraries - Array of library dependencies
220
+ * @param contextUser - Context user for accessing library registry
210
221
  * @returns Map of loaded libraries
211
222
  */
212
- private async loadRequiredLibraries(libraries?: any[]): Promise<Map<string, any>> {
223
+ private async loadRequiredLibraries(libraries: any[], componentLibraries: ComponentLibraryEntity[]): Promise<Map<string, any>> {
213
224
  const loadedLibraries = new Map<string, any>();
214
225
 
226
+ console.log('🔍 loadRequiredLibraries called with:', {
227
+ librariesCount: libraries?.length || 0,
228
+ libraries: libraries?.map(l => ({ name: l.name, version: l.version, globalVariable: l.globalVariable }))
229
+ });
230
+
215
231
  if (!libraries || libraries.length === 0) {
232
+ console.log('📚 No libraries to load, returning empty map');
216
233
  return loadedLibraries;
217
234
  }
218
235
 
@@ -222,28 +239,49 @@ export class ComponentCompiler {
222
239
  return loadedLibraries;
223
240
  }
224
241
 
242
+ // Initialize LibraryRegistry with componentLibraries if provided
243
+ if (componentLibraries) {
244
+ await LibraryRegistry.Config(false, componentLibraries);
245
+ } else {
246
+ console.warn('⚠️ No componentLibraries provided for LibraryRegistry initialization');
247
+ }
248
+
225
249
  const loadPromises = libraries.map(async (lib) => {
250
+ console.log(`📦 Processing library: ${lib.name}`);
251
+
226
252
  // Check if library is approved
227
- if (!LibraryRegistry.isApproved(lib.name)) {
253
+ const isApproved = LibraryRegistry.isApproved(lib.name);
254
+ console.log(` ✓ Approved check for ${lib.name}: ${isApproved}`);
255
+
256
+ if (!isApproved) {
257
+ console.error(` ❌ Library '${lib.name}' is not approved`);
228
258
  throw new Error(`Library '${lib.name}' is not approved. Only approved libraries can be used.`);
229
259
  }
230
260
 
231
261
  // Get library definition for complete info
232
262
  const libraryDef = LibraryRegistry.getLibrary(lib.name);
263
+ console.log(` ✓ Library definition found for ${lib.name}: ${!!libraryDef}`);
264
+
233
265
  if (!libraryDef) {
266
+ console.error(` ❌ Library '${lib.name}' not found in registry`);
234
267
  throw new Error(`Library '${lib.name}' not found in registry`);
235
268
  }
236
269
 
237
270
  // Get CDN URL for the library
238
271
  const resolvedVersion = LibraryRegistry.resolveVersion(lib.name, lib.version);
272
+ console.log(` ✓ Resolved version for ${lib.name}: ${resolvedVersion}`);
273
+
239
274
  const cdnUrl = LibraryRegistry.getCdnUrl(lib.name, resolvedVersion);
275
+ console.log(` ✓ CDN URL for ${lib.name}: ${cdnUrl}`);
240
276
 
241
277
  if (!cdnUrl) {
278
+ console.error(` ❌ No CDN URL found for library '${lib.name}' version '${lib.version || 'default'}'`);
242
279
  throw new Error(`No CDN URL found for library '${lib.name}' version '${lib.version || 'default'}'`);
243
280
  }
244
281
 
245
282
  // Check if already loaded
246
283
  if ((window as any)[lib.globalVariable]) {
284
+ console.log(` ℹ️ Library ${lib.name} already loaded globally as ${lib.globalVariable}`);
247
285
  loadedLibraries.set(lib.globalVariable, (window as any)[lib.globalVariable]);
248
286
  return;
249
287
  }
@@ -255,20 +293,29 @@ export class ComponentCompiler {
255
293
  }
256
294
 
257
295
  // Load the library dynamically (cdnUrl is guaranteed to be non-null here due to check above)
296
+ console.log(` 📥 Loading script from CDN for ${lib.name}...`);
258
297
  await this.loadScript(cdnUrl!, lib.globalVariable);
259
298
 
260
299
  // Capture the library value from global scope
261
300
  // Note: Libraries loaded from CDN typically attach to window automatically
262
301
  // We capture them here to pass through the component's closure
263
302
  const libraryValue = (window as any)[lib.globalVariable];
303
+ console.log(` ✓ Library ${lib.name} loaded successfully, global variable ${lib.globalVariable} is:`, typeof libraryValue);
304
+
264
305
  if (libraryValue) {
265
306
  loadedLibraries.set(lib.globalVariable, libraryValue);
307
+ console.log(` ✅ Added ${lib.name} to loaded libraries map`);
266
308
  } else {
309
+ console.error(` ❌ Library '${lib.name}' failed to expose global variable '${lib.globalVariable}'`);
267
310
  throw new Error(`Library '${lib.name}' failed to load or did not expose '${lib.globalVariable}'`);
268
311
  }
269
312
  });
270
313
 
271
314
  await Promise.all(loadPromises);
315
+
316
+ console.log(`✅ All libraries loaded successfully. Total: ${loadedLibraries.size}`);
317
+ console.log('📚 Loaded libraries map:', Array.from(loadedLibraries.keys()));
318
+
272
319
  return loadedLibraries;
273
320
  }
274
321
 
@@ -313,11 +360,16 @@ export class ComponentCompiler {
313
360
  // Check if script already exists
314
361
  const existingScript = document.querySelector(`script[src="${url}"]`);
315
362
  if (existingScript) {
316
- // Wait for it to finish loading
363
+ // Wait for it to finish loading with exponential backoff
364
+ let attempts = 0;
365
+ const maxAttempts = 50; // 5 seconds total with 100ms intervals
317
366
  const checkLoaded = () => {
318
367
  if ((window as any)[globalName]) {
319
368
  resolve();
369
+ } else if (attempts >= maxAttempts) {
370
+ reject(new Error(`${globalName} not found after ${maxAttempts * 100}ms waiting for existing script`));
320
371
  } else {
372
+ attempts++;
321
373
  setTimeout(checkLoaded, 100);
322
374
  }
323
375
  };
@@ -331,14 +383,28 @@ export class ComponentCompiler {
331
383
  script.async = true;
332
384
 
333
385
  script.onload = () => {
334
- // Give the library a moment to initialize
335
- setTimeout(() => {
386
+ // More robust checking with multiple attempts
387
+ let attempts = 0;
388
+ const maxAttempts = 20; // 2 seconds total
389
+ const checkInterval = 100; // Check every 100ms
390
+
391
+ const checkGlobal = () => {
336
392
  if ((window as any)[globalName]) {
393
+ console.log(` ✓ Global variable ${globalName} found after ${attempts * checkInterval}ms`);
337
394
  resolve();
395
+ } else if (attempts >= maxAttempts) {
396
+ // Final check - some libraries might use a different global name pattern
397
+ console.error(` ❌ ${globalName} not found after ${attempts * checkInterval}ms`);
398
+ console.log(` ℹ️ Window properties:`, Object.keys(window).filter(k => k.toLowerCase().includes(globalName.toLowerCase())));
399
+ reject(new Error(`${globalName} not found after loading script from ${url}`));
338
400
  } else {
339
- reject(new Error(`${globalName} not found after loading script`));
401
+ attempts++;
402
+ setTimeout(checkGlobal, checkInterval);
340
403
  }
341
- }, 100);
404
+ };
405
+
406
+ // Start checking immediately (don't wait 100ms first)
407
+ checkGlobal();
342
408
  };
343
409
 
344
410
  script.onerror = () => {
@@ -366,12 +432,12 @@ export class ComponentCompiler {
366
432
  const factoryCreator = new Function(
367
433
  'React', 'ReactDOM',
368
434
  'useState', 'useEffect', 'useCallback', 'useMemo', 'useRef', 'useContext', 'useReducer', 'useLayoutEffect',
369
- 'libraries', 'styles', 'console',
435
+ 'libraries', 'styles', 'console', 'components',
370
436
  `${transpiledCode}; return createComponent;`
371
437
  );
372
438
 
373
439
  // Return a function that executes the factory with runtime context
374
- return (context: RuntimeContext, styles: any = {}) => {
440
+ return (context: RuntimeContext, styles: any = {}, components: Record<string, any> = {}) => {
375
441
  const { React, ReactDOM, libraries = {} } = context;
376
442
 
377
443
  // Merge loaded libraries with context libraries
@@ -394,7 +460,8 @@ export class ComponentCompiler {
394
460
  React.useLayoutEffect,
395
461
  mergedLibraries,
396
462
  styles,
397
- console
463
+ console,
464
+ components
398
465
  );
399
466
 
400
467
  // Call createComponent to get the actual component
@@ -411,7 +478,8 @@ export class ComponentCompiler {
411
478
  React.useLayoutEffect,
412
479
  mergedLibraries,
413
480
  styles,
414
- console
481
+ console,
482
+ components
415
483
  );
416
484
 
417
485
  // Return the component directly
package/src/index.ts CHANGED
@@ -71,10 +71,6 @@ export {
71
71
  } from './runtime';
72
72
 
73
73
  // Export utilities
74
- export {
75
- RuntimeUtilities,
76
- createRuntimeUtilities
77
- } from './utilities/runtime-utilities';
78
74
 
79
75
  export {
80
76
  SetupStyles,
@@ -93,6 +89,11 @@ export {
93
89
  LibraryLoadResult
94
90
  } from './utilities/library-loader';
95
91
 
92
+ export {
93
+ LibraryRegistry,
94
+ LibraryDefinition
95
+ } from './utilities/library-registry';
96
+
96
97
  export {
97
98
  ComponentErrorAnalyzer,
98
99
  FailedComponentInfo
@@ -167,6 +167,24 @@ export class ComponentRegistry {
167
167
  return components;
168
168
  }
169
169
 
170
+ /**
171
+ * Gets all components in a namespace and version as a map
172
+ * @param namespace - Namespace to query (default: 'Global')
173
+ * @param version - Version to query (default: 'v1')
174
+ * @returns Object mapping component names to components
175
+ */
176
+ getAll(namespace: string = 'Global', version: string = 'v1'): Record<string, any> {
177
+ const components: Record<string, any> = {};
178
+
179
+ for (const entry of this.registry.values()) {
180
+ if (entry.metadata.namespace === namespace && entry.metadata.version === version) {
181
+ components[entry.metadata.name] = entry.component;
182
+ }
183
+ }
184
+
185
+ return components;
186
+ }
187
+
170
188
  /**
171
189
  * Gets all registered namespaces
172
190
  * @returns Array of unique namespace names
@@ -7,13 +7,14 @@
7
7
  import {
8
8
  CompilationResult,
9
9
  CompileOptions,
10
- ComponentStyles,
11
10
  RuntimeContext
12
11
  } from '../types';
13
12
  import { ComponentCompiler } from '../compiler';
14
13
  import { ComponentRegistry } from '../registry';
15
14
 
16
- import { ComponentSpec } from '@memberjunction/interactive-component-types';
15
+ import { ComponentSpec, ComponentStyles } from '@memberjunction/interactive-component-types';
16
+ import { UserInfo } from '@memberjunction/core';
17
+ import { ComponentLibraryEntity } from '@memberjunction/core-entities';
17
18
 
18
19
  /**
19
20
  * Result of a hierarchy registration operation
@@ -48,6 +49,10 @@ export interface HierarchyRegistrationOptions {
48
49
  continueOnError?: boolean;
49
50
  /** Whether to override existing components */
50
51
  allowOverride?: boolean;
52
+ /**
53
+ * Required, metadata for all possible libraries allowed by the system
54
+ */
55
+ allLibraries: ComponentLibraryEntity[];
51
56
  }
52
57
 
53
58
  /**
@@ -68,7 +73,7 @@ export class ComponentHierarchyRegistrar {
68
73
  */
69
74
  async registerHierarchy(
70
75
  rootSpec: ComponentSpec,
71
- options: HierarchyRegistrationOptions = {}
76
+ options: HierarchyRegistrationOptions
72
77
  ): Promise<HierarchyRegistrationResult> {
73
78
  const {
74
79
  styles,
@@ -78,6 +83,13 @@ export class ComponentHierarchyRegistrar {
78
83
  allowOverride = true
79
84
  } = options;
80
85
 
86
+ console.log('🌳 ComponentHierarchyRegistrar.registerHierarchy:', {
87
+ rootComponent: rootSpec.name,
88
+ hasLibraries: !!(rootSpec.libraries && rootSpec.libraries.length > 0),
89
+ libraryCount: rootSpec.libraries?.length || 0,
90
+ libraries: rootSpec.libraries?.map(l => l.name)
91
+ });
92
+
81
93
  const registeredComponents: string[] = [];
82
94
  const errors: ComponentRegistrationError[] = [];
83
95
  const warnings: string[] = [];
@@ -85,7 +97,7 @@ export class ComponentHierarchyRegistrar {
85
97
  // Register the root component
86
98
  const rootResult = await this.registerSingleComponent(
87
99
  rootSpec,
88
- { styles, namespace, version, allowOverride }
100
+ { styles, namespace, version, allowOverride, allLibraries: options.allLibraries }
89
101
  );
90
102
 
91
103
  if (rootResult.success) {
@@ -102,7 +114,7 @@ export class ComponentHierarchyRegistrar {
102
114
  if (childComponents.length > 0) {
103
115
  const childResult = await this.registerChildComponents(
104
116
  childComponents,
105
- { styles, namespace, version, continueOnError, allowOverride },
117
+ { styles, namespace, version, continueOnError, allowOverride, allLibraries: options.allLibraries },
106
118
  registeredComponents,
107
119
  errors,
108
120
  warnings
@@ -130,6 +142,7 @@ export class ComponentHierarchyRegistrar {
130
142
  namespace?: string;
131
143
  version?: string;
132
144
  allowOverride?: boolean;
145
+ allLibraries: ComponentLibraryEntity[];
133
146
  }
134
147
  ): Promise<{ success: boolean; error?: ComponentRegistrationError }> {
135
148
  const { styles, namespace = 'Global', version = 'v1', allowOverride = true } = options;
@@ -161,9 +174,16 @@ export class ComponentHierarchyRegistrar {
161
174
  componentName: spec.name,
162
175
  componentCode: spec.code,
163
176
  styles,
164
- libraries: spec.libraries // Pass along library dependencies from the spec
177
+ libraries: spec.libraries, // Pass along library dependencies from the spec
178
+ dependencies: spec.dependencies, // Pass along child component dependencies
179
+ allLibraries: options.allLibraries
165
180
  };
166
181
 
182
+ console.log(`🔧 Compiling component ${spec.name} with libraries:`, {
183
+ libraryCount: spec.libraries?.length || 0,
184
+ libraries: spec.libraries?.map(l => ({ name: l.name, globalVariable: l.globalVariable }))
185
+ });
186
+
167
187
  const compilationResult = await this.compiler.compile(compileOptions);
168
188
 
169
189
  if (!compilationResult.success) {
@@ -223,7 +243,8 @@ export class ComponentHierarchyRegistrar {
223
243
  styles: options.styles,
224
244
  namespace: options.namespace,
225
245
  version: options.version,
226
- allowOverride: options.allowOverride
246
+ allowOverride: options.allowOverride,
247
+ allLibraries: options.allLibraries
227
248
  });
228
249
 
229
250
  if (childResult.success) {
@@ -266,7 +287,7 @@ export async function registerComponentHierarchy(
266
287
  compiler: ComponentCompiler,
267
288
  registry: ComponentRegistry,
268
289
  runtimeContext: RuntimeContext,
269
- options: HierarchyRegistrationOptions = {}
290
+ options: HierarchyRegistrationOptions
270
291
  ): Promise<HierarchyRegistrationResult> {
271
292
  const registrar = new ComponentHierarchyRegistrar(compiler, registry, runtimeContext);
272
293
  return registrar.registerHierarchy(rootSpec, options);
@@ -4,7 +4,8 @@
4
4
  * @module @memberjunction/react-runtime/runtime
5
5
  */
6
6
 
7
- import { ComponentProps, ComponentCallbacks, ComponentStyles } from '../types';
7
+ import { ComponentStyles } from '@memberjunction/interactive-component-types';
8
+ import { ComponentProps, ComponentCallbacks } from '../types';
8
9
  import { Subject, debounceTime, Subscription } from 'rxjs';
9
10
 
10
11
  /**
@@ -187,7 +188,7 @@ export function mergeProps(...propsList: Partial<ComponentProps>[]): ComponentPr
187
188
  utilities: {},
188
189
  callbacks: {},
189
190
  components: {},
190
- styles: {}
191
+ styles: {} as ComponentStyles
191
192
  };
192
193
 
193
194
  for (const props of propsList) {
@@ -4,6 +4,10 @@
4
4
  * @module @memberjunction/react-runtime/types
5
5
  */
6
6
 
7
+ import { UserInfo } from '@memberjunction/core';
8
+ import { ComponentLibraryEntity } from '@memberjunction/core-entities';
9
+ import { ComponentLibraryDependency, ComponentStyles } from '@memberjunction/interactive-component-types';
10
+
7
11
  /**
8
12
  * Represents a compiled React component with its metadata
9
13
  */
@@ -36,22 +40,20 @@ export interface CompileOptions {
36
40
  babelPlugins?: string[];
37
41
  /** Custom Babel presets to use */
38
42
  babelPresets?: string[];
43
+
39
44
  /** Library dependencies that the component requires */
40
- libraries?: any[]; // Using any[] to avoid circular dependency with InteractiveComponents
41
- }
45
+ libraries?: ComponentLibraryDependency[];
46
+
47
+ /** Child component dependencies that the component requires */
48
+ dependencies?: Array<{ name: string; code?: string }>;
42
49
 
43
- /**
44
- * Component styles that can be applied
45
- */
46
- export interface ComponentStyles {
47
- /** CSS classes to apply */
48
- className?: string;
49
- /** Inline styles */
50
- style?: Record<string, any>;
51
- /** Global CSS to inject */
52
- globalCss?: string;
50
+ /**
51
+ * Required, metadata for all possible libraries allowed by the system
52
+ */
53
+ allLibraries: ComponentLibraryEntity[];
53
54
  }
54
55
 
56
+
55
57
  /**
56
58
  * Registry entry for a compiled component
57
59
  */
@@ -3,7 +3,6 @@
3
3
  * @module @memberjunction/react-runtime/utilities
4
4
  */
5
5
 
6
- export * from './runtime-utilities';
7
6
  export * from './component-styles';
8
7
  export * from './standard-libraries';
9
8
  export * from './library-loader';
@@ -99,6 +99,24 @@ export class LibraryLoader {
99
99
  const ReactDOM = coreResults.find((_, i) => coreLibraries[i].globalVariable === 'ReactDOM');
100
100
  const Babel = coreResults.find((_, i) => coreLibraries[i].globalVariable === 'Babel');
101
101
 
102
+ // Expose React and ReactDOM as globals for UMD libraries that expect them
103
+ // Many React component libraries (Recharts, Victory, etc.) expect these as globals
104
+ if (typeof window !== 'undefined') {
105
+ if (React && !(window as any).React) {
106
+ (window as any).React = React;
107
+ console.log('✓ Exposed React as window.React for UMD compatibility');
108
+ }
109
+ if (ReactDOM && !(window as any).ReactDOM) {
110
+ (window as any).ReactDOM = ReactDOM;
111
+ console.log('✓ Exposed ReactDOM as window.ReactDOM for UMD compatibility');
112
+ }
113
+ // Also expose PropTypes as empty object if not present (for older libraries)
114
+ if (!(window as any).PropTypes) {
115
+ (window as any).PropTypes = {};
116
+ console.log('✓ Exposed empty PropTypes as window.PropTypes for UMD compatibility');
117
+ }
118
+ }
119
+
102
120
  // Now load plugin libraries from configuration
103
121
  const config = StandardLibraryManager.getConfiguration();
104
122
  const enabledLibraries = StandardLibraryManager.getEnabledLibraries();