@memberjunction/react-runtime 2.74.0 → 2.76.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 (54) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +27 -0
  3. package/README.md +96 -4
  4. package/dist/compiler/component-compiler.d.ts +0 -1
  5. package/dist/compiler/component-compiler.d.ts.map +1 -1
  6. package/dist/compiler/component-compiler.js +34 -25
  7. package/dist/index.d.ts +2 -2
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +3 -6
  10. package/dist/registry/component-resolver.d.ts +1 -6
  11. package/dist/registry/component-resolver.d.ts.map +1 -1
  12. package/dist/registry/component-resolver.js +19 -19
  13. package/dist/registry/index.d.ts +2 -1
  14. package/dist/registry/index.d.ts.map +1 -1
  15. package/dist/registry/index.js +3 -1
  16. package/dist/runtime/component-hierarchy.d.ts +1 -1
  17. package/dist/runtime/component-hierarchy.d.ts.map +1 -1
  18. package/dist/runtime/component-hierarchy.js +25 -25
  19. package/dist/runtime/index.d.ts +1 -1
  20. package/dist/runtime/index.d.ts.map +1 -1
  21. package/dist/runtime/index.js +1 -2
  22. package/dist/runtime/prop-builder.d.ts +1 -2
  23. package/dist/runtime/prop-builder.d.ts.map +1 -1
  24. package/dist/runtime/prop-builder.js +4 -76
  25. package/dist/types/index.d.ts +2 -0
  26. package/dist/types/index.d.ts.map +1 -1
  27. package/dist/types/index.js +15 -0
  28. package/dist/types/library-config.d.ts +32 -0
  29. package/dist/types/library-config.d.ts.map +1 -0
  30. package/dist/types/library-config.js +2 -0
  31. package/dist/utilities/core-libraries.d.ts +5 -0
  32. package/dist/utilities/core-libraries.d.ts.map +1 -0
  33. package/dist/utilities/core-libraries.js +52 -0
  34. package/dist/utilities/library-loader.d.ts +3 -2
  35. package/dist/utilities/library-loader.d.ts.map +1 -1
  36. package/dist/utilities/library-loader.js +65 -76
  37. package/dist/utilities/standard-libraries.d.ts +13 -24
  38. package/dist/utilities/standard-libraries.d.ts.map +1 -1
  39. package/dist/utilities/standard-libraries.js +58 -47
  40. package/package.json +4 -4
  41. package/samples/entities-1.js +493 -0
  42. package/src/compiler/component-compiler.ts +64 -35
  43. package/src/index.ts +1 -5
  44. package/src/registry/component-resolver.ts +21 -30
  45. package/src/registry/index.ts +2 -1
  46. package/src/runtime/component-hierarchy.ts +26 -26
  47. package/src/runtime/index.ts +0 -1
  48. package/src/runtime/prop-builder.ts +5 -112
  49. package/src/types/index.ts +6 -1
  50. package/src/types/library-config.ts +75 -0
  51. package/src/utilities/core-libraries.ts +61 -0
  52. package/src/utilities/library-loader.ts +113 -93
  53. package/src/utilities/standard-libraries.ts +104 -71
  54. package/tsconfig.tsbuildinfo +1 -1
@@ -5,12 +5,11 @@
5
5
  */
6
6
 
7
7
  import {
8
- STANDARD_LIBRARY_URLS,
9
8
  StandardLibraries,
10
- getCoreLibraryUrls,
11
- getUILibraryUrls,
12
- getCSSUrls
9
+ StandardLibraryManager
13
10
  } from './standard-libraries';
11
+ import { LibraryConfiguration, ExternalLibraryConfig, LibraryLoadOptions as ConfigLoadOptions } from '../types/library-config';
12
+ import { getCoreRuntimeLibraries, isCoreRuntimeLibrary } from './core-libraries';
14
13
 
15
14
  /**
16
15
  * Represents a loaded script or CSS resource
@@ -22,6 +21,7 @@ interface LoadedResource {
22
21
 
23
22
  /**
24
23
  * Options for loading libraries
24
+ * @deprecated Use LibraryLoadOptions from library-config instead
25
25
  */
26
26
  export interface LibraryLoadOptions {
27
27
  /** Load core libraries (lodash, d3, Chart.js, dayjs) */
@@ -53,17 +53,99 @@ export class LibraryLoader {
53
53
  /**
54
54
  * Load all standard libraries (core + UI + CSS)
55
55
  * This is the main method that should be used by test harness and Angular wrapper
56
+ * @param config Optional full library configuration to replace the default
57
+ * @param additionalLibraries Optional additional libraries to merge with the configuration
56
58
  */
57
- static async loadAllLibraries(): Promise<LibraryLoadResult> {
58
- return this.loadLibraries({
59
- loadCore: true,
60
- loadUI: true,
61
- loadCSS: true
59
+ static async loadAllLibraries(
60
+ config?: LibraryConfiguration,
61
+ additionalLibraries?: ExternalLibraryConfig[]
62
+ ): Promise<LibraryLoadResult> {
63
+ if (config) {
64
+ StandardLibraryManager.setConfiguration(config);
65
+ }
66
+
67
+ // If additional libraries are provided, merge them with the current configuration
68
+ if (additionalLibraries && additionalLibraries.length > 0) {
69
+ const currentConfig = StandardLibraryManager.getConfiguration();
70
+ const mergedConfig: LibraryConfiguration = {
71
+ libraries: [...currentConfig.libraries, ...additionalLibraries],
72
+ metadata: {
73
+ ...currentConfig.metadata,
74
+ lastUpdated: new Date().toISOString()
75
+ }
76
+ };
77
+ StandardLibraryManager.setConfiguration(mergedConfig);
78
+ }
79
+
80
+ return this.loadLibrariesFromConfig();
81
+ }
82
+
83
+ /**
84
+ * Load libraries based on the current configuration
85
+ */
86
+ static async loadLibrariesFromConfig(options?: ConfigLoadOptions): Promise<LibraryLoadResult> {
87
+ // Always load core runtime libraries first
88
+ const coreLibraries = getCoreRuntimeLibraries();
89
+ const corePromises = coreLibraries.map(lib =>
90
+ this.loadScript(lib.cdnUrl, lib.globalVariable)
91
+ );
92
+
93
+ const coreResults = await Promise.all(corePromises);
94
+ const React = coreResults.find((_, i) => coreLibraries[i].globalVariable === 'React');
95
+ const ReactDOM = coreResults.find((_, i) => coreLibraries[i].globalVariable === 'ReactDOM');
96
+ const Babel = coreResults.find((_, i) => coreLibraries[i].globalVariable === 'Babel');
97
+
98
+ // Now load plugin libraries from configuration
99
+ const config = StandardLibraryManager.getConfiguration();
100
+ const enabledLibraries = StandardLibraryManager.getEnabledLibraries();
101
+
102
+ // Filter out any core runtime libraries from plugin configuration
103
+ let pluginLibraries = enabledLibraries.filter(lib => !isCoreRuntimeLibrary(lib.id));
104
+
105
+ // Apply options filters if provided
106
+ if (options) {
107
+ if (options.categories) {
108
+ pluginLibraries = pluginLibraries.filter(lib =>
109
+ options.categories!.includes(lib.category)
110
+ );
111
+ }
112
+ if (options.excludeRuntimeOnly) {
113
+ pluginLibraries = pluginLibraries.filter(lib => !lib.isRuntimeOnly);
114
+ }
115
+ }
116
+
117
+ // Load CSS files for plugin libraries (non-blocking)
118
+ pluginLibraries.forEach(lib => {
119
+ if (lib.cdnCssUrl) {
120
+ this.loadCSS(lib.cdnCssUrl);
121
+ }
122
+ });
123
+
124
+ // Load plugin libraries
125
+ const pluginPromises = pluginLibraries.map(lib =>
126
+ this.loadScript(lib.cdnUrl, lib.globalVariable)
127
+ );
128
+
129
+ const pluginResults = await Promise.all(pluginPromises);
130
+
131
+ // Build libraries object (only contains plugin libraries)
132
+ const libraries: StandardLibraries = {};
133
+
134
+ pluginLibraries.forEach((lib, index) => {
135
+ libraries[lib.globalVariable] = pluginResults[index];
62
136
  });
137
+
138
+ return {
139
+ React: React || (window as any).React,
140
+ ReactDOM: ReactDOM || (window as any).ReactDOM,
141
+ Babel: Babel || (window as any).Babel,
142
+ libraries
143
+ };
63
144
  }
64
145
 
65
146
  /**
66
- * Load libraries with specific options
147
+ * Load libraries with specific options (backward compatibility)
148
+ * @deprecated Use loadLibrariesFromConfig instead
67
149
  */
68
150
  static async loadLibraries(options: LibraryLoadOptions): Promise<LibraryLoadResult> {
69
151
  const {
@@ -73,78 +155,32 @@ export class LibraryLoader {
73
155
  customLibraries = []
74
156
  } = options;
75
157
 
76
- // Load React ecosystem first
77
- const [React, ReactDOM, Babel] = await Promise.all([
78
- this.loadScript(STANDARD_LIBRARY_URLS.REACT, 'React'),
79
- this.loadScript(STANDARD_LIBRARY_URLS.REACT_DOM, 'ReactDOM'),
80
- this.loadScript(STANDARD_LIBRARY_URLS.BABEL, 'Babel')
81
- ]);
82
-
83
- // Load CSS files if requested (non-blocking)
84
- if (loadCSS) {
85
- getCSSUrls().forEach(url => this.loadCSS(url));
86
- }
87
-
88
- // Prepare library loading promises
89
- const libraryPromises: Promise<any>[] = [];
90
- const libraryNames: string[] = [];
91
-
92
- // Core libraries
158
+ // Map old options to new configuration approach
159
+ const categoriesToLoad: Array<ExternalLibraryConfig['category']> = ['runtime'];
93
160
  if (loadCore) {
94
- const coreUrls = getCoreLibraryUrls();
95
- coreUrls.forEach(url => {
96
- const name = this.getLibraryNameFromUrl(url);
97
- libraryNames.push(name);
98
- libraryPromises.push(this.loadScript(url, name));
99
- });
161
+ categoriesToLoad.push('utility', 'charting');
100
162
  }
101
-
102
- // UI libraries
103
163
  if (loadUI) {
104
- const uiUrls = getUILibraryUrls();
105
- uiUrls.forEach(url => {
106
- const name = this.getLibraryNameFromUrl(url);
107
- libraryNames.push(name);
108
- libraryPromises.push(this.loadScript(url, name));
109
- });
164
+ categoriesToLoad.push('ui');
110
165
  }
111
-
112
- // Custom libraries
113
- customLibraries.forEach(({ url, globalName }) => {
114
- libraryNames.push(globalName);
115
- libraryPromises.push(this.loadScript(url, globalName));
116
- });
117
-
118
- // Load all libraries
119
- const loadedLibraries = await Promise.all(libraryPromises);
120
-
121
- // Build libraries object
122
- const libraries: StandardLibraries = {
123
- _: undefined // Initialize with required property
124
- };
125
- libraryNames.forEach((name, index) => {
126
- // Map common names
127
- if (name === '_') {
128
- libraries._ = loadedLibraries[index];
129
- } else {
130
- libraries[name] = loadedLibraries[index];
131
- }
166
+
167
+ const result = await this.loadLibrariesFromConfig({
168
+ categories: categoriesToLoad
132
169
  });
133
-
134
- // Ensure all standard properties exist
135
- if (!libraries._) libraries._ = (window as any)._;
136
- if (!libraries.d3) libraries.d3 = (window as any).d3;
137
- if (!libraries.Chart) libraries.Chart = (window as any).Chart;
138
- if (!libraries.dayjs) libraries.dayjs = (window as any).dayjs;
139
- if (!libraries.antd) libraries.antd = (window as any).antd;
140
- if (!libraries.ReactBootstrap) libraries.ReactBootstrap = (window as any).ReactBootstrap;
141
-
142
- return {
143
- React,
144
- ReactDOM,
145
- Babel,
146
- libraries
147
- };
170
+
171
+ // Load custom libraries if provided
172
+ if (customLibraries.length > 0) {
173
+ const customPromises = customLibraries.map(({ url, globalName }) =>
174
+ this.loadScript(url, globalName)
175
+ );
176
+
177
+ const customResults = await Promise.all(customPromises);
178
+ customLibraries.forEach(({ globalName }, index) => {
179
+ result.libraries[globalName] = customResults[index];
180
+ });
181
+ }
182
+
183
+ return result;
148
184
  }
149
185
 
150
186
  /**
@@ -274,22 +310,6 @@ export class LibraryLoader {
274
310
  script.addEventListener('load', loadHandler);
275
311
  }
276
312
 
277
- /**
278
- * Get library name from URL for global variable mapping
279
- */
280
- private static getLibraryNameFromUrl(url: string): string {
281
- // Map known URLs to their global variable names
282
- if (url.includes('lodash')) return '_';
283
- if (url.includes('d3')) return 'd3';
284
- if (url.includes('Chart.js') || url.includes('chart')) return 'Chart';
285
- if (url.includes('dayjs')) return 'dayjs';
286
- if (url.includes('antd')) return 'antd';
287
- if (url.includes('react-bootstrap')) return 'ReactBootstrap';
288
-
289
- // Default: extract name from URL
290
- const match = url.match(/\/([^\/]+)(?:\.min)?\.js$/);
291
- return match ? match[1] : 'unknown';
292
- }
293
313
 
294
314
  /**
295
315
  * Get all loaded resources (for cleanup)
@@ -3,95 +3,128 @@
3
3
  * @module @memberjunction/react-runtime/utilities
4
4
  */
5
5
 
6
- /**
7
- * CDN URLs for standard libraries used by React components
8
- */
9
- export const STANDARD_LIBRARY_URLS = {
10
- // Core React libraries
11
- REACT: 'https://unpkg.com/react@18/umd/react.development.js',
12
- REACT_DOM: 'https://unpkg.com/react-dom@18/umd/react-dom.development.js',
13
- BABEL: 'https://unpkg.com/@babel/standalone/babel.min.js',
14
-
15
- // Data Visualization
16
- D3: 'https://cdnjs.cloudflare.com/ajax/libs/d3/7.8.5/d3.min.js',
17
- CHART_JS: 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.0/chart.umd.js',
18
-
19
- // Utilities
20
- LODASH: 'https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js',
21
- DAYJS: 'https://unpkg.com/dayjs@1.11.10/dayjs.min.js',
22
-
23
- // UI Libraries (optional)
24
- ANTD: 'https://unpkg.com/antd@5.11.5/dist/antd.min.js',
25
- REACT_BOOTSTRAP: 'https://unpkg.com/react-bootstrap@2.9.1/dist/react-bootstrap.min.js',
26
-
27
- // CSS
28
- ANTD_CSS: 'https://unpkg.com/antd@5.11.5/dist/reset.css',
29
- BOOTSTRAP_CSS: 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css'
30
- };
6
+ import { LibraryConfiguration, ExternalLibraryConfig } from '../types/library-config';
31
7
 
32
- /**
33
- * Interface for standard libraries available to React components
34
- */
35
- export interface StandardLibraries {
36
- _: any; // lodash
37
- d3?: any;
38
- Chart?: any;
39
- dayjs?: any;
40
- antd?: any;
41
- ReactBootstrap?: any;
42
- [key: string]: any; // Allow additional libraries
43
- }
44
8
 
45
9
  /**
46
- * Get the list of core libraries that should always be loaded
10
+ * Type for dynamically loaded libraries available to React components
47
11
  */
48
- export function getCoreLibraryUrls(): string[] {
49
- return [
50
- STANDARD_LIBRARY_URLS.LODASH,
51
- STANDARD_LIBRARY_URLS.D3,
52
- STANDARD_LIBRARY_URLS.CHART_JS,
53
- STANDARD_LIBRARY_URLS.DAYJS
54
- ];
55
- }
12
+ export type StandardLibraries = Record<string, any>;
56
13
 
57
14
  /**
58
- * Get the list of optional UI library URLs
15
+ * Default empty library configuration
16
+ * Libraries should be configured dynamically at runtime
59
17
  */
60
- export function getUILibraryUrls(): string[] {
61
- return [
62
- STANDARD_LIBRARY_URLS.ANTD,
63
- STANDARD_LIBRARY_URLS.REACT_BOOTSTRAP
64
- ];
65
- }
18
+ const DEFAULT_LIBRARY_CONFIG: LibraryConfiguration = {
19
+ libraries: [],
20
+ metadata: {
21
+ version: '1.0.0',
22
+ lastUpdated: new Date().toISOString(),
23
+ description: 'Empty default configuration - libraries should be configured at runtime'
24
+ }
25
+ };
66
26
 
67
27
  /**
68
- * Get the list of CSS URLs for UI libraries
28
+ * Manages standard library configurations with dynamic loading support
69
29
  */
70
- export function getCSSUrls(): string[] {
71
- return [
72
- STANDARD_LIBRARY_URLS.ANTD_CSS,
73
- STANDARD_LIBRARY_URLS.BOOTSTRAP_CSS
74
- ];
30
+ export class StandardLibraryManager {
31
+ private static configuration: LibraryConfiguration = DEFAULT_LIBRARY_CONFIG;
32
+
33
+ /**
34
+ * Set a custom library configuration
35
+ */
36
+ static setConfiguration(config: LibraryConfiguration): void {
37
+ this.configuration = config;
38
+ }
39
+
40
+ /**
41
+ * Get the current library configuration
42
+ */
43
+ static getConfiguration(): LibraryConfiguration {
44
+ return this.configuration;
45
+ }
46
+
47
+ /**
48
+ * Get all enabled libraries
49
+ */
50
+ static getEnabledLibraries(): ExternalLibraryConfig[] {
51
+ return this.configuration.libraries.filter(lib => lib.isEnabled);
52
+ }
53
+
54
+ /**
55
+ * Get libraries by category
56
+ */
57
+ static getLibrariesByCategory(category: ExternalLibraryConfig['category']): ExternalLibraryConfig[] {
58
+ return this.configuration.libraries.filter(lib => lib.category === category && lib.isEnabled);
59
+ }
60
+
61
+ /**
62
+ * Get core libraries (runtime essentials)
63
+ */
64
+ static getCoreLibraries(): ExternalLibraryConfig[] {
65
+ return this.configuration.libraries.filter(lib => lib.isCore && lib.isEnabled);
66
+ }
67
+
68
+ /**
69
+ * Get component libraries (non-runtime)
70
+ */
71
+ static getComponentLibraries(): ExternalLibraryConfig[] {
72
+ return this.configuration.libraries.filter(lib => !lib.isRuntimeOnly && lib.isEnabled);
73
+ }
74
+
75
+ /**
76
+ * Get library by ID
77
+ */
78
+ static getLibraryById(id: string): ExternalLibraryConfig | undefined {
79
+ return this.configuration.libraries.find(lib => lib.id === id);
80
+ }
81
+
82
+ /**
83
+ * Get library URLs as a simple object (for backward compatibility)
84
+ */
85
+ static getLibraryUrls(): Record<string, string> {
86
+ const urls: Record<string, string> = {};
87
+ this.configuration.libraries
88
+ .filter(lib => lib.isEnabled)
89
+ .forEach(lib => {
90
+ // Use uppercase key for backward compatibility
91
+ const key = lib.id.replace(/-/g, '_').toUpperCase();
92
+ urls[key] = lib.cdnUrl;
93
+ if (lib.cdnCssUrl) {
94
+ urls[`${key}_CSS`] = lib.cdnCssUrl;
95
+ }
96
+ });
97
+ return urls;
98
+ }
99
+
100
+ /**
101
+ * Reset to default configuration
102
+ */
103
+ static resetToDefault(): void {
104
+ this.configuration = DEFAULT_LIBRARY_CONFIG;
105
+ }
75
106
  }
76
107
 
108
+
77
109
  /**
78
110
  * Creates a standard libraries object for browser environments
79
- * This assumes the libraries are already loaded as globals
111
+ * Dynamically collects all libraries based on current configuration
80
112
  */
81
113
  export function createStandardLibraries(): StandardLibraries {
82
114
  if (typeof window === 'undefined') {
83
115
  // Return empty object in Node.js environments
84
- return {
85
- _: undefined
86
- };
116
+ return {};
87
117
  }
88
118
 
89
- return {
90
- _: (window as any)._,
91
- d3: (window as any).d3,
92
- Chart: (window as any).Chart,
93
- dayjs: (window as any).dayjs,
94
- antd: (window as any).antd,
95
- ReactBootstrap: (window as any).ReactBootstrap
96
- };
119
+ const libs: StandardLibraries = {};
120
+
121
+ // Add all component libraries as globals based on configuration
122
+ StandardLibraryManager.getComponentLibraries().forEach(lib => {
123
+ const globalValue = (window as any)[lib.globalVariable];
124
+ if (globalValue !== undefined) {
125
+ libs[lib.globalVariable] = globalValue;
126
+ }
127
+ });
128
+
129
+ return libs;
97
130
  }