@arkcit/engine-react 0.3.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/index.js ADDED
@@ -0,0 +1,1371 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defProps = Object.defineProperties;
3
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
+ var __spreadValues = (a, b) => {
9
+ for (var prop in b || (b = {}))
10
+ if (__hasOwnProp.call(b, prop))
11
+ __defNormalProp(a, prop, b[prop]);
12
+ if (__getOwnPropSymbols)
13
+ for (var prop of __getOwnPropSymbols(b)) {
14
+ if (__propIsEnum.call(b, prop))
15
+ __defNormalProp(a, prop, b[prop]);
16
+ }
17
+ return a;
18
+ };
19
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
+
21
+ // src/materialization/materializeCoverContent.tsx
22
+ import React from "react";
23
+ import { Fragment, jsx } from "react/jsx-runtime";
24
+ var materializeCoverContent = ({
25
+ descriptor,
26
+ renderSafeNode
27
+ }) => {
28
+ const resolvedActionChildren = descriptor.actionNodes.map((child) => /* @__PURE__ */ jsx("span", { className: "inline-flex align-middle", children: renderSafeNode(child) }, child.id));
29
+ const resolvedContentChildren = descriptor.contentNodes.map((child) => /* @__PURE__ */ jsx(React.Fragment, { children: renderSafeNode(child) }, child.id));
30
+ return {
31
+ actions: resolvedActionChildren.length > 0 ? resolvedActionChildren.length === 1 ? resolvedActionChildren[0] : /* @__PURE__ */ jsx(Fragment, { children: resolvedActionChildren }) : void 0,
32
+ children: resolvedContentChildren.length > 0 ? resolvedContentChildren.length === 1 ? resolvedContentChildren[0] : /* @__PURE__ */ jsx(Fragment, { children: resolvedContentChildren }) : null
33
+ };
34
+ };
35
+
36
+ // src/composition/applyContentComposition.tsx
37
+ var applyContentComposition = ({
38
+ node,
39
+ componentProps,
40
+ isStudioRendererContext,
41
+ internalStudioNodeTypes,
42
+ schemaNodes,
43
+ onInlineTextEdit,
44
+ captureFieldFocus,
45
+ renderSafeNode,
46
+ normalizeRenderableChild: normalizeRenderableChild2,
47
+ findNodeById,
48
+ runtime,
49
+ plans: providedPlans,
50
+ dependencies
51
+ }) => {
52
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
53
+ const plans = providedPlans != null ? providedPlans : dependencies.resolveContentCompositionPlan({
54
+ node,
55
+ isStudioRendererContext,
56
+ internalStudioNodeTypes
57
+ });
58
+ if (plans.some((plan) => plan.kind === "button-toggle" && plan.disableOnClick)) {
59
+ delete componentProps.onClick;
60
+ }
61
+ if (plans.some((plan) => plan.kind === "form-field")) {
62
+ const rawProps = (_a = node.props) != null ? _a : {};
63
+ const existingField = componentProps.field && typeof componentProps.field === "object" && !Array.isArray(componentProps.field) ? componentProps.field : {};
64
+ const fieldName = String((_c = (_b = existingField.name) != null ? _b : rawProps.name) != null ? _c : "").trim();
65
+ const fieldType = String((_e = (_d = existingField.type) != null ? _d : rawProps.type) != null ? _e : "text");
66
+ const fallbackLabel = fieldName || "Field";
67
+ const fieldLabel = String((_g = (_f = existingField.label) != null ? _f : rawProps.label) != null ? _g : fallbackLabel);
68
+ componentProps.field = __spreadProps(__spreadValues(__spreadValues({}, rawProps), existingField), {
69
+ name: fieldName || "field",
70
+ type: fieldType,
71
+ label: fieldLabel
72
+ });
73
+ if (componentProps.value === void 0) {
74
+ componentProps.value = (_i = (_h = rawProps.value) != null ? _h : rawProps.defaultValue) != null ? _i : "";
75
+ }
76
+ if (!componentProps.dict || typeof componentProps.dict !== "object" || Array.isArray(componentProps.dict)) {
77
+ componentProps.dict = {
78
+ submit: "Submit",
79
+ reset: "Reset",
80
+ loading: "Loading...",
81
+ success: "Saved",
82
+ search: "Search...",
83
+ noResultToShow: "No result"
84
+ };
85
+ }
86
+ if (!componentProps.onChange) {
87
+ componentProps.onChange = (event) => {
88
+ var _a2;
89
+ captureFieldFocus(event.target);
90
+ const target = event.target;
91
+ const nextValue = target.type === "checkbox" ? Boolean(target.checked) : target.value;
92
+ const findParentFormId = (nodes, targetId, lineage = []) => {
93
+ var _a3, _b2;
94
+ for (const candidate of nodes) {
95
+ const nextLineage = [...lineage, candidate];
96
+ if (candidate.id === targetId) {
97
+ for (let index = nextLineage.length - 2; index >= 0; index -= 1) {
98
+ if (((_a3 = nextLineage[index]) == null ? void 0 : _a3.type) === "Form") {
99
+ return nextLineage[index].id;
100
+ }
101
+ }
102
+ return null;
103
+ }
104
+ if ((_b2 = candidate.children) == null ? void 0 : _b2.length) {
105
+ const found = findParentFormId(candidate.children, targetId, nextLineage);
106
+ if (found) return found;
107
+ }
108
+ }
109
+ return null;
110
+ };
111
+ const parentFormId = findParentFormId(schemaNodes, node.id);
112
+ if (parentFormId && onInlineTextEdit && fieldName) {
113
+ const parentForm = findNodeById(parentFormId, schemaNodes);
114
+ const parentProps = (_a2 = parentForm == null ? void 0 : parentForm.props) != null ? _a2 : {};
115
+ const currentValues = parentProps.values && typeof parentProps.values === "object" && !Array.isArray(parentProps.values) ? parentProps.values : {};
116
+ onInlineTextEdit(parentFormId, "values", __spreadProps(__spreadValues({}, currentValues), {
117
+ [fieldName]: nextValue
118
+ }));
119
+ return;
120
+ }
121
+ onInlineTextEdit == null ? void 0 : onInlineTextEdit(node.id, "value", nextValue);
122
+ };
123
+ }
124
+ }
125
+ const studioFormPlan = plans.find((plan) => plan.kind === "studio-form");
126
+ if ((studioFormPlan == null ? void 0 : studioFormPlan.kind) === "studio-form") {
127
+ return dependencies.renderStudioForm({
128
+ node,
129
+ componentProps,
130
+ visibleChildren: studioFormPlan.visibleChildren,
131
+ runtime,
132
+ onInlineTextEdit,
133
+ captureFieldFocus,
134
+ renderSafeNode
135
+ });
136
+ }
137
+ if (isStudioRendererContext && node.type === "Form" && onInlineTextEdit) {
138
+ const existingStudioConfig = componentProps.studio && typeof componentProps.studio === "object" && !Array.isArray(componentProps.studio) ? componentProps.studio : {};
139
+ componentProps.studio = __spreadProps(__spreadValues({}, existingStudioConfig), {
140
+ onSubmitLabelDoubleClick: () => {
141
+ var _a2, _b2;
142
+ return onInlineTextEdit(
143
+ node.id,
144
+ "dict.submit",
145
+ String(
146
+ (_b2 = (_a2 = componentProps.dict) == null ? void 0 : _a2.submit) != null ? _b2 : "Submit"
147
+ )
148
+ );
149
+ },
150
+ onResetLabelDoubleClick: () => {
151
+ var _a2, _b2;
152
+ return onInlineTextEdit(
153
+ node.id,
154
+ "dict.reset",
155
+ String(
156
+ (_b2 = (_a2 = componentProps.dict) == null ? void 0 : _a2.reset) != null ? _b2 : "Reset"
157
+ )
158
+ );
159
+ }
160
+ });
161
+ }
162
+ const coverPlan = plans.find((plan) => plan.kind === "cover-content");
163
+ if ((coverPlan == null ? void 0 : coverPlan.kind) === "cover-content") {
164
+ const content = materializeCoverContent({
165
+ descriptor: coverPlan.descriptor,
166
+ renderSafeNode
167
+ });
168
+ if (content.actions !== void 0) {
169
+ componentProps.actions = content.actions;
170
+ }
171
+ if (content.children !== null) {
172
+ componentProps.children = content.children;
173
+ } else if (componentProps.children === void 0) {
174
+ componentProps.children = null;
175
+ }
176
+ }
177
+ const scrollRevealPlan = plans.find((plan) => plan.kind === "scroll-reveal");
178
+ if ((scrollRevealPlan == null ? void 0 : scrollRevealPlan.kind) === "scroll-reveal") {
179
+ componentProps.children = dependencies.buildScrollRevealChildren({
180
+ rawChildren: scrollRevealPlan.rawChildren,
181
+ renderSafeNode,
182
+ normalizeRenderableChild: normalizeRenderableChild2,
183
+ fallbackChildren: componentProps.children
184
+ });
185
+ }
186
+ return null;
187
+ };
188
+
189
+ // src/materialization/materializeNavigationContent.tsx
190
+ import React2 from "react";
191
+ import { jsx as jsx2 } from "react/jsx-runtime";
192
+ var materializeAccordionItems = ({
193
+ items,
194
+ renderSafeNode
195
+ }) => items.map((item) => {
196
+ var _a;
197
+ return {
198
+ id: item.id,
199
+ title: item.title,
200
+ disabled: item.disabled,
201
+ content: item.contentKind === "nodes" ? /* @__PURE__ */ jsx2("div", { className: "space-y-2", children: item.contentNodes.map((nested) => /* @__PURE__ */ jsx2(React2.Fragment, { children: renderSafeNode(nested) }, nested.id)) }) : (_a = item.contentText) != null ? _a : ""
202
+ };
203
+ });
204
+ var materializeExpandablePanelContent = ({
205
+ descriptor,
206
+ renderSafeNode
207
+ }) => {
208
+ if (descriptor.kind === "empty") {
209
+ return void 0;
210
+ }
211
+ return /* @__PURE__ */ jsx2("div", { className: "space-y-2", children: descriptor.nodes.map((child) => /* @__PURE__ */ jsx2(React2.Fragment, { children: renderSafeNode(child) }, child.id)) });
212
+ };
213
+
214
+ // src/materialization/materializeTabsContent.tsx
215
+ import React3 from "react";
216
+ import { jsx as jsx3 } from "react/jsx-runtime";
217
+ var materializeTabsContent = ({
218
+ tabs,
219
+ renderSafeNode,
220
+ normalizeRenderableChild: normalizeRenderableChild2
221
+ }) => tabs.map((tab) => ({
222
+ id: tab.id,
223
+ title: tab.title,
224
+ label: tab.label,
225
+ content: tab.contentKind === "nodes" ? tab.contentNodes.length === 1 ? renderSafeNode(tab.contentNodes[0]) : tab.contentNodes.map((child) => /* @__PURE__ */ jsx3(React3.Fragment, { children: renderSafeNode(child) }, child.id)) : normalizeRenderableChild2(tab.fallbackContent)
226
+ }));
227
+
228
+ // src/composition/applyNavigationComposition.tsx
229
+ var applyNavigationComposition = ({
230
+ node,
231
+ componentProps,
232
+ isStudioRendererContext,
233
+ selectedNodeId,
234
+ wizardActiveStepByNodeId,
235
+ accordionOpenIdsByNodeId,
236
+ expandablePanelOpenByNodeId,
237
+ runtime,
238
+ setWizardActiveStepByNodeId,
239
+ setAccordionOpenIdsByNodeId,
240
+ setExpandablePanelOpenByNodeId,
241
+ onNodeClick,
242
+ onInlineTextEdit,
243
+ renderSafeNode,
244
+ normalizeRenderableChild: normalizeRenderableChild2,
245
+ captureFieldFocus,
246
+ setInlineEditing,
247
+ internalStudioNodeTypes,
248
+ plans: providedPlans,
249
+ dependencies
250
+ }) => {
251
+ const plans = providedPlans != null ? providedPlans : dependencies.resolveNavigationCompositionPlan({
252
+ node,
253
+ componentProps,
254
+ internalStudioNodeTypes,
255
+ runtime
256
+ });
257
+ if (plans.some((plan) => plan.kind === "form-wizard")) {
258
+ const openInlineEditorForNodeProp = (targetNodeId, propName, rawValue) => {
259
+ setInlineEditing(dependencies.createInlineEditingState(targetNodeId, propName, rawValue));
260
+ };
261
+ dependencies.configureStudioFormWizard({
262
+ node,
263
+ componentProps,
264
+ isStudioRendererContext,
265
+ selectedNodeId,
266
+ wizardActiveStepByNodeId,
267
+ runtime,
268
+ setWizardActiveStepByNodeId,
269
+ onNodeClick,
270
+ onInlineTextEdit,
271
+ renderSafeNode,
272
+ captureFieldFocus,
273
+ openInlineEditorForNodeProp,
274
+ internalStudioNodeTypes
275
+ });
276
+ }
277
+ const accordionPlan = plans.find((plan) => plan.kind === "accordion");
278
+ if ((accordionPlan == null ? void 0 : accordionPlan.kind) === "accordion") {
279
+ const accordionChildren = accordionPlan.accordionChildren;
280
+ if (accordionChildren.length > 0) {
281
+ if (isStudioRendererContext) {
282
+ dependencies.configureStudioAccordion({
283
+ node,
284
+ componentProps,
285
+ accordionChildren,
286
+ selectedNodeId,
287
+ accordionOpenIdsByNodeId,
288
+ setAccordionOpenIdsByNodeId,
289
+ renderSafeNode
290
+ });
291
+ } else {
292
+ componentProps.items = materializeAccordionItems({
293
+ items: accordionPlan.itemDescriptors,
294
+ renderSafeNode
295
+ });
296
+ }
297
+ }
298
+ }
299
+ const expandablePanelPlan = plans.find((plan) => plan.kind === "expandable-panel");
300
+ if ((expandablePanelPlan == null ? void 0 : expandablePanelPlan.kind) === "expandable-panel") {
301
+ const panelChildren = expandablePanelPlan.panelChildren;
302
+ if (isStudioRendererContext) {
303
+ dependencies.configureStudioExpandablePanel({
304
+ node,
305
+ componentProps,
306
+ panelChildren,
307
+ expandablePanelOpenByNodeId,
308
+ setExpandablePanelOpenByNodeId,
309
+ renderSafeNode
310
+ });
311
+ } else if (panelChildren.length > 0) {
312
+ componentProps.children = materializeExpandablePanelContent({
313
+ descriptor: expandablePanelPlan.contentDescriptor,
314
+ renderSafeNode
315
+ });
316
+ }
317
+ }
318
+ const tabsPlan = plans.find((plan) => plan.kind === "tabs");
319
+ if ((tabsPlan == null ? void 0 : tabsPlan.kind) === "tabs") {
320
+ Object.assign(componentProps, tabsPlan.normalizedComponentProps);
321
+ if (isStudioRendererContext) {
322
+ const tabItems = Array.isArray(componentProps.tabs) ? componentProps.tabs : [];
323
+ dependencies.configureStudioTabs({
324
+ componentProps,
325
+ tabItems,
326
+ rawChildren: tabsPlan.rawChildren,
327
+ runtime,
328
+ renderSafeNode,
329
+ normalizeRenderableChild: normalizeRenderableChild2
330
+ });
331
+ } else {
332
+ componentProps.tabs = materializeTabsContent({
333
+ tabs: tabsPlan.tabDescriptors,
334
+ renderSafeNode,
335
+ normalizeRenderableChild: normalizeRenderableChild2
336
+ });
337
+ delete componentProps.children;
338
+ }
339
+ }
340
+ };
341
+
342
+ // src/directives/applyRenderDirectives.ts
343
+ var applyRenderDirectives = ({
344
+ node,
345
+ componentProps,
346
+ renderBindingProps,
347
+ runtime,
348
+ plans: providedPlans,
349
+ dependencies
350
+ }) => {
351
+ const directives = providedPlans != null ? providedPlans : dependencies.resolveRenderDirectivePlan({
352
+ node,
353
+ renderBindingProps
354
+ });
355
+ for (const directive of directives) {
356
+ if (directive.kind === "rows-columns-binding") {
357
+ dependencies.applyRowsAndColumnsBinding({
358
+ componentProps,
359
+ runtime,
360
+ rowsBindingKey: directive.rowsBindingKey,
361
+ columnsBindingKey: directive.columnsBindingKey
362
+ });
363
+ }
364
+ if (directive.kind === "filter-rows-by-query") {
365
+ dependencies.filterRowsByRuntimeQuery({
366
+ nodeId: directive.nodeId,
367
+ componentProps,
368
+ runtime
369
+ });
370
+ }
371
+ if (directive.kind === "cover-media") {
372
+ componentProps.media = dependencies.buildCoverMedia({
373
+ mediaSource: directive.mediaSource,
374
+ mediaSrc: directive.mediaSrc,
375
+ mediaAlt: directive.mediaAlt
376
+ });
377
+ }
378
+ if (directive.kind === "object-binding") {
379
+ dependencies.applyObjectBinding({
380
+ componentProps,
381
+ runtime,
382
+ bindingKey: directive.bindingKey
383
+ });
384
+ }
385
+ if (directive.kind === "decode-translation-binding") {
386
+ dependencies.applyDecodeTranslationBinding({
387
+ componentProps,
388
+ runtime,
389
+ tagContentTranslationKey: directive.tagContentTranslationKey,
390
+ tagContentTranslationValue: directive.tagContentTranslationValue,
391
+ hrefTranslationKey: directive.hrefTranslationKey,
392
+ hrefTranslationValue: directive.hrefTranslationValue
393
+ });
394
+ }
395
+ }
396
+ };
397
+
398
+ // src/engine/EngineWarningFallback.tsx
399
+ import { jsx as jsx4 } from "react/jsx-runtime";
400
+ var EngineWarningFallback = ({ message }) => /* @__PURE__ */ jsx4(
401
+ "div",
402
+ {
403
+ role: "alert",
404
+ className: "rounded-md border border-amber-300 bg-amber-50 px-3 py-2 text-sm text-amber-900",
405
+ children: message
406
+ }
407
+ );
408
+ var EngineWarningFallback_default = EngineWarningFallback;
409
+
410
+ // src/engine/NodeErrorBoundary.tsx
411
+ import React4 from "react";
412
+ import { jsx as jsx5 } from "react/jsx-runtime";
413
+ var NodeErrorBoundary = class extends React4.Component {
414
+ constructor(props) {
415
+ super(props);
416
+ this.state = { hasError: false };
417
+ }
418
+ static getDerivedStateFromError() {
419
+ return { hasError: true };
420
+ }
421
+ componentDidUpdate(prevProps) {
422
+ if (this.state.hasError && prevProps.resetToken !== this.props.resetToken) {
423
+ this.setState({ hasError: false });
424
+ }
425
+ }
426
+ render() {
427
+ if (!this.state.hasError) return this.props.children;
428
+ return /* @__PURE__ */ jsx5(
429
+ EngineWarningFallback_default,
430
+ {
431
+ message: `Renderer fallback: node "${this.props.nodeType}" (${this.props.nodeId}) failed.`
432
+ }
433
+ );
434
+ }
435
+ };
436
+
437
+ // src/engine/ReactWebEngineRoot.tsx
438
+ import React7, { useRef, useState as useState2 } from "react";
439
+
440
+ // src/rendering/resolveResolvedReactNode.ts
441
+ import {
442
+ resolveResolvedNode
443
+ } from "@arkcit/engine-render-layer";
444
+
445
+ // src/rendering/prepareRenderableChildren.tsx
446
+ import React6 from "react";
447
+ import {
448
+ resolveChildContentDescriptor,
449
+ resolveChildDescriptors
450
+ } from "@arkcit/engine-render-layer";
451
+
452
+ // src/rendering/gridItemWrapperProps.ts
453
+ var getGridItemWrapperProps = (colSpan) => ({
454
+ className: "w-full min-w-0",
455
+ style: {
456
+ gridColumn: `span ${colSpan} / span ${colSpan}`
457
+ }
458
+ });
459
+
460
+ // src/materialization/materializeChildContent.tsx
461
+ import React5 from "react";
462
+ import { Fragment as Fragment2, jsx as jsx6 } from "react/jsx-runtime";
463
+ var materializeChildContent = ({
464
+ descriptor,
465
+ renderSafeNode
466
+ }) => {
467
+ if (descriptor.kind === "empty") {
468
+ return null;
469
+ }
470
+ const renderDescriptor = (childDescriptor) => {
471
+ if (childDescriptor.kind === "grid-item") {
472
+ return /* @__PURE__ */ jsx6("div", __spreadProps(__spreadValues({}, getGridItemWrapperProps(childDescriptor.colSpan)), { children: renderSafeNode(childDescriptor.child) }), childDescriptor.child.id);
473
+ }
474
+ return /* @__PURE__ */ jsx6(React5.Fragment, { children: renderSafeNode(childDescriptor.child) }, childDescriptor.child.id);
475
+ };
476
+ if (descriptor.kind === "single") {
477
+ return renderDescriptor(descriptor.child);
478
+ }
479
+ return /* @__PURE__ */ jsx6(Fragment2, { children: descriptor.children.map(renderDescriptor) });
480
+ };
481
+
482
+ // src/rendering/prepareRenderableChildren.tsx
483
+ import { jsx as jsx7 } from "react/jsx-runtime";
484
+ var prepareRenderableChildren = ({
485
+ node,
486
+ internalStudioNodeTypes,
487
+ renderSafeNode,
488
+ childDescriptors,
489
+ childContentDescriptor
490
+ }) => {
491
+ const resolvedDescriptors = childDescriptors != null ? childDescriptors : resolveChildDescriptors({
492
+ node,
493
+ internalStudioNodeTypes
494
+ });
495
+ const children = resolvedDescriptors.map((descriptor) => {
496
+ if (descriptor.kind === "grid-item") {
497
+ return /* @__PURE__ */ jsx7("div", __spreadProps(__spreadValues({}, getGridItemWrapperProps(descriptor.colSpan)), { children: renderSafeNode(descriptor.child) }), descriptor.child.id);
498
+ }
499
+ return /* @__PURE__ */ jsx7(React6.Fragment, { children: renderSafeNode(descriptor.child) }, descriptor.child.id);
500
+ });
501
+ const resolvedChildContentDescriptor = childContentDescriptor != null ? childContentDescriptor : resolveChildContentDescriptor({
502
+ childDescriptors: resolvedDescriptors
503
+ });
504
+ const resolvedChildContent = materializeChildContent({
505
+ descriptor: resolvedChildContentDescriptor,
506
+ renderSafeNode
507
+ });
508
+ return {
509
+ children,
510
+ resolvedChildContent,
511
+ childDescriptors: resolvedDescriptors,
512
+ childContentDescriptor: resolvedChildContentDescriptor
513
+ };
514
+ };
515
+
516
+ // src/rendering/resolveResolvedReactNode.ts
517
+ var resolveResolvedReactNode = ({
518
+ node,
519
+ runtime,
520
+ registry,
521
+ internalStudioNodeTypes,
522
+ renderSafeNode,
523
+ isStudioRendererContext,
524
+ studioSizing
525
+ }) => {
526
+ const registryEntry = registry[node.type];
527
+ if (!registryEntry) {
528
+ return null;
529
+ }
530
+ const resolvedNode = resolveResolvedNode({
531
+ node,
532
+ runtime,
533
+ internalStudioNodeTypes,
534
+ isStudioRendererContext,
535
+ studioSizing
536
+ });
537
+ const { children, resolvedChildContent } = prepareRenderableChildren({
538
+ node,
539
+ internalStudioNodeTypes,
540
+ renderSafeNode,
541
+ childDescriptors: resolvedNode.childDescriptors,
542
+ childContentDescriptor: resolvedNode.childContentDescriptor
543
+ });
544
+ return __spreadProps(__spreadValues({}, resolvedNode), {
545
+ registryEntry,
546
+ children,
547
+ resolvedChildContent
548
+ });
549
+ };
550
+
551
+ // src/rendering/renderReactNode.tsx
552
+ import { jsx as jsx8 } from "react/jsx-runtime";
553
+ var renderReactNode = ({
554
+ node,
555
+ runtime,
556
+ registry,
557
+ schemaNodes,
558
+ renderSafeNode,
559
+ internalStudioNodeTypes,
560
+ overlaysByNodeId,
561
+ onInlineTextEdit,
562
+ isStudioRendererContext,
563
+ dropdownOpenByNodeId,
564
+ setDropdownOpenByNodeId,
565
+ captureFieldFocus,
566
+ selectedNodeId,
567
+ wizardActiveStepByNodeId,
568
+ accordionOpenIdsByNodeId,
569
+ expandablePanelOpenByNodeId,
570
+ setWizardActiveStepByNodeId,
571
+ setAccordionOpenIdsByNodeId,
572
+ setExpandablePanelOpenByNodeId,
573
+ onNodeClick,
574
+ setInlineEditing,
575
+ studioSizing,
576
+ dependencies
577
+ }) => {
578
+ try {
579
+ const resolvedNode = resolveResolvedReactNode({
580
+ node,
581
+ runtime,
582
+ registry,
583
+ internalStudioNodeTypes,
584
+ renderSafeNode,
585
+ isStudioRendererContext,
586
+ studioSizing
587
+ });
588
+ if (!resolvedNode) {
589
+ return /* @__PURE__ */ jsx8(
590
+ EngineWarningFallback_default,
591
+ {
592
+ message: `Unknown component type "${node.type}" for node "${node.id}".`
593
+ }
594
+ );
595
+ }
596
+ const {
597
+ registryEntry,
598
+ componentProps,
599
+ renderBindingProps,
600
+ children,
601
+ resolvedChildContent,
602
+ contentPlans,
603
+ navigationPlans,
604
+ renderDirectivePlans,
605
+ finalRenderPlans
606
+ } = resolvedNode;
607
+ dependencies.applyStudioOverlayComponentProps({
608
+ node,
609
+ componentProps,
610
+ runtime,
611
+ overlaysByNodeId,
612
+ renderBindingProps,
613
+ resolvedChildContent,
614
+ onInlineTextEdit,
615
+ isStudioRendererContext,
616
+ dropdownOpenByNodeId,
617
+ setDropdownOpenByNodeId
618
+ });
619
+ const contentNode = dependencies.applyContentComposition({
620
+ node,
621
+ componentProps,
622
+ isStudioRendererContext,
623
+ internalStudioNodeTypes,
624
+ schemaNodes,
625
+ onInlineTextEdit,
626
+ captureFieldFocus,
627
+ renderSafeNode,
628
+ normalizeRenderableChild: dependencies.normalizeRenderableChild,
629
+ findNodeById: dependencies.findNodeById,
630
+ runtime,
631
+ plans: contentPlans
632
+ });
633
+ if (contentNode) {
634
+ return contentNode;
635
+ }
636
+ dependencies.applyRenderDirectives({
637
+ node,
638
+ componentProps,
639
+ renderBindingProps,
640
+ runtime,
641
+ plans: renderDirectivePlans
642
+ });
643
+ dependencies.applyNavigationComposition({
644
+ node,
645
+ componentProps,
646
+ isStudioRendererContext,
647
+ selectedNodeId: selectedNodeId != null ? selectedNodeId : null,
648
+ wizardActiveStepByNodeId,
649
+ accordionOpenIdsByNodeId,
650
+ expandablePanelOpenByNodeId,
651
+ runtime,
652
+ setWizardActiveStepByNodeId,
653
+ setAccordionOpenIdsByNodeId,
654
+ setExpandablePanelOpenByNodeId,
655
+ onNodeClick,
656
+ onInlineTextEdit,
657
+ renderSafeNode,
658
+ normalizeRenderableChild: dependencies.normalizeRenderableChild,
659
+ captureFieldFocus,
660
+ setInlineEditing,
661
+ internalStudioNodeTypes,
662
+ plans: navigationPlans
663
+ });
664
+ return dependencies.finalizeRenderedNode({
665
+ node,
666
+ children,
667
+ componentProps,
668
+ registryComponent: registryEntry.Component,
669
+ runtime,
670
+ isStudioRendererContext,
671
+ studioSizing,
672
+ plans: finalRenderPlans
673
+ });
674
+ } catch (e) {
675
+ return /* @__PURE__ */ jsx8(
676
+ EngineWarningFallback_default,
677
+ {
678
+ message: `Renderer fallback: node "${node.type}" (${node.id}) could not be resolved.`
679
+ }
680
+ );
681
+ }
682
+ };
683
+
684
+ // src/hooks/useUIEngineState.ts
685
+ import { useState } from "react";
686
+ var useUIEngineState = () => {
687
+ const [inlineEditing, setInlineEditing] = useState(null);
688
+ const [wizardActiveStepByNodeId, setWizardActiveStepByNodeId] = useState({});
689
+ const [expandablePanelOpenByNodeId, setExpandablePanelOpenByNodeId] = useState({});
690
+ const [accordionOpenIdsByNodeId, setAccordionOpenIdsByNodeId] = useState({});
691
+ const [dropdownOpenByNodeId, setDropdownOpenByNodeId] = useState(
692
+ {}
693
+ );
694
+ return {
695
+ inlineEditing,
696
+ setInlineEditing,
697
+ wizardActiveStepByNodeId,
698
+ setWizardActiveStepByNodeId,
699
+ expandablePanelOpenByNodeId,
700
+ setExpandablePanelOpenByNodeId,
701
+ accordionOpenIdsByNodeId,
702
+ setAccordionOpenIdsByNodeId,
703
+ dropdownOpenByNodeId,
704
+ setDropdownOpenByNodeId
705
+ };
706
+ };
707
+
708
+ // src/engine/ReactWebEngineRoot.tsx
709
+ import { jsx as jsx9 } from "react/jsx-runtime";
710
+ var INTERNAL_STUDIO_NODE_TYPES = /* @__PURE__ */ new Set();
711
+ var STUDIO_CANVAS_OVERLAY_ROOT_ID = "studio-canvas-overlay-root";
712
+ var STUDIO_MIN_WIDTH_PCT = 5;
713
+ var STUDIO_MIN_HEIGHT_PCT = 5;
714
+ var STUDIO_MIN_HEIGHT_PX = 20;
715
+ var NOOP_RUNTIME = {
716
+ get: () => void 0,
717
+ dispatch: () => void 0
718
+ };
719
+ var EMPTY_UI_REGISTRY = {};
720
+ var isFormInteractiveTarget = (target) => {
721
+ if (!target) return false;
722
+ const interactive = target.closest(
723
+ "button,input,textarea,select,option,label,[role='button'],[role='link']"
724
+ );
725
+ if (!interactive) return false;
726
+ return true;
727
+ };
728
+ var FallbackInlineTextEditor = ({
729
+ editing,
730
+ onChange,
731
+ onCancel,
732
+ onCommit
733
+ }) => editing.multiline ? /* @__PURE__ */ jsx9(
734
+ "textarea",
735
+ {
736
+ style: editing.editorStyle,
737
+ value: editing.value,
738
+ autoFocus: true,
739
+ "aria-label": "Inline text editor",
740
+ onChange: (event) => onChange(event.target.value),
741
+ onBlur: onCommit,
742
+ onKeyDown: (event) => {
743
+ if (event.key === "Escape") {
744
+ event.preventDefault();
745
+ onCancel();
746
+ return;
747
+ }
748
+ if (event.key === "Enter" && (event.metaKey || event.ctrlKey)) {
749
+ event.preventDefault();
750
+ onCommit();
751
+ }
752
+ }
753
+ }
754
+ ) : /* @__PURE__ */ jsx9(
755
+ "input",
756
+ {
757
+ style: editing.editorStyle,
758
+ value: editing.value,
759
+ autoFocus: true,
760
+ "aria-label": "Inline text editor",
761
+ onChange: (event) => onChange(event.target.value),
762
+ onBlur: onCommit,
763
+ onKeyDown: (event) => {
764
+ if (event.key === "Escape") {
765
+ event.preventDefault();
766
+ onCancel();
767
+ return;
768
+ }
769
+ if (event.key === "Enter") {
770
+ event.preventDefault();
771
+ onCommit();
772
+ }
773
+ }
774
+ }
775
+ );
776
+ var ReactWebEngineRoot = ({
777
+ schema,
778
+ registry = EMPTY_UI_REGISTRY,
779
+ store,
780
+ onNodeClick,
781
+ onInlineTextEdit,
782
+ onNodeResize,
783
+ onNodeResizeStart,
784
+ onNodeResizeEnd,
785
+ onNodeDragStart,
786
+ onNodeDragOverTarget,
787
+ onNodeDropTarget,
788
+ selectedNodeId = null,
789
+ nodeWrapper,
790
+ dependencies
791
+ }) => {
792
+ var _a;
793
+ const runtime = store != null ? store : NOOP_RUNTIME;
794
+ const NodeWrapper = nodeWrapper != null ? nodeWrapper : dependencies.StudioNodeWrapper;
795
+ const InlineTextEditor = (_a = dependencies.InlineTextEditor) != null ? _a : FallbackInlineTextEditor;
796
+ const isStudioRendererContext = Boolean(
797
+ onNodeClick || onInlineTextEdit || onNodeResize || onNodeDragStart || onNodeDragOverTarget || onNodeDropTarget || selectedNodeId
798
+ );
799
+ const [, setVersion] = useState2(0);
800
+ const {
801
+ inlineEditing,
802
+ setInlineEditing,
803
+ wizardActiveStepByNodeId,
804
+ setWizardActiveStepByNodeId,
805
+ expandablePanelOpenByNodeId,
806
+ setExpandablePanelOpenByNodeId,
807
+ accordionOpenIdsByNodeId,
808
+ setAccordionOpenIdsByNodeId,
809
+ dropdownOpenByNodeId,
810
+ setDropdownOpenByNodeId
811
+ } = useUIEngineState();
812
+ const resizeStateRef = useRef(null);
813
+ const pinchStateRef = useRef(null);
814
+ const pendingFieldFocusRef = useRef(null);
815
+ const { ancestorTypeMembership, overlaysByNodeId, captureFieldFocus } = dependencies.useUIEngineEffects({
816
+ schema,
817
+ runtime,
818
+ onNodeResize,
819
+ onNodeResizeEnd,
820
+ resizeStateRef,
821
+ pendingFieldFocusRef,
822
+ setVersion,
823
+ minWidthPct: STUDIO_MIN_WIDTH_PCT,
824
+ minHeightPct: STUDIO_MIN_HEIGHT_PCT,
825
+ minHeightPx: STUDIO_MIN_HEIGHT_PX
826
+ });
827
+ const renderNode = (node, studioSizing) => renderReactNode({
828
+ node,
829
+ runtime,
830
+ registry,
831
+ schemaNodes: schema.nodes,
832
+ renderSafeNode: renderSafeEngineNode,
833
+ internalStudioNodeTypes: INTERNAL_STUDIO_NODE_TYPES,
834
+ overlaysByNodeId,
835
+ onInlineTextEdit,
836
+ isStudioRendererContext,
837
+ dropdownOpenByNodeId,
838
+ setDropdownOpenByNodeId,
839
+ captureFieldFocus,
840
+ selectedNodeId,
841
+ wizardActiveStepByNodeId,
842
+ accordionOpenIdsByNodeId,
843
+ expandablePanelOpenByNodeId,
844
+ setWizardActiveStepByNodeId,
845
+ setAccordionOpenIdsByNodeId,
846
+ setExpandablePanelOpenByNodeId,
847
+ onNodeClick,
848
+ setInlineEditing,
849
+ studioSizing,
850
+ dependencies: dependencies.renderReactNodeDependencies
851
+ });
852
+ const renderSafeEngineNode = (node) => dependencies.renderSafeNode({
853
+ node,
854
+ registry,
855
+ runtime,
856
+ schemaNodes: schema.nodes,
857
+ renderNode,
858
+ isStudioRendererContext,
859
+ overlaysByNodeId,
860
+ selectedNodeId,
861
+ onNodeClick,
862
+ onInlineTextEdit,
863
+ onNodeResize,
864
+ onNodeResizeStart,
865
+ onNodeResizeEnd,
866
+ inlineEditing,
867
+ setInlineEditing,
868
+ ancestorTypeMembership,
869
+ resizeStateRef,
870
+ pinchStateRef,
871
+ minWidthPct: STUDIO_MIN_WIDTH_PCT,
872
+ minHeightPct: STUDIO_MIN_HEIGHT_PCT,
873
+ minHeightPx: STUDIO_MIN_HEIGHT_PX,
874
+ overlayRootId: STUDIO_CANVAS_OVERLAY_ROOT_ID,
875
+ NodeWrapper,
876
+ InlineTextEditorComponent: InlineTextEditor,
877
+ isFormInteractiveTarget
878
+ });
879
+ return /* @__PURE__ */ jsx9("div", { className: "flex h-full min-w-0 w-full flex-wrap content-start items-start gap-3", children: schema.nodes.map((node) => /* @__PURE__ */ jsx9(React7.Fragment, { children: renderSafeEngineNode(node) }, node.id)) });
880
+ };
881
+
882
+ // src/hooks/useUIEngineEffects.ts
883
+ import { useEffect, useLayoutEffect, useMemo } from "react";
884
+ var useUIEngineEffects = ({
885
+ schema,
886
+ runtime,
887
+ onNodeResize,
888
+ onNodeResizeEnd,
889
+ resizeStateRef,
890
+ pendingFieldFocusRef,
891
+ setVersion,
892
+ minWidthPct,
893
+ minHeightPct,
894
+ minHeightPx,
895
+ dependencies
896
+ }) => {
897
+ const ancestorTypeMembership = useMemo(
898
+ () => dependencies.buildAncestorTypeMembership(schema.nodes, ["Form", "FormWizard", "StepForm"]),
899
+ [dependencies, schema.nodes]
900
+ );
901
+ const overlaysByNodeId = dependencies.readOverlayState(runtime);
902
+ const captureFieldFocus = (target) => {
903
+ pendingFieldFocusRef.current = dependencies.capturePendingFieldFocus(target);
904
+ };
905
+ useLayoutEffect(() => {
906
+ const pending = pendingFieldFocusRef.current;
907
+ if (!pending) return;
908
+ pendingFieldFocusRef.current = null;
909
+ dependencies.restorePendingFieldFocus(pending);
910
+ }, [dependencies, schema, pendingFieldFocusRef]);
911
+ useEffect(() => {
912
+ if (!runtime.subscribe) return;
913
+ return runtime.subscribe(() => {
914
+ setVersion((previous) => previous + 1);
915
+ });
916
+ }, [runtime, setVersion]);
917
+ useEffect(() => {
918
+ if (!onNodeResize) return;
919
+ const handleMouseMove = (event) => {
920
+ const state = resizeStateRef.current;
921
+ if (!state) return;
922
+ const nextSize = dependencies.computeMouseResizeSize({
923
+ state,
924
+ clientX: event.clientX,
925
+ clientY: event.clientY,
926
+ minWidthPct,
927
+ minHeightPct,
928
+ minHeightPx
929
+ });
930
+ resizeStateRef.current = __spreadProps(__spreadValues({}, state), {
931
+ lastSize: nextSize
932
+ });
933
+ onNodeResize(state.nodeId, __spreadValues({
934
+ widthPct: nextSize.widthPct,
935
+ heightPct: nextSize.heightPct
936
+ }, nextSize.heightPx !== void 0 ? { heightPx: nextSize.heightPx } : {}));
937
+ };
938
+ const handleMouseUp = () => {
939
+ const state = resizeStateRef.current;
940
+ if (state == null ? void 0 : state.lastSize) {
941
+ onNodeResizeEnd == null ? void 0 : onNodeResizeEnd(state.nodeId, __spreadValues({
942
+ widthPct: state.lastSize.widthPct,
943
+ heightPct: state.lastSize.heightPct
944
+ }, state.lastSize.heightPx !== void 0 ? { heightPx: state.lastSize.heightPx } : {}));
945
+ }
946
+ resizeStateRef.current = null;
947
+ };
948
+ window.addEventListener("mousemove", handleMouseMove);
949
+ window.addEventListener("mouseup", handleMouseUp);
950
+ return () => {
951
+ window.removeEventListener("mousemove", handleMouseMove);
952
+ window.removeEventListener("mouseup", handleMouseUp);
953
+ };
954
+ }, [
955
+ dependencies,
956
+ minHeightPct,
957
+ minHeightPx,
958
+ minWidthPct,
959
+ onNodeResize,
960
+ onNodeResizeEnd,
961
+ resizeStateRef
962
+ ]);
963
+ return {
964
+ ancestorTypeMembership,
965
+ overlaysByNodeId,
966
+ captureFieldFocus
967
+ };
968
+ };
969
+
970
+ // src/materialization/contentStudio.tsx
971
+ import React8 from "react";
972
+ import { Fragment as Fragment3, jsx as jsx10 } from "react/jsx-runtime";
973
+ var buildCoverMedia = ({
974
+ mediaSource,
975
+ mediaSrc,
976
+ mediaAlt
977
+ }) => {
978
+ if (mediaSource === "none") return void 0;
979
+ if (mediaSource === "image" && mediaSrc) {
980
+ return /* @__PURE__ */ jsx10(
981
+ "img",
982
+ {
983
+ src: mediaSrc,
984
+ alt: mediaAlt || "Cover media",
985
+ className: "h-56 w-full rounded-xl object-cover"
986
+ }
987
+ );
988
+ }
989
+ if (mediaSource === "video" && mediaSrc) {
990
+ return /* @__PURE__ */ jsx10(
991
+ "video",
992
+ {
993
+ src: mediaSrc,
994
+ className: "h-56 w-full rounded-xl object-cover",
995
+ controls: true,
996
+ preload: "metadata"
997
+ }
998
+ );
999
+ }
1000
+ return void 0;
1001
+ };
1002
+ var buildCoverContent = ({
1003
+ rawChildren,
1004
+ renderSafeNode
1005
+ }) => {
1006
+ const actionChildren = rawChildren.filter((child) => child.type === "Button" || child.type === "Link");
1007
+ const contentChildren = rawChildren.filter((child) => child.type !== "Button" && child.type !== "Link");
1008
+ const resolvedActionChildren = actionChildren.map((child) => /* @__PURE__ */ jsx10("span", { className: "inline-flex align-middle", children: renderSafeNode(child) }, child.id));
1009
+ const resolvedContentChildren = contentChildren.map((child) => /* @__PURE__ */ jsx10(React8.Fragment, { children: renderSafeNode(child) }, child.id));
1010
+ return {
1011
+ actions: resolvedActionChildren.length > 0 ? resolvedActionChildren.length === 1 ? resolvedActionChildren[0] : /* @__PURE__ */ jsx10(Fragment3, { children: resolvedActionChildren }) : void 0,
1012
+ children: resolvedContentChildren.length > 0 ? resolvedContentChildren.length === 1 ? resolvedContentChildren[0] : /* @__PURE__ */ jsx10(Fragment3, { children: resolvedContentChildren }) : null
1013
+ };
1014
+ };
1015
+ var buildScrollRevealChildren = ({
1016
+ rawChildren,
1017
+ renderSafeNode,
1018
+ normalizeRenderableChild: normalizeRenderableChild2,
1019
+ fallbackChildren
1020
+ }) => {
1021
+ if (rawChildren.length > 0) {
1022
+ return rawChildren.length === 1 ? /* @__PURE__ */ jsx10(React8.Fragment, { children: renderSafeNode(rawChildren[0]) }, rawChildren[0].id) : /* @__PURE__ */ jsx10(Fragment3, { children: rawChildren.map((child) => /* @__PURE__ */ jsx10(React8.Fragment, { children: renderSafeNode(child) }, child.id)) });
1023
+ }
1024
+ return normalizeRenderableChild2(fallbackChildren);
1025
+ };
1026
+
1027
+ // src/materialization/materializeBoundTable.tsx
1028
+ import React9 from "react";
1029
+
1030
+ // src/rendering/resolveBoundTableData.ts
1031
+ var resolveBoundTableData = ({
1032
+ nodeId,
1033
+ componentProps,
1034
+ runtime
1035
+ }) => {
1036
+ var _a, _b, _c, _d;
1037
+ const rows = Array.isArray(componentProps.rows) ? componentProps.rows : [];
1038
+ const columns = Array.isArray(componentProps.columns) ? componentProps.columns : [];
1039
+ const paginationCandidate = componentProps.pagination;
1040
+ const pagination = paginationCandidate && typeof paginationCandidate === "object" ? paginationCandidate : null;
1041
+ const pageRaw = Number((_a = pagination == null ? void 0 : pagination.page) != null ? _a : 1);
1042
+ const pageSizeRaw = Number(((_b = pagination == null ? void 0 : pagination.pageSize) != null ? _b : rows.length) || 1);
1043
+ const page = Number.isFinite(pageRaw) && pageRaw > 0 ? pageRaw : 1;
1044
+ const pageSize = Number.isFinite(pageSizeRaw) && pageSizeRaw > 0 ? pageSizeRaw : rows.length || 1;
1045
+ const tableQueriesRaw = runtime.get("table.queriesByNodeId");
1046
+ const tableQueries = tableQueriesRaw && typeof tableQueriesRaw === "object" ? tableQueriesRaw : {};
1047
+ const query = String((_d = (_c = tableQueries[nodeId]) != null ? _c : tableQueries.__all__) != null ? _d : "").trim().toLowerCase();
1048
+ const filteredRows = query.length === 0 ? rows : rows.filter(
1049
+ (row) => columns.some((column) => {
1050
+ var _a2;
1051
+ const key = String((_a2 = column.key) != null ? _a2 : "").trim();
1052
+ if (!key) return false;
1053
+ const value = row[key];
1054
+ return String(value != null ? value : "").toLowerCase().includes(query);
1055
+ })
1056
+ );
1057
+ const startIndex = (page - 1) * pageSize;
1058
+ const pagedRows = pagination ? filteredRows.slice(startIndex, startIndex + pageSize) : filteredRows;
1059
+ return {
1060
+ columns,
1061
+ rows,
1062
+ filteredRows,
1063
+ pagedRows,
1064
+ pagination,
1065
+ page,
1066
+ pageSize,
1067
+ query
1068
+ };
1069
+ };
1070
+
1071
+ // src/materialization/materializeBoundTable.tsx
1072
+ var RENDER_INTERNAL_PROP_NAMES = /* @__PURE__ */ new Set([
1073
+ "bindingEnabled",
1074
+ "valueBindingKey",
1075
+ "optionsBindingKey",
1076
+ "useBindingData",
1077
+ "entitiesBindingKey",
1078
+ "videoBindingKey",
1079
+ "mapBindingKey",
1080
+ "productBindingKey",
1081
+ "useTranslationKeys",
1082
+ "tagContentTranslationKey",
1083
+ "tagContentTranslationValue",
1084
+ "hrefTranslationKey",
1085
+ "hrefTranslationValue",
1086
+ "mediaSource",
1087
+ "mediaSrc",
1088
+ "mediaAlt",
1089
+ "rowsBindingKey",
1090
+ "columnsBindingKey"
1091
+ ]);
1092
+ var omitInternalProps = (props) => {
1093
+ const next = __spreadValues({}, props);
1094
+ delete next.__studio;
1095
+ for (const propName of RENDER_INTERNAL_PROP_NAMES) {
1096
+ delete next[propName];
1097
+ }
1098
+ return next;
1099
+ };
1100
+ var materializeBoundTable = ({
1101
+ nodeId,
1102
+ componentProps,
1103
+ runtime,
1104
+ TableComponent
1105
+ }) => {
1106
+ const { columns, pagedRows } = resolveBoundTableData({
1107
+ nodeId,
1108
+ componentProps,
1109
+ runtime
1110
+ });
1111
+ delete componentProps.rows;
1112
+ delete componentProps.columns;
1113
+ delete componentProps.pagination;
1114
+ delete componentProps.rowsBindingKey;
1115
+ delete componentProps.columnsBindingKey;
1116
+ delete componentProps.useBindingData;
1117
+ if (columns.length === 0) return null;
1118
+ delete componentProps.children;
1119
+ const headerNode = React9.createElement(
1120
+ TableComponent.Header,
1121
+ null,
1122
+ React9.createElement(
1123
+ TableComponent.Row,
1124
+ null,
1125
+ ...columns.map(
1126
+ (column, columnIndex) => {
1127
+ var _a, _b, _c;
1128
+ return React9.createElement(
1129
+ TableComponent.Head,
1130
+ { key: `table-head-${String((_a = column.key) != null ? _a : columnIndex)}` },
1131
+ String((_c = (_b = column.header) != null ? _b : column.key) != null ? _c : `Column ${columnIndex + 1}`)
1132
+ );
1133
+ }
1134
+ )
1135
+ )
1136
+ );
1137
+ const bodyNode = React9.createElement(
1138
+ TableComponent.Body,
1139
+ null,
1140
+ ...pagedRows.map(
1141
+ (row, rowIndex) => {
1142
+ var _a;
1143
+ return React9.createElement(
1144
+ TableComponent.Row,
1145
+ { key: `table-row-${String((_a = row.id) != null ? _a : rowIndex)}` },
1146
+ ...columns.map((column, columnIndex) => {
1147
+ var _a2, _b;
1148
+ const key = String((_a2 = column.key) != null ? _a2 : "").trim();
1149
+ const value = key ? row[key] : "";
1150
+ return React9.createElement(
1151
+ TableComponent.Cell,
1152
+ { key: `table-cell-${String((_b = row.id) != null ? _b : rowIndex)}-${key || columnIndex}` },
1153
+ value == null ? "" : String(value)
1154
+ );
1155
+ })
1156
+ );
1157
+ }
1158
+ )
1159
+ );
1160
+ return React9.createElement(
1161
+ TableComponent,
1162
+ omitInternalProps(componentProps),
1163
+ headerNode,
1164
+ bodyNode
1165
+ );
1166
+ };
1167
+
1168
+ // src/materialization/navigationStudio.tsx
1169
+ import React10 from "react";
1170
+ import { jsx as jsx11 } from "react/jsx-runtime";
1171
+ var buildAccordionItems = (accordionChildren, renderSafeNode) => accordionChildren.map((child, index) => {
1172
+ var _a, _b, _c, _d, _e, _f, _g;
1173
+ const childProps = (_a = child.props) != null ? _a : {};
1174
+ return {
1175
+ id: String((_c = (_b = childProps.id) != null ? _b : child.id) != null ? _c : `item-${index + 1}`),
1176
+ title: String((_d = childProps.title) != null ? _d : `Section ${index + 1}`),
1177
+ content: ((_e = child.children) != null ? _e : []).length > 0 ? /* @__PURE__ */ jsx11("div", { className: "space-y-2", children: ((_f = child.children) != null ? _f : []).map((nested) => /* @__PURE__ */ jsx11(React10.Fragment, { children: renderSafeNode(nested) }, nested.id)) }) : String((_g = childProps.content) != null ? _g : ""),
1178
+ disabled: Boolean(childProps.disabled)
1179
+ };
1180
+ });
1181
+ var buildExpandablePanelChildren = (panelChildren, renderSafeNode) => {
1182
+ if (panelChildren.length === 0) return void 0;
1183
+ return /* @__PURE__ */ jsx11("div", { className: "space-y-2", children: panelChildren.map((child) => /* @__PURE__ */ jsx11(React10.Fragment, { children: renderSafeNode(child) }, child.id)) });
1184
+ };
1185
+
1186
+ // src/rendering/finalizeRenderedNode.tsx
1187
+ import React11 from "react";
1188
+
1189
+ // src/rendering/previewLinkBehavior.ts
1190
+ var configurePreviewLinkBehavior = (componentProps) => {
1191
+ const existingOnClick = componentProps.onClick;
1192
+ componentProps.onClick = (event) => {
1193
+ event.preventDefault();
1194
+ if (typeof existingOnClick === "function") {
1195
+ existingOnClick(event);
1196
+ }
1197
+ };
1198
+ };
1199
+
1200
+ // src/rendering/finalizeRenderedNode.tsx
1201
+ var finalizeRenderedNode = ({
1202
+ node,
1203
+ children,
1204
+ componentProps,
1205
+ registryComponent,
1206
+ runtime,
1207
+ isStudioRendererContext,
1208
+ studioSizing,
1209
+ plans: providedPlans,
1210
+ dependencies
1211
+ }) => {
1212
+ const plans = providedPlans != null ? providedPlans : dependencies.resolveFinalRenderPlan({
1213
+ node,
1214
+ componentProps,
1215
+ isStudioRendererContext,
1216
+ studioSizing
1217
+ });
1218
+ for (const plan of plans) {
1219
+ if (plan.kind === "style-sizing") {
1220
+ componentProps.style = plan.style;
1221
+ }
1222
+ if (plan.kind === "configure-studio-link") {
1223
+ configurePreviewLinkBehavior(componentProps);
1224
+ }
1225
+ if (plan.kind === "cleanup-studio-props") {
1226
+ delete componentProps.__studioColSpan;
1227
+ delete componentProps.__studioWrapperClassName;
1228
+ delete componentProps.__studioWidthPct;
1229
+ delete componentProps.__studioHeightPct;
1230
+ delete componentProps.__studioHeightPx;
1231
+ delete componentProps.__studioCardSection;
1232
+ delete componentProps.layout;
1233
+ }
1234
+ }
1235
+ if (plans.some((plan) => plan.kind === "table-fallback")) {
1236
+ const tableNode = materializeBoundTable({
1237
+ nodeId: node.id,
1238
+ componentProps,
1239
+ runtime,
1240
+ TableComponent: registryComponent
1241
+ });
1242
+ if (tableNode) {
1243
+ return tableNode;
1244
+ }
1245
+ }
1246
+ const finalComponentProps = dependencies.omitStudioProps(componentProps);
1247
+ if (children && children.length > 0) {
1248
+ if (node.type === "Cover" || node.type === "Tabs" || node.type === "Accordion") {
1249
+ return React11.createElement(registryComponent, finalComponentProps);
1250
+ }
1251
+ return React11.createElement(registryComponent, finalComponentProps, children);
1252
+ }
1253
+ return React11.createElement(registryComponent, finalComponentProps);
1254
+ };
1255
+
1256
+ // src/rendering/nodeResetToken.ts
1257
+ import { isValidElement } from "react";
1258
+ var buildNodeResetToken = (node) => {
1259
+ var _a, _b, _c, _d, _e, _f;
1260
+ const seen = /* @__PURE__ */ new WeakSet();
1261
+ try {
1262
+ return JSON.stringify(
1263
+ {
1264
+ type: node.type,
1265
+ props: (_a = node.props) != null ? _a : null,
1266
+ events: (_b = node.events) != null ? _b : null,
1267
+ children: (_d = (_c = node.children) == null ? void 0 : _c.map((child) => child.id)) != null ? _d : []
1268
+ },
1269
+ (_key, value) => {
1270
+ if (typeof value === "function") return "[function]";
1271
+ if (isValidElement(value)) return "[react-element]";
1272
+ if (value && typeof value === "object") {
1273
+ if (seen.has(value)) return "[circular]";
1274
+ seen.add(value);
1275
+ }
1276
+ return value;
1277
+ }
1278
+ );
1279
+ } catch (e) {
1280
+ return `${node.type}:${node.id}:${Object.keys((_e = node.props) != null ? _e : {}).join(",")}:${((_f = node.children) != null ? _f : []).map((child) => child.id).join(",")}`;
1281
+ }
1282
+ };
1283
+
1284
+ // src/rendering/renderChildren.tsx
1285
+ import React12, { isValidElement as isValidElement2 } from "react";
1286
+ import { jsx as jsx12 } from "react/jsx-runtime";
1287
+ var toBoolean = (value) => {
1288
+ if (typeof value === "boolean") return value;
1289
+ if (typeof value === "string") return value.toLowerCase() === "true";
1290
+ return false;
1291
+ };
1292
+ var normalizeRenderableChild = (value) => {
1293
+ if (value == null || typeof value === "boolean") return null;
1294
+ if (typeof value === "string" || typeof value === "number") return value;
1295
+ if (isValidElement2(value)) return value;
1296
+ if (Array.isArray(value)) {
1297
+ return value.map((item, index) => /* @__PURE__ */ jsx12(React12.Fragment, { children: normalizeRenderableChild(item) }, `normalized-child-${index}`));
1298
+ }
1299
+ if (value && typeof value === "object") {
1300
+ const candidate = value;
1301
+ if ("props" in candidate && candidate.props && typeof candidate.props === "object") {
1302
+ const nestedChildren = candidate.props.children;
1303
+ return normalizeRenderableChild(nestedChildren);
1304
+ }
1305
+ }
1306
+ return null;
1307
+ };
1308
+
1309
+ // src/rendering/resolveReactNodePlan.ts
1310
+ import { resolveNodeBase } from "@arkcit/engine-render-layer";
1311
+ var resolveReactNodePlan = ({
1312
+ node,
1313
+ runtime,
1314
+ registry,
1315
+ internalStudioNodeTypes,
1316
+ renderSafeNode
1317
+ }) => {
1318
+ const registryEntry = registry[node.type];
1319
+ if (!registryEntry) {
1320
+ return null;
1321
+ }
1322
+ const resolvedNodeBase = resolveNodeBase({
1323
+ node,
1324
+ runtime,
1325
+ internalStudioNodeTypes
1326
+ });
1327
+ const { children, resolvedChildContent } = prepareRenderableChildren({
1328
+ node,
1329
+ internalStudioNodeTypes,
1330
+ renderSafeNode,
1331
+ childDescriptors: resolvedNodeBase.childDescriptors,
1332
+ childContentDescriptor: resolvedNodeBase.childContentDescriptor
1333
+ });
1334
+ return __spreadProps(__spreadValues({}, resolvedNodeBase), {
1335
+ registryEntry,
1336
+ children,
1337
+ resolvedChildContent
1338
+ });
1339
+ };
1340
+ export {
1341
+ EngineWarningFallback_default as EngineWarningFallback,
1342
+ NodeErrorBoundary,
1343
+ ReactWebEngineRoot,
1344
+ applyContentComposition,
1345
+ applyNavigationComposition,
1346
+ applyRenderDirectives,
1347
+ buildAccordionItems,
1348
+ buildCoverContent,
1349
+ buildCoverMedia,
1350
+ buildExpandablePanelChildren,
1351
+ buildNodeResetToken,
1352
+ buildScrollRevealChildren,
1353
+ configurePreviewLinkBehavior,
1354
+ finalizeRenderedNode,
1355
+ getGridItemWrapperProps,
1356
+ materializeAccordionItems,
1357
+ materializeBoundTable,
1358
+ materializeChildContent,
1359
+ materializeCoverContent,
1360
+ materializeExpandablePanelContent,
1361
+ materializeTabsContent,
1362
+ normalizeRenderableChild,
1363
+ prepareRenderableChildren,
1364
+ renderReactNode,
1365
+ resolveBoundTableData,
1366
+ resolveReactNodePlan,
1367
+ resolveResolvedReactNode,
1368
+ toBoolean,
1369
+ useUIEngineEffects,
1370
+ useUIEngineState
1371
+ };