xmlui 0.7.19 → 0.7.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/dist/{apiInterceptorWorker-C3bvewX6.mjs → apiInterceptorWorker-LRHkKnha.mjs} +1 -1
  2. package/dist/{grammar.tmLanguage-69iP6c5d.mjs → grammar.tmLanguage-DNepe_jP.mjs} +1 -1
  3. package/dist/index-5NLXyjX0.mjs +31055 -0
  4. package/dist/index.css +1 -1
  5. package/dist/scripts/bin/build-lib.js +1 -1
  6. package/dist/scripts/bin/index.js +2 -2
  7. package/dist/scripts/bin/start.js +23 -6
  8. package/dist/scripts/bin/viteConfig.js +1 -0
  9. package/dist/scripts/package.json +2 -1
  10. package/dist/scripts/src/abstractions/ExtensionDefs.js +2 -0
  11. package/dist/scripts/src/components/Carousel/CarouselItemNative.js +7 -4
  12. package/dist/scripts/src/components/Carousel/CarouselNative.js +6 -6
  13. package/dist/scripts/src/components/ComponentProvider.js +171 -148
  14. package/dist/scripts/src/components/FormItem/FormItemNative.js +1 -1
  15. package/dist/scripts/src/components/HtmlTags/HtmlTags.js +33 -0
  16. package/dist/scripts/src/components/RawHtml/RawHtml.js +39 -0
  17. package/dist/scripts/src/components/RawHtml/RawHtmlNative.js +13 -0
  18. package/dist/scripts/src/components/Theme/ThemeNative.js +1 -1
  19. package/dist/scripts/src/components-core/LoaderComponent.js +1 -1
  20. package/dist/scripts/src/components-core/RestApiProxy.js +1 -1
  21. package/dist/scripts/src/components-core/StandaloneApp.js +19 -19
  22. package/dist/scripts/src/components-core/{StandaloneComponentManager.js → StandaloneExtensionManager.js} +6 -13
  23. package/dist/scripts/src/components-core/action/APICall.js +1 -1
  24. package/dist/scripts/src/components-core/loader/PageableLoader.js +4 -4
  25. package/dist/scripts/src/components-core/{AppRoot.js → rendering/AppContent.js} +60 -145
  26. package/dist/scripts/src/components-core/rendering/AppRoot.js +55 -0
  27. package/dist/scripts/src/components-core/rendering/AppWrapper.js +44 -0
  28. package/dist/scripts/src/components-core/{ComponentBed.js → rendering/ComponentAdapter.js} +8 -8
  29. package/dist/scripts/src/components-core/rendering/ComponentWrapper.js +147 -0
  30. package/dist/scripts/src/components-core/rendering/Container.js +576 -0
  31. package/dist/scripts/src/components-core/rendering/ContainerWrapper.js +82 -0
  32. package/dist/scripts/src/components-core/{ErrorBoundary.js → rendering/ErrorBoundary.js} +9 -3
  33. package/dist/scripts/src/components-core/rendering/StateContainer.js +331 -0
  34. package/dist/scripts/src/components-core/{container → rendering}/buildProxy.js +11 -7
  35. package/dist/scripts/src/components-core/{container → rendering}/collectFnVarDeps.js +2 -2
  36. package/dist/scripts/src/components-core/{container → rendering}/reducer.js +3 -0
  37. package/dist/scripts/src/components-core/rendering/renderChild.js +81 -0
  38. package/dist/scripts/src/index.js +3 -6
  39. package/dist/scripts/src/parsers/xmlui-parser/transform.js +193 -164
  40. package/dist/scripts/src/syntax/grammar.tmLanguage.json +1 -1
  41. package/dist/style.css +1 -1
  42. package/dist/xmlui-metadata.mjs +4216 -4232
  43. package/dist/xmlui-metadata.umd.js +16 -16
  44. package/dist/xmlui-standalone.umd.js +262 -290
  45. package/dist/xmlui.d.ts +36 -61
  46. package/dist/xmlui.mjs +1 -1
  47. package/package.json +2 -1
  48. package/dist/index-BwlAHBcX.mjs +0 -76810
  49. package/dist/scripts/src/components/BarChart/BarChart.js +0 -49
  50. package/dist/scripts/src/components/BarChart/BarChartNative.js +0 -176
  51. package/dist/scripts/src/components/Map/Map.js +0 -75
  52. package/dist/scripts/src/components/Map/world_countries.json +0 -45307
  53. package/dist/scripts/src/components/PieChart/PieChart.js +0 -45
  54. package/dist/scripts/src/components/PieChart/PieChartNative.js +0 -165
  55. package/dist/scripts/src/components/chart-color-schemes.js +0 -43
  56. package/dist/scripts/src/components-core/container/Container.js +0 -1186
  57. package/dist/scripts/src/components-core/container/ContainerComponentDef.js +0 -15
  58. /package/dist/scripts/src/components-core/{InvalidComponent.js → rendering/InvalidComponent.js} +0 -0
  59. /package/dist/scripts/src/components-core/{UnknownComponent.js → rendering/UnknownComponent.js} +0 -0
  60. /package/dist/scripts/src/components-core/{container → rendering}/valueExtractor.js +0 -0
@@ -1,1186 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
- return new (P || (P = Promise))(function (resolve, reject) {
38
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
- step((generator = generator.apply(thisArg, _arguments || [])).next());
42
- });
43
- };
44
- var __rest = (this && this.__rest) || function (s, e) {
45
- var t = {};
46
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
47
- t[p] = s[p];
48
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
49
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
50
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
51
- t[p[i]] = s[p[i]];
52
- }
53
- return t;
54
- };
55
- var __importDefault = (this && this.__importDefault) || function (mod) {
56
- return (mod && mod.__esModule) ? mod : { "default": mod };
57
- };
58
- Object.defineProperty(exports, "__esModule", { value: true });
59
- exports.renderRoot = renderRoot;
60
- exports.eventHandlerStarted = eventHandlerStarted;
61
- exports.eventHandlerCompleted = eventHandlerCompleted;
62
- exports.eventHandlerError = eventHandlerError;
63
- exports.statePartChanged = statePartChanged;
64
- const jsx_runtime_1 = require("react/jsx-runtime");
65
- const react_1 = __importStar(require("react"));
66
- const memoize_one_1 = __importDefault(require("memoize-one"));
67
- const immer_1 = __importDefault(require("immer"));
68
- const react_compose_refs_1 = require("@radix-ui/react-compose-refs");
69
- const ContainerComponentDef_1 = require("./ContainerComponentDef");
70
- const buildProxy_1 = __importDefault(require("./buildProxy"));
71
- const containers_1 = require("@components-core/abstractions/containers");
72
- const lodash_es_1 = require("lodash-es");
73
- const ErrorBoundary_1 = require("@components-core/ErrorBoundary");
74
- const extractParam_1 = require("@components-core/utils/extractParam");
75
- const misc_1 = require("@components-core/utils/misc");
76
- const process_statement_async_1 = require("@components-core/script-runner/process-statement-async");
77
- const process_statement_sync_1 = require("@components-core/script-runner/process-statement-sync");
78
- const ComponentBed_1 = __importDefault(require("@components-core/ComponentBed"));
79
- const constants_1 = require("@components-core/constants");
80
- const statementUtils_1 = require("@components-core/utils/statementUtils");
81
- const react_2 = require("@remix-run/react");
82
- const AppContext_1 = require("@components-core/AppContext");
83
- const visitors_1 = require("@components-core/script-runner/visitors");
84
- const ParameterParser_1 = require("@components-core/script-runner/ParameterParser");
85
- const ThemeContext_1 = require("@components-core/theming/ThemeContext");
86
- const code_behind_collect_1 = require("../../parsers/scripting/code-behind-collect");
87
- const eval_tree_sync_1 = require("@components-core/script-runner/eval-tree-sync");
88
- const collectFnVarDeps_1 = require("@components-core/container/collectFnVarDeps");
89
- const hooks_1 = require("@components-core/utils/hooks");
90
- const LoaderComponent_1 = require("@components-core/LoaderComponent");
91
- const DebugViewProvider_1 = require("@components-core/DebugViewProvider");
92
- const StateViewerNative_1 = require("@components/StateViewer/StateViewerNative");
93
- const reducer_1 = require("./reducer");
94
- // This function renders the entire component tree starting from the root component. As it works recursively,
95
- // all child components will be rendered, including the wrapping containers
96
- function renderRoot(node, memoedVarsRef) {
97
- return renderChild({
98
- node,
99
- state: constants_1.EMPTY_OBJECT,
100
- dispatch: constants_1.noop,
101
- appContext: undefined,
102
- lookupAction: constants_1.noop,
103
- lookupSyncCallback: constants_1.noop,
104
- registerComponentApi: constants_1.noop,
105
- renderChild: constants_1.noop,
106
- stateFieldPartChanged: constants_1.noop,
107
- cleanup: constants_1.noop,
108
- memoedVarsRef,
109
- });
110
- }
111
- // React component to display a view container and implement its behavior
112
- const MemoizedContainer = (0, react_1.memo)((0, react_1.forwardRef)(function Container({ node, componentState, dispatch: containerDispatch, parentDispatch, resolvedKey, version, setVersion, stateFieldPartChanged, registerComponentApi: containerRegisterComponentApi, parentRegisterComponentApi, layoutContextRef, parentRenderContext, memoedVarsRef, isImplicit, uidInfoRef: parentUidInfoRef, }, ref) {
113
- var _a;
114
- const { apiBoundContainer } = node;
115
- const dispatch = isImplicit ? parentDispatch : containerDispatch;
116
- const registerComponentApi = isImplicit
117
- ? parentRegisterComponentApi
118
- : containerRegisterComponentApi;
119
- const appContext = (0, AppContext_1.useAppContext)();
120
- const { getThemeVar } = (0, ThemeContext_1.useTheme)();
121
- const navigate = (0, react_2.useNavigate)();
122
- const location = (0, react_2.useLocation)();
123
- const fnsRef = (0, react_1.useRef)({});
124
- const stateRef = (0, react_1.useRef)(componentState);
125
- //generally bad practise to write ref in render (https://react.dev/learn/referencing-values-with-refs#best-practices-for-refs), but:
126
- // this stateRef is only used in runCodeSync/async functions, which are memoized, so it's safe to use it here (as I know: illesg)
127
- // In case we sync up the stateRef with the componentState in the useEffect/useInsertionEffect/useLayoutEffect, the stateRef would lag behind the componentState
128
- stateRef.current = componentState;
129
- const parsedStatementsRef = (0, react_1.useRef)({});
130
- const statementPromises = (0, react_1.useRef)(new Map());
131
- const [_, startTransition] = (0, react_1.useTransition)();
132
- const mountedRef = (0, react_1.useRef)(true);
133
- (0, hooks_1.useIsomorphicLayoutEffect)(() => {
134
- for (const resolve of statementPromises.current.values()) {
135
- resolve();
136
- }
137
- }, [version]);
138
- (0, react_1.useEffect)(() => {
139
- mountedRef.current = true;
140
- const leftPromises = statementPromises.current;
141
- return () => {
142
- mountedRef.current = false;
143
- for (const resolve of leftPromises.values()) {
144
- resolve();
145
- }
146
- };
147
- }, []);
148
- const runCodeAsync = (0, misc_1.useEvent)((source, componentUid, options, ...eventArgs) => __awaiter(this, void 0, void 0, function* () {
149
- var _a, _b, _c;
150
- // console.log({
151
- // source,
152
- // componentUid,
153
- // options,
154
- // eventArgs,
155
- // state: stateRef.current,
156
- // "$this": stateRef.current[componentUid]
157
- // });
158
- let changes = [];
159
- const getComponentStateClone = () => {
160
- changes.length = 0;
161
- const poj = (0, lodash_es_1.cloneDeep)(Object.assign({}, stateRef.current));
162
- poj["$this"] = stateRef.current[componentUid];
163
- return (0, buildProxy_1.default)(poj, (changeInfo) => {
164
- var _a;
165
- const idRoot = (_a = changeInfo.pathArray) === null || _a === void 0 ? void 0 : _a[0];
166
- if (idRoot === null || idRoot === void 0 ? void 0 : idRoot.startsWith("$")) {
167
- throw new Error("Cannot update a read-only variable");
168
- }
169
- changes.push(changeInfo);
170
- });
171
- };
172
- const evalAppContext = Object.assign(Object.assign({}, appContext), { getThemeVar });
173
- const evalContext = {
174
- appContext: evalAppContext,
175
- eventArgs,
176
- localContext: getComponentStateClone(),
177
- implicitContextGetter: () => {
178
- return {
179
- uid: componentUid,
180
- state: stateRef.current,
181
- dispatch,
182
- appContext: evalAppContext,
183
- navigate,
184
- location,
185
- lookupAction: (action, uid, actionOptions = {}) => {
186
- return lookupAction(action, uid, Object.assign(Object.assign({}, actionOptions), { ephemeral: true }));
187
- },
188
- };
189
- },
190
- options: {
191
- defaultToOptionalMemberAccess: typeof ((_a = appContext.appGlobals) === null || _a === void 0 ? void 0 : _a.defaultToOptionalMemberAccess) === "boolean"
192
- ? appContext.appGlobals.defaultToOptionalMemberAccess
193
- : true,
194
- },
195
- };
196
- try {
197
- // --- Prepare the event handler to an arrow expression statement
198
- let statements;
199
- if (typeof source === "string") {
200
- if (!parsedStatementsRef.current[source]) {
201
- parsedStatementsRef.current[source] = (0, statementUtils_1.prepareHandlerStatements)((0, statementUtils_1.parseHandlerCode)(source), evalContext);
202
- }
203
- statements = parsedStatementsRef.current[source];
204
- }
205
- else {
206
- statements = [
207
- {
208
- type: "ArrowS",
209
- expression: (0, lodash_es_1.cloneDeep)(source), //TODO illesg (talk it through why we need to deep clone, it it's omitted, it gets slower every time we run it)
210
- },
211
- ];
212
- }
213
- if (!(statements === null || statements === void 0 ? void 0 : statements.length)) {
214
- return;
215
- }
216
- if (canSignEventLifecycle(componentUid.description, options === null || options === void 0 ? void 0 : options.eventName)) {
217
- dispatch(eventHandlerStarted(componentUid.description, options.eventName));
218
- }
219
- let mainThreadBlockingRuns = 0;
220
- yield (0, process_statement_async_1.processStatementQueueAsync)(statements, evalContext, undefined, (evalContext, completedStatement) => __awaiter(this, void 0, void 0, function* () {
221
- if (changes.length) {
222
- mainThreadBlockingRuns = 0;
223
- changes.forEach((change) => {
224
- stateFieldPartChanged(change.pathArray, (0, lodash_es_1.cloneDeep)(change.newValue), change.target, change.action);
225
- });
226
- let resolve = null;
227
- const stateUpdatedPromise = new Promise((res) => {
228
- resolve = () => {
229
- res(null);
230
- };
231
- });
232
- const key = (0, misc_1.generatedId)();
233
- statementPromises.current.set(key, resolve);
234
- // We use this to tell react that this update is not high-priority.
235
- // If we don't put it to a transition, the whole app would be blocked if we run a long,
236
- // update intensive queue (e.g. an infinite loop which
237
- // increments a counter, see playground example learning/01_Experiments/01_Event_Framework/app ).
238
- // Before this solution, we used a setTimeout(..., 0); hack, but some browsers (chrome especially)
239
- // do some funky stuff with the background tabs (e.g. all the setTimeouts are
240
- // maximized to run in 1 time / minute, doesn't matter if it's timeout is 0)
241
- // As of 2023. June 20, this solution works with backgrounded tabs, too.
242
- startTransition(() => {
243
- setVersion((prev) => prev + 1);
244
- });
245
- //TODO this could be a problem - if this container gets unmounted, we still have to wait for the update,
246
- // but in that case this update probably happened in the parent (e.g. a button's event handler removes the whole container
247
- // where the button lives, but it still has some statements to run).
248
- // with this solution the statement execution doesn't stop, and we fallback waiting with a setTimeout(0)
249
- if (mountedRef.current) {
250
- yield stateUpdatedPromise;
251
- }
252
- else {
253
- yield (0, misc_1.delay)(0);
254
- }
255
- statementPromises.current.delete(key);
256
- changes = [];
257
- }
258
- else {
259
- //in this else branch normally we block the main thread (we don't wait for any state promise to be resolved),
260
- // so in a long-running (typically infinite loop) situation, where there aren't any changes in the state
261
- // we block the main thread indefinitely... this 'mainThreadBlockingRuns' var solution makes sure that
262
- // we pause in every 100 runs, and let the main thread breath a bit, so it's not frozen for the whole time
263
- // (we clear that counter above, too, where we use a startTransition call to de-prioritize this work)
264
- mainThreadBlockingRuns++;
265
- if (mainThreadBlockingRuns > 100) {
266
- mainThreadBlockingRuns = 0;
267
- yield (0, misc_1.delay)(0);
268
- }
269
- }
270
- evalContext.localContext = getComponentStateClone();
271
- }));
272
- if (canSignEventLifecycle(componentUid.description, options === null || options === void 0 ? void 0 : options.eventName)) {
273
- dispatch(eventHandlerCompleted(componentUid.description, options.eventName));
274
- }
275
- if ((_c = (_b = evalContext.mainThread) === null || _b === void 0 ? void 0 : _b.blocks) === null || _c === void 0 ? void 0 : _c.length) {
276
- return evalContext.mainThread.blocks[evalContext.mainThread.blocks.length - 1]
277
- .returnValue;
278
- }
279
- }
280
- catch (e) {
281
- //if we pass down an event handler to a component, we should sign the error once, not in every step of the component chain
282
- // (we use it in the compoundComponent, resolving it's event handlers)
283
- if ((options === null || options === void 0 ? void 0 : options.signError) !== false) {
284
- appContext.signError(e);
285
- }
286
- if (canSignEventLifecycle(componentUid.description, options === null || options === void 0 ? void 0 : options.eventName)) {
287
- dispatch(eventHandlerError(componentUid.description, options.eventName, e));
288
- }
289
- throw e;
290
- }
291
- }));
292
- const runCodeSync = (0, react_1.useCallback)((arrowExpression, ...eventArgs) => {
293
- var _a, _b;
294
- const evalContext = {
295
- localContext: (0, lodash_es_1.cloneDeep)(stateRef.current),
296
- appContext,
297
- eventArgs,
298
- };
299
- try {
300
- const arrowStmt = {
301
- type: "ArrowS",
302
- expression: arrowExpression,
303
- };
304
- (0, process_statement_sync_1.processStatementQueue)([arrowStmt], evalContext);
305
- if ((_b = (_a = evalContext.mainThread) === null || _a === void 0 ? void 0 : _a.blocks) === null || _b === void 0 ? void 0 : _b.length) {
306
- return evalContext.mainThread.blocks[evalContext.mainThread.blocks.length - 1]
307
- .returnValue;
308
- }
309
- }
310
- catch (e) {
311
- console.error(e);
312
- throw e;
313
- }
314
- }, [appContext]);
315
- const getOrCreateEventHandlerFn = (0, misc_1.useEvent)((src, uid, options) => {
316
- var _a;
317
- const stringSrc = typeof src === "string" ? src : src.statement.source;
318
- const fnCacheKey = `${options === null || options === void 0 ? void 0 : options.eventName};${stringSrc}`;
319
- const handler = (...eventArgs) => {
320
- return runCodeAsync(src, uid, options, ...(0, lodash_es_1.cloneDeep)(eventArgs));
321
- };
322
- if (options === null || options === void 0 ? void 0 : options.ephemeral) {
323
- return handler;
324
- }
325
- if (!((_a = fnsRef.current[uid]) === null || _a === void 0 ? void 0 : _a[fnCacheKey])) {
326
- fnsRef.current[uid] = fnsRef.current[uid] || {};
327
- fnsRef.current[uid][fnCacheKey] = handler;
328
- }
329
- return fnsRef.current[uid][fnCacheKey];
330
- });
331
- const getOrCreateSyncCallbackFn = (0, react_1.useCallback)((arrowExpression, uid) => {
332
- var _a;
333
- const fnCacheKey = `sync-callback-${arrowExpression.source}`;
334
- if (!((_a = fnsRef.current[uid]) === null || _a === void 0 ? void 0 : _a[fnCacheKey])) {
335
- fnsRef.current[uid] = fnsRef.current[uid] || {};
336
- fnsRef.current[uid][fnCacheKey] = (0, memoize_one_1.default)((arrowExpression) => {
337
- // console.log('busting sync callback cache', arrowExpression);
338
- return (...eventArgs) => {
339
- // console.log("calling sync callback", arrowExpression);
340
- return runCodeSync(arrowExpression, ...eventArgs);
341
- };
342
- });
343
- }
344
- return fnsRef.current[uid][fnCacheKey](arrowExpression);
345
- }, [runCodeSync]);
346
- const lookupSyncCallback = (0, react_1.useCallback)((action, uid) => {
347
- if (!action) {
348
- return undefined;
349
- }
350
- if (typeof action === "function") {
351
- return action;
352
- }
353
- // const resolvedAction = extractParam(componentState, action, appContext, true);
354
- if (!action) {
355
- return undefined;
356
- }
357
- if (typeof action === "function") {
358
- return action;
359
- }
360
- if (!action._ARROW_EXPR_) {
361
- throw new Error("Only arrow expression allowed in sync callback");
362
- }
363
- return getOrCreateSyncCallbackFn(action, uid);
364
- }, [getOrCreateSyncCallbackFn]);
365
- const lookupAction = (0, react_1.useCallback)((action, uid, options) => {
366
- let safeAction = action;
367
- if (!action && uid.description && (options === null || options === void 0 ? void 0 : options.eventName)) {
368
- const handlerFnName = `${uid.description}_on${(0, misc_1.capitalizeFirstLetter)(options === null || options === void 0 ? void 0 : options.eventName)}`;
369
- if (componentState[handlerFnName] && componentState[handlerFnName]._ARROW_EXPR_) {
370
- safeAction = componentState[handlerFnName];
371
- }
372
- }
373
- if (!safeAction) {
374
- return undefined;
375
- }
376
- if (typeof safeAction === "function") {
377
- return safeAction;
378
- }
379
- return getOrCreateEventHandlerFn(safeAction, uid, options);
380
- }, [componentState, getOrCreateEventHandlerFn]);
381
- const isApiRegisteredInnerRef = (0, react_1.useRef)(false);
382
- (0, react_1.useEffect)(() => {
383
- if (!node.api) {
384
- return;
385
- }
386
- if (!node.containerUid) {
387
- return;
388
- }
389
- if (isApiRegisteredInnerRef.current) {
390
- return;
391
- }
392
- isApiRegisteredInnerRef.current = true;
393
- const api = {};
394
- const self = Symbol("$self");
395
- Object.entries(node.api).forEach(([key, value]) => {
396
- api[key] = lookupAction(value, self);
397
- });
398
- if (!isImplicit) {
399
- registerComponentApi(self, api); //we register the api as $self for the compound components,
400
- }
401
- parentRegisterComponentApi(node.containerUid, api); // and register it for the parent component instance
402
- }, [
403
- lookupAction,
404
- node.api,
405
- node.containerUid,
406
- node.uid,
407
- isImplicit,
408
- parentRegisterComponentApi,
409
- registerComponentApi,
410
- ]);
411
- const cleanup = (0, misc_1.useEvent)((uid) => {
412
- // console.log("CLEANUP CALLED FOR", node);
413
- //TODO cleanup registered component api for that uid
414
- //TODO cleanup state for that uid
415
- delete fnsRef.current[uid];
416
- });
417
- // --- The container wraps the `renderChild` function to provide that to the child components
418
- const stableRenderChild = (0, react_1.useCallback)((childNode, lc, pRenderContext, uidInfoRef) => {
419
- // TODO: Check if this is a valid use case
420
- if (typeof childNode === "string") {
421
- throw Error("should be resolved for now");
422
- }
423
- // --- Make children an array if it's not
424
- const children = (0, lodash_es_1.isArray)(childNode) ? childNode : [childNode];
425
- if (!children || !children.length) {
426
- // --- No child, nothing to render
427
- return null;
428
- }
429
- // --- If there are multiple children, we need to add a `key` to each of them
430
- const wrapWithFragment = children.length > 1;
431
- // --- Render each child
432
- const renderedChildren = children.map((child, childIndex) => {
433
- if (!child) {
434
- // --- No child, nothing to render: Should not happen
435
- return undefined;
436
- }
437
- // --- Invoke the jolly-joker `renderChild` function to render the child. Note that
438
- // --- in ithe context, we pass the `stableRenderChild` function, so the child can
439
- // --- render its children recursively.
440
- const renderedChild = renderChild({
441
- node: child,
442
- state: componentState,
443
- dispatch,
444
- appContext,
445
- lookupAction,
446
- lookupSyncCallback,
447
- registerComponentApi,
448
- renderChild: stableRenderChild,
449
- stateFieldPartChanged,
450
- layoutContext: lc,
451
- parentRenderContext: pRenderContext,
452
- memoedVarsRef,
453
- cleanup,
454
- uidInfoRef,
455
- });
456
- if (renderedChild === undefined) {
457
- // --- No displayable child, nothing to render
458
- return undefined;
459
- }
460
- // --- Let's process the rendered child
461
- let rendered = renderedChild;
462
- const key = `${childIndex}_${child.uid}`;
463
- if (wrapWithFragment) {
464
- // --- Add the `key` attribute to the child
465
- if (react_1.default.isValidElement(renderedChild)) {
466
- // --- React can display this element
467
- rendered = react_1.default.cloneElement(renderedChild, { key });
468
- }
469
- else {
470
- // --- A simple text node (or alike). We need to wrap it in a `Fragment`
471
- rendered = (0, jsx_runtime_1.jsx)(react_1.Fragment, { children: renderedChild }, key);
472
- }
473
- }
474
- // --- Done.
475
- return rendered;
476
- });
477
- // --- At this point we have a React node for each child
478
- if (renderedChildren.length === 1) {
479
- // --- If we have a single (and valid React element) child, we compose its
480
- // --- `ref` with the parent's `ref`. This allows the parent to access the child's
481
- // --- DOM node. Otherwise, we use the child as is.
482
- return ref && renderedChildren[0] && (0, react_1.isValidElement)(renderedChildren[0])
483
- ? react_1.default.cloneElement(renderedChildren[0], {
484
- ref: (0, react_compose_refs_1.composeRefs)(ref, renderedChildren[0].ref),
485
- })
486
- : renderedChildren[0];
487
- }
488
- // --- Done.
489
- return renderedChildren;
490
- }, [
491
- componentState,
492
- dispatch,
493
- appContext,
494
- lookupAction,
495
- lookupSyncCallback,
496
- registerComponentApi,
497
- stateFieldPartChanged,
498
- memoedVarsRef,
499
- cleanup,
500
- ref,
501
- ]);
502
- // --- Log the component state if you need it for debugging
503
- if ((_a = node.props) === null || _a === void 0 ? void 0 : _a.debug) {
504
- console.log(`Container: ${resolvedKey}`, {
505
- componentState,
506
- node,
507
- });
508
- }
509
- // --- Use this object to store information about already rendered UIDs.
510
- // --- We do not allow any action, loader, or transform to use the same UID; however (as of now) children
511
- // --- may use the same UID.
512
- const uidInfo = {};
513
- const thisUidInfoRef = (0, react_1.useRef)({});
514
- const uidInfoRef = node.uses === undefined ? parentUidInfoRef : thisUidInfoRef;
515
- const debugContext = (0, DebugViewProvider_1.useDebugView)();
516
- const stateViewProps = debugContext === null || debugContext === void 0 ? void 0 : debugContext.stateViewOptions;
517
- const showContainer = stateViewProps && debugContext.displayStateView;
518
- return ((0, jsx_runtime_1.jsxs)(react_1.Fragment, { children: [showContainer && ((0, jsx_runtime_1.jsxs)(StateViewerNative_1.StateViewer, { state: componentState, showBoundary: stateViewProps === null || stateViewProps === void 0 ? void 0 : stateViewProps.showBoundary, blink: stateViewProps === null || stateViewProps === void 0 ? void 0 : stateViewProps.blink, children: [renderLoaders({
519
- uidInfo,
520
- uidInfoRef,
521
- loaders: node.loaders,
522
- componentState,
523
- memoedVarsRef,
524
- //if it's an api bound container, we always use this container, otherwise use the parent if it's an implicit one
525
- dispatch: apiBoundContainer ? containerDispatch : dispatch,
526
- registerComponentApi: apiBoundContainer
527
- ? containerRegisterComponentApi
528
- : registerComponentApi,
529
- appContext,
530
- lookupAction,
531
- lookupSyncCallback,
532
- cleanup,
533
- }), stableRenderChild(node.children, layoutContextRef === null || layoutContextRef === void 0 ? void 0 : layoutContextRef.current, parentRenderContext, uidInfoRef)] })), !showContainer && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [renderLoaders({
534
- uidInfo,
535
- uidInfoRef,
536
- loaders: node.loaders,
537
- componentState,
538
- memoedVarsRef,
539
- //if it's an api bound container, we always use this container, otherwise use the parent if it's an implicit one
540
- dispatch: apiBoundContainer ? containerDispatch : dispatch,
541
- registerComponentApi: apiBoundContainer
542
- ? containerRegisterComponentApi
543
- : registerComponentApi,
544
- appContext,
545
- lookupAction,
546
- lookupSyncCallback,
547
- cleanup,
548
- }), stableRenderChild(node.children, layoutContextRef === null || layoutContextRef === void 0 ? void 0 : layoutContextRef.current, parentRenderContext, uidInfoRef)] }))] }, node.uid
549
- ? `${resolvedKey}>${(0, extractParam_1.extractParam)(componentState, node.uid, appContext, true)}`
550
- : undefined));
551
- }));
552
- const useRoutingParams = () => {
553
- const [queryParams] = (0, react_2.useSearchParams)();
554
- const routeParams = (0, react_2.useParams)();
555
- const queryParamsMap = (0, react_1.useMemo)(() => {
556
- const result = {};
557
- for (const [key, value] of Array.from(queryParams.entries())) {
558
- result[key] = value;
559
- }
560
- return result;
561
- }, [queryParams]);
562
- return (0, react_1.useMemo)(() => {
563
- return {
564
- $routeParams: routeParams,
565
- $queryParams: queryParamsMap,
566
- };
567
- }, [queryParamsMap, routeParams]);
568
- };
569
- class CodeBehindParseError extends Error {
570
- constructor(errors) {
571
- const mainErrors = errors["Main"] || [];
572
- const messages = mainErrors.map((errorMessage) => {
573
- let ret = `${errorMessage.code} : ${errorMessage.text}`;
574
- const posInfo = [];
575
- if (errorMessage.line !== undefined) {
576
- posInfo.push(`line:${errorMessage.line}`);
577
- }
578
- if (errorMessage.column !== undefined) {
579
- posInfo.push(`column:${errorMessage.column}`);
580
- }
581
- if (posInfo.length) {
582
- ret = `${ret} (${posInfo.join(", ")})`;
583
- }
584
- return ret;
585
- });
586
- super(messages.join("\n"));
587
- Object.setPrototypeOf(this, CodeBehindParseError.prototype);
588
- }
589
- }
590
- // A React component that wraps a view container into an error boundary
591
- // (it's a named function inside the memo, this way it will be visible with that name in the react devtools)
592
- const MemoizedErrorProneContainer = (0, react_1.memo)((0, react_1.forwardRef)(function ErrorProneContainer({ node, parentState, resolvedKey, parentStateFieldPartChanged, parentRegisterComponentApi, layoutContextRef, parentRenderContext, isImplicit, parentDispatch, uidInfoRef, }, ref) {
593
- const [version, setVersion] = (0, react_1.useState)(0);
594
- const routingParams = useRoutingParams();
595
- const memoedVars = (0, react_1.useRef)(new Map());
596
- const stateFromOutside = (0, hooks_1.useShallowCompareMemoize)((0, react_1.useMemo)(() => extractScopedState(parentState, node.uses), [node.uses, parentState]));
597
- // --- All state manipulation happens through the container reducer, which is created here.
598
- // --- This reducer allow collecting state changes for debugging purposes. The `debugView`
599
- // --- contains the debug configuration; it may enable (or disable) logging.
600
- const debugView = (0, DebugViewProvider_1.useDebugView)();
601
- const containerReducer = (0, reducer_1.createContainerReducer)(debugView);
602
- const [componentState, dispatch] = (0, react_1.useReducer)(containerReducer, constants_1.EMPTY_OBJECT);
603
- const [componentApis, setComponentApis] = (0, react_1.useState)(constants_1.EMPTY_OBJECT);
604
- const componentStateWithApis = (0, hooks_1.useShallowCompareMemoize)((0, react_1.useMemo)(() => {
605
- const ret = Object.assign({}, componentState);
606
- for (const stateKey of Object.getOwnPropertySymbols(componentState)) {
607
- const value = componentState[stateKey];
608
- if (stateKey.description) {
609
- ret[stateKey.description] = value;
610
- }
611
- }
612
- if (Reflect.ownKeys(componentApis).length === 0) {
613
- //skip containers with no registered apis
614
- return ret;
615
- }
616
- for (const componentApiKey of Object.getOwnPropertySymbols(componentApis)) {
617
- const value = componentApis[componentApiKey];
618
- if (componentApiKey.description) {
619
- const key = componentApiKey.description;
620
- ret[key] = Object.assign(Object.assign({}, (ret[key] || {})), value);
621
- }
622
- ret[componentApiKey] = Object.assign(Object.assign({}, ret[componentApiKey]), value);
623
- }
624
- return ret;
625
- }, [componentState, componentApis]));
626
- const localVarsStateContext = useCombinedState(stateFromOutside, componentStateWithApis, node.contextVars);
627
- const parsedScriptPart = node.scriptCollected;
628
- if ((parsedScriptPart === null || parsedScriptPart === void 0 ? void 0 : parsedScriptPart.moduleErrors) && !(0, lodash_es_1.isEmpty)(parsedScriptPart.moduleErrors)) {
629
- throw new CodeBehindParseError(parsedScriptPart.moduleErrors);
630
- }
631
- if (node.scriptError && !(0, lodash_es_1.isEmpty)(node.scriptError)) {
632
- throw new CodeBehindParseError(node.scriptError);
633
- }
634
- const referenceTrackedApi = (0, hooks_1.useReferenceTrackedApi)(componentState);
635
- const varDefinitions = (0, hooks_1.useShallowCompareMemoize)(Object.assign(Object.assign(Object.assign(Object.assign({}, parsedScriptPart === null || parsedScriptPart === void 0 ? void 0 : parsedScriptPart.functions), node.functions), parsedScriptPart === null || parsedScriptPart === void 0 ? void 0 : parsedScriptPart.vars), node.vars));
636
- //first: collection function (arrowExpressions) dependencies
637
- // -> do it until there's no function dep, only var deps
638
- const functionDeps = (0, react_1.useMemo)(() => {
639
- const fnDeps = {};
640
- Object.entries(varDefinitions).forEach(([key, value]) => {
641
- if (isParsedValue(value) && value.tree.type === "ArrowE") {
642
- fnDeps[key] = (0, visitors_1.collectVariableDependencies)(value.tree, referenceTrackedApi);
643
- }
644
- });
645
- return (0, collectFnVarDeps_1.collectFnVarDeps)(fnDeps);
646
- }, [referenceTrackedApi, varDefinitions]);
647
- // then resolve vars and replace function deps with the collected deps for that function
648
- //first resolve round (we do 2, to make sure that the order of the definitions doesn't cause problems)
649
- // e.g. 'testFn' uses $props, but $props is not resolved yet
650
- const preResolvedLocalVars = useVars(varDefinitions, functionDeps, localVarsStateContext, (0, react_1.useRef)(new Map()));
651
- const localVarsStateContextWithPreResolvedLocalVars = (0, hooks_1.useShallowCompareMemoize)(Object.assign(Object.assign({}, preResolvedLocalVars), localVarsStateContext));
652
- const resolvedLocalVars = useVars(varDefinitions, functionDeps, localVarsStateContextWithPreResolvedLocalVars, memoedVars);
653
- const mergedWithVars = useMergedState(resolvedLocalVars, componentStateWithApis);
654
- const combinedState = useCombinedState(stateFromOutside, node.contextVars, mergedWithVars, routingParams);
655
- const registerComponentApi = (0, react_1.useCallback)((uid, api) => {
656
- setComponentApis((0, immer_1.default)((draft) => {
657
- // console.log("-----BUST----setComponentApis");
658
- if (!draft[uid]) {
659
- draft[uid] = {};
660
- }
661
- Object.entries(api).forEach(([key, value]) => {
662
- if (draft[uid][key] !== value) {
663
- // console.log(`-----BUST------new api for ${uid}`, draft[uid][key], value)
664
- draft[uid][key] = value;
665
- }
666
- });
667
- }));
668
- }, []);
669
- const componentStateRef = (0, react_1.useRef)(componentStateWithApis);
670
- const stateFieldPartChanged = (0, react_1.useCallback)((pathArray, newValue, target, action) => {
671
- const key = pathArray[0];
672
- if (key in componentStateRef.current || key in resolvedLocalVars) {
673
- dispatch(statePartChanged(pathArray, newValue, target, action));
674
- }
675
- else {
676
- if (!node.uses || node.uses.includes(key)) {
677
- parentStateFieldPartChanged(pathArray, newValue, target, action);
678
- }
679
- }
680
- }, [resolvedLocalVars, node.uses, parentStateFieldPartChanged]);
681
- return ((0, jsx_runtime_1.jsx)(ErrorBoundary_1.ErrorBoundary, { node: node, location: "container", children: (0, jsx_runtime_1.jsx)(MemoizedContainer, { resolvedKey: resolvedKey, node: node, componentState: combinedState, dispatch: dispatch, parentDispatch: parentDispatch, setVersion: setVersion, version: version, stateFieldPartChanged: stateFieldPartChanged, registerComponentApi: registerComponentApi, parentRegisterComponentApi: parentRegisterComponentApi, layoutContextRef: layoutContextRef, parentRenderContext: parentRenderContext, memoedVarsRef: memoedVars, isImplicit: isImplicit, ref: ref, uidInfoRef: uidInfoRef }) }));
682
- }));
683
- /**
684
- * Wraps the specified component node with a container
685
- * @param node The component node to wrap
686
- * @returns A "Container" node
687
- */
688
- const getWrappedWithContainer = (node) => {
689
- var _a, _b;
690
- if (node.type === "Container") {
691
- // --- Already wrapped
692
- return node;
693
- }
694
- // --- Clone the node and remove the properties that will be moved to the container
695
- // --- Note: we need the "when" property in the ModalDialog component, so we don't remove it
696
- const wrappedNode = Object.assign(Object.assign({}, node), { props: Object.assign({}, node.props) });
697
- delete wrappedNode.loaders;
698
- delete wrappedNode.vars;
699
- delete wrappedNode.functions;
700
- delete wrappedNode.script;
701
- delete wrappedNode.scriptCollected;
702
- delete wrappedNode.scriptError;
703
- delete wrappedNode.uses;
704
- (_a = wrappedNode.props) === null || _a === void 0 ? true : delete _a.uses;
705
- delete wrappedNode.api;
706
- delete wrappedNode.contextVars;
707
- // --- Do the wrapping
708
- return {
709
- type: "Container",
710
- uid: node.uid,
711
- when: node.when,
712
- loaders: node.loaders,
713
- vars: node.vars,
714
- functions: node.functions,
715
- scriptCollected: node.scriptCollected,
716
- scriptError: node.scriptError,
717
- // TODO: it seems so that we need only node.uses, but we have to check it
718
- uses: node.uses, // || node.props?.uses?.split(",").map((txt: string) => txt.trim()),
719
- api: node.api,
720
- containerUid: "containerUid" in node && node.containerUid,
721
- apiBoundContainer: "apiBoundContainer" in node && node.apiBoundContainer,
722
- contextVars: node.contextVars,
723
- props: {
724
- debug: (_b = node.props) === null || _b === void 0 ? void 0 : _b.debug,
725
- // debug: true,
726
- },
727
- children: [wrappedNode],
728
- };
729
- };
730
- const ComponentContainer = (0, react_1.memo)((0, react_1.forwardRef)(function ComponentContainer({ resolvedKey, node, parentState, parentStateFieldPartChanged, parentRegisterComponentApi, layoutContextRef, parentRenderContext, parentDispatch, uidInfoRef, }, ref) {
731
- const enhancedNode = (0, react_1.useMemo)(() => getWrappedWithContainer(node), [node]);
732
- return ((0, jsx_runtime_1.jsx)(ErrorBoundary_1.ErrorBoundary, { node: node, location: "container", children: (0, jsx_runtime_1.jsx)(MemoizedErrorProneContainer, { parentStateFieldPartChanged: parentStateFieldPartChanged, resolvedKey: resolvedKey, node: enhancedNode, parentState: parentState, layoutContextRef: layoutContextRef, parentRenderContext: parentRenderContext, isImplicit: node.type !== "Container" && enhancedNode.uses === undefined, parentRegisterComponentApi: parentRegisterComponentApi, parentDispatch: parentDispatch, ref: ref, uidInfoRef: uidInfoRef }) }));
733
- }));
734
- /**
735
- * This function is the jolly-joker of the rendering process. It renders a child component
736
- * based on the specified context, which contains the component's definition, the current state,
737
- * and other necessary information.
738
- *
739
- * The function checks a few special cases:
740
- * - <Slot> with a single text node child: it renders the text in the context of the parent component.
741
- * - CDATA text nodes: it renders the text as is without parsing it.
742
- * - TextNode: it extracts the text from the node and renders it.
743
- *
744
- * In other cases, it extracts the component's ID and renders the component as a <ComponentNode>.
745
- *
746
- * As this function passes itself as a renderChild function to the <ComponentNode>, it can render
747
- * nested components recursively.
748
- */
749
- function renderChild({ node, state, dispatch, appContext, lookupAction, lookupSyncCallback, registerComponentApi, renderChild, stateFieldPartChanged, layoutContext, parentRenderContext, memoedVarsRef, cleanup, uidInfoRef, }) {
750
- var _a, _b, _c;
751
- // --- Render only visible components
752
- if (!(0, extractParam_1.shouldKeep)(node.when, state, appContext)) {
753
- return null;
754
- }
755
- // --- We do not parse text nodes specified with CDATA to avoid whitespace collapsing
756
- const nodeValue = (_a = node.props) === null || _a === void 0 ? void 0 : _a.value;
757
- if (node.type === "TextNodeCData") {
758
- return nodeValue !== null && nodeValue !== void 0 ? nodeValue : "";
759
- }
760
- // --- A TextNode value may contain nexted expressions, so we extract it.
761
- if (node.type === "TextNode") {
762
- return (0, extractParam_1.extractParam)(state, nodeValue, appContext, true);
763
- }
764
- // --- Rendering a Slot requires some preparations, as TextNode and
765
- // --- TextNodeCData are virtual nodes. Also, slots may have default templates
766
- // --- to render when no slot children are specified. The following section
767
- // --- handles these cases.
768
- if (node.type === "Slot") {
769
- // --- Check for special Slot cases
770
- let slotChildren;
771
- const templateName = (_b = node.props) === null || _b === void 0 ? void 0 : _b.name;
772
- console.log("templateName", templateName);
773
- if (templateName) {
774
- // --- Let's check the validity of the slot name
775
- if (!templateName.endsWith("Template")) {
776
- throw new Error(`Slot name '${templateName}' is not valid. ` +
777
- "A named slot should use a name ending with 'Template'.");
778
- }
779
- // --- Named slot: use a template property from the parent component
780
- slotChildren = (_c = parentRenderContext === null || parentRenderContext === void 0 ? void 0 : parentRenderContext.props) === null || _c === void 0 ? void 0 : _c[templateName];
781
- }
782
- else {
783
- // --- Children slot: use the children of the parent component
784
- slotChildren = parentRenderContext === null || parentRenderContext === void 0 ? void 0 : parentRenderContext.children;
785
- }
786
- if (!slotChildren) {
787
- // --- No children to render, let's try the default slot template (if there is any)
788
- slotChildren = node.children;
789
- }
790
- if (slotChildren) {
791
- const toRender = Array.isArray(slotChildren) ? slotChildren : [slotChildren];
792
- // --- Check for the virtual nodes. At this point, parentRendererContext is
793
- // --- undefined when the parent does not provide slot children. In this case,
794
- // --- the ComponentBed component will render the default slot template.
795
- if (toRender.length === 1 && parentRenderContext) {
796
- if (toRender[0].type === "TextNodeCData" || toRender[0].type === "TextNode") {
797
- // --- Preserve the text and render it in the parent context
798
- return parentRenderContext.renderChild(toRender);
799
- }
800
- }
801
- }
802
- }
803
- // --- In other cases, we extract the component ID, and then render the component.
804
- // --- A component's ID is generally a string with identifier syntax. However, some
805
- // --- internal components have IDs with expressions, so we evaluate them.
806
- const key = (0, extractParam_1.extractParam)(state, node.uid, appContext, true);
807
- return ((0, jsx_runtime_1.jsx)(ComponentNode, { resolvedKey: key, node: node, cleanup: cleanup, stateFieldPartChanged: stateFieldPartChanged, memoedVarsRef: memoedVarsRef, state: state, dispatch: dispatch, appContext: appContext, lookupAction: lookupAction, lookupSyncCallback: lookupSyncCallback, registerComponentApi: registerComponentApi, renderChild: renderChild, layoutContext: layoutContext, parentRenderContext: parentRenderContext, uidInfoRef: uidInfoRef }, key));
808
- }
809
- function transformNodeWithChildDatasource(node) {
810
- var _a;
811
- let didResolve = false;
812
- let loaders = node.loaders;
813
- let children = undefined;
814
- (_a = node.children) === null || _a === void 0 ? void 0 : _a.forEach((child) => {
815
- if ((child === null || child === void 0 ? void 0 : child.type) === "DataSource") {
816
- didResolve = true;
817
- if (!loaders) {
818
- loaders = [];
819
- }
820
- loaders.push({
821
- uid: child.uid,
822
- type: "DataLoader",
823
- props: child.props,
824
- events: child.events,
825
- when: child.when,
826
- });
827
- }
828
- else {
829
- if (!children) {
830
- children = [];
831
- }
832
- children.push(child);
833
- }
834
- });
835
- if (didResolve) {
836
- return Object.assign(Object.assign({}, node), { children,
837
- loaders });
838
- }
839
- return node;
840
- }
841
- function transformNodeWithDataSourceRefProp(node, uidInfoRef) {
842
- if (!node.props) {
843
- return node;
844
- }
845
- let ret = Object.assign({}, node);
846
- let resolved = false;
847
- Object.entries(node.props).forEach(([key, value]) => {
848
- let uidInfoForDatasource;
849
- try {
850
- uidInfoForDatasource = (0, extractParam_1.extractParam)(uidInfoRef.current, value);
851
- }
852
- catch (e) { }
853
- if ((uidInfoForDatasource === null || uidInfoForDatasource === void 0 ? void 0 : uidInfoForDatasource.type) === "loader") {
854
- resolved = true;
855
- ret = Object.assign(Object.assign({}, ret), { props: Object.assign(Object.assign({}, ret.props), { [key]: {
856
- type: "DataSourceRef",
857
- uid: uidInfoForDatasource.uid,
858
- } }) });
859
- }
860
- });
861
- if (resolved) {
862
- return ret;
863
- }
864
- return node;
865
- }
866
- function transformNodeWithDataProp(node, resolvedDataPropIsString, uidInfoRef) {
867
- var _a;
868
- if (!((_a = node.props) === null || _a === void 0 ? void 0 : _a.__DATA_RESOLVED) &&
869
- node.props &&
870
- "data" in node.props &&
871
- resolvedDataPropIsString) {
872
- //we skip the transformation if the data prop is a binding expression for a loader value
873
- if ((0, extractParam_1.extractParam)(uidInfoRef.current, node.props.data) === "loaderValue") {
874
- return node;
875
- }
876
- return Object.assign(Object.assign({}, node), { props: Object.assign(Object.assign({}, node.props), { data: {
877
- type: "DataSource",
878
- props: {
879
- url: node.props.data,
880
- },
881
- } }) });
882
- }
883
- return node;
884
- }
885
- function transformNodeWithRawDataProp(node) {
886
- if (node.props && "raw_data" in node.props) {
887
- return Object.assign(Object.assign({}, node), { props: Object.assign(Object.assign({}, node.props), { __DATA_RESOLVED: true, data: node.props.raw_data }) });
888
- }
889
- return node;
890
- }
891
- /**
892
- * The ComponentNode it the outermost React component wrapping an xmlui component.
893
- */
894
- const ComponentNode = (0, react_1.memo)((0, react_1.forwardRef)(function ComponentNode(_a, ref) {
895
- var _b;
896
- var { node, state, dispatch, appContext, lookupAction, lookupSyncCallback, registerComponentApi, renderChild, stateFieldPartChanged, layoutContext, parentRenderContext, memoedVarsRef, resolvedKey, cleanup, uidInfoRef } = _a, rest = __rest(_a, ["node", "state", "dispatch", "appContext", "lookupAction", "lookupSyncCallback", "registerComponentApi", "renderChild", "stateFieldPartChanged", "layoutContext", "parentRenderContext", "memoedVarsRef", "resolvedKey", "cleanup", "uidInfoRef"]);
897
- // --- We pass the layout context to the child components, so we need to
898
- // --- make sure that it is stable
899
- const stableLayoutContext = (0, react_1.useRef)(layoutContext);
900
- // --- Transform the various data sources within the xmlui component definition
901
- const nodeWithTransformedLoaders = (0, react_1.useMemo)(() => {
902
- let transformed = transformNodeWithChildDatasource(node); //if we have an DataSource child, we transform it to a loader on the node
903
- transformed = transformNodeWithDataSourceRefProp(transformed, uidInfoRef);
904
- transformed = transformNodeWithRawDataProp(transformed);
905
- return transformed;
906
- }, [node, uidInfoRef]);
907
- const resolvedDataPropIsString = (0, react_1.useMemo)(() => {
908
- var _a;
909
- const resolvedDataProp = (0, extractParam_1.extractParam)(state, (_a = nodeWithTransformedLoaders.props) === null || _a === void 0 ? void 0 : _a.data, appContext, true);
910
- return typeof resolvedDataProp === "string";
911
- }, [appContext, (_b = nodeWithTransformedLoaders.props) === null || _b === void 0 ? void 0 : _b.data, state]);
912
- const nodeWithTransformedDatasourceProp = (0, react_1.useMemo)(() => {
913
- return transformNodeWithDataProp(nodeWithTransformedLoaders, resolvedDataPropIsString, uidInfoRef);
914
- }, [nodeWithTransformedLoaders, resolvedDataPropIsString, uidInfoRef]);
915
- let renderedChild = null;
916
- if ((0, ContainerComponentDef_1.isContainerLike)(nodeWithTransformedDatasourceProp)) {
917
- renderedChild = ((0, jsx_runtime_1.jsx)(ComponentContainer, { resolvedKey: resolvedKey, node: nodeWithTransformedDatasourceProp, parentState: state, parentDispatch: dispatch, layoutContextRef: stableLayoutContext, parentRenderContext: parentRenderContext, parentStateFieldPartChanged: stateFieldPartChanged, parentRegisterComponentApi: registerComponentApi, uidInfoRef: uidInfoRef, ref: ref }));
918
- }
919
- else {
920
- renderedChild = ((0, jsx_runtime_1.jsx)(ComponentBed_1.default, Object.assign({ onUnmount: cleanup, memoedVarsRef: memoedVarsRef, node: nodeWithTransformedDatasourceProp, state: state, dispatch: dispatch, appContext: appContext, lookupAction: lookupAction, lookupSyncCallback: lookupSyncCallback, registerComponentApi: registerComponentApi, renderChild: renderChild, parentRenderContext: parentRenderContext, layoutContextRef: stableLayoutContext, ref: ref, uidInfoRef: uidInfoRef }, rest)));
921
- }
922
- return renderedChild;
923
- }));
924
- // Extracts the `state` property values defined in a component definition's `uses` property. It uses the specified
925
- // `appContext` when resolving the state values.
926
- function extractScopedState(parentState, uses) {
927
- if (!uses) {
928
- return parentState;
929
- }
930
- if (uses.length === 0) {
931
- return constants_1.EMPTY_OBJECT;
932
- }
933
- return (0, lodash_es_1.pick)(parentState, uses);
934
- }
935
- // This hook combines state properties in a list of states so that a particular state property in a higher
936
- // argument index overrides the same-named state property in a lower argument index.
937
- function useCombinedState(...states) {
938
- const combined = (0, react_1.useMemo)(() => {
939
- let ret = {};
940
- states.forEach((state = constants_1.EMPTY_OBJECT) => {
941
- // console.log("st", state);
942
- if (state !== constants_1.EMPTY_OBJECT) {
943
- ret = Object.assign(Object.assign({}, ret), state);
944
- }
945
- // console.log("ret", ret);
946
- });
947
- return ret;
948
- }, [states]);
949
- return (0, hooks_1.useShallowCompareMemoize)(combined);
950
- }
951
- // This hook combines state properties in a list of states so that a particular state property in a higher
952
- // argument index merges into the same-named state property in a lower argument index.
953
- // This hook combines state properties in a list of states so that a particular state property in a higher
954
- // argument index merges into the same-named state property in a lower argument index.
955
- function useMergedState(localVars, componentState) {
956
- const merged = (0, react_1.useMemo)(() => {
957
- const ret = Object.assign({}, localVars);
958
- Reflect.ownKeys(componentState).forEach((key) => {
959
- const value = componentState[key];
960
- if (ret[key] === undefined) {
961
- ret[key] = value;
962
- }
963
- else {
964
- if ((0, lodash_es_1.isPlainObject)(ret[key]) && (0, lodash_es_1.isPlainObject)(value)) {
965
- ret[key] = (0, lodash_es_1.merge)((0, lodash_es_1.cloneDeep)(ret[key]), value);
966
- }
967
- else if (Array.isArray(ret[key]) && Array.isArray(value)) {
968
- ret[key] = Object.assign([], ret[key], value);
969
- }
970
- else {
971
- ret[key] = value;
972
- }
973
- }
974
- });
975
- return ret;
976
- }, [localVars, componentState]);
977
- return (0, hooks_1.useShallowCompareMemoize)(merged);
978
- }
979
- class ParseVarError extends Error {
980
- constructor(varName, originalError) {
981
- super(`Error on var: ${varName} - ${(originalError === null || originalError === void 0 ? void 0 : originalError.message) || "unknown"}`);
982
- }
983
- }
984
- //true if it's coming from a code behind or a script tag
985
- function isParsedValue(value) {
986
- return value && typeof value === "object" && value[code_behind_collect_1.PARSED_MARK_PROP];
987
- }
988
- // This hook resolves variables to their current value (using binding expression evaluation)
989
- function useVars(vars = constants_1.EMPTY_OBJECT, fnDeps = constants_1.EMPTY_OBJECT, componentState, memoedVars) {
990
- const appContext = (0, AppContext_1.useAppContext)();
991
- const referenceTrackedApi = (0, hooks_1.useReferenceTrackedApi)(componentState);
992
- const resolvedVars = (0, react_1.useMemo)(() => {
993
- const ret = {};
994
- Object.entries(vars).forEach(([key, value]) => {
995
- if (key === "$props") {
996
- // --- We already resolved props in a compound component
997
- ret[key] = value;
998
- }
999
- else {
1000
- if (!isParsedValue(value) && typeof value !== "string") {
1001
- ret[key] = value;
1002
- }
1003
- else {
1004
- // --- Resolve each variable's value, without going into the details of arrays and objects
1005
- if (!memoedVars.current.has(value)) {
1006
- memoedVars.current.set(value, {
1007
- getDependencies: (0, memoize_one_1.default)((value, referenceTrackedApi) => {
1008
- if (isParsedValue(value)) {
1009
- return (0, visitors_1.collectVariableDependencies)(value.tree, referenceTrackedApi);
1010
- }
1011
- // console.log(`GETTING DEPENDENCY FOR ${value} with:`, referenceTrackedApi);
1012
- const params = (0, ParameterParser_1.parseParameterString)(value);
1013
- let ret = new Set();
1014
- params.forEach((param) => {
1015
- if (param.type === "expression") {
1016
- ret = new Set([
1017
- ...ret,
1018
- ...(0, visitors_1.collectVariableDependencies)(param.value, referenceTrackedApi),
1019
- ]);
1020
- }
1021
- });
1022
- return Array.from(ret);
1023
- }),
1024
- obtainValue: (0, memoize_one_1.default)((value, state, appContext, strict, deps, appContextDeps) => {
1025
- // console.log(
1026
- // "VARS, BUST, obtain value called with",
1027
- // value,
1028
- // { state, appContext },
1029
- // {
1030
- // deps,
1031
- // appContextDeps,
1032
- // }
1033
- // );
1034
- try {
1035
- return isParsedValue(value)
1036
- ? (0, eval_tree_sync_1.evalBinding)(value.tree, {
1037
- localContext: state,
1038
- appContext,
1039
- options: {
1040
- defaultToOptionalMemberAccess: true,
1041
- },
1042
- })
1043
- : (0, extractParam_1.extractParam)(state, value, appContext, strict);
1044
- }
1045
- catch (e) {
1046
- console.log(state);
1047
- throw new ParseVarError(value, e);
1048
- }
1049
- }, ([_newExpression, _newState, _newAppContext, _newStrict, newDeps, newAppContextDeps,], [_lastExpression, _lastState, _lastAppContext, _lastStrict, lastDeps, lastAppContextDeps,]) => {
1050
- return ((0, misc_1.shallowCompare)(newDeps, lastDeps) &&
1051
- (0, misc_1.shallowCompare)(newAppContextDeps, lastAppContextDeps));
1052
- }),
1053
- });
1054
- }
1055
- const stateContext = Object.assign(Object.assign({}, ret), componentState);
1056
- let dependencies = [];
1057
- if (fnDeps[key]) {
1058
- dependencies = fnDeps[key];
1059
- }
1060
- else {
1061
- memoedVars.current
1062
- .get(value)
1063
- .getDependencies(value, referenceTrackedApi)
1064
- .forEach((dep) => {
1065
- if (fnDeps[dep]) {
1066
- dependencies.push(...fnDeps[dep]);
1067
- }
1068
- else {
1069
- dependencies.push(dep);
1070
- }
1071
- });
1072
- dependencies = [...new Set(dependencies)];
1073
- }
1074
- const stateDepValues = (0, misc_1.pickFromObject)(stateContext, dependencies);
1075
- const appContextDepValues = (0, misc_1.pickFromObject)(appContext, dependencies);
1076
- // console.log("VARS, obtain value called with", stateDepValues, appContextDepValues);
1077
- ret[key] = memoedVars.current
1078
- .get(value)
1079
- .obtainValue(value, stateContext, appContext, true, stateDepValues, appContextDepValues);
1080
- }
1081
- }
1082
- });
1083
- return ret;
1084
- }, [appContext, componentState, fnDeps, memoedVars, referenceTrackedApi, vars]);
1085
- return (0, hooks_1.useShallowCompareMemoize)(resolvedVars);
1086
- }
1087
- // --- Tests if a particular component (`componentUid`) can sign event (with `eventName`)
1088
- // --- life cycle changes
1089
- function canSignEventLifecycle(componentUid, eventName) {
1090
- return componentUid !== undefined && eventName !== undefined;
1091
- }
1092
- // Signs that a particular component (`uid`) has started running an event handler
1093
- // for the event with `eventName`.
1094
- function eventHandlerStarted(uid, eventName) {
1095
- return {
1096
- type: containers_1.ContainerActionKind.EVENT_HANDLER_STARTED,
1097
- payload: {
1098
- uid,
1099
- eventName,
1100
- },
1101
- };
1102
- }
1103
- // Signs that a particular component (`uid`) has completed running an event handler
1104
- // for the event with `eventName`.
1105
- function eventHandlerCompleted(uid, eventName) {
1106
- return {
1107
- type: containers_1.ContainerActionKind.EVENT_HANDLER_COMPLETED,
1108
- payload: {
1109
- uid,
1110
- eventName,
1111
- },
1112
- };
1113
- }
1114
- // Signs that a particular component (`uid`) has received an error while running an event handler
1115
- // for the event with `eventName`.
1116
- function eventHandlerError(uid, eventName, error) {
1117
- return {
1118
- type: containers_1.ContainerActionKind.EVENT_HANDLER_ERROR,
1119
- payload: {
1120
- uid,
1121
- eventName,
1122
- error,
1123
- },
1124
- };
1125
- }
1126
- // Signs that a particular state part (`path`) has been changed to a new `value` on a `target` object
1127
- // when executing an `action`.
1128
- function statePartChanged(path, value, target, action) {
1129
- return {
1130
- type: containers_1.ContainerActionKind.STATE_PART_CHANGED,
1131
- payload: {
1132
- path,
1133
- value,
1134
- target,
1135
- actionType: action,
1136
- },
1137
- };
1138
- }
1139
- function renderLoaders({ uidInfo, uidInfoRef, loaders = constants_1.EMPTY_ARRAY, componentState, dispatch, appContext, registerComponentApi, lookupAction, lookupSyncCallback, cleanup, memoedVarsRef, }) {
1140
- return loaders.map((loader) => {
1141
- // --- Check for the uniqueness of UIDs
1142
- if (loader === null || loader === void 0 ? void 0 : loader.uid) {
1143
- if (uidInfo[loader.uid]) {
1144
- // --- We have a duplicated ID (another loader)
1145
- throw new Error(`Another ${uidInfo[loader.uid]} definition in this container already uses the uid '${loader.uid}'`);
1146
- }
1147
- uidInfo[loader.uid] = "loader";
1148
- uidInfoRef.current[loader.uid] = {
1149
- type: "loader",
1150
- value: "loaderValue",
1151
- uid: loader.uid,
1152
- };
1153
- }
1154
- // --- Render the current loader
1155
- const renderedLoader = renderLoader({
1156
- loader,
1157
- componentState,
1158
- dispatch,
1159
- appContext,
1160
- registerComponentApi,
1161
- lookupAction,
1162
- lookupSyncCallback,
1163
- memoedVarsRef,
1164
- cleanup,
1165
- });
1166
- // --- Skip loaders with rendering errors
1167
- if (renderedLoader === undefined) {
1168
- return undefined;
1169
- }
1170
- // --- Take care to use a key property for the loader
1171
- return (0, jsx_runtime_1.jsx)(react_1.Fragment, { children: renderedLoader }, loader.uid);
1172
- });
1173
- function renderLoader({ loader, componentState, dispatch, appContext, registerComponentApi, lookupAction, lookupSyncCallback, cleanup, memoedVarsRef, }) {
1174
- // --- For the sake of avoiding further issues
1175
- if (!loader) {
1176
- return null;
1177
- }
1178
- // --- Evaluate "when" to decide if the loader should be rendered
1179
- // --- Render only visible components
1180
- if (!(0, extractParam_1.shouldKeep)(loader.when, componentState, appContext)) {
1181
- return null;
1182
- }
1183
- // --- Use the loader type's renderer function
1184
- return ((0, jsx_runtime_1.jsx)(LoaderComponent_1.LoaderComponent, { onUnmount: cleanup, node: loader, state: componentState, dispatch: dispatch, registerComponentApi: registerComponentApi, lookupAction: lookupAction, lookupSyncCallback: lookupSyncCallback, memoedVarsRef: memoedVarsRef, appContext: appContext }));
1185
- }
1186
- }