@arkcit/engine-react 0.3.9 → 0.3.10
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/engine.js +128 -3
- package/dist/index.js +131 -6
- package/dist/static-engine.js +8 -1
- package/package.json +1 -1
package/dist/engine.js
CHANGED
|
@@ -58,7 +58,7 @@ var NodeErrorBoundary = class extends React.Component {
|
|
|
58
58
|
};
|
|
59
59
|
|
|
60
60
|
// src/engine/ReactWebEngineRoot.tsx
|
|
61
|
-
import React4, { useRef, useState as useState2 } from "react";
|
|
61
|
+
import React4, { useEffect, useRef, useState as useState2 } from "react";
|
|
62
62
|
|
|
63
63
|
// src/rendering/resolveResolvedReactNode.ts
|
|
64
64
|
import {
|
|
@@ -387,6 +387,111 @@ var useUIEngineState = () => {
|
|
|
387
387
|
};
|
|
388
388
|
};
|
|
389
389
|
|
|
390
|
+
// src/engine/tablistController.ts
|
|
391
|
+
var TAB_ACTION_SELECTOR = '[role="tab"],[data-saas-preview-tab-panel-id]';
|
|
392
|
+
var asHTMLElement = (value) => value instanceof HTMLElement ? value : null;
|
|
393
|
+
var closestHTMLElement = (target, selector) => {
|
|
394
|
+
const element = target;
|
|
395
|
+
return typeof (element == null ? void 0 : element.closest) === "function" ? asHTMLElement(element.closest(selector)) : null;
|
|
396
|
+
};
|
|
397
|
+
var queryByIdOrNodeId = (root, id) => {
|
|
398
|
+
var _a, _b;
|
|
399
|
+
if (!id) return null;
|
|
400
|
+
if (typeof CSS !== "undefined" && typeof CSS.escape === "function") {
|
|
401
|
+
const escapedId = CSS.escape(id);
|
|
402
|
+
return asHTMLElement(root.querySelector(`#${escapedId},[data-node-id="${escapedId}"]`));
|
|
403
|
+
}
|
|
404
|
+
return (_b = (_a = Array.from(root.querySelectorAll("[id]")).find((element) => element.id === id)) != null ? _a : Array.from(root.querySelectorAll("[data-node-id]")).find(
|
|
405
|
+
(element) => element.getAttribute("data-node-id") === id
|
|
406
|
+
)) != null ? _b : null;
|
|
407
|
+
};
|
|
408
|
+
var readHashTargetId = (element) => {
|
|
409
|
+
var _a, _b;
|
|
410
|
+
const href = (_b = (_a = element.getAttribute("href")) == null ? void 0 : _a.trim()) != null ? _b : "";
|
|
411
|
+
const hashIndex = href.indexOf("#");
|
|
412
|
+
return hashIndex >= 0 ? href.slice(hashIndex + 1).trim() : "";
|
|
413
|
+
};
|
|
414
|
+
var readTabPanelId = (element) => {
|
|
415
|
+
var _a, _b;
|
|
416
|
+
return ((_a = element.getAttribute("data-saas-preview-tab-panel-id")) == null ? void 0 : _a.trim()) || ((_b = element.getAttribute("aria-controls")) == null ? void 0 : _b.trim()) || readHashTargetId(element);
|
|
417
|
+
};
|
|
418
|
+
var readTabSectionId = (element) => {
|
|
419
|
+
var _a, _b, _c;
|
|
420
|
+
return ((_a = element.getAttribute("data-saas-preview-tab-section-id")) == null ? void 0 : _a.trim()) || ((_c = (_b = element.closest("[data-saas-preview-tab-section-id]")) == null ? void 0 : _b.getAttribute("data-saas-preview-tab-section-id")) == null ? void 0 : _c.trim()) || "";
|
|
421
|
+
};
|
|
422
|
+
var isDisabledTabAction = (element) => element.getAttribute("aria-disabled") === "true" || element instanceof HTMLButtonElement && element.disabled;
|
|
423
|
+
var getTabListTabs = (tabList) => Array.from(tabList.querySelectorAll('[role="tab"]')).filter(
|
|
424
|
+
(tab) => tab.closest('[role="tablist"]') === tabList
|
|
425
|
+
);
|
|
426
|
+
var findMatchingTab = (root, action) => {
|
|
427
|
+
var _a;
|
|
428
|
+
const panelId = readTabPanelId(action);
|
|
429
|
+
if (!panelId) return null;
|
|
430
|
+
const sectionId = readTabSectionId(action);
|
|
431
|
+
return (_a = Array.from(root.querySelectorAll('[role="tab"]')).find((tab) => {
|
|
432
|
+
if (readTabPanelId(tab) !== panelId) return false;
|
|
433
|
+
return !sectionId || readTabSectionId(tab) === sectionId;
|
|
434
|
+
})) != null ? _a : null;
|
|
435
|
+
};
|
|
436
|
+
var applyTablistSelection = (root, activeTab) => {
|
|
437
|
+
const tabList = activeTab.closest('[role="tablist"]');
|
|
438
|
+
if (!tabList || !root.contains(tabList)) return false;
|
|
439
|
+
const tabs = getTabListTabs(tabList);
|
|
440
|
+
if (!tabs.includes(activeTab) || isDisabledTabAction(activeTab)) return true;
|
|
441
|
+
const panelByTab = /* @__PURE__ */ new Map();
|
|
442
|
+
for (const tab of tabs) {
|
|
443
|
+
const panel = queryByIdOrNodeId(root, readTabPanelId(tab));
|
|
444
|
+
if (panel) {
|
|
445
|
+
panelByTab.set(tab, panel);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
const activePanel = panelByTab.get(activeTab);
|
|
449
|
+
if (!activePanel || panelByTab.size === 0) return false;
|
|
450
|
+
for (const tab of tabs) {
|
|
451
|
+
const selected = tab === activeTab;
|
|
452
|
+
tab.setAttribute("aria-selected", selected ? "true" : "false");
|
|
453
|
+
tab.tabIndex = selected ? 0 : -1;
|
|
454
|
+
}
|
|
455
|
+
for (const panel of panelByTab.values()) {
|
|
456
|
+
const selected = panel === activePanel;
|
|
457
|
+
panel.hidden = !selected;
|
|
458
|
+
panel.setAttribute("aria-hidden", selected ? "false" : "true");
|
|
459
|
+
if (selected) {
|
|
460
|
+
panel.style.removeProperty("display");
|
|
461
|
+
} else {
|
|
462
|
+
panel.style.display = "none";
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
return true;
|
|
466
|
+
};
|
|
467
|
+
var initializeTablistPanels = (root) => {
|
|
468
|
+
var _a, _b;
|
|
469
|
+
const tabLists = Array.from(root.querySelectorAll('[role="tablist"]'));
|
|
470
|
+
for (const tabList of tabLists) {
|
|
471
|
+
const tabs = getTabListTabs(tabList);
|
|
472
|
+
const activeTab = (_b = (_a = tabs.find(
|
|
473
|
+
(tab) => tab.getAttribute("aria-selected") === "true" && !isDisabledTabAction(tab)
|
|
474
|
+
)) != null ? _a : tabs.find((tab) => !isDisabledTabAction(tab))) != null ? _b : null;
|
|
475
|
+
if (activeTab) {
|
|
476
|
+
applyTablistSelection(root, activeTab);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
};
|
|
480
|
+
var bindTablistController = (root) => {
|
|
481
|
+
initializeTablistPanels(root);
|
|
482
|
+
const handleClick = (event) => {
|
|
483
|
+
const action = closestHTMLElement(event.target, TAB_ACTION_SELECTOR);
|
|
484
|
+
if (!action || !root.contains(action) || isDisabledTabAction(action)) return;
|
|
485
|
+
const tab = action.getAttribute("role") === "tab" ? action : findMatchingTab(root, action);
|
|
486
|
+
if (!tab || !applyTablistSelection(root, tab)) return;
|
|
487
|
+
event.preventDefault();
|
|
488
|
+
};
|
|
489
|
+
root.addEventListener("click", handleClick, true);
|
|
490
|
+
return () => {
|
|
491
|
+
root.removeEventListener("click", handleClick, true);
|
|
492
|
+
};
|
|
493
|
+
};
|
|
494
|
+
|
|
390
495
|
// src/engine/ReactWebEngineRoot.tsx
|
|
391
496
|
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
392
497
|
var INTERNAL_STUDIO_NODE_TYPES = /* @__PURE__ */ new Set();
|
|
@@ -494,6 +599,7 @@ var ReactWebEngineRoot = ({
|
|
|
494
599
|
const resizeStateRef = useRef(null);
|
|
495
600
|
const pinchStateRef = useRef(null);
|
|
496
601
|
const pendingFieldFocusRef = useRef(null);
|
|
602
|
+
const rootRef = useRef(null);
|
|
497
603
|
const { ancestorTypeMembership, overlaysByNodeId, captureFieldFocus } = dependencies.useUIEngineEffects({
|
|
498
604
|
schema,
|
|
499
605
|
runtime,
|
|
@@ -558,7 +664,19 @@ var ReactWebEngineRoot = ({
|
|
|
558
664
|
InlineTextEditorComponent: InlineTextEditor,
|
|
559
665
|
isFormInteractiveTarget
|
|
560
666
|
});
|
|
561
|
-
|
|
667
|
+
useEffect(() => {
|
|
668
|
+
const root = rootRef.current;
|
|
669
|
+
return root ? bindTablistController(root) : void 0;
|
|
670
|
+
}, [schema]);
|
|
671
|
+
return /* @__PURE__ */ jsx6(
|
|
672
|
+
"div",
|
|
673
|
+
{
|
|
674
|
+
ref: rootRef,
|
|
675
|
+
"data-arkcit-engine-root": true,
|
|
676
|
+
className: "flex min-w-0 w-full flex-wrap content-start items-start gap-3",
|
|
677
|
+
children: schema.nodes.map((node) => /* @__PURE__ */ jsx6(React4.Fragment, { children: renderSafeEngineNode(node) }, node.id))
|
|
678
|
+
}
|
|
679
|
+
);
|
|
562
680
|
};
|
|
563
681
|
|
|
564
682
|
// src/engine/StaticReactWebEngineRoot.tsx
|
|
@@ -653,7 +771,14 @@ var StaticReactWebEngineRoot = ({
|
|
|
653
771
|
NodeWrapper,
|
|
654
772
|
isFormInteractiveTarget: isFormInteractiveTarget2
|
|
655
773
|
});
|
|
656
|
-
return /* @__PURE__ */ jsx7(
|
|
774
|
+
return /* @__PURE__ */ jsx7(
|
|
775
|
+
"div",
|
|
776
|
+
{
|
|
777
|
+
"data-arkcit-engine-root": true,
|
|
778
|
+
className: "flex min-w-0 w-full flex-wrap content-start items-start gap-3",
|
|
779
|
+
children: schema.nodes.map((node) => /* @__PURE__ */ jsx7(React5.Fragment, { children: renderSafeEngineNode(node) }, node.id))
|
|
780
|
+
}
|
|
781
|
+
);
|
|
657
782
|
};
|
|
658
783
|
export {
|
|
659
784
|
EngineWarningFallback_default as EngineWarningFallback,
|
package/dist/index.js
CHANGED
|
@@ -436,7 +436,7 @@ var NodeErrorBoundary = class extends React4.Component {
|
|
|
436
436
|
};
|
|
437
437
|
|
|
438
438
|
// src/engine/ReactWebEngineRoot.tsx
|
|
439
|
-
import React7, { useRef, useState as useState2 } from "react";
|
|
439
|
+
import React7, { useEffect, useRef, useState as useState2 } from "react";
|
|
440
440
|
|
|
441
441
|
// src/rendering/resolveResolvedReactNode.ts
|
|
442
442
|
import {
|
|
@@ -765,6 +765,111 @@ var useUIEngineState = () => {
|
|
|
765
765
|
};
|
|
766
766
|
};
|
|
767
767
|
|
|
768
|
+
// src/engine/tablistController.ts
|
|
769
|
+
var TAB_ACTION_SELECTOR = '[role="tab"],[data-saas-preview-tab-panel-id]';
|
|
770
|
+
var asHTMLElement = (value) => value instanceof HTMLElement ? value : null;
|
|
771
|
+
var closestHTMLElement = (target, selector) => {
|
|
772
|
+
const element = target;
|
|
773
|
+
return typeof (element == null ? void 0 : element.closest) === "function" ? asHTMLElement(element.closest(selector)) : null;
|
|
774
|
+
};
|
|
775
|
+
var queryByIdOrNodeId = (root, id) => {
|
|
776
|
+
var _a, _b;
|
|
777
|
+
if (!id) return null;
|
|
778
|
+
if (typeof CSS !== "undefined" && typeof CSS.escape === "function") {
|
|
779
|
+
const escapedId = CSS.escape(id);
|
|
780
|
+
return asHTMLElement(root.querySelector(`#${escapedId},[data-node-id="${escapedId}"]`));
|
|
781
|
+
}
|
|
782
|
+
return (_b = (_a = Array.from(root.querySelectorAll("[id]")).find((element) => element.id === id)) != null ? _a : Array.from(root.querySelectorAll("[data-node-id]")).find(
|
|
783
|
+
(element) => element.getAttribute("data-node-id") === id
|
|
784
|
+
)) != null ? _b : null;
|
|
785
|
+
};
|
|
786
|
+
var readHashTargetId = (element) => {
|
|
787
|
+
var _a, _b;
|
|
788
|
+
const href = (_b = (_a = element.getAttribute("href")) == null ? void 0 : _a.trim()) != null ? _b : "";
|
|
789
|
+
const hashIndex = href.indexOf("#");
|
|
790
|
+
return hashIndex >= 0 ? href.slice(hashIndex + 1).trim() : "";
|
|
791
|
+
};
|
|
792
|
+
var readTabPanelId = (element) => {
|
|
793
|
+
var _a, _b;
|
|
794
|
+
return ((_a = element.getAttribute("data-saas-preview-tab-panel-id")) == null ? void 0 : _a.trim()) || ((_b = element.getAttribute("aria-controls")) == null ? void 0 : _b.trim()) || readHashTargetId(element);
|
|
795
|
+
};
|
|
796
|
+
var readTabSectionId = (element) => {
|
|
797
|
+
var _a, _b, _c;
|
|
798
|
+
return ((_a = element.getAttribute("data-saas-preview-tab-section-id")) == null ? void 0 : _a.trim()) || ((_c = (_b = element.closest("[data-saas-preview-tab-section-id]")) == null ? void 0 : _b.getAttribute("data-saas-preview-tab-section-id")) == null ? void 0 : _c.trim()) || "";
|
|
799
|
+
};
|
|
800
|
+
var isDisabledTabAction = (element) => element.getAttribute("aria-disabled") === "true" || element instanceof HTMLButtonElement && element.disabled;
|
|
801
|
+
var getTabListTabs = (tabList) => Array.from(tabList.querySelectorAll('[role="tab"]')).filter(
|
|
802
|
+
(tab) => tab.closest('[role="tablist"]') === tabList
|
|
803
|
+
);
|
|
804
|
+
var findMatchingTab = (root, action) => {
|
|
805
|
+
var _a;
|
|
806
|
+
const panelId = readTabPanelId(action);
|
|
807
|
+
if (!panelId) return null;
|
|
808
|
+
const sectionId = readTabSectionId(action);
|
|
809
|
+
return (_a = Array.from(root.querySelectorAll('[role="tab"]')).find((tab) => {
|
|
810
|
+
if (readTabPanelId(tab) !== panelId) return false;
|
|
811
|
+
return !sectionId || readTabSectionId(tab) === sectionId;
|
|
812
|
+
})) != null ? _a : null;
|
|
813
|
+
};
|
|
814
|
+
var applyTablistSelection = (root, activeTab) => {
|
|
815
|
+
const tabList = activeTab.closest('[role="tablist"]');
|
|
816
|
+
if (!tabList || !root.contains(tabList)) return false;
|
|
817
|
+
const tabs = getTabListTabs(tabList);
|
|
818
|
+
if (!tabs.includes(activeTab) || isDisabledTabAction(activeTab)) return true;
|
|
819
|
+
const panelByTab = /* @__PURE__ */ new Map();
|
|
820
|
+
for (const tab of tabs) {
|
|
821
|
+
const panel = queryByIdOrNodeId(root, readTabPanelId(tab));
|
|
822
|
+
if (panel) {
|
|
823
|
+
panelByTab.set(tab, panel);
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
const activePanel = panelByTab.get(activeTab);
|
|
827
|
+
if (!activePanel || panelByTab.size === 0) return false;
|
|
828
|
+
for (const tab of tabs) {
|
|
829
|
+
const selected = tab === activeTab;
|
|
830
|
+
tab.setAttribute("aria-selected", selected ? "true" : "false");
|
|
831
|
+
tab.tabIndex = selected ? 0 : -1;
|
|
832
|
+
}
|
|
833
|
+
for (const panel of panelByTab.values()) {
|
|
834
|
+
const selected = panel === activePanel;
|
|
835
|
+
panel.hidden = !selected;
|
|
836
|
+
panel.setAttribute("aria-hidden", selected ? "false" : "true");
|
|
837
|
+
if (selected) {
|
|
838
|
+
panel.style.removeProperty("display");
|
|
839
|
+
} else {
|
|
840
|
+
panel.style.display = "none";
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
return true;
|
|
844
|
+
};
|
|
845
|
+
var initializeTablistPanels = (root) => {
|
|
846
|
+
var _a, _b;
|
|
847
|
+
const tabLists = Array.from(root.querySelectorAll('[role="tablist"]'));
|
|
848
|
+
for (const tabList of tabLists) {
|
|
849
|
+
const tabs = getTabListTabs(tabList);
|
|
850
|
+
const activeTab = (_b = (_a = tabs.find(
|
|
851
|
+
(tab) => tab.getAttribute("aria-selected") === "true" && !isDisabledTabAction(tab)
|
|
852
|
+
)) != null ? _a : tabs.find((tab) => !isDisabledTabAction(tab))) != null ? _b : null;
|
|
853
|
+
if (activeTab) {
|
|
854
|
+
applyTablistSelection(root, activeTab);
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
};
|
|
858
|
+
var bindTablistController = (root) => {
|
|
859
|
+
initializeTablistPanels(root);
|
|
860
|
+
const handleClick = (event) => {
|
|
861
|
+
const action = closestHTMLElement(event.target, TAB_ACTION_SELECTOR);
|
|
862
|
+
if (!action || !root.contains(action) || isDisabledTabAction(action)) return;
|
|
863
|
+
const tab = action.getAttribute("role") === "tab" ? action : findMatchingTab(root, action);
|
|
864
|
+
if (!tab || !applyTablistSelection(root, tab)) return;
|
|
865
|
+
event.preventDefault();
|
|
866
|
+
};
|
|
867
|
+
root.addEventListener("click", handleClick, true);
|
|
868
|
+
return () => {
|
|
869
|
+
root.removeEventListener("click", handleClick, true);
|
|
870
|
+
};
|
|
871
|
+
};
|
|
872
|
+
|
|
768
873
|
// src/engine/ReactWebEngineRoot.tsx
|
|
769
874
|
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
770
875
|
var INTERNAL_STUDIO_NODE_TYPES = /* @__PURE__ */ new Set();
|
|
@@ -872,6 +977,7 @@ var ReactWebEngineRoot = ({
|
|
|
872
977
|
const resizeStateRef = useRef(null);
|
|
873
978
|
const pinchStateRef = useRef(null);
|
|
874
979
|
const pendingFieldFocusRef = useRef(null);
|
|
980
|
+
const rootRef = useRef(null);
|
|
875
981
|
const { ancestorTypeMembership, overlaysByNodeId, captureFieldFocus } = dependencies.useUIEngineEffects({
|
|
876
982
|
schema,
|
|
877
983
|
runtime,
|
|
@@ -936,7 +1042,19 @@ var ReactWebEngineRoot = ({
|
|
|
936
1042
|
InlineTextEditorComponent: InlineTextEditor,
|
|
937
1043
|
isFormInteractiveTarget
|
|
938
1044
|
});
|
|
939
|
-
|
|
1045
|
+
useEffect(() => {
|
|
1046
|
+
const root = rootRef.current;
|
|
1047
|
+
return root ? bindTablistController(root) : void 0;
|
|
1048
|
+
}, [schema]);
|
|
1049
|
+
return /* @__PURE__ */ jsx9(
|
|
1050
|
+
"div",
|
|
1051
|
+
{
|
|
1052
|
+
ref: rootRef,
|
|
1053
|
+
"data-arkcit-engine-root": true,
|
|
1054
|
+
className: "flex min-w-0 w-full flex-wrap content-start items-start gap-3",
|
|
1055
|
+
children: schema.nodes.map((node) => /* @__PURE__ */ jsx9(React7.Fragment, { children: renderSafeEngineNode(node) }, node.id))
|
|
1056
|
+
}
|
|
1057
|
+
);
|
|
940
1058
|
};
|
|
941
1059
|
|
|
942
1060
|
// src/engine/StaticReactWebEngineRoot.tsx
|
|
@@ -1031,11 +1149,18 @@ var StaticReactWebEngineRoot = ({
|
|
|
1031
1149
|
NodeWrapper,
|
|
1032
1150
|
isFormInteractiveTarget: isFormInteractiveTarget2
|
|
1033
1151
|
});
|
|
1034
|
-
return /* @__PURE__ */ jsx10(
|
|
1152
|
+
return /* @__PURE__ */ jsx10(
|
|
1153
|
+
"div",
|
|
1154
|
+
{
|
|
1155
|
+
"data-arkcit-engine-root": true,
|
|
1156
|
+
className: "flex min-w-0 w-full flex-wrap content-start items-start gap-3",
|
|
1157
|
+
children: schema.nodes.map((node) => /* @__PURE__ */ jsx10(React8.Fragment, { children: renderSafeEngineNode(node) }, node.id))
|
|
1158
|
+
}
|
|
1159
|
+
);
|
|
1035
1160
|
};
|
|
1036
1161
|
|
|
1037
1162
|
// src/hooks/useUIEngineEffects.ts
|
|
1038
|
-
import { useEffect, useLayoutEffect, useMemo } from "react";
|
|
1163
|
+
import { useEffect as useEffect2, useLayoutEffect, useMemo } from "react";
|
|
1039
1164
|
var useUIEngineEffects = ({
|
|
1040
1165
|
schema,
|
|
1041
1166
|
runtime,
|
|
@@ -1063,13 +1188,13 @@ var useUIEngineEffects = ({
|
|
|
1063
1188
|
pendingFieldFocusRef.current = null;
|
|
1064
1189
|
dependencies.restorePendingFieldFocus(pending);
|
|
1065
1190
|
}, [dependencies, schema, pendingFieldFocusRef]);
|
|
1066
|
-
|
|
1191
|
+
useEffect2(() => {
|
|
1067
1192
|
if (!runtime.subscribe) return;
|
|
1068
1193
|
return runtime.subscribe(() => {
|
|
1069
1194
|
setVersion((previous) => previous + 1);
|
|
1070
1195
|
});
|
|
1071
1196
|
}, [runtime, setVersion]);
|
|
1072
|
-
|
|
1197
|
+
useEffect2(() => {
|
|
1073
1198
|
if (!onNodeResize) return;
|
|
1074
1199
|
const handleMouseMove = (event) => {
|
|
1075
1200
|
const state = resizeStateRef.current;
|
package/dist/static-engine.js
CHANGED
|
@@ -427,7 +427,14 @@ var StaticReactWebEngineRoot = ({
|
|
|
427
427
|
NodeWrapper,
|
|
428
428
|
isFormInteractiveTarget
|
|
429
429
|
});
|
|
430
|
-
return /* @__PURE__ */ jsx5(
|
|
430
|
+
return /* @__PURE__ */ jsx5(
|
|
431
|
+
"div",
|
|
432
|
+
{
|
|
433
|
+
"data-arkcit-engine-root": true,
|
|
434
|
+
className: "flex min-w-0 w-full flex-wrap content-start items-start gap-3",
|
|
435
|
+
children: schema.nodes.map((node) => /* @__PURE__ */ jsx5(React3.Fragment, { children: renderSafeEngineNode(node) }, node.id))
|
|
436
|
+
}
|
|
437
|
+
);
|
|
431
438
|
};
|
|
432
439
|
export {
|
|
433
440
|
StaticReactWebEngineRoot
|