@memberjunction/ng-react 2.75.0 → 2.76.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -192,27 +192,7 @@ const styles: SkipComponentStyles = {
192
192
  }
193
193
  };
194
194
  ```
195
-
196
- ### State Management
197
-
198
- ```typescript
199
- // In your Angular component
200
- onStateChange(event: StateChangeEvent) {
201
- console.log(`State ${event.path} changed to:`, event.value);
202
- // Update your Angular component state
203
- }
204
-
205
- // In your React component
206
- function MyComponent({ userState, callbacks }) {
207
- const updateState = () => {
208
- callbacks.UpdateUserState({
209
- counter: userState.counter + 1
210
- });
211
- };
212
-
213
- return <button onClick={updateState}>Count: {userState.counter}</button>;
214
- }
215
- ```
195
+
216
196
 
217
197
  ## Services
218
198
 
@@ -23,6 +23,14 @@ export interface StateChangeEvent {
23
23
  path: string;
24
24
  value: any;
25
25
  }
26
+ /**
27
+ * User settings changed event emitted when component saves user preferences
28
+ */
29
+ export interface UserSettingsChangedEvent {
30
+ settings: Record<string, any>;
31
+ componentName?: string;
32
+ timestamp: Date;
33
+ }
26
34
  /**
27
35
  * Angular component that hosts React components with proper memory management.
28
36
  * This component provides a bridge between Angular and React, allowing React components
@@ -41,6 +49,9 @@ export declare class MJReactComponent implements AfterViewInit, OnDestroy {
41
49
  get state(): any;
42
50
  utilities: any;
43
51
  styles?: Partial<ComponentStyles>;
52
+ private _savedUserSettings;
53
+ set savedUserSettings(value: any);
54
+ get savedUserSettings(): any;
44
55
  stateChange: EventEmitter<StateChangeEvent>;
45
56
  componentEvent: EventEmitter<ReactComponentEvent>;
46
57
  refreshData: EventEmitter<void>;
@@ -48,6 +59,7 @@ export declare class MJReactComponent implements AfterViewInit, OnDestroy {
48
59
  entityName: string;
49
60
  key: CompositeKey;
50
61
  }>;
62
+ userSettingsChanged: EventEmitter<UserSettingsChangedEvent>;
51
63
  container: ElementRef<HTMLDivElement>;
52
64
  private reactRoot;
53
65
  private compiledComponent;
@@ -83,6 +95,11 @@ export declare class MJReactComponent implements AfterViewInit, OnDestroy {
83
95
  * Handle React component errors
84
96
  */
85
97
  private handleReactError;
98
+ /**
99
+ * Handle onSaveUserSettings from components
100
+ * This implements the SavedUserSettings pattern
101
+ */
102
+ private handleSaveUserSettings;
86
103
  /**
87
104
  * Clean up resources
88
105
  */
@@ -103,5 +120,5 @@ export declare class MJReactComponent implements AfterViewInit, OnDestroy {
103
120
  */
104
121
  private isEqual;
105
122
  static ɵfac: i0.ɵɵFactoryDeclaration<MJReactComponent, never>;
106
- static ɵcmp: i0.ɵɵComponentDeclaration<MJReactComponent, "mj-react-component", never, { "component": { "alias": "component"; "required": false; }; "data": { "alias": "data"; "required": false; }; "state": { "alias": "state"; "required": false; }; "utilities": { "alias": "utilities"; "required": false; }; "styles": { "alias": "styles"; "required": false; }; }, { "stateChange": "stateChange"; "componentEvent": "componentEvent"; "refreshData": "refreshData"; "openEntityRecord": "openEntityRecord"; }, never, never, false, never>;
123
+ static ɵcmp: i0.ɵɵComponentDeclaration<MJReactComponent, "mj-react-component", never, { "component": { "alias": "component"; "required": false; }; "data": { "alias": "data"; "required": false; }; "state": { "alias": "state"; "required": false; }; "utilities": { "alias": "utilities"; "required": false; }; "styles": { "alias": "styles"; "required": false; }; "savedUserSettings": { "alias": "savedUserSettings"; "required": false; }; }, { "stateChange": "stateChange"; "componentEvent": "componentEvent"; "refreshData": "refreshData"; "openEntityRecord": "openEntityRecord"; "userSettingsChanged": "userSettingsChanged"; }, never, never, false, never>;
107
124
  }
@@ -8,7 +8,7 @@ import { Subject } from 'rxjs';
8
8
  import { ComponentSpec } from '@memberjunction/interactive-component-types';
9
9
  import { ReactBridgeService } from '../services/react-bridge.service';
10
10
  import { AngularAdapterService } from '../services/angular-adapter.service';
11
- import { buildComponentProps, cleanupPropBuilder, createErrorBoundary, ComponentHierarchyRegistrar } from '@memberjunction/react-runtime';
11
+ import { createErrorBoundary, ComponentHierarchyRegistrar } from '@memberjunction/react-runtime';
12
12
  import { LogError, CompositeKey } from '@memberjunction/core';
13
13
  import * as i0 from "@angular/core";
14
14
  import * as i1 from "../services/react-bridge.service";
@@ -51,6 +51,16 @@ export class MJReactComponent {
51
51
  get state() {
52
52
  return this._state;
53
53
  }
54
+ set savedUserSettings(value) {
55
+ this._savedUserSettings = value || {};
56
+ // Re-render if component is initialized
57
+ if (this.isInitialized) {
58
+ this.renderComponent();
59
+ }
60
+ }
61
+ get savedUserSettings() {
62
+ return this._savedUserSettings;
63
+ }
54
64
  constructor(reactBridge, adapter, cdr) {
55
65
  this.reactBridge = reactBridge;
56
66
  this.adapter = adapter;
@@ -58,10 +68,12 @@ export class MJReactComponent {
58
68
  this._data = {};
59
69
  this._state = {};
60
70
  this.utilities = {};
71
+ this._savedUserSettings = {};
61
72
  this.stateChange = new EventEmitter();
62
73
  this.componentEvent = new EventEmitter();
63
74
  this.refreshData = new EventEmitter();
64
75
  this.openEntityRecord = new EventEmitter();
76
+ this.userSettingsChanged = new EventEmitter();
65
77
  this.reactRoot = null;
66
78
  this.compiledComponent = null;
67
79
  this.destroyed$ = new Subject();
@@ -180,10 +192,16 @@ export class MJReactComponent {
180
192
  if (!this.currentCallbacks) {
181
193
  this.currentCallbacks = this.createCallbacks();
182
194
  }
183
- // Build props - pass styles as-is for Skip components
184
- const props = buildComponentProps(this._data || {}, this.currentState, this.utilities || {}, this.currentCallbacks, components, this.styles, // Skip components expect the full SkipComponentStyles structure
185
- { debounceUpdateUserState: 3000 } // 3 second debounce by default
186
- );
195
+ // Build props with savedUserSettings pattern
196
+ const props = {
197
+ ...this._data, // Spread data properties directly
198
+ utilities: this.utilities || {},
199
+ callbacks: this.currentCallbacks,
200
+ components,
201
+ styles: this.styles,
202
+ savedUserSettings: this._savedUserSettings,
203
+ onSaveUserSettings: this.handleSaveUserSettings.bind(this)
204
+ };
187
205
  // Create error boundary
188
206
  const ErrorBoundary = createErrorBoundary(React, {
189
207
  onError: this.handleReactError.bind(this),
@@ -239,9 +257,6 @@ export class MJReactComponent {
239
257
  */
240
258
  createCallbacks() {
241
259
  return {
242
- RefreshData: () => {
243
- this.refreshData.emit();
244
- },
245
260
  OpenEntityRecord: (entityName, key) => {
246
261
  let keyToUse = null;
247
262
  if (key instanceof Array) {
@@ -262,35 +277,6 @@ export class MJReactComponent {
262
277
  if (keyToUse) {
263
278
  this.openEntityRecord.emit({ entityName, key: keyToUse });
264
279
  }
265
- },
266
- UpdateUserState: (userState) => {
267
- // Prevent updates during rendering or destruction
268
- if (this.isRendering || this.isDestroying) {
269
- return;
270
- }
271
- // Deep comparison to detect actual changes
272
- const hasChanges = Object.keys(userState).some(key => {
273
- const currentValue = this.currentState[key];
274
- const newValue = userState[key];
275
- return !this.isEqual(currentValue, newValue);
276
- });
277
- if (!hasChanges) {
278
- // No actual changes, skip update to prevent infinite loop
279
- return;
280
- }
281
- this.currentState = {
282
- ...this.currentState,
283
- ...userState
284
- };
285
- // Emit change for each key in the state update
286
- Object.keys(userState).forEach(path => {
287
- this.stateChange.emit({ path, value: userState[path] });
288
- });
289
- // Schedule re-render
290
- this.renderComponent();
291
- },
292
- NotifyEvent: (event, data) => {
293
- this.componentEvent.emit({ type: event, payload: data });
294
280
  }
295
281
  };
296
282
  }
@@ -308,6 +294,28 @@ export class MJReactComponent {
308
294
  }
309
295
  });
310
296
  }
297
+ /**
298
+ * Handle onSaveUserSettings from components
299
+ * This implements the SavedUserSettings pattern
300
+ */
301
+ handleSaveUserSettings(newSettings) {
302
+ // Check if there are actual changes
303
+ const hasChanges = !this.isEqual(this._savedUserSettings, newSettings);
304
+ if (!hasChanges) {
305
+ // No actual changes, skip update to prevent infinite loop
306
+ return;
307
+ }
308
+ // Update saved settings
309
+ this._savedUserSettings = { ...newSettings };
310
+ // Emit user settings changed event
311
+ this.userSettingsChanged.emit({
312
+ settings: this._savedUserSettings,
313
+ componentName: this.component?.name,
314
+ timestamp: new Date()
315
+ });
316
+ // Schedule re-render
317
+ this.renderComponent();
318
+ }
311
319
  /**
312
320
  * Clean up resources
313
321
  */
@@ -319,7 +327,6 @@ export class MJReactComponent {
319
327
  }
320
328
  // Clean up prop builder subscriptions
321
329
  if (this.currentCallbacks) {
322
- cleanupPropBuilder(this.currentCallbacks);
323
330
  this.currentCallbacks = null;
324
331
  }
325
332
  // Unmount React root only if not currently rendering
@@ -387,7 +394,7 @@ export class MJReactComponent {
387
394
  } if (rf & 2) {
388
395
  let _t;
389
396
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.container = _t.first);
390
- } }, inputs: { component: "component", data: "data", state: "state", utilities: "utilities", styles: "styles" }, outputs: { stateChange: "stateChange", componentEvent: "componentEvent", refreshData: "refreshData", openEntityRecord: "openEntityRecord" }, decls: 4, vars: 3, consts: [["container", ""], [1, "react-component-wrapper"], [1, "react-component-container"], [1, "loading-overlay"], [1, "loading-spinner"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "loading-text"]], template: function MJReactComponent_Template(rf, ctx) { if (rf & 1) {
397
+ } }, inputs: { component: "component", data: "data", state: "state", utilities: "utilities", styles: "styles", savedUserSettings: "savedUserSettings" }, outputs: { stateChange: "stateChange", componentEvent: "componentEvent", refreshData: "refreshData", openEntityRecord: "openEntityRecord", userSettingsChanged: "userSettingsChanged" }, decls: 4, vars: 3, consts: [["container", ""], [1, "react-component-wrapper"], [1, "react-component-container"], [1, "loading-overlay"], [1, "loading-spinner"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "loading-text"]], template: function MJReactComponent_Template(rf, ctx) { if (rf & 1) {
391
398
  i0.ɵɵelementStart(0, "div", 1);
392
399
  i0.ɵɵelement(1, "div", 2, 0);
393
400
  i0.ɵɵtemplate(3, MJReactComponent_Conditional_3_Template, 5, 0, "div", 3);
@@ -424,6 +431,8 @@ export class MJReactComponent {
424
431
  type: Input
425
432
  }], styles: [{
426
433
  type: Input
434
+ }], savedUserSettings: [{
435
+ type: Input
427
436
  }], stateChange: [{
428
437
  type: Output
429
438
  }], componentEvent: [{
@@ -432,9 +441,11 @@ export class MJReactComponent {
432
441
  type: Output
433
442
  }], openEntityRecord: [{
434
443
  type: Output
444
+ }], userSettingsChanged: [{
445
+ type: Output
435
446
  }], container: [{
436
447
  type: ViewChild,
437
448
  args: ['container', { read: ElementRef, static: true }]
438
449
  }] }); })();
439
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJReactComponent, { className: "MJReactComponent", filePath: "lib/components/mj-react-component.component.ts", lineNumber: 115 }); })();
450
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJReactComponent, { className: "MJReactComponent", filePath: "lib/components/mj-react-component.component.ts", lineNumber: 122 }); })();
440
451
  //# sourceMappingURL=mj-react-component.component.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mj-react-component.component.js","sourceRoot":"","sources":["../../../src/lib/components/mj-react-component.component.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,SAAS,EACT,KAAK,EACL,MAAM,EACN,YAAY,EACZ,SAAS,EACT,UAAU,EAGV,uBAAuB,EACvB,iBAAiB,EAClB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,OAAO,EAAa,MAAM,MAAM,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAuC,MAAM,6CAA6C,CAAC;AACjH,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAElB,mBAAmB,EACnB,2BAA2B,EAE5B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAgB,MAAM,sBAAsB,CAAC;;;;;;IA8BlE,AADF,8BAA6B,aACE;IAC3B,uBAA2C;IAC7C,iBAAM;IACN,8BAA0B;IAAA,oCAAoB;IAChD,AADgD,iBAAM,EAChD;;AAhBd;;;;GAIG;AA8DH,MAAM,OAAO,gBAAgB;IAI3B,IACI,IAAI,CAAC,KAAU;QACjB,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC;QAC3B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QAEnB,uEAAuE;QACvE,IAAI,IAAI,CAAC,aAAa,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC;YACxD,IAAI,CAAC,eAAe,EAAE,CAAC;QACzB,CAAC;IACH,CAAC;IACD,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAGD,IACI,KAAK,CAAC,KAAU;QAClB,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QAEpB,yDAAyD;QACzD,IAAI,IAAI,CAAC,aAAa,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC;YACzD,IAAI,CAAC,YAAY,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC;YACjC,IAAI,CAAC,eAAe,EAAE,CAAC;QACzB,CAAC;IACH,CAAC;IACD,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAwBD,YACU,WAA+B,EAC/B,OAA8B,EAC9B,GAAsB;QAFtB,gBAAW,GAAX,WAAW,CAAoB;QAC/B,YAAO,GAAP,OAAO,CAAuB;QAC9B,QAAG,GAAH,GAAG,CAAmB;QAxDxB,UAAK,GAAQ,EAAE,CAAC;QAehB,WAAM,GAAQ,EAAE,CAAC;QAgBhB,cAAS,GAAQ,EAAE,CAAC;QAGnB,gBAAW,GAAG,IAAI,YAAY,EAAoB,CAAC;QACnD,mBAAc,GAAG,IAAI,YAAY,EAAuB,CAAC;QACzD,gBAAW,GAAG,IAAI,YAAY,EAAQ,CAAC;QACvC,qBAAgB,GAAG,IAAI,YAAY,EAA6C,CAAC;QAInF,cAAS,GAAQ,IAAI,CAAC;QACtB,sBAAiB,GAAQ,IAAI,CAAC;QAC9B,eAAU,GAAG,IAAI,OAAO,EAAQ,CAAC;QACjC,qBAAgB,GAA8B,IAAI,CAAC;QACnD,iBAAY,GAAQ,EAAE,CAAC;QAC/B,kBAAa,GAAG,KAAK,CAAC;QACd,gBAAW,GAAG,KAAK,CAAC;QACpB,kBAAa,GAAG,KAAK,CAAC;QACtB,iBAAY,GAAG,KAAK,CAAC;QACrB,kBAAa,GAAQ,IAAI,CAAC;QAClC,aAAQ,GAAG,KAAK,CAAC;IAMd,CAAC;IAEJ,KAAK,CAAC,eAAe;QACnB,iDAAiD;QACjD,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QACzB,MAAM,IAAI,CAAC,mBAAmB,EAAE,CAAC;IACnC,CAAC;IAED,WAAW;QACT,kCAAkC;QAClC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QAEzB,6BAA6B;QAC7B,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;QAE3B,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QACvB,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC;QAC3B,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAGD;;OAEG;IACK,KAAK,CAAC,mBAAmB;QAC/B,IAAI,CAAC;YACH,yBAAyB;YACzB,MAAM,IAAI,CAAC,WAAW,CAAC,eAAe,EAAE,CAAC;YAEzC,8DAA8D;YAC9D,MAAM,IAAI,CAAC,WAAW,CAAC,iBAAiB,EAAE,CAAC;YAE3C,+BAA+B;YAC/B,MAAM,IAAI,CAAC,0BAA0B,EAAE,CAAC;YAExC,yBAAyB;YACzB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC;gBACjD,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI;gBAClC,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI;gBAClC,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CAAC,CAAC;YAEH,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACpB,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,IAAI,8BAA8B,CAAC,CAAC;YAC3E,CAAC;YAED,oDAAoD;YACpD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC;YACjD,IAAI,CAAC,iBAAiB,GAAG,MAAM,CAAC,SAAU,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;YAC3E,IAAI,CAAC,YAAY,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;YAEvC,oBAAoB;YACpB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;YAE3E,iBAAiB;YACjB,IAAI,CAAC,eAAe,EAAE,CAAC;YACvB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;YAE1B,oDAAoD;YACpD,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAE3B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;YACrB,QAAQ,CAAC,yCAAyC,KAAK,EAAE,CAAC,CAAC;YAC3D,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC;gBACvB,IAAI,EAAE,OAAO;gBACb,OAAO,EAAE;oBACP,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;oBAC7D,MAAM,EAAE,gBAAgB;iBACzB;aACF,CAAC,CAAC;YACH,+CAA+C;YAC/C,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAC3B,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,0BAA0B;QACtC,sEAAsE;QACtE,MAAM,SAAS,GAAG,IAAI,2BAA2B,CAC/C,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAC1B,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAC1B,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,CACjC,CAAC;QAEF,gCAAgC;QAChC,MAAM,MAAM,GAAgC,MAAM,SAAS,CAAC,iBAAiB,CAC3E,IAAI,CAAC,SAAS,EACd;YACE,MAAM,EAAE,IAAI,CAAC,MAAa,EAAE,8DAA8D;YAC1F,SAAS,EAAE,QAAQ;YACnB,OAAO,EAAE,IAAI;SACd,CACF,CAAC;QAEF,mBAAmB;QACnB,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAC1C,GAAG,CAAC,CAAC,aAAa,KAAK,CAAC,CAAC,KAAK,EAAE,CACjC,CAAC;YACF,MAAM,IAAI,KAAK,CAAC,kCAAkC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChF,CAAC;IACH,CAAC;IAED;;OAEG;IACK,eAAe;QACrB,+CAA+C;QAC/C,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,OAAO;QACT,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,iBAAiB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YAC/C,OAAO;QACT,CAAC;QAED,6BAA6B;QAC7B,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;YAC1B,OAAO;QACT,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,iBAAiB,EAAE,CAAC;QACrD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO;QACT,CAAC;QAED,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;QAE1B,+BAA+B;QAC/B,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAEhF,+CAA+C;QAC/C,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC3B,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;QACjD,CAAC;QAED,sDAAsD;QACtD,MAAM,KAAK,GAAG,mBAAmB,CAC/B,IAAI,CAAC,KAAK,IAAI,EAAE,EAChB,IAAI,CAAC,YAAY,EACjB,IAAI,CAAC,SAAS,IAAI,EAAE,EACpB,IAAI,CAAC,gBAAgB,EACrB,UAAU,EACV,IAAI,CAAC,MAAa,EAAE,gEAAgE;QACpF,EAAE,uBAAuB,EAAE,IAAI,EAAE,CAAC,+BAA+B;SAClE,CAAC;QAEF,wBAAwB;QACxB,MAAM,aAAa,GAAG,mBAAmB,CAAC,KAAK,EAAE;YAC/C,OAAO,EAAE,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC;YACzC,SAAS,EAAE,IAAI;YACf,QAAQ,EAAE,OAAO;SAClB,CAAC,CAAC;QAEH,qCAAqC;QACrC,MAAM,OAAO,GAAG,KAAK,CAAC,aAAa,CACjC,aAAa,EACb,IAAI,EACJ,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,iBAAiB,CAAC,SAAS,EAAE,KAAK,CAAC,CAC7D,CAAC;QAEF,oCAAoC;QACpC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACnC,CAAC;QAED,iCAAiC;QACjC,IAAI,CAAC,aAAa,GAAG,UAAU,CAAC,GAAG,EAAE;YACnC,6CAA6C;YAC7C,IAAI,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;gBAC3C,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC;oBACvB,IAAI,EAAE,OAAO;oBACb,OAAO,EAAE;wBACP,KAAK,EAAE,4DAA4D;wBACnE,MAAM,EAAE,QAAQ;qBACjB;iBACF,CAAC,CAAC;YACL,CAAC;QACH,CAAC,EAAE,IAAI,CAAC,CAAC;QAET,IAAI,CAAC;YACH,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAC/B,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACjC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;YAE1B,oEAAoE;YACpE,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;gBAC1B,+CAA+C;gBAC/C,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;oBACtB,OAAO;gBACT,CAAC;gBAED,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;gBAEzB,wDAAwD;gBACxD,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;oBACvB,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;oBAC3B,IAAI,CAAC,eAAe,EAAE,CAAC;gBACzB,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACjC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;YAC1B,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;YACzB,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAED;;OAEG;IACK,eAAe;QACrB,OAAO;YACL,WAAW,EAAE,GAAG,EAAE;gBAChB,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;YAC1B,CAAC;YACD,gBAAgB,EAAE,CAAC,UAAkB,EAAE,GAAiB,EAAE,EAAE;gBAC1D,IAAI,QAAQ,GAAwB,IAAI,CAAC;gBACzC,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;oBACzB,QAAQ,GAAG,YAAY,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;gBACjD,CAAC;qBACI,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC,mBAAmB,EAAE,CAAC;oBAC9D,QAAQ,GAAG,GAAmB,CAAC;gBACjC,CAAC;qBACI,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;oBACjC,wCAAwC;oBACxC,oEAAoE;oBACpE,iCAAiC;oBACjC,MAAM,MAAM,GAAG,GAAU,CAAC;oBAC1B,IAAI,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;wBACrC,QAAQ,GAAG,YAAY,CAAC,iBAAiB,CAAC,CAAC,MAAsB,CAAC,CAAC,CAAC;oBACtE,CAAC;gBACH,CAAC;gBACD,IAAI,QAAQ,EAAE,CAAC;oBACb,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;gBAC5D,CAAC;YACH,CAAC;YACD,eAAe,EAAE,CAAC,SAAc,EAAE,EAAE;gBAClC,kDAAkD;gBAClD,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;oBAC1C,OAAO;gBACT,CAAC;gBAED,2CAA2C;gBAC3C,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;oBACnD,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;oBAC5C,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;oBAChC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;gBAC/C,CAAC,CAAC,CAAC;gBAEH,IAAI,CAAC,UAAU,EAAE,CAAC;oBAChB,0DAA0D;oBAC1D,OAAO;gBACT,CAAC;gBAED,IAAI,CAAC,YAAY,GAAG;oBAClB,GAAG,IAAI,CAAC,YAAY;oBACpB,GAAG,SAAS;iBACb,CAAC;gBAEF,+CAA+C;gBAC/C,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;oBACpC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBAC1D,CAAC,CAAC,CAAC;gBAEH,qBAAqB;gBACrB,IAAI,CAAC,eAAe,EAAE,CAAC;YACzB,CAAC;YACD,WAAW,EAAE,CAAC,KAAa,EAAE,IAAS,EAAE,EAAE;gBACxC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YAC3D,CAAC;SACF,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,gBAAgB,CAAC,KAAU,EAAE,SAAe;QAClD,QAAQ,CAAC,0BAA0B,KAAK,EAAE,QAAQ,EAAE,IAAI,eAAe,EAAE,EAAE,SAAS,CAAC,CAAC;QACtF,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC;YACvB,IAAI,EAAE,OAAO;YACb,OAAO,EAAE;gBACP,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,eAAe;gBAC3C,SAAS;gBACT,MAAM,EAAE,OAAO;aAChB;SACF,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACK,OAAO;QACb,mCAAmC;QACnC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACjC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC5B,CAAC;QAED,sCAAsC;QACtC,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC1B,kBAAkB,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YAC1C,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC/B,CAAC;QAED,qDAAqD;QACrD,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,4DAA4D;YAC5D,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;gBACrB,uBAAuB;gBACvB,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;gBACzB,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;YAC7B,CAAC;YAED,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC7C,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACxB,CAAC;QAED,mBAAmB;QACnB,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAC9B,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;QACvB,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;QAE3B,2BAA2B;QAC3B,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,OAAO,EAAE,CAAC;IACvC,CAAC;IAED;;;OAGG;IACH,OAAO,CAAC,OAAa;QACnB,IAAI,OAAO,EAAE,CAAC;YACZ,6CAA6C;YAC7C,IAAI,CAAC,IAAI,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,GAAG,OAAO,EAAE,CAAC;QAC5C,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,eAAe,EAAE,CAAC;QACzB,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,WAAW,CAAC,IAAY,EAAE,KAAU;QAClC,IAAI,CAAC,YAAY,GAAG;YAClB,GAAG,IAAI,CAAC,YAAY;YACpB,CAAC,IAAI,CAAC,EAAE,KAAK;SACd,CAAC;QACF,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACvC,IAAI,CAAC,eAAe,EAAE,CAAC;IACzB,CAAC;IAED;;OAEG;IACK,OAAO,CAAC,CAAM,EAAE,CAAM;QAC5B,8BAA8B;QAC9B,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QACzB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI;YAAE,OAAO,KAAK,CAAC;QAEzC,0CAA0C;QAC1C,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;YACnD,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QACjD,CAAC;QAED,OAAO,CAAC,KAAK,CAAC,CAAC;IACjB,CAAC;iFAjbU,gBAAgB;oEAAhB,gBAAgB;mCA0CK,UAAU;;;;;YApGxC,8BAAqC;YACnC,4BAAyF;YACzF,yEAAmC;YAQrC,iBAAM;;YAT8C,cAAgC;YAAhC,6CAAgC;YAClF,eAOC;YAPD,8DAOC;;;iFAiDM,gBAAgB;cA7D5B,SAAS;2BACE,oBAAoB,YACpB;;;;;;;;;;;;GAYT,mBA6CgB,uBAAuB,CAAC,MAAM;uHAGtC,SAAS;kBAAjB,KAAK;YAIF,IAAI;kBADP,KAAK;YAgBF,KAAK;kBADR,KAAK;YAeG,SAAS;kBAAjB,KAAK;YACG,MAAM;kBAAd,KAAK;YAEI,WAAW;kBAApB,MAAM;YACG,cAAc;kBAAvB,MAAM;YACG,WAAW;kBAApB,MAAM;YACG,gBAAgB;kBAAzB,MAAM;YAEqD,SAAS;kBAApE,SAAS;mBAAC,WAAW,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE;;kFA1C/C,gBAAgB","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}"]}
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 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 * User settings changed event emitted when component saves user preferences\n */\nexport interface UserSettingsChangedEvent {\n settings: Record<string, any>;\n componentName?: string;\n timestamp: Date;\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 private _savedUserSettings: any = {};\n @Input()\n set savedUserSettings(value: any) {\n this._savedUserSettings = value || {};\n // Re-render if component is initialized\n if (this.isInitialized) {\n this.renderComponent();\n }\n }\n get savedUserSettings(): any {\n return this._savedUserSettings;\n }\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 @Output() userSettingsChanged = new EventEmitter<UserSettingsChangedEvent>();\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 with savedUserSettings pattern\n const props = {\n ...this._data, // Spread data properties directly\n utilities: this.utilities || {},\n callbacks: this.currentCallbacks,\n components,\n styles: this.styles as any,\n savedUserSettings: this._savedUserSettings,\n onSaveUserSettings: this.handleSaveUserSettings.bind(this)\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 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 };\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 * Handle onSaveUserSettings from components\n * This implements the SavedUserSettings pattern\n */\n private handleSaveUserSettings(newSettings: Record<string, any>) {\n // Check if there are actual changes\n const hasChanges = !this.isEqual(this._savedUserSettings, newSettings);\n \n if (!hasChanges) {\n // No actual changes, skip update to prevent infinite loop\n return;\n }\n \n // Update saved settings\n this._savedUserSettings = { ...newSettings };\n \n // Emit user settings changed event\n this.userSettingsChanged.emit({\n settings: this._savedUserSettings,\n componentName: this.component?.name,\n timestamp: new Date()\n });\n \n // Schedule re-render\n this.renderComponent();\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 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,4 +1,4 @@
1
- import { ComponentCompiler, ComponentRegistry, ComponentResolver, CompileOptions, RuntimeContext } from '@memberjunction/react-runtime';
1
+ import { ComponentCompiler, ComponentRegistry, ComponentResolver, CompileOptions, RuntimeContext, ExternalLibraryConfig, LibraryConfiguration } from '@memberjunction/react-runtime';
2
2
  import { ScriptLoaderService } from './script-loader.service';
3
3
  import * as i0 from "@angular/core";
4
4
  /**
@@ -12,9 +12,11 @@ export declare class AngularAdapterService {
12
12
  constructor(scriptLoader: ScriptLoaderService);
13
13
  /**
14
14
  * Initialize the React runtime with Angular-specific configuration
15
+ * @param config Optional library configuration
16
+ * @param additionalLibraries Optional additional libraries to merge
15
17
  * @returns Promise resolving when runtime is ready
16
18
  */
17
- initialize(): Promise<void>;
19
+ initialize(config?: LibraryConfiguration, additionalLibraries?: ExternalLibraryConfig[]): Promise<void>;
18
20
  /**
19
21
  * Get the component compiler
20
22
  * @returns Component compiler instance
@@ -19,14 +19,16 @@ export class AngularAdapterService {
19
19
  }
20
20
  /**
21
21
  * Initialize the React runtime with Angular-specific configuration
22
+ * @param config Optional library configuration
23
+ * @param additionalLibraries Optional additional libraries to merge
22
24
  * @returns Promise resolving when runtime is ready
23
25
  */
24
- async initialize() {
26
+ async initialize(config, additionalLibraries) {
25
27
  if (this.runtime) {
26
28
  return; // Already initialized
27
29
  }
28
- // Load React ecosystem
29
- const ecosystem = await this.scriptLoader.loadReactEcosystem();
30
+ // Load React ecosystem with optional additional libraries
31
+ const ecosystem = await this.scriptLoader.loadReactEcosystem(config, additionalLibraries);
30
32
  // Create runtime context
31
33
  this.runtimeContext = {
32
34
  React: ecosystem.React,
@@ -111,6 +113,24 @@ export class AngularAdapterService {
111
113
  * @returns Promise resolving to compilation result
112
114
  */
113
115
  async compileComponent(options) {
116
+ // Validate options before initialization
117
+ if (!options) {
118
+ throw new Error('Angular adapter error: No compilation options provided.\n' +
119
+ 'This usually means the component spec is null or undefined.\n' +
120
+ 'Please check that:\n' +
121
+ '1. Your component data is loaded properly\n' +
122
+ '2. The component spec has "name" and "code" properties\n' +
123
+ '3. The component input is not undefined');
124
+ }
125
+ if (!options.componentName || options.componentName.trim() === '') {
126
+ throw new Error('Angular adapter error: Component name is missing or empty.\n' +
127
+ `Received options: ${JSON.stringify(options, null, 2)}\n` +
128
+ 'Make sure your component spec includes a "name" property.');
129
+ }
130
+ if (!options.componentCode || options.componentCode.trim() === '') {
131
+ throw new Error(`Angular adapter error: Component code is missing or empty for component "${options.componentName}".\n` +
132
+ 'Make sure your component spec includes a "code" property with the React component source.');
133
+ }
114
134
  await this.initialize();
115
135
  // Apply default styles if not provided
116
136
  const optionsWithDefaults = {
@@ -1 +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}"]}
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 ExternalLibraryConfig,\n LibraryConfiguration\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 * @param config Optional library configuration\n * @param additionalLibraries Optional additional libraries to merge\n * @returns Promise resolving when runtime is ready\n */\n async initialize(\n config?: LibraryConfiguration,\n additionalLibraries?: ExternalLibraryConfig[]\n ): Promise<void> {\n if (this.runtime) {\n return; // Already initialized\n }\n\n // Load React ecosystem with optional additional libraries\n const ecosystem = await this.scriptLoader.loadReactEcosystem(config, additionalLibraries);\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 // Validate options before initialization\n if (!options) {\n throw new Error(\n 'Angular adapter error: No compilation options provided.\\n' +\n 'This usually means the component spec is null or undefined.\\n' +\n 'Please check that:\\n' +\n '1. Your component data is loaded properly\\n' +\n '2. The component spec has \"name\" and \"code\" properties\\n' +\n '3. The component input is not undefined'\n );\n }\n\n if (!options.componentName || options.componentName.trim() === '') {\n throw new Error(\n 'Angular adapter error: Component name is missing or empty.\\n' +\n `Received options: ${JSON.stringify(options, null, 2)}\\n` +\n 'Make sure your component spec includes a \"name\" property.'\n );\n }\n\n if (!options.componentCode || options.componentCode.trim() === '') {\n throw new Error(\n `Angular adapter error: Component code is missing or empty for component \"${options.componentName}\".\\n` +\n 'Make sure your component spec includes a \"code\" property with the React component source.'\n );\n }\n\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}"]}
@@ -4,7 +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
+ import { LibraryConfiguration, ExternalLibraryConfig } from '@memberjunction/react-runtime';
8
8
  import * as i0 from "@angular/core";
9
9
  /**
10
10
  * Service for loading external scripts and CSS with proper cleanup.
@@ -39,9 +39,10 @@ export declare class ScriptLoaderService implements OnDestroy {
39
39
  /**
40
40
  * Load common React libraries and UI frameworks
41
41
  * @param config Optional library configuration
42
+ * @param additionalLibraries Optional additional libraries to merge
42
43
  * @returns Promise resolving to React ecosystem objects
43
44
  */
44
- loadReactEcosystem(config?: LibraryConfiguration): Promise<{
45
+ loadReactEcosystem(config?: LibraryConfiguration, additionalLibraries?: ExternalLibraryConfig[]): Promise<{
45
46
  React: any;
46
47
  ReactDOM: any;
47
48
  Babel: any;
@@ -92,11 +92,12 @@ export class ScriptLoaderService {
92
92
  /**
93
93
  * Load common React libraries and UI frameworks
94
94
  * @param config Optional library configuration
95
+ * @param additionalLibraries Optional additional libraries to merge
95
96
  * @returns Promise resolving to React ecosystem objects
96
97
  */
97
- async loadReactEcosystem(config) {
98
+ async loadReactEcosystem(config, additionalLibraries) {
98
99
  // Use the new LibraryLoader from react-runtime for consistency
99
- const result = await LibraryLoader.loadAllLibraries(config);
100
+ const result = await LibraryLoader.loadAllLibraries(config, additionalLibraries);
100
101
  // The LibraryLoader handles all the loading, but we need to ensure
101
102
  // ReactDOM.createRoot is available for Angular's specific needs
102
103
  // 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 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}"]}
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 ExternalLibraryConfig\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 * @param additionalLibraries Optional additional libraries to merge\n * @returns Promise resolving to React ecosystem objects\n */\n async loadReactEcosystem(\n config?: LibraryConfiguration,\n additionalLibraries?: ExternalLibraryConfig[]\n ): 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, additionalLibraries);\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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-react",
3
- "version": "2.75.0",
3
+ "version": "2.76.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.75.0",
44
- "@memberjunction/react-runtime": "2.75.0",
45
- "@memberjunction/interactive-component-types": "^2.75.0",
43
+ "@memberjunction/core": "2.76.0",
44
+ "@memberjunction/react-runtime": "2.76.0",
45
+ "@memberjunction/interactive-component-types": "^2.76.0",
46
46
  "@angular/common": ">=18.0.0",
47
47
  "@angular/core": ">=18.0.0",
48
48
  "@angular/platform-browser": ">=18.0.0",