@memberjunction/ng-react 2.73.0 → 2.75.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.
- package/README.md +80 -15
- package/dist/lib/components/mj-react-component.component.d.ts +2 -2
- package/dist/lib/components/mj-react-component.component.js +3 -2
- package/dist/lib/components/mj-react-component.component.js.map +1 -1
- package/dist/lib/services/script-loader.service.d.ts +3 -1
- package/dist/lib/services/script-loader.service.js +3 -2
- package/dist/lib/services/script-loader.service.js.map +1 -1
- package/dist/public-api.d.ts +0 -1
- package/dist/public-api.js +0 -2
- package/dist/public-api.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -10,6 +10,7 @@ The `@memberjunction/ng-react` package enables Angular applications to render Re
|
|
|
10
10
|
|
|
11
11
|
- **Dynamic React Component Rendering**: Compile and render React components from source code
|
|
12
12
|
- **Automatic Dependency Loading**: Loads React, ReactDOM, and Babel from CDN
|
|
13
|
+
- **Dynamic Library Management**: Configure external libraries per organization or use case
|
|
13
14
|
- **Component Registry**: Manages compiled components with namespace support
|
|
14
15
|
- **Error Boundaries**: Comprehensive error handling for React components
|
|
15
16
|
- **Two-Way Data Binding**: Seamless data flow between Angular and React
|
|
@@ -57,7 +58,7 @@ export class YourModule { }
|
|
|
57
58
|
|
|
58
59
|
```typescript
|
|
59
60
|
import { Component } from '@angular/core';
|
|
60
|
-
import {
|
|
61
|
+
import { ComponentSpec } from '@memberjunction/interactive-component-types';
|
|
61
62
|
|
|
62
63
|
@Component({
|
|
63
64
|
selector: 'app-example',
|
|
@@ -69,9 +70,9 @@ import { SkipComponentRootSpec } from '@memberjunction/skip-types';
|
|
|
69
70
|
`
|
|
70
71
|
})
|
|
71
72
|
export class ExampleComponent {
|
|
72
|
-
reactComponent:
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
reactComponent: ComponentSpec = {
|
|
74
|
+
name: 'MyReactComponent',
|
|
75
|
+
code: `
|
|
75
76
|
function MyReactComponent({ data, callbacks }) {
|
|
76
77
|
return (
|
|
77
78
|
<div>
|
|
@@ -113,20 +114,66 @@ interface ComponentProps {
|
|
|
113
114
|
|
|
114
115
|
## Advanced Features
|
|
115
116
|
|
|
117
|
+
### Dynamic Library Configuration
|
|
118
|
+
|
|
119
|
+
Configure which external libraries are available to React components:
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
import { ScriptLoaderService, LibraryConfiguration } from '@memberjunction/ng-react';
|
|
123
|
+
|
|
124
|
+
// Define organization-specific library configuration
|
|
125
|
+
const orgLibraryConfig: LibraryConfiguration = {
|
|
126
|
+
libraries: [
|
|
127
|
+
{
|
|
128
|
+
id: 'lodash',
|
|
129
|
+
name: 'lodash',
|
|
130
|
+
displayName: 'Lodash',
|
|
131
|
+
category: 'utility',
|
|
132
|
+
globalVariable: '_',
|
|
133
|
+
version: '4.17.21',
|
|
134
|
+
cdnUrl: 'https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js',
|
|
135
|
+
isEnabled: true,
|
|
136
|
+
isCore: false
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
id: 'chart-js',
|
|
140
|
+
name: 'Chart',
|
|
141
|
+
displayName: 'Chart.js',
|
|
142
|
+
category: 'charting',
|
|
143
|
+
globalVariable: 'Chart',
|
|
144
|
+
version: '4.4.0',
|
|
145
|
+
cdnUrl: 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.0/chart.umd.js',
|
|
146
|
+
isEnabled: true,
|
|
147
|
+
isCore: false
|
|
148
|
+
}
|
|
149
|
+
// Add more libraries as needed
|
|
150
|
+
],
|
|
151
|
+
metadata: {
|
|
152
|
+
version: '1.0.0',
|
|
153
|
+
lastUpdated: '2024-01-01'
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
// Load libraries before rendering components
|
|
158
|
+
async ngOnInit() {
|
|
159
|
+
await this.scriptLoader.loadReactEcosystem(orgLibraryConfig);
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
116
163
|
### Component Hierarchies
|
|
117
164
|
|
|
118
165
|
```typescript
|
|
119
|
-
const componentSpec:
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
166
|
+
const componentSpec: ComponentSpec = {
|
|
167
|
+
name: 'ParentComponent',
|
|
168
|
+
code: '...',
|
|
169
|
+
dependencies: [
|
|
123
170
|
{
|
|
124
|
-
|
|
125
|
-
|
|
171
|
+
name: 'ChildComponent1',
|
|
172
|
+
code: '...'
|
|
126
173
|
},
|
|
127
174
|
{
|
|
128
|
-
|
|
129
|
-
|
|
175
|
+
name: 'ChildComponent2',
|
|
176
|
+
code: '...'
|
|
130
177
|
}
|
|
131
178
|
]
|
|
132
179
|
};
|
|
@@ -171,12 +218,30 @@ function MyComponent({ userState, callbacks }) {
|
|
|
171
218
|
|
|
172
219
|
### ScriptLoaderService
|
|
173
220
|
|
|
174
|
-
Manages loading of external scripts and CSS:
|
|
221
|
+
Manages loading of external scripts and CSS with support for dynamic library configurations:
|
|
175
222
|
|
|
176
223
|
```typescript
|
|
177
224
|
constructor(private scriptLoader: ScriptLoaderService) {}
|
|
178
225
|
|
|
179
|
-
|
|
226
|
+
// Load with default configuration
|
|
227
|
+
async loadDefaultLibraries() {
|
|
228
|
+
await this.scriptLoader.loadReactEcosystem();
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Load with custom configuration
|
|
232
|
+
async loadCustomLibraries() {
|
|
233
|
+
const customConfig = {
|
|
234
|
+
libraries: [
|
|
235
|
+
// Define your custom library set
|
|
236
|
+
],
|
|
237
|
+
metadata: { version: '1.0.0' }
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
await this.scriptLoader.loadReactEcosystem(customConfig);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Load individual library
|
|
244
|
+
async loadSingleLibrary() {
|
|
180
245
|
const lib = await this.scriptLoader.loadScript(
|
|
181
246
|
'https://cdn.example.com/lib.js',
|
|
182
247
|
'MyLibrary'
|
|
@@ -245,7 +310,7 @@ This package requires:
|
|
|
245
310
|
- Angular 18+
|
|
246
311
|
- React 18+
|
|
247
312
|
- @memberjunction/react-runtime
|
|
248
|
-
- @memberjunction/
|
|
313
|
+
- @memberjunction/interactive-component-types
|
|
249
314
|
- @memberjunction/core
|
|
250
315
|
|
|
251
316
|
## License
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @module @memberjunction/ng-react
|
|
5
5
|
*/
|
|
6
6
|
import { EventEmitter, ElementRef, AfterViewInit, OnDestroy, ChangeDetectorRef } from '@angular/core';
|
|
7
|
-
import {
|
|
7
|
+
import { ComponentSpec, ComponentStyles } from '@memberjunction/interactive-component-types';
|
|
8
8
|
import { ReactBridgeService } from '../services/react-bridge.service';
|
|
9
9
|
import { AngularAdapterService } from '../services/angular-adapter.service';
|
|
10
10
|
import { CompositeKey } from '@memberjunction/core';
|
|
@@ -32,7 +32,7 @@ export declare class MJReactComponent implements AfterViewInit, OnDestroy {
|
|
|
32
32
|
private reactBridge;
|
|
33
33
|
private adapter;
|
|
34
34
|
private cdr;
|
|
35
|
-
component:
|
|
35
|
+
component: ComponentSpec;
|
|
36
36
|
private _data;
|
|
37
37
|
set data(value: any);
|
|
38
38
|
get data(): any;
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { Component, Input, Output, EventEmitter, ViewChild, ElementRef, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
|
|
7
7
|
import { Subject } from 'rxjs';
|
|
8
|
+
import { ComponentSpec } from '@memberjunction/interactive-component-types';
|
|
8
9
|
import { ReactBridgeService } from '../services/react-bridge.service';
|
|
9
10
|
import { AngularAdapterService } from '../services/angular-adapter.service';
|
|
10
11
|
import { buildComponentProps, cleanupPropBuilder, createErrorBoundary, ComponentHierarchyRegistrar } from '@memberjunction/react-runtime';
|
|
@@ -100,8 +101,8 @@ export class MJReactComponent {
|
|
|
100
101
|
await this.registerComponentHierarchy();
|
|
101
102
|
// Compile main component
|
|
102
103
|
const result = await this.adapter.compileComponent({
|
|
103
|
-
componentName: this.component.
|
|
104
|
-
componentCode: this.component.
|
|
104
|
+
componentName: this.component.name,
|
|
105
|
+
componentCode: this.component.code,
|
|
105
106
|
styles: this.styles
|
|
106
107
|
});
|
|
107
108
|
if (!result.success) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mj-react-component.component.js","sourceRoot":"","sources":["../../../src/lib/components/mj-react-component.component.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Angular component that hosts React components with proper memory management.\n * Provides a bridge between Angular and React ecosystems in MemberJunction applications.\n * @module @memberjunction/ng-react\n */\n\nimport {\n Component,\n Input,\n Output,\n EventEmitter,\n ViewChild,\n ElementRef,\n AfterViewInit,\n OnDestroy,\n ChangeDetectionStrategy,\n ChangeDetectorRef\n} from '@angular/core';\nimport { Subject, takeUntil } from 'rxjs';\nimport { ComponentRootSpec, ComponentCallbacks, ComponentStyles } from '@memberjunction/interactive-component-types';\nimport { ReactBridgeService } from '../services/react-bridge.service';\nimport { AngularAdapterService } from '../services/angular-adapter.service';\nimport { \n buildComponentProps,\n cleanupPropBuilder,\n ComponentError,\n createErrorBoundary,\n ComponentHierarchyRegistrar,\n HierarchyRegistrationResult\n} from '@memberjunction/react-runtime';\nimport { LogError, CompositeKey, KeyValuePair } from '@memberjunction/core';\n\n/**\n * Event emitted by React components\n */\nexport interface ReactComponentEvent {\n type: string;\n payload: any;\n}\n\n/**\n * State change event emitted when component state updates\n */\nexport interface StateChangeEvent {\n path: string;\n value: any;\n}\n\n/**\n * Angular component that hosts React components with proper memory management.\n * This component provides a bridge between Angular and React, allowing React components\n * to be used seamlessly within Angular applications.\n */\n@Component({\n selector: 'mj-react-component',\n template: `\n <div class=\"react-component-wrapper\">\n <div #container class=\"react-component-container\" [class.loading]=\"!isInitialized\"></div>\n @if (!isInitialized && !hasError) {\n <div class=\"loading-overlay\">\n <div class=\"loading-spinner\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n </div>\n <div class=\"loading-text\">Loading component...</div>\n </div>\n }\n </div>\n `,\n styles: [`\n :host {\n display: block;\n width: 100%;\n height: 100%;\n }\n .react-component-wrapper {\n position: relative;\n width: 100%;\n height: 100%;\n }\n .react-component-container {\n width: 100%;\n height: 100%;\n transition: opacity 0.3s ease;\n }\n .react-component-container.loading {\n opacity: 0;\n }\n .loading-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n background-color: rgba(255, 255, 255, 0.9);\n z-index: 1;\n }\n .loading-spinner {\n font-size: 48px;\n color: #5B4FE9;\n margin-bottom: 16px;\n }\n .loading-text {\n font-family: -apple-system, BlinkMacSystemFont, \"Inter\", \"Segoe UI\", Roboto, sans-serif;\n font-size: 14px;\n color: #64748B;\n margin-top: 8px;\n }\n `],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class MJReactComponent implements AfterViewInit, OnDestroy {\n @Input() component!: ComponentRootSpec;\n \n private _data: any = {};\n @Input() \n set data(value: any) {\n const oldData = this._data;\n this._data = value;\n \n // Only re-render if data actually changed and component is initialized\n if (this.isInitialized && !this.isEqual(oldData, value)) {\n this.renderComponent();\n }\n }\n get data(): any {\n return this._data;\n }\n \n private _state: any = {};\n @Input() \n set state(value: any) {\n const oldState = this._state;\n this._state = value;\n \n // Only update state and re-render if it actually changed\n if (this.isInitialized && !this.isEqual(oldState, value)) {\n this.currentState = { ...value };\n this.renderComponent();\n }\n }\n get state(): any {\n return this._state;\n }\n \n @Input() utilities: any = {};\n @Input() styles?: Partial<ComponentStyles>;\n \n @Output() stateChange = new EventEmitter<StateChangeEvent>();\n @Output() componentEvent = new EventEmitter<ReactComponentEvent>();\n @Output() refreshData = new EventEmitter<void>();\n @Output() openEntityRecord = new EventEmitter<{ entityName: string; key: CompositeKey }>();\n \n @ViewChild('container', { read: ElementRef, static: true }) container!: ElementRef<HTMLDivElement>;\n \n private reactRoot: any = null;\n private compiledComponent: any = null;\n private destroyed$ = new Subject<void>();\n private currentCallbacks: ComponentCallbacks | null = null;\n private currentState: any = {};\n isInitialized = false;\n private isRendering = false;\n private pendingRender = false;\n private isDestroying = false;\n private renderTimeout: any = null;\n hasError = false;\n\n constructor(\n private reactBridge: ReactBridgeService,\n private adapter: AngularAdapterService,\n private cdr: ChangeDetectorRef\n ) {}\n\n async ngAfterViewInit() {\n // Trigger change detection to show loading state\n this.cdr.detectChanges();\n await this.initializeComponent();\n }\n\n ngOnDestroy() {\n // Set destroying flag immediately\n this.isDestroying = true;\n \n // Cancel any pending renders\n this.pendingRender = false;\n \n this.destroyed$.next();\n this.destroyed$.complete();\n this.cleanup();\n }\n\n\n /**\n * Initialize the React component\n */\n private async initializeComponent() {\n try {\n // Ensure React is loaded\n await this.reactBridge.getReactContext();\n \n // Wait for React to be fully ready (handles first-load delay)\n await this.reactBridge.waitForReactReady();\n \n // Register component hierarchy\n await this.registerComponentHierarchy();\n \n // Compile main component\n const result = await this.adapter.compileComponent({\n componentName: this.component.componentName,\n componentCode: this.component.componentCode,\n styles: this.styles\n });\n\n if (!result.success) {\n throw new Error(result.error?.message || 'Component compilation failed');\n }\n\n // Get runtime context and execute component factory\n const context = this.adapter.getRuntimeContext();\n this.compiledComponent = result.component!.component(context, this.styles);\n this.currentState = { ...this._state };\n \n // Create React root\n this.reactRoot = this.reactBridge.createRoot(this.container.nativeElement);\n \n // Initial render\n this.renderComponent();\n this.isInitialized = true;\n \n // Trigger change detection since we're using OnPush\n this.cdr.detectChanges();\n \n } catch (error) {\n this.hasError = true;\n LogError(`Failed to initialize React component: ${error}`);\n this.componentEvent.emit({\n type: 'error',\n payload: {\n error: error instanceof Error ? error.message : String(error),\n source: 'initialization'\n }\n });\n // Trigger change detection to show error state\n this.cdr.detectChanges();\n }\n }\n\n /**\n * Register all components in the hierarchy\n */\n private async registerComponentHierarchy() {\n // Create the hierarchy registrar with adapter's compiler and registry\n const registrar = new ComponentHierarchyRegistrar(\n this.adapter.getCompiler(),\n this.adapter.getRegistry(),\n this.adapter.getRuntimeContext()\n );\n \n // Register the entire hierarchy\n const result: HierarchyRegistrationResult = await registrar.registerHierarchy(\n this.component,\n {\n styles: this.styles as any, // Skip components use SkipComponentStyles which is a superset\n namespace: 'Global',\n version: 'v1'\n }\n );\n \n // Check for errors\n if (!result.success) {\n const errorMessages = result.errors.map(e => \n `${e.componentName}: ${e.error}`\n );\n throw new Error(`Component registration failed: ${errorMessages.join(', ')}`);\n }\n }\n\n /**\n * Render the React component\n */\n private renderComponent() {\n // Don't render if component is being destroyed\n if (this.isDestroying) {\n return;\n }\n \n if (!this.compiledComponent || !this.reactRoot) {\n return;\n }\n\n // Prevent concurrent renders\n if (this.isRendering) {\n this.pendingRender = true;\n return;\n }\n\n const context = this.reactBridge.getCurrentContext();\n if (!context) {\n return;\n }\n\n this.isRendering = true;\n const { React } = context;\n \n // Get components from resolver\n const components = this.adapter.getResolver().resolveComponents(this.component);\n \n // Create callbacks once per component instance\n if (!this.currentCallbacks) {\n this.currentCallbacks = this.createCallbacks();\n }\n \n // Build props - pass styles as-is for Skip components\n const props = buildComponentProps(\n this._data || {},\n this.currentState,\n this.utilities || {},\n this.currentCallbacks,\n components,\n this.styles as any, // Skip components expect the full SkipComponentStyles structure\n { debounceUpdateUserState: 3000 } // 3 second debounce by default\n );\n\n // Create error boundary\n const ErrorBoundary = createErrorBoundary(React, {\n onError: this.handleReactError.bind(this),\n logErrors: true,\n recovery: 'retry'\n });\n\n // Create element with error boundary\n const element = React.createElement(\n ErrorBoundary,\n null,\n React.createElement(this.compiledComponent.component, props)\n );\n\n // Clear any existing render timeout\n if (this.renderTimeout) {\n clearTimeout(this.renderTimeout);\n }\n \n // Render with timeout protection\n this.renderTimeout = setTimeout(() => {\n // Check if still rendering and not destroyed\n if (this.isRendering && !this.isDestroying) {\n this.componentEvent.emit({\n type: 'error',\n payload: {\n error: 'Component render timeout - possible infinite loop detected',\n source: 'render'\n }\n });\n }\n }, 5000);\n\n try {\n this.reactRoot.render(element);\n clearTimeout(this.renderTimeout);\n this.renderTimeout = null;\n \n // Reset rendering flag after a microtask to allow React to complete\n Promise.resolve().then(() => {\n // Don't update state if component is destroyed\n if (this.isDestroying) {\n return;\n }\n \n this.isRendering = false;\n \n // If there was a pending render request, execute it now\n if (this.pendingRender) {\n this.pendingRender = false;\n this.renderComponent();\n }\n });\n } catch (error) {\n clearTimeout(this.renderTimeout);\n this.renderTimeout = null;\n this.isRendering = false;\n this.handleReactError(error);\n }\n }\n\n /**\n * Create callbacks for the React component\n */\n private createCallbacks(): ComponentCallbacks {\n return {\n RefreshData: () => {\n this.refreshData.emit();\n },\n OpenEntityRecord: (entityName: string, key: CompositeKey) => {\n let keyToUse: CompositeKey | null = null;\n if (key instanceof Array) {\n keyToUse = CompositeKey.FromKeyValuePairs(key);\n }\n else if (typeof key === 'object' && !!key.GetValueByFieldName) {\n keyToUse = key as CompositeKey;\n }\n else if (typeof key === 'object') {\n //} && !!key.FieldName && !!key.Value) {\n // possible that have an object that is a simple key/value pair with\n // FieldName and value properties\n const keyAny = key as any;\n if (keyAny.FieldName && keyAny.Value) {\n keyToUse = CompositeKey.FromKeyValuePairs([keyAny as KeyValuePair]);\n }\n }\n if (keyToUse) {\n this.openEntityRecord.emit({ entityName, key: keyToUse });\n } \n },\n UpdateUserState: (userState: any) => {\n // Prevent updates during rendering or destruction\n if (this.isRendering || this.isDestroying) {\n return;\n }\n \n // Deep comparison to detect actual changes\n const hasChanges = Object.keys(userState).some(key => {\n const currentValue = this.currentState[key];\n const newValue = userState[key];\n return !this.isEqual(currentValue, newValue);\n });\n \n if (!hasChanges) {\n // No actual changes, skip update to prevent infinite loop\n return;\n }\n \n this.currentState = {\n ...this.currentState,\n ...userState\n };\n \n // Emit change for each key in the state update\n Object.keys(userState).forEach(path => {\n this.stateChange.emit({ path, value: userState[path] });\n });\n \n // Schedule re-render\n this.renderComponent();\n },\n NotifyEvent: (event: string, data: any) => {\n this.componentEvent.emit({ type: event, payload: data });\n }\n };\n }\n\n /**\n * Handle React component errors\n */\n private handleReactError(error: any, errorInfo?: any) {\n LogError(`React component error: ${error?.toString() || 'Unknown error'}`, errorInfo);\n this.componentEvent.emit({\n type: 'error',\n payload: {\n error: error?.toString() || 'Unknown error',\n errorInfo,\n source: 'react'\n }\n });\n }\n\n /**\n * Clean up resources\n */\n private cleanup() {\n // Clear any pending render timeout\n if (this.renderTimeout) {\n clearTimeout(this.renderTimeout);\n this.renderTimeout = null;\n }\n \n // Clean up prop builder subscriptions\n if (this.currentCallbacks) {\n cleanupPropBuilder(this.currentCallbacks);\n this.currentCallbacks = null;\n }\n \n // Unmount React root only if not currently rendering\n if (this.reactRoot) {\n // If still rendering, wait for completion before unmounting\n if (this.isRendering) {\n // Force stop rendering\n this.isRendering = false;\n this.pendingRender = false;\n }\n \n this.reactBridge.unmountRoot(this.reactRoot);\n this.reactRoot = null;\n }\n\n // Clear references\n this.compiledComponent = null;\n this.currentState = {};\n this.isInitialized = false;\n\n // Trigger registry cleanup\n this.adapter.getRegistry().cleanup();\n }\n\n /**\n * Public method to refresh the component\n * @param newData - Optional new data to merge\n */\n refresh(newData?: any) {\n if (newData) {\n // Use the setter to trigger change detection\n this.data = { ...this._data, ...newData };\n } else {\n this.renderComponent();\n }\n }\n\n /**\n * Public method to update state programmatically\n * @param path - State path to update\n * @param value - New value\n */\n updateState(path: string, value: any) {\n this.currentState = {\n ...this.currentState,\n [path]: value\n };\n this.stateChange.emit({ path, value });\n this.renderComponent();\n }\n\n /**\n * Deep equality check that handles null/undefined properly\n */\n private isEqual(a: any, b: any): boolean {\n // Handle null/undefined cases\n if (a === b) return true;\n if (a == null || b == null) return false;\n \n // For objects/arrays, use JSON comparison\n if (typeof a === 'object' && typeof b === 'object') {\n return JSON.stringify(a) === JSON.stringify(b);\n }\n \n return a === b;\n }\n}"]}
|
|
1
|
+
{"version":3,"file":"mj-react-component.component.js","sourceRoot":"","sources":["../../../src/lib/components/mj-react-component.component.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Angular component that hosts React components with proper memory management.\n * Provides a bridge between Angular and React ecosystems in MemberJunction applications.\n * @module @memberjunction/ng-react\n */\n\nimport {\n Component,\n Input,\n Output,\n EventEmitter,\n ViewChild,\n ElementRef,\n AfterViewInit,\n OnDestroy,\n ChangeDetectionStrategy,\n ChangeDetectorRef\n} from '@angular/core';\nimport { Subject, takeUntil } from 'rxjs';\nimport { ComponentSpec, ComponentCallbacks, ComponentStyles } from '@memberjunction/interactive-component-types';\nimport { ReactBridgeService } from '../services/react-bridge.service';\nimport { AngularAdapterService } from '../services/angular-adapter.service';\nimport { \n buildComponentProps,\n cleanupPropBuilder,\n ComponentError,\n createErrorBoundary,\n ComponentHierarchyRegistrar,\n HierarchyRegistrationResult\n} from '@memberjunction/react-runtime';\nimport { LogError, CompositeKey, KeyValuePair } from '@memberjunction/core';\n\n/**\n * Event emitted by React components\n */\nexport interface ReactComponentEvent {\n type: string;\n payload: any;\n}\n\n/**\n * State change event emitted when component state updates\n */\nexport interface StateChangeEvent {\n path: string;\n value: any;\n}\n\n/**\n * Angular component that hosts React components with proper memory management.\n * This component provides a bridge between Angular and React, allowing React components\n * to be used seamlessly within Angular applications.\n */\n@Component({\n selector: 'mj-react-component',\n template: `\n <div class=\"react-component-wrapper\">\n <div #container class=\"react-component-container\" [class.loading]=\"!isInitialized\"></div>\n @if (!isInitialized && !hasError) {\n <div class=\"loading-overlay\">\n <div class=\"loading-spinner\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n </div>\n <div class=\"loading-text\">Loading component...</div>\n </div>\n }\n </div>\n `,\n styles: [`\n :host {\n display: block;\n width: 100%;\n height: 100%;\n }\n .react-component-wrapper {\n position: relative;\n width: 100%;\n height: 100%;\n }\n .react-component-container {\n width: 100%;\n height: 100%;\n transition: opacity 0.3s ease;\n }\n .react-component-container.loading {\n opacity: 0;\n }\n .loading-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n background-color: rgba(255, 255, 255, 0.9);\n z-index: 1;\n }\n .loading-spinner {\n font-size: 48px;\n color: #5B4FE9;\n margin-bottom: 16px;\n }\n .loading-text {\n font-family: -apple-system, BlinkMacSystemFont, \"Inter\", \"Segoe UI\", Roboto, sans-serif;\n font-size: 14px;\n color: #64748B;\n margin-top: 8px;\n }\n `],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class MJReactComponent implements AfterViewInit, OnDestroy {\n @Input() component!: ComponentSpec;\n \n private _data: any = {};\n @Input() \n set data(value: any) {\n const oldData = this._data;\n this._data = value;\n \n // Only re-render if data actually changed and component is initialized\n if (this.isInitialized && !this.isEqual(oldData, value)) {\n this.renderComponent();\n }\n }\n get data(): any {\n return this._data;\n }\n \n private _state: any = {};\n @Input() \n set state(value: any) {\n const oldState = this._state;\n this._state = value;\n \n // Only update state and re-render if it actually changed\n if (this.isInitialized && !this.isEqual(oldState, value)) {\n this.currentState = { ...value };\n this.renderComponent();\n }\n }\n get state(): any {\n return this._state;\n }\n \n @Input() utilities: any = {};\n @Input() styles?: Partial<ComponentStyles>;\n \n @Output() stateChange = new EventEmitter<StateChangeEvent>();\n @Output() componentEvent = new EventEmitter<ReactComponentEvent>();\n @Output() refreshData = new EventEmitter<void>();\n @Output() openEntityRecord = new EventEmitter<{ entityName: string; key: CompositeKey }>();\n \n @ViewChild('container', { read: ElementRef, static: true }) container!: ElementRef<HTMLDivElement>;\n \n private reactRoot: any = null;\n private compiledComponent: any = null;\n private destroyed$ = new Subject<void>();\n private currentCallbacks: ComponentCallbacks | null = null;\n private currentState: any = {};\n isInitialized = false;\n private isRendering = false;\n private pendingRender = false;\n private isDestroying = false;\n private renderTimeout: any = null;\n hasError = false;\n\n constructor(\n private reactBridge: ReactBridgeService,\n private adapter: AngularAdapterService,\n private cdr: ChangeDetectorRef\n ) {}\n\n async ngAfterViewInit() {\n // Trigger change detection to show loading state\n this.cdr.detectChanges();\n await this.initializeComponent();\n }\n\n ngOnDestroy() {\n // Set destroying flag immediately\n this.isDestroying = true;\n \n // Cancel any pending renders\n this.pendingRender = false;\n \n this.destroyed$.next();\n this.destroyed$.complete();\n this.cleanup();\n }\n\n\n /**\n * Initialize the React component\n */\n private async initializeComponent() {\n try {\n // Ensure React is loaded\n await this.reactBridge.getReactContext();\n \n // Wait for React to be fully ready (handles first-load delay)\n await this.reactBridge.waitForReactReady();\n \n // Register component hierarchy\n await this.registerComponentHierarchy();\n \n // Compile main component\n const result = await this.adapter.compileComponent({\n componentName: this.component.name,\n componentCode: this.component.code,\n styles: this.styles\n });\n\n if (!result.success) {\n throw new Error(result.error?.message || 'Component compilation failed');\n }\n\n // Get runtime context and execute component factory\n const context = this.adapter.getRuntimeContext();\n this.compiledComponent = result.component!.component(context, this.styles);\n this.currentState = { ...this._state };\n \n // Create React root\n this.reactRoot = this.reactBridge.createRoot(this.container.nativeElement);\n \n // Initial render\n this.renderComponent();\n this.isInitialized = true;\n \n // Trigger change detection since we're using OnPush\n this.cdr.detectChanges();\n \n } catch (error) {\n this.hasError = true;\n LogError(`Failed to initialize React component: ${error}`);\n this.componentEvent.emit({\n type: 'error',\n payload: {\n error: error instanceof Error ? error.message : String(error),\n source: 'initialization'\n }\n });\n // Trigger change detection to show error state\n this.cdr.detectChanges();\n }\n }\n\n /**\n * Register all components in the hierarchy\n */\n private async registerComponentHierarchy() {\n // Create the hierarchy registrar with adapter's compiler and registry\n const registrar = new ComponentHierarchyRegistrar(\n this.adapter.getCompiler(),\n this.adapter.getRegistry(),\n this.adapter.getRuntimeContext()\n );\n \n // Register the entire hierarchy\n const result: HierarchyRegistrationResult = await registrar.registerHierarchy(\n this.component,\n {\n styles: this.styles as any, // Skip components use SkipComponentStyles which is a superset\n namespace: 'Global',\n version: 'v1'\n }\n );\n \n // Check for errors\n if (!result.success) {\n const errorMessages = result.errors.map(e => \n `${e.componentName}: ${e.error}`\n );\n throw new Error(`Component registration failed: ${errorMessages.join(', ')}`);\n }\n }\n\n /**\n * Render the React component\n */\n private renderComponent() {\n // Don't render if component is being destroyed\n if (this.isDestroying) {\n return;\n }\n \n if (!this.compiledComponent || !this.reactRoot) {\n return;\n }\n\n // Prevent concurrent renders\n if (this.isRendering) {\n this.pendingRender = true;\n return;\n }\n\n const context = this.reactBridge.getCurrentContext();\n if (!context) {\n return;\n }\n\n this.isRendering = true;\n const { React } = context;\n \n // Get components from resolver\n const components = this.adapter.getResolver().resolveComponents(this.component);\n \n // Create callbacks once per component instance\n if (!this.currentCallbacks) {\n this.currentCallbacks = this.createCallbacks();\n }\n \n // Build props - pass styles as-is for Skip components\n const props = buildComponentProps(\n this._data || {},\n this.currentState,\n this.utilities || {},\n this.currentCallbacks,\n components,\n this.styles as any, // Skip components expect the full SkipComponentStyles structure\n { debounceUpdateUserState: 3000 } // 3 second debounce by default\n );\n\n // Create error boundary\n const ErrorBoundary = createErrorBoundary(React, {\n onError: this.handleReactError.bind(this),\n logErrors: true,\n recovery: 'retry'\n });\n\n // Create element with error boundary\n const element = React.createElement(\n ErrorBoundary,\n null,\n React.createElement(this.compiledComponent.component, props)\n );\n\n // Clear any existing render timeout\n if (this.renderTimeout) {\n clearTimeout(this.renderTimeout);\n }\n \n // Render with timeout protection\n this.renderTimeout = setTimeout(() => {\n // Check if still rendering and not destroyed\n if (this.isRendering && !this.isDestroying) {\n this.componentEvent.emit({\n type: 'error',\n payload: {\n error: 'Component render timeout - possible infinite loop detected',\n source: 'render'\n }\n });\n }\n }, 5000);\n\n try {\n this.reactRoot.render(element);\n clearTimeout(this.renderTimeout);\n this.renderTimeout = null;\n \n // Reset rendering flag after a microtask to allow React to complete\n Promise.resolve().then(() => {\n // Don't update state if component is destroyed\n if (this.isDestroying) {\n return;\n }\n \n this.isRendering = false;\n \n // If there was a pending render request, execute it now\n if (this.pendingRender) {\n this.pendingRender = false;\n this.renderComponent();\n }\n });\n } catch (error) {\n clearTimeout(this.renderTimeout);\n this.renderTimeout = null;\n this.isRendering = false;\n this.handleReactError(error);\n }\n }\n\n /**\n * Create callbacks for the React component\n */\n private createCallbacks(): ComponentCallbacks {\n return {\n RefreshData: () => {\n this.refreshData.emit();\n },\n OpenEntityRecord: (entityName: string, key: CompositeKey) => {\n let keyToUse: CompositeKey | null = null;\n if (key instanceof Array) {\n keyToUse = CompositeKey.FromKeyValuePairs(key);\n }\n else if (typeof key === 'object' && !!key.GetValueByFieldName) {\n keyToUse = key as CompositeKey;\n }\n else if (typeof key === 'object') {\n //} && !!key.FieldName && !!key.Value) {\n // possible that have an object that is a simple key/value pair with\n // FieldName and value properties\n const keyAny = key as any;\n if (keyAny.FieldName && keyAny.Value) {\n keyToUse = CompositeKey.FromKeyValuePairs([keyAny as KeyValuePair]);\n }\n }\n if (keyToUse) {\n this.openEntityRecord.emit({ entityName, key: keyToUse });\n } \n },\n UpdateUserState: (userState: any) => {\n // Prevent updates during rendering or destruction\n if (this.isRendering || this.isDestroying) {\n return;\n }\n \n // Deep comparison to detect actual changes\n const hasChanges = Object.keys(userState).some(key => {\n const currentValue = this.currentState[key];\n const newValue = userState[key];\n return !this.isEqual(currentValue, newValue);\n });\n \n if (!hasChanges) {\n // No actual changes, skip update to prevent infinite loop\n return;\n }\n \n this.currentState = {\n ...this.currentState,\n ...userState\n };\n \n // Emit change for each key in the state update\n Object.keys(userState).forEach(path => {\n this.stateChange.emit({ path, value: userState[path] });\n });\n \n // Schedule re-render\n this.renderComponent();\n },\n NotifyEvent: (event: string, data: any) => {\n this.componentEvent.emit({ type: event, payload: data });\n }\n };\n }\n\n /**\n * Handle React component errors\n */\n private handleReactError(error: any, errorInfo?: any) {\n LogError(`React component error: ${error?.toString() || 'Unknown error'}`, errorInfo);\n this.componentEvent.emit({\n type: 'error',\n payload: {\n error: error?.toString() || 'Unknown error',\n errorInfo,\n source: 'react'\n }\n });\n }\n\n /**\n * Clean up resources\n */\n private cleanup() {\n // Clear any pending render timeout\n if (this.renderTimeout) {\n clearTimeout(this.renderTimeout);\n this.renderTimeout = null;\n }\n \n // Clean up prop builder subscriptions\n if (this.currentCallbacks) {\n cleanupPropBuilder(this.currentCallbacks);\n this.currentCallbacks = null;\n }\n \n // Unmount React root only if not currently rendering\n if (this.reactRoot) {\n // If still rendering, wait for completion before unmounting\n if (this.isRendering) {\n // Force stop rendering\n this.isRendering = false;\n this.pendingRender = false;\n }\n \n this.reactBridge.unmountRoot(this.reactRoot);\n this.reactRoot = null;\n }\n\n // Clear references\n this.compiledComponent = null;\n this.currentState = {};\n this.isInitialized = false;\n\n // Trigger registry cleanup\n this.adapter.getRegistry().cleanup();\n }\n\n /**\n * Public method to refresh the component\n * @param newData - Optional new data to merge\n */\n refresh(newData?: any) {\n if (newData) {\n // Use the setter to trigger change detection\n this.data = { ...this._data, ...newData };\n } else {\n this.renderComponent();\n }\n }\n\n /**\n * Public method to update state programmatically\n * @param path - State path to update\n * @param value - New value\n */\n updateState(path: string, value: any) {\n this.currentState = {\n ...this.currentState,\n [path]: value\n };\n this.stateChange.emit({ path, value });\n this.renderComponent();\n }\n\n /**\n * Deep equality check that handles null/undefined properly\n */\n private isEqual(a: any, b: any): boolean {\n // Handle null/undefined cases\n if (a === b) return true;\n if (a == null || b == null) return false;\n \n // For objects/arrays, use JSON comparison\n if (typeof a === 'object' && typeof b === 'object') {\n return JSON.stringify(a) === JSON.stringify(b);\n }\n \n return a === b;\n }\n}"]}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* @module @memberjunction/ng-react
|
|
5
5
|
*/
|
|
6
6
|
import { OnDestroy } from '@angular/core';
|
|
7
|
+
import { LibraryConfiguration } from '@memberjunction/react-runtime';
|
|
7
8
|
import * as i0 from "@angular/core";
|
|
8
9
|
/**
|
|
9
10
|
* Service for loading external scripts and CSS with proper cleanup.
|
|
@@ -37,9 +38,10 @@ export declare class ScriptLoaderService implements OnDestroy {
|
|
|
37
38
|
loadCSS(url: string): void;
|
|
38
39
|
/**
|
|
39
40
|
* Load common React libraries and UI frameworks
|
|
41
|
+
* @param config Optional library configuration
|
|
40
42
|
* @returns Promise resolving to React ecosystem objects
|
|
41
43
|
*/
|
|
42
|
-
loadReactEcosystem(): Promise<{
|
|
44
|
+
loadReactEcosystem(config?: LibraryConfiguration): Promise<{
|
|
43
45
|
React: any;
|
|
44
46
|
ReactDOM: any;
|
|
45
47
|
Babel: any;
|
|
@@ -91,11 +91,12 @@ export class ScriptLoaderService {
|
|
|
91
91
|
}
|
|
92
92
|
/**
|
|
93
93
|
* Load common React libraries and UI frameworks
|
|
94
|
+
* @param config Optional library configuration
|
|
94
95
|
* @returns Promise resolving to React ecosystem objects
|
|
95
96
|
*/
|
|
96
|
-
async loadReactEcosystem() {
|
|
97
|
+
async loadReactEcosystem(config) {
|
|
97
98
|
// Use the new LibraryLoader from react-runtime for consistency
|
|
98
|
-
const result = await LibraryLoader.loadAllLibraries();
|
|
99
|
+
const result = await LibraryLoader.loadAllLibraries(config);
|
|
99
100
|
// The LibraryLoader handles all the loading, but we need to ensure
|
|
100
101
|
// ReactDOM.createRoot is available for Angular's specific needs
|
|
101
102
|
// The ReactBridgeService will handle the delayed validation
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"script-loader.service.js","sourceRoot":"","sources":["../../../src/lib/services/script-loader.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Service for loading external scripts and CSS in Angular applications.\n * Manages the lifecycle of dynamically loaded resources with proper cleanup.\n * @module @memberjunction/ng-react\n */\n\nimport { Injectable, OnDestroy } from '@angular/core';\nimport { \n STANDARD_LIBRARY_URLS,\n getCoreLibraryUrls,\n getUILibraryUrls,\n getCSSUrls,\n LibraryLoader\n} from '@memberjunction/react-runtime';\n\n/**\n * Represents a loaded script or CSS resource\n */\ninterface LoadedScript {\n element: HTMLScriptElement | HTMLLinkElement;\n promise: Promise<any>;\n}\n\n/**\n * Service for loading external scripts and CSS with proper cleanup.\n * Provides methods to dynamically load React and related libraries from CDN.\n */\n@Injectable({ providedIn: 'root' })\nexport class ScriptLoaderService implements OnDestroy {\n private loadedResources = new Map<string, LoadedScript>();\n private readonly cleanupOnDestroy = new Set<string>();\n\n ngOnDestroy(): void {\n this.cleanup();\n }\n\n /**\n * Load a script from URL with automatic cleanup tracking\n * @param url - Script URL to load\n * @param globalName - Expected global variable name\n * @param autoCleanup - Whether to cleanup on service destroy\n * @returns Promise resolving to the global object\n */\n async loadScript(url: string, globalName: string, autoCleanup = false): Promise<any> {\n const existing = this.loadedResources.get(url);\n if (existing) {\n return existing.promise;\n }\n\n const promise = this.createScriptPromise(url, globalName);\n const element = document.querySelector(`script[src=\"${url}\"]`) as HTMLScriptElement;\n \n if (element) {\n this.loadedResources.set(url, { element, promise });\n if (autoCleanup) {\n this.cleanupOnDestroy.add(url);\n }\n }\n\n return promise;\n }\n\n /**\n * Load a script with additional validation function\n * @param url - Script URL to load\n * @param globalName - Expected global variable name\n * @param validator - Function to validate the loaded object\n * @param autoCleanup - Whether to cleanup on service destroy\n * @returns Promise resolving to the validated global object\n */\n async loadScriptWithValidation(\n url: string, \n globalName: string, \n validator: (obj: any) => boolean,\n autoCleanup = false\n ): Promise<any> {\n const existing = this.loadedResources.get(url);\n if (existing) {\n const obj = await existing.promise;\n // Re-validate even for cached resources\n if (!validator(obj)) {\n throw new Error(`${globalName} loaded but failed validation`);\n }\n return obj;\n }\n\n const promise = this.createScriptPromiseWithValidation(url, globalName, validator);\n const element = document.querySelector(`script[src=\"${url}\"]`) as HTMLScriptElement;\n \n if (element) {\n this.loadedResources.set(url, { element, promise });\n if (autoCleanup) {\n this.cleanupOnDestroy.add(url);\n }\n }\n\n return promise;\n }\n\n /**\n * Load CSS from URL\n * @param url - CSS URL to load\n */\n loadCSS(url: string): void {\n if (this.loadedResources.has(url)) {\n return;\n }\n\n const existingLink = document.querySelector(`link[href=\"${url}\"]`);\n if (existingLink) {\n return;\n }\n\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = url;\n document.head.appendChild(link);\n\n this.loadedResources.set(url, {\n element: link,\n promise: Promise.resolve()\n });\n }\n\n /**\n * Load common React libraries and UI frameworks\n * @returns Promise resolving to React ecosystem objects\n */\n async loadReactEcosystem(): Promise<{\n React: any;\n ReactDOM: any;\n Babel: any;\n libraries: any;\n }> {\n // Use the new LibraryLoader from react-runtime for consistency\n const result = await LibraryLoader.loadAllLibraries();\n \n // The LibraryLoader handles all the loading, but we need to ensure\n // ReactDOM.createRoot is available for Angular's specific needs\n // The ReactBridgeService will handle the delayed validation\n \n // Track loaded resources for cleanup\n LibraryLoader.getLoadedResources().forEach((resource, url) => {\n this.loadedResources.set(url, resource);\n });\n \n return result;\n }\n\n /**\n * Get library name from URL for global variable mapping\n * @param url - Library URL\n * @returns Global variable name\n */\n private getLibraryNameFromUrl(url: string): string {\n // Map known URLs to their global variable names\n if (url.includes('lodash')) return '_';\n if (url.includes('d3')) return 'd3';\n if (url.includes('Chart.js') || url.includes('chart')) return 'Chart';\n if (url.includes('dayjs')) return 'dayjs';\n if (url.includes('antd')) return 'antd';\n if (url.includes('react-bootstrap')) return 'ReactBootstrap';\n if (url.includes('react-dom')) return 'ReactDOM';\n if (url.includes('react')) return 'React';\n if (url.includes('babel')) return 'Babel';\n \n // Default: extract library name from filename\n const match = url.match(/\\/([^/]+?)(?:\\.min)?\\.js$/i);\n return match ? match[1] : 'UnknownLibrary';\n }\n\n /**\n * Remove a specific loaded resource\n * @param url - URL of resource to remove\n */\n removeResource(url: string): void {\n const resource = this.loadedResources.get(url);\n if (resource?.element && resource.element.parentNode) {\n resource.element.parentNode.removeChild(resource.element);\n }\n this.loadedResources.delete(url);\n this.cleanupOnDestroy.delete(url);\n }\n\n /**\n * Clean up all resources marked for auto-cleanup\n */\n private cleanup(): void {\n for (const url of this.cleanupOnDestroy) {\n this.removeResource(url);\n }\n this.cleanupOnDestroy.clear();\n }\n\n /**\n * Create a promise that resolves when script loads\n * @param url - Script URL\n * @param globalName - Expected global variable\n * @returns Promise resolving to global object\n */\n private createScriptPromise(url: string, globalName: string): Promise<any> {\n return new Promise((resolve, reject) => {\n // Check if already loaded\n if ((window as any)[globalName]) {\n resolve((window as any)[globalName]);\n return;\n }\n\n // Check if script tag exists\n const existingScript = document.querySelector(`script[src=\"${url}\"]`);\n if (existingScript) {\n this.waitForScriptLoad(existingScript as HTMLScriptElement, globalName, resolve, reject);\n return;\n }\n\n // Create new script\n const script = document.createElement('script');\n script.src = url;\n script.async = true;\n\n script.onload = () => {\n const global = (window as any)[globalName];\n if (global) {\n resolve(global);\n } else {\n reject(new Error(`${globalName} not found after script load`));\n }\n };\n\n script.onerror = () => {\n reject(new Error(`Failed to load script: ${url}`));\n };\n\n document.head.appendChild(script);\n this.loadedResources.set(url, { element: script, promise: Promise.resolve() });\n });\n }\n\n /**\n * Create a promise that resolves when script loads and passes validation\n * @param url - Script URL\n * @param globalName - Expected global variable\n * @param validator - Validation function\n * @returns Promise resolving to validated global object\n */\n private createScriptPromiseWithValidation(\n url: string, \n globalName: string, \n validator: (obj: any) => boolean\n ): Promise<any> {\n return new Promise((resolve, reject) => {\n // Check if already loaded and valid\n const existingGlobal = (window as any)[globalName];\n if (existingGlobal && validator(existingGlobal)) {\n resolve(existingGlobal);\n return;\n }\n\n // Check if script tag exists\n const existingScript = document.querySelector(`script[src=\"${url}\"]`);\n if (existingScript) {\n this.waitForScriptLoadWithValidation(\n existingScript as HTMLScriptElement, \n globalName, \n validator,\n resolve, \n reject\n );\n return;\n }\n\n // Create new script\n const script = document.createElement('script');\n script.src = url;\n script.async = true;\n\n script.onload = () => {\n this.waitForValidation(globalName, validator, resolve, reject);\n };\n\n script.onerror = () => {\n reject(new Error(`Failed to load script: ${url}`));\n };\n\n document.head.appendChild(script);\n this.loadedResources.set(url, { element: script, promise: Promise.resolve() });\n });\n }\n\n /**\n * Wait for global object to be available and valid\n * @param globalName - Global variable name\n * @param validator - Validation function\n * @param resolve - Promise resolve function\n * @param reject - Promise reject function\n * @param attempts - Current attempt number\n * @param maxAttempts - Maximum attempts before failing\n */\n private waitForValidation(\n globalName: string,\n validator: (obj: any) => boolean,\n resolve: (value: any) => void,\n reject: (reason: any) => void,\n attempts = 0,\n maxAttempts = 50 // 5 seconds total with 100ms intervals\n ): void {\n const global = (window as any)[globalName];\n \n if (global && validator(global)) {\n resolve(global);\n return;\n }\n\n if (attempts >= maxAttempts) {\n if (global) {\n reject(new Error(`${globalName} loaded but validation failed after ${maxAttempts} attempts`));\n } else {\n reject(new Error(`${globalName} not found after ${maxAttempts} attempts`));\n }\n return;\n }\n\n // Retry with exponential backoff for first few attempts, then fixed interval\n const delay = attempts < 5 ? Math.min(100 * Math.pow(1.5, attempts), 500) : 100;\n setTimeout(() => {\n this.waitForValidation(globalName, validator, resolve, reject, attempts + 1, maxAttempts);\n }, delay);\n }\n\n /**\n * Wait for existing script to load\n * @param script - Script element\n * @param globalName - Expected global variable\n * @param resolve - Promise resolve function\n * @param reject - Promise reject function\n */\n private waitForScriptLoad(\n script: HTMLScriptElement,\n globalName: string,\n resolve: (value: any) => void,\n reject: (reason: any) => void\n ): void {\n const checkGlobal = () => {\n if ((window as any)[globalName]) {\n resolve((window as any)[globalName]);\n return;\n }\n // Give it a moment for the global to be defined\n setTimeout(() => {\n if ((window as any)[globalName]) {\n resolve((window as any)[globalName]);\n } else {\n reject(new Error(`${globalName} not found after script load`));\n }\n }, 100);\n };\n\n if ('readyState' in script) {\n // IE support\n (script as any).onreadystatechange = () => {\n if ((script as any).readyState === 'loaded' || (script as any).readyState === 'complete') {\n (script as any).onreadystatechange = null;\n checkGlobal();\n }\n };\n } else {\n // Modern browsers\n const loadHandler = () => {\n script.removeEventListener('load', loadHandler);\n checkGlobal();\n };\n script.addEventListener('load', loadHandler);\n }\n }\n\n /**\n * Wait for existing script to load with validation\n * @param script - Script element\n * @param globalName - Expected global variable\n * @param validator - Validation function\n * @param resolve - Promise resolve function\n * @param reject - Promise reject function\n */\n private waitForScriptLoadWithValidation(\n script: HTMLScriptElement,\n globalName: string,\n validator: (obj: any) => boolean,\n resolve: (value: any) => void,\n reject: (reason: any) => void\n ): void {\n const checkGlobal = () => {\n this.waitForValidation(globalName, validator, resolve, reject);\n };\n\n if ('readyState' in script) {\n // IE support\n (script as any).onreadystatechange = () => {\n if ((script as any).readyState === 'loaded' || (script as any).readyState === 'complete') {\n (script as any).onreadystatechange = null;\n checkGlobal();\n }\n };\n } else {\n // Modern browsers\n const loadHandler = () => {\n script.removeEventListener('load', loadHandler);\n checkGlobal();\n };\n script.addEventListener('load', loadHandler);\n }\n }\n}"]}
|
|
1
|
+
{"version":3,"file":"script-loader.service.js","sourceRoot":"","sources":["../../../src/lib/services/script-loader.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Service for loading external scripts and CSS in Angular applications.\n * Manages the lifecycle of dynamically loaded resources with proper cleanup.\n * @module @memberjunction/ng-react\n */\n\nimport { Injectable, OnDestroy } from '@angular/core';\nimport { \n LibraryLoader,\n LibraryConfiguration\n} from '@memberjunction/react-runtime';\n\n/**\n * Represents a loaded script or CSS resource\n */\ninterface LoadedScript {\n element: HTMLScriptElement | HTMLLinkElement;\n promise: Promise<any>;\n}\n\n/**\n * Service for loading external scripts and CSS with proper cleanup.\n * Provides methods to dynamically load React and related libraries from CDN.\n */\n@Injectable({ providedIn: 'root' })\nexport class ScriptLoaderService implements OnDestroy {\n private loadedResources = new Map<string, LoadedScript>();\n private readonly cleanupOnDestroy = new Set<string>();\n\n ngOnDestroy(): void {\n this.cleanup();\n }\n\n /**\n * Load a script from URL with automatic cleanup tracking\n * @param url - Script URL to load\n * @param globalName - Expected global variable name\n * @param autoCleanup - Whether to cleanup on service destroy\n * @returns Promise resolving to the global object\n */\n async loadScript(url: string, globalName: string, autoCleanup = false): Promise<any> {\n const existing = this.loadedResources.get(url);\n if (existing) {\n return existing.promise;\n }\n\n const promise = this.createScriptPromise(url, globalName);\n const element = document.querySelector(`script[src=\"${url}\"]`) as HTMLScriptElement;\n \n if (element) {\n this.loadedResources.set(url, { element, promise });\n if (autoCleanup) {\n this.cleanupOnDestroy.add(url);\n }\n }\n\n return promise;\n }\n\n /**\n * Load a script with additional validation function\n * @param url - Script URL to load\n * @param globalName - Expected global variable name\n * @param validator - Function to validate the loaded object\n * @param autoCleanup - Whether to cleanup on service destroy\n * @returns Promise resolving to the validated global object\n */\n async loadScriptWithValidation(\n url: string, \n globalName: string, \n validator: (obj: any) => boolean,\n autoCleanup = false\n ): Promise<any> {\n const existing = this.loadedResources.get(url);\n if (existing) {\n const obj = await existing.promise;\n // Re-validate even for cached resources\n if (!validator(obj)) {\n throw new Error(`${globalName} loaded but failed validation`);\n }\n return obj;\n }\n\n const promise = this.createScriptPromiseWithValidation(url, globalName, validator);\n const element = document.querySelector(`script[src=\"${url}\"]`) as HTMLScriptElement;\n \n if (element) {\n this.loadedResources.set(url, { element, promise });\n if (autoCleanup) {\n this.cleanupOnDestroy.add(url);\n }\n }\n\n return promise;\n }\n\n /**\n * Load CSS from URL\n * @param url - CSS URL to load\n */\n loadCSS(url: string): void {\n if (this.loadedResources.has(url)) {\n return;\n }\n\n const existingLink = document.querySelector(`link[href=\"${url}\"]`);\n if (existingLink) {\n return;\n }\n\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = url;\n document.head.appendChild(link);\n\n this.loadedResources.set(url, {\n element: link,\n promise: Promise.resolve()\n });\n }\n\n /**\n * Load common React libraries and UI frameworks\n * @param config Optional library configuration\n * @returns Promise resolving to React ecosystem objects\n */\n async loadReactEcosystem(config?: LibraryConfiguration): Promise<{\n React: any;\n ReactDOM: any;\n Babel: any;\n libraries: any;\n }> {\n // Use the new LibraryLoader from react-runtime for consistency\n const result = await LibraryLoader.loadAllLibraries(config);\n \n // The LibraryLoader handles all the loading, but we need to ensure\n // ReactDOM.createRoot is available for Angular's specific needs\n // The ReactBridgeService will handle the delayed validation\n \n // Track loaded resources for cleanup\n LibraryLoader.getLoadedResources().forEach((resource, url) => {\n this.loadedResources.set(url, resource);\n });\n \n return result;\n }\n\n /**\n * Get library name from URL for global variable mapping\n * @param url - Library URL\n * @returns Global variable name\n */\n private getLibraryNameFromUrl(url: string): string {\n // Map known URLs to their global variable names\n if (url.includes('lodash')) return '_';\n if (url.includes('d3')) return 'd3';\n if (url.includes('Chart.js') || url.includes('chart')) return 'Chart';\n if (url.includes('dayjs')) return 'dayjs';\n if (url.includes('antd')) return 'antd';\n if (url.includes('react-bootstrap')) return 'ReactBootstrap';\n if (url.includes('react-dom')) return 'ReactDOM';\n if (url.includes('react')) return 'React';\n if (url.includes('babel')) return 'Babel';\n \n // Default: extract library name from filename\n const match = url.match(/\\/([^/]+?)(?:\\.min)?\\.js$/i);\n return match ? match[1] : 'UnknownLibrary';\n }\n\n /**\n * Remove a specific loaded resource\n * @param url - URL of resource to remove\n */\n removeResource(url: string): void {\n const resource = this.loadedResources.get(url);\n if (resource?.element && resource.element.parentNode) {\n resource.element.parentNode.removeChild(resource.element);\n }\n this.loadedResources.delete(url);\n this.cleanupOnDestroy.delete(url);\n }\n\n /**\n * Clean up all resources marked for auto-cleanup\n */\n private cleanup(): void {\n for (const url of this.cleanupOnDestroy) {\n this.removeResource(url);\n }\n this.cleanupOnDestroy.clear();\n }\n\n /**\n * Create a promise that resolves when script loads\n * @param url - Script URL\n * @param globalName - Expected global variable\n * @returns Promise resolving to global object\n */\n private createScriptPromise(url: string, globalName: string): Promise<any> {\n return new Promise((resolve, reject) => {\n // Check if already loaded\n if ((window as any)[globalName]) {\n resolve((window as any)[globalName]);\n return;\n }\n\n // Check if script tag exists\n const existingScript = document.querySelector(`script[src=\"${url}\"]`);\n if (existingScript) {\n this.waitForScriptLoad(existingScript as HTMLScriptElement, globalName, resolve, reject);\n return;\n }\n\n // Create new script\n const script = document.createElement('script');\n script.src = url;\n script.async = true;\n\n script.onload = () => {\n const global = (window as any)[globalName];\n if (global) {\n resolve(global);\n } else {\n reject(new Error(`${globalName} not found after script load`));\n }\n };\n\n script.onerror = () => {\n reject(new Error(`Failed to load script: ${url}`));\n };\n\n document.head.appendChild(script);\n this.loadedResources.set(url, { element: script, promise: Promise.resolve() });\n });\n }\n\n /**\n * Create a promise that resolves when script loads and passes validation\n * @param url - Script URL\n * @param globalName - Expected global variable\n * @param validator - Validation function\n * @returns Promise resolving to validated global object\n */\n private createScriptPromiseWithValidation(\n url: string, \n globalName: string, \n validator: (obj: any) => boolean\n ): Promise<any> {\n return new Promise((resolve, reject) => {\n // Check if already loaded and valid\n const existingGlobal = (window as any)[globalName];\n if (existingGlobal && validator(existingGlobal)) {\n resolve(existingGlobal);\n return;\n }\n\n // Check if script tag exists\n const existingScript = document.querySelector(`script[src=\"${url}\"]`);\n if (existingScript) {\n this.waitForScriptLoadWithValidation(\n existingScript as HTMLScriptElement, \n globalName, \n validator,\n resolve, \n reject\n );\n return;\n }\n\n // Create new script\n const script = document.createElement('script');\n script.src = url;\n script.async = true;\n\n script.onload = () => {\n this.waitForValidation(globalName, validator, resolve, reject);\n };\n\n script.onerror = () => {\n reject(new Error(`Failed to load script: ${url}`));\n };\n\n document.head.appendChild(script);\n this.loadedResources.set(url, { element: script, promise: Promise.resolve() });\n });\n }\n\n /**\n * Wait for global object to be available and valid\n * @param globalName - Global variable name\n * @param validator - Validation function\n * @param resolve - Promise resolve function\n * @param reject - Promise reject function\n * @param attempts - Current attempt number\n * @param maxAttempts - Maximum attempts before failing\n */\n private waitForValidation(\n globalName: string,\n validator: (obj: any) => boolean,\n resolve: (value: any) => void,\n reject: (reason: any) => void,\n attempts = 0,\n maxAttempts = 50 // 5 seconds total with 100ms intervals\n ): void {\n const global = (window as any)[globalName];\n \n if (global && validator(global)) {\n resolve(global);\n return;\n }\n\n if (attempts >= maxAttempts) {\n if (global) {\n reject(new Error(`${globalName} loaded but validation failed after ${maxAttempts} attempts`));\n } else {\n reject(new Error(`${globalName} not found after ${maxAttempts} attempts`));\n }\n return;\n }\n\n // Retry with exponential backoff for first few attempts, then fixed interval\n const delay = attempts < 5 ? Math.min(100 * Math.pow(1.5, attempts), 500) : 100;\n setTimeout(() => {\n this.waitForValidation(globalName, validator, resolve, reject, attempts + 1, maxAttempts);\n }, delay);\n }\n\n /**\n * Wait for existing script to load\n * @param script - Script element\n * @param globalName - Expected global variable\n * @param resolve - Promise resolve function\n * @param reject - Promise reject function\n */\n private waitForScriptLoad(\n script: HTMLScriptElement,\n globalName: string,\n resolve: (value: any) => void,\n reject: (reason: any) => void\n ): void {\n const checkGlobal = () => {\n if ((window as any)[globalName]) {\n resolve((window as any)[globalName]);\n return;\n }\n // Give it a moment for the global to be defined\n setTimeout(() => {\n if ((window as any)[globalName]) {\n resolve((window as any)[globalName]);\n } else {\n reject(new Error(`${globalName} not found after script load`));\n }\n }, 100);\n };\n\n if ('readyState' in script) {\n // IE support\n (script as any).onreadystatechange = () => {\n if ((script as any).readyState === 'loaded' || (script as any).readyState === 'complete') {\n (script as any).onreadystatechange = null;\n checkGlobal();\n }\n };\n } else {\n // Modern browsers\n const loadHandler = () => {\n script.removeEventListener('load', loadHandler);\n checkGlobal();\n };\n script.addEventListener('load', loadHandler);\n }\n }\n\n /**\n * Wait for existing script to load with validation\n * @param script - Script element\n * @param globalName - Expected global variable\n * @param validator - Validation function\n * @param resolve - Promise resolve function\n * @param reject - Promise reject function\n */\n private waitForScriptLoadWithValidation(\n script: HTMLScriptElement,\n globalName: string,\n validator: (obj: any) => boolean,\n resolve: (value: any) => void,\n reject: (reason: any) => void\n ): void {\n const checkGlobal = () => {\n this.waitForValidation(globalName, validator, resolve, reject);\n };\n\n if ('readyState' in script) {\n // IE support\n (script as any).onreadystatechange = () => {\n if ((script as any).readyState === 'loaded' || (script as any).readyState === 'complete') {\n (script as any).onreadystatechange = null;\n checkGlobal();\n }\n };\n } else {\n // Modern browsers\n const loadHandler = () => {\n script.removeEventListener('load', loadHandler);\n checkGlobal();\n };\n script.addEventListener('load', loadHandler);\n }\n }\n}"]}
|
package/dist/public-api.d.ts
CHANGED
|
@@ -8,6 +8,5 @@ export * from './lib/components/mj-react-component.component';
|
|
|
8
8
|
export * from './lib/services/script-loader.service';
|
|
9
9
|
export * from './lib/services/react-bridge.service';
|
|
10
10
|
export * from './lib/services/angular-adapter.service';
|
|
11
|
-
export { STANDARD_LIBRARY_URLS, getCoreLibraryUrls, getUILibraryUrls, getCSSUrls } from '@memberjunction/react-runtime';
|
|
12
11
|
export * from './lib/default-styles';
|
|
13
12
|
export { ComponentProps, ComponentCallbacks, ComponentStyles, ComponentError, CompileOptions, CompilationResult } from '@memberjunction/react-runtime';
|
package/dist/public-api.js
CHANGED
|
@@ -12,7 +12,5 @@ export * from './lib/services/script-loader.service';
|
|
|
12
12
|
export * from './lib/services/react-bridge.service';
|
|
13
13
|
export * from './lib/services/angular-adapter.service';
|
|
14
14
|
// Constants
|
|
15
|
-
// CDN URLs are now provided by @memberjunction/react-runtime
|
|
16
|
-
export { STANDARD_LIBRARY_URLS, getCoreLibraryUrls, getUILibraryUrls, getCSSUrls } from '@memberjunction/react-runtime';
|
|
17
15
|
export * from './lib/default-styles';
|
|
18
16
|
//# sourceMappingURL=public-api.js.map
|
package/dist/public-api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public-api.js","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,SAAS;AACT,cAAc,cAAc,CAAC;AAE7B,aAAa;AACb,cAAc,+CAA+C,CAAC;AAE9D,WAAW;AACX,cAAc,sCAAsC,CAAC;AACrD,cAAc,qCAAqC,CAAC;AACpD,cAAc,wCAAwC,CAAC;AAEvD,YAAY;AACZ,
|
|
1
|
+
{"version":3,"file":"public-api.js","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,SAAS;AACT,cAAc,cAAc,CAAC;AAE7B,aAAa;AACb,cAAc,+CAA+C,CAAC;AAE9D,WAAW;AACX,cAAc,sCAAsC,CAAC;AACrD,cAAc,qCAAqC,CAAC;AACpD,cAAc,wCAAwC,CAAC;AAEvD,YAAY;AACZ,cAAc,sBAAsB,CAAC","sourcesContent":["/**\n * @fileoverview Public API Surface of @memberjunction/ng-react\n * This file exports all public APIs from the Angular React integration library.\n * @module @memberjunction/ng-react\n */\n\n// Module\nexport * from './lib/module';\n\n// Components\nexport * from './lib/components/mj-react-component.component';\n\n// Services\nexport * from './lib/services/script-loader.service';\nexport * from './lib/services/react-bridge.service';\nexport * from './lib/services/angular-adapter.service';\n\n// Constants\nexport * from './lib/default-styles';\n\n// Re-export useful types from react-runtime for convenience\nexport { \n ComponentProps,\n ComponentCallbacks,\n ComponentStyles,\n ComponentError,\n CompileOptions,\n CompilationResult\n} from '@memberjunction/react-runtime';"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/ng-react",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.75.0",
|
|
4
4
|
"description": "Angular components for hosting React components in MemberJunction applications",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "ngc -p tsconfig.json",
|
|
@@ -40,9 +40,9 @@
|
|
|
40
40
|
"styles"
|
|
41
41
|
],
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@memberjunction/core": "2.
|
|
44
|
-
"@memberjunction/react-runtime": "2.
|
|
45
|
-
"@memberjunction/interactive-component-types": "^2.
|
|
43
|
+
"@memberjunction/core": "2.75.0",
|
|
44
|
+
"@memberjunction/react-runtime": "2.75.0",
|
|
45
|
+
"@memberjunction/interactive-component-types": "^2.75.0",
|
|
46
46
|
"@angular/common": ">=18.0.0",
|
|
47
47
|
"@angular/core": ">=18.0.0",
|
|
48
48
|
"@angular/platform-browser": ">=18.0.0",
|