-
Notifications
You must be signed in to change notification settings - Fork 1.9k
/
Copy pathTaipyElement.tsx
112 lines (101 loc) · 4.36 KB
/
TaipyElement.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import React, { ComponentType, useContext, useEffect, useMemo, useRef, useState } from "react";
import { createPortal } from "react-dom";
import { ErrorBoundary } from "react-error-boundary";
import JsxParser from "react-jsx-parser";
import { PageContext, TaipyContext } from "../../../../src/context/taipyContext";
import { Element, ElementActionEnum } from "../../element/elementManager";
import useStore, { getElementAction } from "../../store";
import { getJsx, getTaipyElementId } from "./utils";
import { emptyArray } from "../../../../src/utils";
import ErrorFallback from "../../../../src/utils/ErrorBoundary";
import { getRegisteredComponents } from "../../../../src/components/Taipy";
import { renderError, unregisteredRender } from "../../../../src/components/Taipy/Unregistered";
import "./taipyelements.css";
interface TaipyElementProps {
editMode: boolean;
element: Element;
}
const TaipyElement = (props: TaipyElementProps) => {
const { state } = useContext(TaipyContext);
const [module, setModule] = useState<string>("");
const [jsx, setJsx] = useState<string>("");
const app = useStore((state) => state.app);
const styleHandler = useStore((state) => state.styleHandler);
const prevElement = useRef(props.element);
const renderConfig = useMemo(
() => (props.editMode ? props.element.editModeRenderConfig : props.element.renderConfig),
[props.element, props.editMode],
);
const pageState = useMemo(() => {
return { jsx, module };
}, [jsx, module]);
useEffect(() => {
app && setModule(app.getContext());
}, [app]);
useEffect(() => {
const setJsxAsync = async () => {
if (!app || !renderConfig) {
setJsx("");
return;
}
const res = await getJsx(app, props.element, props.editMode);
setJsx(`${renderConfig.wrapper[0]}${res}${renderConfig.wrapper[1]}`);
};
setJsxAsync();
}, [app, props.editMode, props.element, renderConfig]);
useEffect(() => {
if (prevElement.current === props.element) {
// Initial render
const potentialAction = { action: ElementActionEnum.Add, id: props.element.id, editMode: props.editMode };
app && app.onCanvasReRenderEvent(props.editMode, getElementAction(potentialAction));
} else {
// Modify render
const potentialAction = {
action: ElementActionEnum.Modify,
id: props.element.id,
editMode: props.editMode,
};
app && app.onCanvasReRenderEvent(props.editMode, getElementAction(potentialAction));
}
prevElement.current = props.element;
return () => {
// ComponenetWillUnmount --> delete element
const potentialAction = {
action: ElementActionEnum.Delete,
id: props.element.id,
editMode: props.editMode,
};
app && app.onCanvasReRenderEvent(props.editMode, getElementAction(potentialAction));
};
}, [props.element, app, props.editMode]);
useEffect(() => {
const potentialElementId = getTaipyElementId(props.element.id, props.editMode);
document.getElementById(potentialElementId) &&
styleHandler &&
props.element.styles &&
styleHandler(potentialElementId, props.element.styles);
}, [pageState.jsx, props.element.id, props.editMode, props.element.styles, styleHandler]);
return renderConfig ? (
createPortal(
<PageContext.Provider value={pageState}>
<ErrorBoundary FallbackComponent={ErrorFallback}>
<JsxParser
disableKeyGeneration={true}
bindings={state.data}
components={getRegisteredComponents() as Record<string, ComponentType>}
jsx={pageState.jsx}
renderUnrecognized={unregisteredRender}
allowUnknownElements={false}
renderError={renderError}
blacklistedAttrs={emptyArray}
renderInWrapper={false}
/>
</ErrorBoundary>
</PageContext.Provider>,
renderConfig.root,
)
) : (
<></>
);
};
export default TaipyElement;