@memberjunction/ng-skip-chat 2.44.0 → 2.46.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/dist/lib/artifacts/skip-artifact-viewer.component.d.ts +33 -1
- package/dist/lib/artifacts/skip-artifact-viewer.component.d.ts.map +1 -1
- package/dist/lib/artifacts/skip-artifact-viewer.component.js +82 -86
- package/dist/lib/artifacts/skip-artifact-viewer.component.js.map +1 -1
- package/dist/lib/dynamic-report/base-report.d.ts.map +1 -1
- package/dist/lib/dynamic-report/base-report.js +2 -1
- package/dist/lib/dynamic-report/base-report.js.map +1 -1
- package/dist/lib/dynamic-report/dynamic-chart.d.ts.map +1 -1
- package/dist/lib/dynamic-report/dynamic-chart.js +5 -2
- package/dist/lib/dynamic-report/dynamic-chart.js.map +1 -1
- package/dist/lib/dynamic-report/dynamic-grid.d.ts.map +1 -1
- package/dist/lib/dynamic-report/dynamic-grid.js +6 -3
- package/dist/lib/dynamic-report/dynamic-grid.js.map +1 -1
- package/dist/lib/dynamic-report/dynamic-html-report.d.ts +90 -11
- package/dist/lib/dynamic-report/dynamic-html-report.d.ts.map +1 -1
- package/dist/lib/dynamic-report/dynamic-html-report.js +1023 -163
- package/dist/lib/dynamic-report/dynamic-html-report.js.map +1 -1
- package/dist/lib/dynamic-report/linear-report.d.ts +4 -0
- package/dist/lib/dynamic-report/linear-report.d.ts.map +1 -1
- package/dist/lib/dynamic-report/linear-report.js +78 -75
- package/dist/lib/dynamic-report/linear-report.js.map +1 -1
- package/dist/lib/dynamic-report/skip-react-component-host.d.ts +128 -0
- package/dist/lib/dynamic-report/skip-react-component-host.d.ts.map +1 -0
- package/dist/lib/dynamic-report/skip-react-component-host.js +677 -0
- package/dist/lib/dynamic-report/skip-react-component-host.js.map +1 -0
- package/dist/lib/skip-chat/skip-chat.component.d.ts +67 -1
- package/dist/lib/skip-chat/skip-chat.component.d.ts.map +1 -1
- package/dist/lib/skip-chat/skip-chat.component.js +321 -65
- package/dist/lib/skip-chat/skip-chat.component.js.map +1 -1
- package/dist/lib/split-panel/skip-split-panel.component.d.ts +18 -1
- package/dist/lib/split-panel/skip-split-panel.component.d.ts.map +1 -1
- package/dist/lib/split-panel/skip-split-panel.component.js +135 -8
- package/dist/lib/split-panel/skip-split-panel.component.js.map +1 -1
- package/package.json +17 -13
|
@@ -0,0 +1,677 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { LogError } from '@memberjunction/core';
|
|
11
|
+
/**
|
|
12
|
+
* CDN URLs for external dependencies
|
|
13
|
+
* These can be configured via environment variables in the future
|
|
14
|
+
*/
|
|
15
|
+
const CDN_URLS = {
|
|
16
|
+
// Core React dependencies
|
|
17
|
+
BABEL_STANDALONE: 'https://unpkg.com/@babel/standalone@7/babel.min.js',
|
|
18
|
+
REACT: 'https://unpkg.com/react@18/umd/react.development.js',
|
|
19
|
+
REACT_DOM: 'https://unpkg.com/react-dom@18/umd/react-dom.development.js',
|
|
20
|
+
// Ant Design dependencies
|
|
21
|
+
DAYJS: 'https://unpkg.com/dayjs@1.11.10/dayjs.min.js',
|
|
22
|
+
// UI Libraries - Using UMD builds that work with global React
|
|
23
|
+
ANTD_JS: 'https://unpkg.com/antd@5.12.8/dist/antd.js',
|
|
24
|
+
ANTD_CSS: 'https://unpkg.com/antd@5.12.8/dist/reset.css',
|
|
25
|
+
REACT_BOOTSTRAP_JS: 'https://unpkg.com/react-bootstrap@2.9.1/dist/react-bootstrap.js',
|
|
26
|
+
BOOTSTRAP_CSS: 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css',
|
|
27
|
+
// Data Visualization
|
|
28
|
+
D3_JS: 'https://cdnjs.cloudflare.com/ajax/libs/d3/7.8.5/d3.min.js',
|
|
29
|
+
CHART_JS: 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.0/chart.umd.js',
|
|
30
|
+
// Utilities
|
|
31
|
+
LODASH_JS: 'https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js'
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Default styles that match the Skip design system
|
|
35
|
+
*/
|
|
36
|
+
const DEFAULT_STYLES = {
|
|
37
|
+
colors: {
|
|
38
|
+
// Primary colors - modern purple/blue gradient feel
|
|
39
|
+
primary: '#5B4FE9',
|
|
40
|
+
primaryHover: '#4940D4',
|
|
41
|
+
primaryLight: '#E8E6FF',
|
|
42
|
+
// Secondary colors - sophisticated gray
|
|
43
|
+
secondary: '#64748B',
|
|
44
|
+
secondaryHover: '#475569',
|
|
45
|
+
// Status colors
|
|
46
|
+
success: '#10B981',
|
|
47
|
+
successLight: '#D1FAE5',
|
|
48
|
+
warning: '#F59E0B',
|
|
49
|
+
warningLight: '#FEF3C7',
|
|
50
|
+
error: '#EF4444',
|
|
51
|
+
errorLight: '#FEE2E2',
|
|
52
|
+
info: '#3B82F6',
|
|
53
|
+
infoLight: '#DBEAFE',
|
|
54
|
+
// Base colors
|
|
55
|
+
background: '#FFFFFF',
|
|
56
|
+
surface: '#F8FAFC',
|
|
57
|
+
surfaceHover: '#F1F5F9',
|
|
58
|
+
// Text colors with better contrast
|
|
59
|
+
text: '#1E293B',
|
|
60
|
+
textSecondary: '#64748B',
|
|
61
|
+
textTertiary: '#94A3B8',
|
|
62
|
+
textInverse: '#FFFFFF',
|
|
63
|
+
// Border colors
|
|
64
|
+
border: '#E2E8F0',
|
|
65
|
+
borderLight: '#F1F5F9',
|
|
66
|
+
borderFocus: '#5B4FE9',
|
|
67
|
+
// Shadows (as color strings for easy use)
|
|
68
|
+
shadow: 'rgba(0, 0, 0, 0.05)',
|
|
69
|
+
shadowMedium: 'rgba(0, 0, 0, 0.1)',
|
|
70
|
+
shadowLarge: 'rgba(0, 0, 0, 0.15)',
|
|
71
|
+
},
|
|
72
|
+
spacing: {
|
|
73
|
+
xs: '4px',
|
|
74
|
+
sm: '8px',
|
|
75
|
+
md: '16px',
|
|
76
|
+
lg: '24px',
|
|
77
|
+
xl: '32px',
|
|
78
|
+
xxl: '48px',
|
|
79
|
+
xxxl: '64px',
|
|
80
|
+
},
|
|
81
|
+
typography: {
|
|
82
|
+
fontFamily: '-apple-system, BlinkMacSystemFont, "Inter", "Segoe UI", Roboto, sans-serif',
|
|
83
|
+
fontSize: {
|
|
84
|
+
xs: '11px',
|
|
85
|
+
sm: '12px',
|
|
86
|
+
md: '14px',
|
|
87
|
+
lg: '16px',
|
|
88
|
+
xl: '20px',
|
|
89
|
+
xxl: '24px',
|
|
90
|
+
xxxl: '32px',
|
|
91
|
+
},
|
|
92
|
+
fontWeight: {
|
|
93
|
+
light: '300',
|
|
94
|
+
regular: '400',
|
|
95
|
+
medium: '500',
|
|
96
|
+
semibold: '600',
|
|
97
|
+
bold: '700',
|
|
98
|
+
},
|
|
99
|
+
lineHeight: {
|
|
100
|
+
tight: '1.25',
|
|
101
|
+
normal: '1.5',
|
|
102
|
+
relaxed: '1.75',
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
borders: {
|
|
106
|
+
radius: {
|
|
107
|
+
sm: '6px',
|
|
108
|
+
md: '8px',
|
|
109
|
+
lg: '12px',
|
|
110
|
+
xl: '16px',
|
|
111
|
+
full: '9999px',
|
|
112
|
+
},
|
|
113
|
+
width: {
|
|
114
|
+
thin: '1px',
|
|
115
|
+
medium: '2px',
|
|
116
|
+
thick: '3px',
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
shadows: {
|
|
120
|
+
sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
|
|
121
|
+
md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
|
|
122
|
+
lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
|
|
123
|
+
xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
|
|
124
|
+
inner: 'inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)',
|
|
125
|
+
},
|
|
126
|
+
transitions: {
|
|
127
|
+
fast: '150ms ease-in-out',
|
|
128
|
+
normal: '250ms ease-in-out',
|
|
129
|
+
slow: '350ms ease-in-out',
|
|
130
|
+
},
|
|
131
|
+
overflow: 'auto'
|
|
132
|
+
};
|
|
133
|
+
/**
|
|
134
|
+
* Host class for integrating Skip-generated React components into Angular applications.
|
|
135
|
+
* This class handles the lifecycle management, state synchronization, and communication
|
|
136
|
+
* between React components and their Angular host containers.
|
|
137
|
+
*/
|
|
138
|
+
export class SkipReactComponentHost {
|
|
139
|
+
constructor(config) {
|
|
140
|
+
this.config = config;
|
|
141
|
+
this.componentResult = null;
|
|
142
|
+
this.reactRoot = null;
|
|
143
|
+
this.componentContainer = null;
|
|
144
|
+
this.destroyed = false;
|
|
145
|
+
this.currentState = {};
|
|
146
|
+
this.loadReactLibraries();
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Load React and ReactDOM dynamically
|
|
150
|
+
*/
|
|
151
|
+
loadReactLibraries() {
|
|
152
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
153
|
+
// Check if React is already loaded globally
|
|
154
|
+
if (window.React && window.ReactDOM) {
|
|
155
|
+
this.React = window.React;
|
|
156
|
+
this.ReactDOM = window.ReactDOM;
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
// Load React from CDN to ensure it's available globally for other libraries
|
|
160
|
+
try {
|
|
161
|
+
// Load React first
|
|
162
|
+
yield this.loadScriptFromCDN(CDN_URLS.REACT, 'React');
|
|
163
|
+
// Then load ReactDOM (it depends on React being available)
|
|
164
|
+
yield this.loadScriptFromCDN(CDN_URLS.REACT_DOM, 'ReactDOM');
|
|
165
|
+
this.React = window.React;
|
|
166
|
+
this.ReactDOM = window.ReactDOM;
|
|
167
|
+
// Verify they loaded correctly
|
|
168
|
+
if (!this.React || !this.ReactDOM) {
|
|
169
|
+
throw new Error('React and ReactDOM failed to load from CDN');
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
// Try ES modules as fallback
|
|
174
|
+
try {
|
|
175
|
+
const [ReactModule, ReactDOMModule] = yield Promise.all([
|
|
176
|
+
import('react'),
|
|
177
|
+
import('react-dom/client')
|
|
178
|
+
]);
|
|
179
|
+
this.React = ReactModule;
|
|
180
|
+
this.ReactDOM = ReactDOMModule;
|
|
181
|
+
// Also set them globally for other libraries
|
|
182
|
+
window.React = ReactModule;
|
|
183
|
+
window.ReactDOM = ReactDOMModule;
|
|
184
|
+
}
|
|
185
|
+
catch (moduleError) {
|
|
186
|
+
throw new Error('Failed to load React and ReactDOM from any source');
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Generic method to load a script from CDN
|
|
193
|
+
*/
|
|
194
|
+
loadScriptFromCDN(url, globalName) {
|
|
195
|
+
return new Promise((resolve, reject) => {
|
|
196
|
+
// Check if already loaded
|
|
197
|
+
if (window[globalName]) {
|
|
198
|
+
resolve(window[globalName]);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
// Check if script is already in DOM
|
|
202
|
+
const existingScript = document.querySelector(`script[src="${url}"]`);
|
|
203
|
+
if (existingScript) {
|
|
204
|
+
// Wait for it to load
|
|
205
|
+
existingScript.addEventListener('load', () => {
|
|
206
|
+
if (window[globalName]) {
|
|
207
|
+
resolve(window[globalName]);
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
reject(new Error(`${globalName} not found after script load`));
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
// Load new script
|
|
216
|
+
const script = document.createElement('script');
|
|
217
|
+
script.src = url;
|
|
218
|
+
script.onload = () => {
|
|
219
|
+
if (window[globalName]) {
|
|
220
|
+
resolve(window[globalName]);
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
reject(new Error(`${globalName} not found after script load`));
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
script.onerror = () => reject(new Error(`Failed to load script: ${url}`));
|
|
227
|
+
document.head.appendChild(script);
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Load Babel standalone for JSX transpilation
|
|
232
|
+
*/
|
|
233
|
+
loadBabel() {
|
|
234
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
235
|
+
return this.loadScriptFromCDN(CDN_URLS.BABEL_STANDALONE, 'Babel');
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Load a CSS file from CDN
|
|
240
|
+
*/
|
|
241
|
+
loadCSS(url) {
|
|
242
|
+
// Check if CSS is already loaded
|
|
243
|
+
const existingLink = document.querySelector(`link[href="${url}"]`);
|
|
244
|
+
if (existingLink) {
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
const link = document.createElement('link');
|
|
248
|
+
link.rel = 'stylesheet';
|
|
249
|
+
link.href = url;
|
|
250
|
+
document.head.appendChild(link);
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Load a script from CDN with promise
|
|
254
|
+
*/
|
|
255
|
+
loadScript(url, globalName) {
|
|
256
|
+
return this.loadScriptFromCDN(url, globalName);
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Load common UI and utility libraries
|
|
260
|
+
*/
|
|
261
|
+
loadCommonLibraries() {
|
|
262
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
263
|
+
// If already cached, return immediately
|
|
264
|
+
if (SkipReactComponentHost.cachedLibraries) {
|
|
265
|
+
return SkipReactComponentHost.cachedLibraries;
|
|
266
|
+
}
|
|
267
|
+
// If currently loading, wait for the existing promise
|
|
268
|
+
if (SkipReactComponentHost.libraryLoadPromise) {
|
|
269
|
+
return SkipReactComponentHost.libraryLoadPromise;
|
|
270
|
+
}
|
|
271
|
+
// Start loading libraries
|
|
272
|
+
SkipReactComponentHost.libraryLoadPromise = this.doLoadLibraries();
|
|
273
|
+
try {
|
|
274
|
+
SkipReactComponentHost.cachedLibraries = yield SkipReactComponentHost.libraryLoadPromise;
|
|
275
|
+
return SkipReactComponentHost.cachedLibraries;
|
|
276
|
+
}
|
|
277
|
+
finally {
|
|
278
|
+
SkipReactComponentHost.libraryLoadPromise = null;
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Actually load the libraries
|
|
284
|
+
*/
|
|
285
|
+
doLoadLibraries() {
|
|
286
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
287
|
+
// Load CSS files first (these don't need to be awaited)
|
|
288
|
+
this.loadCSS(CDN_URLS.ANTD_CSS);
|
|
289
|
+
this.loadCSS(CDN_URLS.BOOTSTRAP_CSS);
|
|
290
|
+
// Load base dependencies first
|
|
291
|
+
const [dayjs, _, d3, Chart] = yield Promise.all([
|
|
292
|
+
this.loadScript(CDN_URLS.DAYJS, 'dayjs'),
|
|
293
|
+
this.loadScript(CDN_URLS.LODASH_JS, '_'),
|
|
294
|
+
this.loadScript(CDN_URLS.D3_JS, 'd3'),
|
|
295
|
+
this.loadScript(CDN_URLS.CHART_JS, 'Chart')
|
|
296
|
+
]);
|
|
297
|
+
// Then load UI libraries that depend on React
|
|
298
|
+
const [antd, ReactBootstrap] = yield Promise.all([
|
|
299
|
+
this.loadScript(CDN_URLS.ANTD_JS, 'antd'),
|
|
300
|
+
this.loadScript(CDN_URLS.REACT_BOOTSTRAP_JS, 'ReactBootstrap')
|
|
301
|
+
]);
|
|
302
|
+
return {
|
|
303
|
+
antd,
|
|
304
|
+
ReactBootstrap,
|
|
305
|
+
d3,
|
|
306
|
+
Chart,
|
|
307
|
+
_,
|
|
308
|
+
dayjs
|
|
309
|
+
};
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Initialize the React component
|
|
314
|
+
*/
|
|
315
|
+
initialize() {
|
|
316
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
317
|
+
var _a, _b, _c, _d, _e;
|
|
318
|
+
try {
|
|
319
|
+
// First load React to ensure it's available globally
|
|
320
|
+
yield this.loadReactLibraries();
|
|
321
|
+
// Then load Babel and common libraries in parallel
|
|
322
|
+
const [Babel, libraries] = yield Promise.all([
|
|
323
|
+
this.loadBabel(),
|
|
324
|
+
this.loadCommonLibraries()
|
|
325
|
+
]);
|
|
326
|
+
// Create utility functions
|
|
327
|
+
const createStateUpdater = this.createStateUpdaterFunction();
|
|
328
|
+
const createStandardEventHandler = this.createStandardEventHandlerFunction();
|
|
329
|
+
// Get or create the style system
|
|
330
|
+
const styles = this.getOrCreateStyleSystem();
|
|
331
|
+
// Transpile the JSX code to JavaScript
|
|
332
|
+
let transpiledCode;
|
|
333
|
+
try {
|
|
334
|
+
const result = Babel.transform(this.config.componentCode, {
|
|
335
|
+
presets: ['react'],
|
|
336
|
+
filename: 'component.jsx'
|
|
337
|
+
});
|
|
338
|
+
transpiledCode = result.code;
|
|
339
|
+
}
|
|
340
|
+
catch (transpileError) {
|
|
341
|
+
LogError(`Failed to transpile JSX: ${transpileError}`);
|
|
342
|
+
if ((_a = this.config.callbacks) === null || _a === void 0 ? void 0 : _a.NotifyEvent) {
|
|
343
|
+
this.config.callbacks.NotifyEvent('componentError', {
|
|
344
|
+
error: `JSX transpilation failed: ${transpileError}`,
|
|
345
|
+
source: 'JSX Transpilation'
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
throw new Error(`JSX transpilation failed: ${transpileError}`);
|
|
349
|
+
}
|
|
350
|
+
// Create the component factory function from the transpiled code
|
|
351
|
+
// Always pass all libraries - unused ones will just be undefined in older components
|
|
352
|
+
let createComponent;
|
|
353
|
+
try {
|
|
354
|
+
createComponent = new Function('React', 'styles', 'console', 'antd', 'ReactBootstrap', 'd3', 'Chart', '_', 'dayjs', `${transpiledCode}; return createComponent;`)(this.React, styles, console, libraries.antd, libraries.ReactBootstrap, libraries.d3, libraries.Chart, libraries._, libraries.dayjs);
|
|
355
|
+
}
|
|
356
|
+
catch (evalError) {
|
|
357
|
+
LogError(`Failed to evaluate component code: ${evalError}`);
|
|
358
|
+
console.error('Component code evaluation error:', evalError);
|
|
359
|
+
console.error('Transpiled code:', transpiledCode);
|
|
360
|
+
if ((_b = this.config.callbacks) === null || _b === void 0 ? void 0 : _b.NotifyEvent) {
|
|
361
|
+
this.config.callbacks.NotifyEvent('componentError', {
|
|
362
|
+
error: `Component code evaluation failed: ${evalError}`,
|
|
363
|
+
source: 'Code Evaluation'
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
throw new Error(`Component code evaluation failed: ${evalError}`);
|
|
367
|
+
}
|
|
368
|
+
// Debug: Check if React hooks are available
|
|
369
|
+
if (!this.React.useState) {
|
|
370
|
+
console.error('React.useState is not available. React object:', this.React);
|
|
371
|
+
if ((_c = this.config.callbacks) === null || _c === void 0 ? void 0 : _c.NotifyEvent) {
|
|
372
|
+
this.config.callbacks.NotifyEvent('componentError', {
|
|
373
|
+
error: 'React hooks are not available. Make sure React is loaded correctly.',
|
|
374
|
+
source: 'React Initialization'
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
throw new Error('React hooks are not available. Make sure React is loaded correctly.');
|
|
378
|
+
}
|
|
379
|
+
// Call createComponent with all parameters - older components will just ignore the extra libraries parameter
|
|
380
|
+
try {
|
|
381
|
+
this.componentResult = createComponent(this.React, this.ReactDOM, this.React.useState, this.React.useEffect, this.React.useCallback, createStateUpdater, createStandardEventHandler, libraries);
|
|
382
|
+
}
|
|
383
|
+
catch (factoryError) {
|
|
384
|
+
LogError(`Component factory failed: ${factoryError}`);
|
|
385
|
+
if ((_d = this.config.callbacks) === null || _d === void 0 ? void 0 : _d.NotifyEvent) {
|
|
386
|
+
this.config.callbacks.NotifyEvent('componentError', {
|
|
387
|
+
error: `Component factory failed: ${factoryError}`,
|
|
388
|
+
source: 'Component Factory'
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
throw factoryError;
|
|
392
|
+
}
|
|
393
|
+
// Create container if it doesn't exist
|
|
394
|
+
if (!this.componentContainer) {
|
|
395
|
+
this.componentContainer = document.createElement('div');
|
|
396
|
+
this.componentContainer.className = 'react-component-container';
|
|
397
|
+
this.componentContainer.style.width = '100%';
|
|
398
|
+
this.componentContainer.style.height = '100%';
|
|
399
|
+
this.config.container.appendChild(this.componentContainer);
|
|
400
|
+
}
|
|
401
|
+
// Store initial state
|
|
402
|
+
this.currentState = this.config.initialState || {};
|
|
403
|
+
// Render the component
|
|
404
|
+
this.render();
|
|
405
|
+
}
|
|
406
|
+
catch (error) {
|
|
407
|
+
LogError(error);
|
|
408
|
+
if ((_e = this.config.callbacks) === null || _e === void 0 ? void 0 : _e.NotifyEvent) {
|
|
409
|
+
this.config.callbacks.NotifyEvent('componentError', {
|
|
410
|
+
error: String(error),
|
|
411
|
+
source: 'Component Initialization'
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Create an error boundary component
|
|
419
|
+
*/
|
|
420
|
+
createErrorBoundary() {
|
|
421
|
+
const React = this.React;
|
|
422
|
+
class ErrorBoundary extends React.Component {
|
|
423
|
+
constructor(props) {
|
|
424
|
+
super(props);
|
|
425
|
+
this.state = {
|
|
426
|
+
hasError: false,
|
|
427
|
+
error: null,
|
|
428
|
+
errorInfo: null
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
static getDerivedStateFromError(_error) {
|
|
432
|
+
return { hasError: true };
|
|
433
|
+
}
|
|
434
|
+
componentDidCatch(error, errorInfo) {
|
|
435
|
+
var _a, _b;
|
|
436
|
+
console.error('React Error Boundary caught:', error, errorInfo);
|
|
437
|
+
// Bubble error up to Angular
|
|
438
|
+
const host = this.props.host;
|
|
439
|
+
if ((_b = (_a = host === null || host === void 0 ? void 0 : host.config) === null || _a === void 0 ? void 0 : _a.callbacks) === null || _b === void 0 ? void 0 : _b.NotifyEvent) {
|
|
440
|
+
host.config.callbacks.NotifyEvent('componentError', {
|
|
441
|
+
error: (error === null || error === void 0 ? void 0 : error.toString()) || 'Unknown error',
|
|
442
|
+
errorInfo: errorInfo,
|
|
443
|
+
stackTrace: errorInfo === null || errorInfo === void 0 ? void 0 : errorInfo.componentStack,
|
|
444
|
+
source: 'React Error Boundary'
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
// Set state to prevent re-rendering the broken component
|
|
448
|
+
this.setState({
|
|
449
|
+
error: error,
|
|
450
|
+
errorInfo: errorInfo
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
render() {
|
|
454
|
+
if (this.state.hasError) {
|
|
455
|
+
// Just return an empty div - Angular will show the error
|
|
456
|
+
return React.createElement('div', {
|
|
457
|
+
style: {
|
|
458
|
+
display: 'none'
|
|
459
|
+
}
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
return this.props.children;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
return ErrorBoundary;
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Render or re-render the React component with new props
|
|
469
|
+
*/
|
|
470
|
+
render() {
|
|
471
|
+
var _a, _b;
|
|
472
|
+
if (!this.componentResult || !this.componentResult.component || this.destroyed) {
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
475
|
+
const Component = this.componentResult.component;
|
|
476
|
+
const ErrorBoundary = this.createErrorBoundary();
|
|
477
|
+
// Ensure utilities and callbacks are available
|
|
478
|
+
const utilities = this.config.utilities || {};
|
|
479
|
+
const callbacks = this.createCallbacks();
|
|
480
|
+
const styles = this.getOrCreateStyleSystem();
|
|
481
|
+
const componentProps = {
|
|
482
|
+
data: this.config.data || {},
|
|
483
|
+
utilities: utilities,
|
|
484
|
+
userState: this.currentState,
|
|
485
|
+
callbacks: callbacks,
|
|
486
|
+
styles: styles
|
|
487
|
+
};
|
|
488
|
+
// Debug: Log the data being passed to the component
|
|
489
|
+
console.log('=== SkipReactComponentHost: Rendering component ===');
|
|
490
|
+
console.log('Data:', componentProps.data);
|
|
491
|
+
console.log('User state:', componentProps.userState);
|
|
492
|
+
if ((_a = componentProps.data) === null || _a === void 0 ? void 0 : _a.data_item_0) {
|
|
493
|
+
console.log('First entity:', componentProps.data.data_item_0[0]);
|
|
494
|
+
console.log('Entity count:', componentProps.data.data_item_0.length);
|
|
495
|
+
}
|
|
496
|
+
else {
|
|
497
|
+
console.log('WARNING: No data_item_0 found in data');
|
|
498
|
+
}
|
|
499
|
+
console.log('=== End component props debug ===');
|
|
500
|
+
if (!this.reactRoot && this.componentContainer) {
|
|
501
|
+
this.reactRoot = this.ReactDOM.createRoot(this.componentContainer);
|
|
502
|
+
}
|
|
503
|
+
if (this.reactRoot) {
|
|
504
|
+
try {
|
|
505
|
+
// Wrap component in error boundary, passing host reference
|
|
506
|
+
const wrappedElement = this.React.createElement(ErrorBoundary, { host: this }, this.React.createElement(Component, componentProps));
|
|
507
|
+
// Set a timeout to prevent infinite loops from freezing the browser
|
|
508
|
+
const renderTimeout = setTimeout(() => {
|
|
509
|
+
var _a;
|
|
510
|
+
console.error('Component render timeout - possible infinite loop detected');
|
|
511
|
+
if ((_a = this.config.callbacks) === null || _a === void 0 ? void 0 : _a.NotifyEvent) {
|
|
512
|
+
this.config.callbacks.NotifyEvent('componentError', {
|
|
513
|
+
error: 'Component render timeout - possible infinite loop or heavy computation detected',
|
|
514
|
+
source: 'Render Timeout'
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
}, 5000); // 5 second timeout
|
|
518
|
+
this.reactRoot.render(wrappedElement);
|
|
519
|
+
// Clear timeout if render completes
|
|
520
|
+
clearTimeout(renderTimeout);
|
|
521
|
+
}
|
|
522
|
+
catch (renderError) {
|
|
523
|
+
console.error('Failed to render React component:', renderError);
|
|
524
|
+
console.error('Component:', Component);
|
|
525
|
+
console.error('Props:', componentProps);
|
|
526
|
+
if ((_b = this.config.callbacks) === null || _b === void 0 ? void 0 : _b.NotifyEvent) {
|
|
527
|
+
this.config.callbacks.NotifyEvent('componentError', {
|
|
528
|
+
error: `Component render failed: ${renderError}`,
|
|
529
|
+
source: 'React Render'
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* Update the component state
|
|
537
|
+
*/
|
|
538
|
+
updateState(path, value) {
|
|
539
|
+
// Update the current state
|
|
540
|
+
this.currentState = Object.assign(Object.assign({}, this.currentState), { [path]: value });
|
|
541
|
+
// Re-render with new state
|
|
542
|
+
this.render();
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Update the component data
|
|
546
|
+
*/
|
|
547
|
+
updateData(newData) {
|
|
548
|
+
this.config.data = Object.assign(Object.assign({}, this.config.data), newData);
|
|
549
|
+
// Re-render with new data
|
|
550
|
+
this.render();
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* Refresh the component with optional new data
|
|
554
|
+
*/
|
|
555
|
+
refresh(newData) {
|
|
556
|
+
if (newData) {
|
|
557
|
+
this.updateData(newData);
|
|
558
|
+
}
|
|
559
|
+
if (this.componentResult && this.componentResult.refresh) {
|
|
560
|
+
this.componentResult.refresh(this.config.data);
|
|
561
|
+
}
|
|
562
|
+
else {
|
|
563
|
+
// Re-render the component if no refresh method is available
|
|
564
|
+
this.render();
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Print the component
|
|
569
|
+
*/
|
|
570
|
+
print() {
|
|
571
|
+
if (this.componentResult && this.componentResult.print) {
|
|
572
|
+
this.componentResult.print();
|
|
573
|
+
}
|
|
574
|
+
else {
|
|
575
|
+
window.print();
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
/**
|
|
579
|
+
* Clean up resources
|
|
580
|
+
*/
|
|
581
|
+
destroy() {
|
|
582
|
+
this.destroyed = true;
|
|
583
|
+
if (this.reactRoot) {
|
|
584
|
+
this.reactRoot.unmount();
|
|
585
|
+
this.reactRoot = null;
|
|
586
|
+
}
|
|
587
|
+
if (this.componentContainer && this.componentContainer.parentNode) {
|
|
588
|
+
this.componentContainer.parentNode.removeChild(this.componentContainer);
|
|
589
|
+
}
|
|
590
|
+
this.componentContainer = null;
|
|
591
|
+
this.componentResult = null;
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* Create the callbacks object to pass to the React component
|
|
595
|
+
*/
|
|
596
|
+
createCallbacks() {
|
|
597
|
+
return this.config.callbacks || {
|
|
598
|
+
RefreshData: () => { },
|
|
599
|
+
OpenEntityRecord: () => { },
|
|
600
|
+
UpdateUserState: () => { },
|
|
601
|
+
NotifyEvent: () => { }
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
/**
|
|
605
|
+
* Get or create the cached style system
|
|
606
|
+
*/
|
|
607
|
+
getOrCreateStyleSystem() {
|
|
608
|
+
// If we already have a cached style system, return it
|
|
609
|
+
if (SkipReactComponentHost.cachedStyleSystem) {
|
|
610
|
+
return SkipReactComponentHost.cachedStyleSystem;
|
|
611
|
+
}
|
|
612
|
+
// Create the style system by merging defaults with config
|
|
613
|
+
SkipReactComponentHost.cachedStyleSystem = this.createStyleSystem(this.config.styles);
|
|
614
|
+
return SkipReactComponentHost.cachedStyleSystem;
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Create a unified style system for the component
|
|
618
|
+
*/
|
|
619
|
+
createStyleSystem(baseStyles) {
|
|
620
|
+
return Object.assign(Object.assign({}, DEFAULT_STYLES), baseStyles);
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* Create the state updater utility function for the React component
|
|
624
|
+
*/
|
|
625
|
+
createStateUpdaterFunction() {
|
|
626
|
+
return function createStateUpdater(statePath, parentStateUpdater) {
|
|
627
|
+
return (componentStateUpdate) => {
|
|
628
|
+
if (!statePath) {
|
|
629
|
+
// Root component - call container callback directly
|
|
630
|
+
parentStateUpdater(componentStateUpdate);
|
|
631
|
+
}
|
|
632
|
+
else {
|
|
633
|
+
// Sub-component - bubble up with path context
|
|
634
|
+
const pathParts = statePath.split('.');
|
|
635
|
+
const componentKey = pathParts[pathParts.length - 1];
|
|
636
|
+
parentStateUpdater({
|
|
637
|
+
[componentKey]: Object.assign({}, componentStateUpdate)
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
};
|
|
641
|
+
};
|
|
642
|
+
}
|
|
643
|
+
/**
|
|
644
|
+
* Create the standard event handler utility function for the React component
|
|
645
|
+
*/
|
|
646
|
+
createStandardEventHandlerFunction() {
|
|
647
|
+
return function createStandardEventHandler(updateUserState, callbacksParam) {
|
|
648
|
+
return (event) => {
|
|
649
|
+
var _a, _b;
|
|
650
|
+
switch (event.type) {
|
|
651
|
+
case 'stateChanged':
|
|
652
|
+
if (((_a = event.payload) === null || _a === void 0 ? void 0 : _a.statePath) && ((_b = event.payload) === null || _b === void 0 ? void 0 : _b.newState)) {
|
|
653
|
+
const update = {};
|
|
654
|
+
update[event.payload.statePath] = event.payload.newState;
|
|
655
|
+
updateUserState(update);
|
|
656
|
+
}
|
|
657
|
+
break;
|
|
658
|
+
case 'navigate':
|
|
659
|
+
if ((callbacksParam === null || callbacksParam === void 0 ? void 0 : callbacksParam.OpenEntityRecord) && event.payload) {
|
|
660
|
+
callbacksParam.OpenEntityRecord(event.payload.entityName, event.payload.key);
|
|
661
|
+
}
|
|
662
|
+
break;
|
|
663
|
+
default:
|
|
664
|
+
if (callbacksParam === null || callbacksParam === void 0 ? void 0 : callbacksParam.NotifyEvent) {
|
|
665
|
+
callbacksParam.NotifyEvent(event.type, event.payload);
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
};
|
|
669
|
+
};
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
// Static style system that's created once and reused
|
|
673
|
+
SkipReactComponentHost.cachedStyleSystem = null;
|
|
674
|
+
// Static cached libraries
|
|
675
|
+
SkipReactComponentHost.cachedLibraries = null;
|
|
676
|
+
SkipReactComponentHost.libraryLoadPromise = null;
|
|
677
|
+
//# sourceMappingURL=skip-react-component-host.js.map
|