@memberjunction/ng-react 2.70.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 +253 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/cdn-urls.d.ts +22 -0
- package/dist/lib/cdn-urls.js +28 -0
- package/dist/lib/cdn-urls.js.map +1 -0
- package/dist/lib/components/mj-react-component.component.d.ts +109 -0
- package/dist/lib/components/mj-react-component.component.js +391 -0
- package/dist/lib/components/mj-react-component.component.js.map +1 -0
- package/dist/lib/default-styles.d.ts +10 -0
- package/dist/lib/default-styles.js +106 -0
- package/dist/lib/default-styles.js.map +1 -0
- package/dist/lib/module.d.ts +22 -0
- package/dist/lib/module.js +58 -0
- package/dist/lib/module.js.map +1 -0
- package/dist/lib/services/angular-adapter.service.d.ts +97 -0
- package/dist/lib/services/angular-adapter.service.js +209 -0
- package/dist/lib/services/angular-adapter.service.js.map +1 -0
- package/dist/lib/services/react-bridge.service.d.ts +76 -0
- package/dist/lib/services/react-bridge.service.js +189 -0
- package/dist/lib/services/react-bridge.service.js.map +1 -0
- package/dist/lib/services/script-loader.service.d.ts +101 -0
- package/dist/lib/services/script-loader.service.js +333 -0
- package/dist/lib/services/script-loader.service.js.map +1 -0
- package/dist/public-api.d.ts +13 -0
- package/dist/public-api.js +17 -0
- package/dist/public-api.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module.js","sourceRoot":"","sources":["../../src/lib/module.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,aAAa;AACb,OAAO,EAAE,gBAAgB,EAAE,MAAM,2CAA2C,CAAC;AAE7E,WAAW;AACX,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;;AAE3E;;;;;;;;;;;;;GAaG;AAiBH,MAAM,OAAO,aAAa;8EAAb,aAAa;mEAAb,aAAa;wEATb;YACT,mBAAmB;YACnB,kBAAkB;YAClB,qBAAqB;SACtB,YANC,YAAY;;iFAWH,aAAa;cAhBzB,QAAQ;eAAC;gBACR,YAAY,EAAE;oBACZ,gBAAgB;iBACjB;gBACD,OAAO,EAAE;oBACP,YAAY;iBACb;gBACD,SAAS,EAAE;oBACT,mBAAmB;oBACnB,kBAAkB;oBAClB,qBAAqB;iBACtB;gBACD,OAAO,EAAE;oBACP,gBAAgB;iBACjB;aACF;;wFACY,aAAa,mBAdtB,gBAAgB,aAGhB,YAAY,aAQZ,gBAAgB","sourcesContent":["/**\n * @fileoverview Angular module for React component integration in MemberJunction.\n * Provides components and services for hosting React components within Angular applications.\n * @module @memberjunction/ng-react\n */\n\nimport { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\n\n// Components\nimport { MJReactComponent } from './components/mj-react-component.component';\n\n// Services\nimport { ScriptLoaderService } from './services/script-loader.service';\nimport { ReactBridgeService } from './services/react-bridge.service';\nimport { AngularAdapterService } from './services/angular-adapter.service';\n\n/**\n * Angular module that provides React component hosting capabilities.\n * Import this module to use React components within your Angular application.\n * \n * @example\n * ```typescript\n * import { MJReactModule } from '@memberjunction/ng-react';\n * \n * @NgModule({\n * imports: [MJReactModule]\n * })\n * export class MyModule {}\n * ```\n */\n@NgModule({\n declarations: [\n MJReactComponent\n ],\n imports: [\n CommonModule\n ],\n providers: [\n ScriptLoaderService,\n ReactBridgeService,\n AngularAdapterService\n ],\n exports: [\n MJReactComponent\n ]\n})\nexport class MJReactModule { }"]}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { ComponentCompiler, ComponentRegistry, ComponentResolver, CompileOptions, RuntimeContext } from '@memberjunction/react-runtime';
|
|
2
|
+
import { ScriptLoaderService } from './script-loader.service';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
/**
|
|
5
|
+
* Angular-specific adapter for the React runtime.
|
|
6
|
+
* Manages the integration between Angular services and the platform-agnostic React runtime.
|
|
7
|
+
*/
|
|
8
|
+
export declare class AngularAdapterService {
|
|
9
|
+
private scriptLoader;
|
|
10
|
+
private runtime?;
|
|
11
|
+
private runtimeContext?;
|
|
12
|
+
constructor(scriptLoader: ScriptLoaderService);
|
|
13
|
+
/**
|
|
14
|
+
* Initialize the React runtime with Angular-specific configuration
|
|
15
|
+
* @returns Promise resolving when runtime is ready
|
|
16
|
+
*/
|
|
17
|
+
initialize(): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Get the component compiler
|
|
20
|
+
* @returns Component compiler instance
|
|
21
|
+
*/
|
|
22
|
+
getCompiler(): ComponentCompiler;
|
|
23
|
+
/**
|
|
24
|
+
* Get the component registry
|
|
25
|
+
* @returns Component registry instance
|
|
26
|
+
*/
|
|
27
|
+
getRegistry(): ComponentRegistry;
|
|
28
|
+
/**
|
|
29
|
+
* Get the component resolver
|
|
30
|
+
* @returns Component resolver instance
|
|
31
|
+
*/
|
|
32
|
+
getResolver(): ComponentResolver;
|
|
33
|
+
/**
|
|
34
|
+
* Get the runtime context
|
|
35
|
+
* @returns Runtime context with React and libraries
|
|
36
|
+
*/
|
|
37
|
+
getRuntimeContext(): RuntimeContext;
|
|
38
|
+
/**
|
|
39
|
+
* Convert SkipComponentStyles to ComponentStyles
|
|
40
|
+
* @param skipStyles - Skip component styles
|
|
41
|
+
* @returns Component styles for React runtime
|
|
42
|
+
*/
|
|
43
|
+
private convertStyles;
|
|
44
|
+
/**
|
|
45
|
+
* Compile a component with Angular-specific defaults
|
|
46
|
+
* @param options - Compilation options
|
|
47
|
+
* @returns Promise resolving to compilation result
|
|
48
|
+
*/
|
|
49
|
+
compileComponent(options: CompileOptions & {
|
|
50
|
+
styles?: any;
|
|
51
|
+
}): Promise<import("@memberjunction/react-runtime").CompilationResult>;
|
|
52
|
+
/**
|
|
53
|
+
* Register a component in the registry
|
|
54
|
+
* @param name - Component name
|
|
55
|
+
* @param component - Compiled component
|
|
56
|
+
* @param namespace - Component namespace
|
|
57
|
+
* @param version - Component version
|
|
58
|
+
* @returns Component metadata
|
|
59
|
+
*/
|
|
60
|
+
registerComponent(name: string, component: any, namespace?: string, version?: string): import("@memberjunction/react-runtime").ComponentMetadata;
|
|
61
|
+
/**
|
|
62
|
+
* Get a component from the registry
|
|
63
|
+
* @param name - Component name
|
|
64
|
+
* @param namespace - Component namespace
|
|
65
|
+
* @param version - Component version
|
|
66
|
+
* @returns Component if found
|
|
67
|
+
*/
|
|
68
|
+
getComponent(name: string, namespace?: string, version?: string): any;
|
|
69
|
+
/**
|
|
70
|
+
* Check if runtime is initialized
|
|
71
|
+
* @returns true if initialized
|
|
72
|
+
*/
|
|
73
|
+
isInitialized(): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Get runtime version
|
|
76
|
+
* @returns Runtime version string
|
|
77
|
+
*/
|
|
78
|
+
getVersion(): string;
|
|
79
|
+
/**
|
|
80
|
+
* Clean up resources
|
|
81
|
+
*/
|
|
82
|
+
destroy(): void;
|
|
83
|
+
/**
|
|
84
|
+
* Get Babel instance for direct use
|
|
85
|
+
* @returns Babel instance
|
|
86
|
+
*/
|
|
87
|
+
getBabel(): any;
|
|
88
|
+
/**
|
|
89
|
+
* Transpile JSX code directly
|
|
90
|
+
* @param code - JSX code to transpile
|
|
91
|
+
* @param filename - Optional filename for better error messages
|
|
92
|
+
* @returns Transpiled JavaScript code
|
|
93
|
+
*/
|
|
94
|
+
transpileJSX(code: string, filename?: string): string;
|
|
95
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<AngularAdapterService, never>;
|
|
96
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<AngularAdapterService>;
|
|
97
|
+
}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Angular adapter service that bridges the React runtime with Angular.
|
|
3
|
+
* Provides Angular-specific functionality for the platform-agnostic React runtime.
|
|
4
|
+
* @module @memberjunction/ng-react
|
|
5
|
+
*/
|
|
6
|
+
import { Injectable } from '@angular/core';
|
|
7
|
+
import { createReactRuntime } from '@memberjunction/react-runtime';
|
|
8
|
+
import { ScriptLoaderService } from './script-loader.service';
|
|
9
|
+
import { DEFAULT_STYLES } from '../default-styles';
|
|
10
|
+
import * as i0 from "@angular/core";
|
|
11
|
+
import * as i1 from "./script-loader.service";
|
|
12
|
+
/**
|
|
13
|
+
* Angular-specific adapter for the React runtime.
|
|
14
|
+
* Manages the integration between Angular services and the platform-agnostic React runtime.
|
|
15
|
+
*/
|
|
16
|
+
export class AngularAdapterService {
|
|
17
|
+
constructor(scriptLoader) {
|
|
18
|
+
this.scriptLoader = scriptLoader;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Initialize the React runtime with Angular-specific configuration
|
|
22
|
+
* @returns Promise resolving when runtime is ready
|
|
23
|
+
*/
|
|
24
|
+
async initialize() {
|
|
25
|
+
if (this.runtime) {
|
|
26
|
+
return; // Already initialized
|
|
27
|
+
}
|
|
28
|
+
// Load React ecosystem
|
|
29
|
+
const ecosystem = await this.scriptLoader.loadReactEcosystem();
|
|
30
|
+
// Create runtime context
|
|
31
|
+
this.runtimeContext = {
|
|
32
|
+
React: ecosystem.React,
|
|
33
|
+
ReactDOM: ecosystem.ReactDOM,
|
|
34
|
+
libraries: ecosystem.libraries,
|
|
35
|
+
utilities: {
|
|
36
|
+
// Add any Angular-specific utilities here
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
// Create the React runtime
|
|
40
|
+
this.runtime = createReactRuntime(ecosystem.Babel, {
|
|
41
|
+
compiler: {
|
|
42
|
+
cache: true,
|
|
43
|
+
maxCacheSize: 100
|
|
44
|
+
},
|
|
45
|
+
registry: {
|
|
46
|
+
maxComponents: 1000,
|
|
47
|
+
cleanupInterval: 60000,
|
|
48
|
+
useLRU: true,
|
|
49
|
+
enableNamespaces: true
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Get the component compiler
|
|
55
|
+
* @returns Component compiler instance
|
|
56
|
+
*/
|
|
57
|
+
getCompiler() {
|
|
58
|
+
if (!this.runtime) {
|
|
59
|
+
throw new Error('React runtime not initialized. Call initialize() first.');
|
|
60
|
+
}
|
|
61
|
+
return this.runtime.compiler;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Get the component registry
|
|
65
|
+
* @returns Component registry instance
|
|
66
|
+
*/
|
|
67
|
+
getRegistry() {
|
|
68
|
+
if (!this.runtime) {
|
|
69
|
+
throw new Error('React runtime not initialized. Call initialize() first.');
|
|
70
|
+
}
|
|
71
|
+
return this.runtime.registry;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Get the component resolver
|
|
75
|
+
* @returns Component resolver instance
|
|
76
|
+
*/
|
|
77
|
+
getResolver() {
|
|
78
|
+
if (!this.runtime) {
|
|
79
|
+
throw new Error('React runtime not initialized. Call initialize() first.');
|
|
80
|
+
}
|
|
81
|
+
return this.runtime.resolver;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Get the runtime context
|
|
85
|
+
* @returns Runtime context with React and libraries
|
|
86
|
+
*/
|
|
87
|
+
getRuntimeContext() {
|
|
88
|
+
if (!this.runtimeContext) {
|
|
89
|
+
throw new Error('React runtime not initialized. Call initialize() first.');
|
|
90
|
+
}
|
|
91
|
+
return this.runtimeContext;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Convert SkipComponentStyles to ComponentStyles
|
|
95
|
+
* @param skipStyles - Skip component styles
|
|
96
|
+
* @returns Component styles for React runtime
|
|
97
|
+
*/
|
|
98
|
+
convertStyles(skipStyles) {
|
|
99
|
+
if (!skipStyles)
|
|
100
|
+
return undefined;
|
|
101
|
+
// Extract CSS-compatible properties
|
|
102
|
+
return {
|
|
103
|
+
className: skipStyles.className,
|
|
104
|
+
style: skipStyles.style,
|
|
105
|
+
globalCss: skipStyles.globalCss
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Compile a component with Angular-specific defaults
|
|
110
|
+
* @param options - Compilation options
|
|
111
|
+
* @returns Promise resolving to compilation result
|
|
112
|
+
*/
|
|
113
|
+
async compileComponent(options) {
|
|
114
|
+
await this.initialize();
|
|
115
|
+
// Apply default styles if not provided
|
|
116
|
+
const optionsWithDefaults = {
|
|
117
|
+
...options,
|
|
118
|
+
styles: options.styles || DEFAULT_STYLES
|
|
119
|
+
};
|
|
120
|
+
return this.runtime.compiler.compile(optionsWithDefaults);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Register a component in the registry
|
|
124
|
+
* @param name - Component name
|
|
125
|
+
* @param component - Compiled component
|
|
126
|
+
* @param namespace - Component namespace
|
|
127
|
+
* @param version - Component version
|
|
128
|
+
* @returns Component metadata
|
|
129
|
+
*/
|
|
130
|
+
registerComponent(name, component, namespace = 'Global', version = 'v1') {
|
|
131
|
+
if (!this.runtime) {
|
|
132
|
+
throw new Error('React runtime not initialized. Call initialize() first.');
|
|
133
|
+
}
|
|
134
|
+
return this.runtime.registry.register(name, component, namespace, version);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Get a component from the registry
|
|
138
|
+
* @param name - Component name
|
|
139
|
+
* @param namespace - Component namespace
|
|
140
|
+
* @param version - Component version
|
|
141
|
+
* @returns Component if found
|
|
142
|
+
*/
|
|
143
|
+
getComponent(name, namespace = 'Global', version) {
|
|
144
|
+
if (!this.runtime) {
|
|
145
|
+
throw new Error('React runtime not initialized. Call initialize() first.');
|
|
146
|
+
}
|
|
147
|
+
return this.runtime.registry.get(name, namespace, version);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Check if runtime is initialized
|
|
151
|
+
* @returns true if initialized
|
|
152
|
+
*/
|
|
153
|
+
isInitialized() {
|
|
154
|
+
return !!this.runtime && !!this.runtimeContext;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Get runtime version
|
|
158
|
+
* @returns Runtime version string
|
|
159
|
+
*/
|
|
160
|
+
getVersion() {
|
|
161
|
+
return this.runtime?.version || 'unknown';
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Clean up resources
|
|
165
|
+
*/
|
|
166
|
+
destroy() {
|
|
167
|
+
if (this.runtime) {
|
|
168
|
+
this.runtime.registry.destroy();
|
|
169
|
+
this.runtime = undefined;
|
|
170
|
+
this.runtimeContext = undefined;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Get Babel instance for direct use
|
|
175
|
+
* @returns Babel instance
|
|
176
|
+
*/
|
|
177
|
+
getBabel() {
|
|
178
|
+
return this.runtimeContext?.libraries?.Babel || window.Babel;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Transpile JSX code directly
|
|
182
|
+
* @param code - JSX code to transpile
|
|
183
|
+
* @param filename - Optional filename for better error messages
|
|
184
|
+
* @returns Transpiled JavaScript code
|
|
185
|
+
*/
|
|
186
|
+
transpileJSX(code, filename) {
|
|
187
|
+
const babel = this.getBabel();
|
|
188
|
+
if (!babel) {
|
|
189
|
+
throw new Error('Babel not loaded. Initialize the runtime first.');
|
|
190
|
+
}
|
|
191
|
+
try {
|
|
192
|
+
const result = babel.transform(code, {
|
|
193
|
+
presets: ['react'],
|
|
194
|
+
filename: filename || 'component.jsx'
|
|
195
|
+
});
|
|
196
|
+
return result.code;
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
throw new Error(`Failed to transpile JSX: ${error.message}`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
static { this.ɵfac = function AngularAdapterService_Factory(t) { return new (t || AngularAdapterService)(i0.ɵɵinject(i1.ScriptLoaderService)); }; }
|
|
203
|
+
static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: AngularAdapterService, factory: AngularAdapterService.ɵfac, providedIn: 'root' }); }
|
|
204
|
+
}
|
|
205
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(AngularAdapterService, [{
|
|
206
|
+
type: Injectable,
|
|
207
|
+
args: [{ providedIn: 'root' }]
|
|
208
|
+
}], () => [{ type: i1.ScriptLoaderService }], null); })();
|
|
209
|
+
//# sourceMappingURL=angular-adapter.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"angular-adapter.service.js","sourceRoot":"","sources":["../../../src/lib/services/angular-adapter.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Angular adapter service that bridges the React runtime with Angular.\n * Provides Angular-specific functionality for the platform-agnostic React runtime.\n * @module @memberjunction/ng-react\n */\n\nimport { Injectable } from '@angular/core';\nimport { \n ComponentCompiler,\n ComponentRegistry,\n ComponentResolver,\n createReactRuntime,\n CompileOptions,\n RuntimeContext,\n ComponentStyles\n} from '@memberjunction/react-runtime';\nimport { ScriptLoaderService } from './script-loader.service';\nimport { DEFAULT_STYLES } from '../default-styles';\n\n/**\n * Angular-specific adapter for the React runtime.\n * Manages the integration between Angular services and the platform-agnostic React runtime.\n */\n@Injectable({ providedIn: 'root' })\nexport class AngularAdapterService {\n private runtime?: {\n compiler: ComponentCompiler;\n registry: ComponentRegistry;\n resolver: ComponentResolver;\n version: string;\n };\n private runtimeContext?: RuntimeContext;\n\n constructor(private scriptLoader: ScriptLoaderService) {}\n\n /**\n * Initialize the React runtime with Angular-specific configuration\n * @returns Promise resolving when runtime is ready\n */\n async initialize(): Promise<void> {\n if (this.runtime) {\n return; // Already initialized\n }\n\n // Load React ecosystem\n const ecosystem = await this.scriptLoader.loadReactEcosystem();\n \n // Create runtime context\n this.runtimeContext = {\n React: ecosystem.React,\n ReactDOM: ecosystem.ReactDOM,\n libraries: ecosystem.libraries,\n utilities: {\n // Add any Angular-specific utilities here\n }\n };\n\n // Create the React runtime\n this.runtime = createReactRuntime(ecosystem.Babel, {\n compiler: {\n cache: true,\n maxCacheSize: 100\n },\n registry: {\n maxComponents: 1000,\n cleanupInterval: 60000,\n useLRU: true,\n enableNamespaces: true\n }\n });\n }\n\n /**\n * Get the component compiler\n * @returns Component compiler instance\n */\n getCompiler(): ComponentCompiler {\n if (!this.runtime) {\n throw new Error('React runtime not initialized. Call initialize() first.');\n }\n return this.runtime.compiler;\n }\n\n /**\n * Get the component registry\n * @returns Component registry instance\n */\n getRegistry(): ComponentRegistry {\n if (!this.runtime) {\n throw new Error('React runtime not initialized. Call initialize() first.');\n }\n return this.runtime.registry;\n }\n\n /**\n * Get the component resolver\n * @returns Component resolver instance\n */\n getResolver(): ComponentResolver {\n if (!this.runtime) {\n throw new Error('React runtime not initialized. Call initialize() first.');\n }\n return this.runtime.resolver;\n }\n\n /**\n * Get the runtime context\n * @returns Runtime context with React and libraries\n */\n getRuntimeContext(): RuntimeContext {\n if (!this.runtimeContext) {\n throw new Error('React runtime not initialized. Call initialize() first.');\n }\n return this.runtimeContext;\n }\n\n /**\n * Convert SkipComponentStyles to ComponentStyles\n * @param skipStyles - Skip component styles\n * @returns Component styles for React runtime\n */\n private convertStyles(skipStyles?: any): ComponentStyles | undefined {\n if (!skipStyles) return undefined;\n \n // Extract CSS-compatible properties\n return {\n className: skipStyles.className,\n style: skipStyles.style,\n globalCss: skipStyles.globalCss\n };\n }\n\n /**\n * Compile a component with Angular-specific defaults\n * @param options - Compilation options\n * @returns Promise resolving to compilation result\n */\n async compileComponent(options: CompileOptions & { styles?: any }) {\n await this.initialize();\n \n // Apply default styles if not provided\n const optionsWithDefaults = {\n ...options,\n styles: options.styles || DEFAULT_STYLES\n };\n\n return this.runtime!.compiler.compile(optionsWithDefaults);\n }\n\n /**\n * Register a component in the registry\n * @param name - Component name\n * @param component - Compiled component\n * @param namespace - Component namespace\n * @param version - Component version\n * @returns Component metadata\n */\n registerComponent(\n name: string,\n component: any,\n namespace: string = 'Global',\n version: string = 'v1'\n ) {\n if (!this.runtime) {\n throw new Error('React runtime not initialized. Call initialize() first.');\n }\n return this.runtime.registry.register(name, component, namespace, version);\n }\n\n /**\n * Get a component from the registry\n * @param name - Component name\n * @param namespace - Component namespace\n * @param version - Component version\n * @returns Component if found\n */\n getComponent(name: string, namespace: string = 'Global', version?: string) {\n if (!this.runtime) {\n throw new Error('React runtime not initialized. Call initialize() first.');\n }\n return this.runtime.registry.get(name, namespace, version);\n }\n\n /**\n * Check if runtime is initialized\n * @returns true if initialized\n */\n isInitialized(): boolean {\n return !!this.runtime && !!this.runtimeContext;\n }\n\n /**\n * Get runtime version\n * @returns Runtime version string\n */\n getVersion(): string {\n return this.runtime?.version || 'unknown';\n }\n\n /**\n * Clean up resources\n */\n destroy(): void {\n if (this.runtime) {\n this.runtime.registry.destroy();\n this.runtime = undefined;\n this.runtimeContext = undefined;\n }\n }\n\n /**\n * Get Babel instance for direct use\n * @returns Babel instance\n */\n getBabel(): any {\n return this.runtimeContext?.libraries?.Babel || (window as any).Babel;\n }\n\n /**\n * Transpile JSX code directly\n * @param code - JSX code to transpile\n * @param filename - Optional filename for better error messages\n * @returns Transpiled JavaScript code\n */\n transpileJSX(code: string, filename?: string): string {\n const babel = this.getBabel();\n if (!babel) {\n throw new Error('Babel not loaded. Initialize the runtime first.');\n }\n\n try {\n const result = babel.transform(code, {\n presets: ['react'],\n filename: filename || 'component.jsx'\n });\n return result.code;\n } catch (error: any) {\n throw new Error(`Failed to transpile JSX: ${error.message}`);\n }\n }\n}"]}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Service to manage React and ReactDOM instances with proper lifecycle.
|
|
3
|
+
* Bridges Angular components with React rendering capabilities.
|
|
4
|
+
* @module @memberjunction/ng-react
|
|
5
|
+
*/
|
|
6
|
+
import { OnDestroy } from '@angular/core';
|
|
7
|
+
import { AngularAdapterService } from './angular-adapter.service';
|
|
8
|
+
import { RuntimeContext } from '@memberjunction/react-runtime';
|
|
9
|
+
import * as i0 from "@angular/core";
|
|
10
|
+
/**
|
|
11
|
+
* Service to manage React and ReactDOM instances with proper lifecycle.
|
|
12
|
+
* Provides methods for creating and managing React roots in Angular applications.
|
|
13
|
+
*/
|
|
14
|
+
export declare class ReactBridgeService implements OnDestroy {
|
|
15
|
+
private adapter;
|
|
16
|
+
private reactRoots;
|
|
17
|
+
private reactReadySubject;
|
|
18
|
+
reactReady$: import("rxjs").Observable<boolean>;
|
|
19
|
+
private firstComponentAttempted;
|
|
20
|
+
private maxWaitTime;
|
|
21
|
+
private checkInterval;
|
|
22
|
+
constructor(adapter: AngularAdapterService);
|
|
23
|
+
ngOnDestroy(): void;
|
|
24
|
+
/**
|
|
25
|
+
* Bootstrap React early during service initialization
|
|
26
|
+
*/
|
|
27
|
+
private bootstrapReact;
|
|
28
|
+
/**
|
|
29
|
+
* Wait for React to be ready, with special handling for first component
|
|
30
|
+
*/
|
|
31
|
+
waitForReactReady(): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Get the current React context if loaded
|
|
34
|
+
* @returns React context with React, ReactDOM, Babel, and libraries
|
|
35
|
+
*/
|
|
36
|
+
getReactContext(): Promise<RuntimeContext>;
|
|
37
|
+
/**
|
|
38
|
+
* Get the current React context synchronously
|
|
39
|
+
* @returns React context or null if not loaded
|
|
40
|
+
*/
|
|
41
|
+
getCurrentContext(): RuntimeContext | null;
|
|
42
|
+
/**
|
|
43
|
+
* Create a React root for rendering
|
|
44
|
+
* @param container - DOM element to render into
|
|
45
|
+
* @returns React root instance
|
|
46
|
+
*/
|
|
47
|
+
createRoot(container: HTMLElement): any;
|
|
48
|
+
/**
|
|
49
|
+
* Unmount and clean up a React root
|
|
50
|
+
* @param root - React root to unmount
|
|
51
|
+
*/
|
|
52
|
+
unmountRoot(root: any): void;
|
|
53
|
+
/**
|
|
54
|
+
* Transpile JSX code to JavaScript
|
|
55
|
+
* @param code - JSX code to transpile
|
|
56
|
+
* @param filename - Optional filename for error messages
|
|
57
|
+
* @returns Transpiled JavaScript code
|
|
58
|
+
*/
|
|
59
|
+
transpileJSX(code: string, filename: string): string;
|
|
60
|
+
/**
|
|
61
|
+
* Clean up all React roots and reset context
|
|
62
|
+
*/
|
|
63
|
+
private cleanup;
|
|
64
|
+
/**
|
|
65
|
+
* Check if React is currently ready
|
|
66
|
+
* @returns true if React is ready
|
|
67
|
+
*/
|
|
68
|
+
isReady(): boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Get the number of active React roots
|
|
71
|
+
* @returns Number of active roots
|
|
72
|
+
*/
|
|
73
|
+
getActiveRootsCount(): number;
|
|
74
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<ReactBridgeService, never>;
|
|
75
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<ReactBridgeService>;
|
|
76
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Service to manage React and ReactDOM instances with proper lifecycle.
|
|
3
|
+
* Bridges Angular components with React rendering capabilities.
|
|
4
|
+
* @module @memberjunction/ng-react
|
|
5
|
+
*/
|
|
6
|
+
import { Injectable } from '@angular/core';
|
|
7
|
+
import { BehaviorSubject, firstValueFrom } from 'rxjs';
|
|
8
|
+
import { filter } from 'rxjs/operators';
|
|
9
|
+
import { AngularAdapterService } from './angular-adapter.service';
|
|
10
|
+
import * as i0 from "@angular/core";
|
|
11
|
+
import * as i1 from "./angular-adapter.service";
|
|
12
|
+
/**
|
|
13
|
+
* Service to manage React and ReactDOM instances with proper lifecycle.
|
|
14
|
+
* Provides methods for creating and managing React roots in Angular applications.
|
|
15
|
+
*/
|
|
16
|
+
export class ReactBridgeService {
|
|
17
|
+
constructor(adapter) {
|
|
18
|
+
this.adapter = adapter;
|
|
19
|
+
this.reactRoots = new Set();
|
|
20
|
+
// Track React readiness state
|
|
21
|
+
this.reactReadySubject = new BehaviorSubject(false);
|
|
22
|
+
this.reactReady$ = this.reactReadySubject.asObservable();
|
|
23
|
+
// Track if this is the first component trying to use React
|
|
24
|
+
this.firstComponentAttempted = false;
|
|
25
|
+
this.maxWaitTime = 5000; // Maximum 5 seconds wait time
|
|
26
|
+
this.checkInterval = 200; // Check every 200ms
|
|
27
|
+
// Bootstrap React immediately on service initialization
|
|
28
|
+
this.bootstrapReact();
|
|
29
|
+
}
|
|
30
|
+
ngOnDestroy() {
|
|
31
|
+
this.cleanup();
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Bootstrap React early during service initialization
|
|
35
|
+
*/
|
|
36
|
+
async bootstrapReact() {
|
|
37
|
+
try {
|
|
38
|
+
await this.adapter.initialize();
|
|
39
|
+
console.log('React ecosystem pre-loaded successfully');
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
console.error('Failed to pre-load React ecosystem:', error);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Wait for React to be ready, with special handling for first component
|
|
47
|
+
*/
|
|
48
|
+
async waitForReactReady() {
|
|
49
|
+
// If already ready, return immediately
|
|
50
|
+
if (this.reactReadySubject.value) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
// Check if this is the first component attempting to use React
|
|
54
|
+
const isFirstComponent = !this.firstComponentAttempted;
|
|
55
|
+
this.firstComponentAttempted = true;
|
|
56
|
+
if (isFirstComponent) {
|
|
57
|
+
// First component - check periodically until React is ready
|
|
58
|
+
console.log('First React component loading - checking for React initialization');
|
|
59
|
+
const startTime = Date.now();
|
|
60
|
+
while (Date.now() - startTime < this.maxWaitTime) {
|
|
61
|
+
try {
|
|
62
|
+
const testDiv = document.createElement('div');
|
|
63
|
+
const context = this.adapter.getRuntimeContext();
|
|
64
|
+
if (context.ReactDOM?.createRoot) {
|
|
65
|
+
// Try to create a test root
|
|
66
|
+
const testRoot = context.ReactDOM.createRoot(testDiv);
|
|
67
|
+
if (testRoot) {
|
|
68
|
+
testRoot.unmount();
|
|
69
|
+
// React is ready!
|
|
70
|
+
this.reactReadySubject.next(true);
|
|
71
|
+
console.log(`React is fully ready after ${Date.now() - startTime}ms`);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
// Not ready yet, continue checking
|
|
78
|
+
}
|
|
79
|
+
// Wait before next check
|
|
80
|
+
await new Promise(resolve => setTimeout(resolve, this.checkInterval));
|
|
81
|
+
}
|
|
82
|
+
// If we've exhausted the wait time, throw error
|
|
83
|
+
console.error('React readiness test failed after maximum wait time');
|
|
84
|
+
this.firstComponentAttempted = false;
|
|
85
|
+
throw new Error(`ReactDOM.createRoot not available after ${this.maxWaitTime}ms`);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
// Subsequent components wait for the ready signal
|
|
89
|
+
await firstValueFrom(this.reactReady$.pipe(filter(ready => ready)));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Get the current React context if loaded
|
|
94
|
+
* @returns React context with React, ReactDOM, Babel, and libraries
|
|
95
|
+
*/
|
|
96
|
+
async getReactContext() {
|
|
97
|
+
await this.adapter.initialize();
|
|
98
|
+
return this.adapter.getRuntimeContext();
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Get the current React context synchronously
|
|
102
|
+
* @returns React context or null if not loaded
|
|
103
|
+
*/
|
|
104
|
+
getCurrentContext() {
|
|
105
|
+
if (!this.adapter.isInitialized()) {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
return this.adapter.getRuntimeContext();
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Create a React root for rendering
|
|
112
|
+
* @param container - DOM element to render into
|
|
113
|
+
* @returns React root instance
|
|
114
|
+
*/
|
|
115
|
+
createRoot(container) {
|
|
116
|
+
const context = this.getCurrentContext();
|
|
117
|
+
if (!context?.ReactDOM?.createRoot) {
|
|
118
|
+
throw new Error('ReactDOM.createRoot not available');
|
|
119
|
+
}
|
|
120
|
+
const root = context.ReactDOM.createRoot(container);
|
|
121
|
+
this.reactRoots.add(root);
|
|
122
|
+
return root;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Unmount and clean up a React root
|
|
126
|
+
* @param root - React root to unmount
|
|
127
|
+
*/
|
|
128
|
+
unmountRoot(root) {
|
|
129
|
+
if (root && typeof root.unmount === 'function') {
|
|
130
|
+
try {
|
|
131
|
+
root.unmount();
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
console.warn('Failed to unmount React root:', error);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
this.reactRoots.delete(root);
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Transpile JSX code to JavaScript
|
|
141
|
+
* @param code - JSX code to transpile
|
|
142
|
+
* @param filename - Optional filename for error messages
|
|
143
|
+
* @returns Transpiled JavaScript code
|
|
144
|
+
*/
|
|
145
|
+
transpileJSX(code, filename) {
|
|
146
|
+
return this.adapter.transpileJSX(code, filename);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Clean up all React roots and reset context
|
|
150
|
+
*/
|
|
151
|
+
cleanup() {
|
|
152
|
+
// Unmount all tracked React roots
|
|
153
|
+
for (const root of this.reactRoots) {
|
|
154
|
+
try {
|
|
155
|
+
root.unmount();
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
console.warn('Failed to unmount React root:', error);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
this.reactRoots.clear();
|
|
162
|
+
// Reset readiness state
|
|
163
|
+
this.reactReadySubject.next(false);
|
|
164
|
+
this.firstComponentAttempted = false;
|
|
165
|
+
// Clean up adapter
|
|
166
|
+
this.adapter.destroy();
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Check if React is currently ready
|
|
170
|
+
* @returns true if React is ready
|
|
171
|
+
*/
|
|
172
|
+
isReady() {
|
|
173
|
+
return this.reactReadySubject.value;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Get the number of active React roots
|
|
177
|
+
* @returns Number of active roots
|
|
178
|
+
*/
|
|
179
|
+
getActiveRootsCount() {
|
|
180
|
+
return this.reactRoots.size;
|
|
181
|
+
}
|
|
182
|
+
static { this.ɵfac = function ReactBridgeService_Factory(t) { return new (t || ReactBridgeService)(i0.ɵɵinject(i1.AngularAdapterService)); }; }
|
|
183
|
+
static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: ReactBridgeService, factory: ReactBridgeService.ɵfac, providedIn: 'root' }); }
|
|
184
|
+
}
|
|
185
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ReactBridgeService, [{
|
|
186
|
+
type: Injectable,
|
|
187
|
+
args: [{ providedIn: 'root' }]
|
|
188
|
+
}], () => [{ type: i1.AngularAdapterService }], null); })();
|
|
189
|
+
//# sourceMappingURL=react-bridge.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react-bridge.service.js","sourceRoot":"","sources":["../../../src/lib/services/react-bridge.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Service to manage React and ReactDOM instances with proper lifecycle.\n * Bridges Angular components with React rendering capabilities.\n * @module @memberjunction/ng-react\n */\n\nimport { Injectable, OnDestroy } from '@angular/core';\nimport { BehaviorSubject, firstValueFrom } from 'rxjs';\nimport { filter } from 'rxjs/operators';\nimport { AngularAdapterService } from './angular-adapter.service';\nimport { RuntimeContext } from '@memberjunction/react-runtime';\n\n/**\n * Service to manage React and ReactDOM instances with proper lifecycle.\n * Provides methods for creating and managing React roots in Angular applications.\n */\n@Injectable({ providedIn: 'root' })\nexport class ReactBridgeService implements OnDestroy {\n private reactRoots = new Set<any>();\n \n // Track React readiness state\n private reactReadySubject = new BehaviorSubject<boolean>(false);\n public reactReady$ = this.reactReadySubject.asObservable();\n \n // Track if this is the first component trying to use React\n private firstComponentAttempted = false;\n private maxWaitTime = 5000; // Maximum 5 seconds wait time\n private checkInterval = 200; // Check every 200ms\n\n constructor(private adapter: AngularAdapterService) {\n // Bootstrap React immediately on service initialization\n this.bootstrapReact();\n }\n\n ngOnDestroy(): void {\n this.cleanup();\n }\n\n /**\n * Bootstrap React early during service initialization\n */\n private async bootstrapReact(): Promise<void> {\n try {\n await this.adapter.initialize();\n console.log('React ecosystem pre-loaded successfully');\n } catch (error) {\n console.error('Failed to pre-load React ecosystem:', error);\n }\n }\n\n /**\n * Wait for React to be ready, with special handling for first component\n */\n async waitForReactReady(): Promise<void> {\n // If already ready, return immediately\n if (this.reactReadySubject.value) {\n return;\n }\n\n // Check if this is the first component attempting to use React\n const isFirstComponent = !this.firstComponentAttempted;\n this.firstComponentAttempted = true;\n\n if (isFirstComponent) {\n // First component - check periodically until React is ready\n console.log('First React component loading - checking for React initialization');\n \n const startTime = Date.now();\n \n while (Date.now() - startTime < this.maxWaitTime) {\n try {\n const testDiv = document.createElement('div');\n const context = this.adapter.getRuntimeContext();\n \n if (context.ReactDOM?.createRoot) {\n // Try to create a test root\n const testRoot = context.ReactDOM.createRoot(testDiv);\n if (testRoot) {\n testRoot.unmount();\n // React is ready!\n this.reactReadySubject.next(true);\n console.log(`React is fully ready after ${Date.now() - startTime}ms`);\n return;\n }\n }\n } catch (error) {\n // Not ready yet, continue checking\n }\n \n // Wait before next check\n await new Promise(resolve => setTimeout(resolve, this.checkInterval));\n }\n \n // If we've exhausted the wait time, throw error\n console.error('React readiness test failed after maximum wait time');\n this.firstComponentAttempted = false;\n throw new Error(`ReactDOM.createRoot not available after ${this.maxWaitTime}ms`);\n } else {\n // Subsequent components wait for the ready signal\n await firstValueFrom(this.reactReady$.pipe(filter(ready => ready)));\n }\n }\n\n /**\n * Get the current React context if loaded\n * @returns React context with React, ReactDOM, Babel, and libraries\n */\n async getReactContext(): Promise<RuntimeContext> {\n await this.adapter.initialize();\n return this.adapter.getRuntimeContext();\n }\n\n /**\n * Get the current React context synchronously\n * @returns React context or null if not loaded\n */\n getCurrentContext(): RuntimeContext | null {\n if (!this.adapter.isInitialized()) {\n return null;\n }\n return this.adapter.getRuntimeContext();\n }\n\n /**\n * Create a React root for rendering\n * @param container - DOM element to render into\n * @returns React root instance\n */\n createRoot(container: HTMLElement): any {\n const context = this.getCurrentContext();\n if (!context?.ReactDOM?.createRoot) {\n throw new Error('ReactDOM.createRoot not available');\n }\n\n const root = context.ReactDOM.createRoot(container);\n this.reactRoots.add(root);\n return root;\n }\n\n /**\n * Unmount and clean up a React root\n * @param root - React root to unmount\n */\n unmountRoot(root: any): void {\n if (root && typeof root.unmount === 'function') {\n try {\n root.unmount();\n } catch (error) {\n console.warn('Failed to unmount React root:', error);\n }\n }\n this.reactRoots.delete(root);\n }\n\n /**\n * Transpile JSX code to JavaScript\n * @param code - JSX code to transpile\n * @param filename - Optional filename for error messages\n * @returns Transpiled JavaScript code\n */\n transpileJSX(code: string, filename: string): string {\n return this.adapter.transpileJSX(code, filename);\n }\n\n /**\n * Clean up all React roots and reset context\n */\n private cleanup(): void {\n // Unmount all tracked React roots\n for (const root of this.reactRoots) {\n try {\n root.unmount();\n } catch (error) {\n console.warn('Failed to unmount React root:', error);\n }\n }\n this.reactRoots.clear();\n \n // Reset readiness state\n this.reactReadySubject.next(false);\n this.firstComponentAttempted = false;\n\n // Clean up adapter\n this.adapter.destroy();\n }\n\n /**\n * Check if React is currently ready\n * @returns true if React is ready\n */\n isReady(): boolean {\n return this.reactReadySubject.value;\n }\n\n /**\n * Get the number of active React roots\n * @returns Number of active roots\n */\n getActiveRootsCount(): number {\n return this.reactRoots.size;\n }\n}"]}
|