@flozy/editor 1.1.7 → 1.1.8
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/Editor/CollaborativeEditor.js +4 -3
- package/dist/Editor/CommonEditor.js +74 -49
- package/dist/Editor/DialogWrapper.js +43 -0
- package/dist/Editor/Elements/CodeToText/HtmlCode.js +0 -2
- package/dist/Editor/Elements/Equation/EquationButton.js +0 -1
- package/dist/Editor/Elements/Signature/SignatureOptions/UploadSignature.js +0 -1
- package/dist/Editor/common/StyleBuilder/index.js +0 -1
- package/dist/Editor/hooks/useTimeout.js +21 -0
- package/dist/Editor/utils/serializer.js +7 -29
- package/package.json +1 -1
|
@@ -16,7 +16,8 @@ const CollaborativeEditor = props => {
|
|
|
16
16
|
onSave,
|
|
17
17
|
user,
|
|
18
18
|
socketURL,
|
|
19
|
-
apiHOST
|
|
19
|
+
apiHOST,
|
|
20
|
+
...rest
|
|
20
21
|
} = props;
|
|
21
22
|
const convertedContent = draftToSlate({
|
|
22
23
|
data: content
|
|
@@ -105,7 +106,6 @@ const CollaborativeEditor = props => {
|
|
|
105
106
|
provider.destroy();
|
|
106
107
|
setConnected(false);
|
|
107
108
|
setMessage("Seems your connection is lost... Reload the page to edit the document...");
|
|
108
|
-
console.log("closed", provider);
|
|
109
109
|
});
|
|
110
110
|
if (authenticated.status === null || !connected === null || !editor) {
|
|
111
111
|
return /*#__PURE__*/_jsx("h1", {
|
|
@@ -122,7 +122,8 @@ const CollaborativeEditor = props => {
|
|
|
122
122
|
otherProps: {
|
|
123
123
|
token: user?.token,
|
|
124
124
|
API_HOST: apiHOST
|
|
125
|
-
}
|
|
125
|
+
},
|
|
126
|
+
...rest
|
|
126
127
|
});
|
|
127
128
|
};
|
|
128
129
|
export default CollaborativeEditor;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
|
2
|
+
import { createEditor } from "slate";
|
|
2
3
|
import { Slate, Editable } from "slate-react";
|
|
3
4
|
import Toolbar from "./Toolbar/Toolbar";
|
|
4
5
|
import { getMarked, getBlock } from "./utils/SlateUtilityFunctions";
|
|
5
|
-
import "./Editor.css";
|
|
6
6
|
import CodeToText from "./Elements/CodeToText/CodeToText";
|
|
7
7
|
import { draftToSlate } from "./utils/draftToSlate";
|
|
8
8
|
import useMentions from "./hooks/useMentions";
|
|
@@ -10,7 +10,10 @@ import MentionsPopup from "./common/MentionsPopup";
|
|
|
10
10
|
import { RemoteCursorOverlay } from "./RemoteCursorOverlay/Overlay";
|
|
11
11
|
import { mentionsEvent, commands } from "./utils/events";
|
|
12
12
|
import withCommon from "./hooks/withCommon";
|
|
13
|
-
import
|
|
13
|
+
import DialogWrapper from "./DialogWrapper";
|
|
14
|
+
import useTimeout from "./hooks/useTimeout";
|
|
15
|
+
import "./Editor.css";
|
|
16
|
+
import { serialize } from "./utils/serializer";
|
|
14
17
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
15
18
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
16
19
|
const Element = props => {
|
|
@@ -34,12 +37,17 @@ const CommonEditor = props => {
|
|
|
34
37
|
onSave,
|
|
35
38
|
editor: collaborativeEditor,
|
|
36
39
|
readOnly,
|
|
37
|
-
otherProps
|
|
40
|
+
otherProps,
|
|
41
|
+
timeoutInMS = 1000
|
|
38
42
|
} = props;
|
|
39
43
|
const convertedContent = draftToSlate({
|
|
40
44
|
data: content
|
|
41
45
|
});
|
|
42
46
|
const [value, setValue] = useState(convertedContent);
|
|
47
|
+
const [lastUpdated, setLastUpdated] = useState(value);
|
|
48
|
+
const [count] = useTimeout({
|
|
49
|
+
timeoutInMS: timeoutInMS
|
|
50
|
+
});
|
|
43
51
|
const editor = useMemo(() => {
|
|
44
52
|
if (collaborativeEditor) return collaborativeEditor;
|
|
45
53
|
return withCommon(createEditor());
|
|
@@ -63,6 +71,11 @@ const CommonEditor = props => {
|
|
|
63
71
|
data: content
|
|
64
72
|
}));
|
|
65
73
|
}, [id, content]);
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
if (count > 0) {
|
|
76
|
+
updateChanges(value);
|
|
77
|
+
}
|
|
78
|
+
}, [count]);
|
|
66
79
|
const [htmlAction, setHtmlAction] = useState({
|
|
67
80
|
showInput: false,
|
|
68
81
|
html: "",
|
|
@@ -82,9 +95,18 @@ const CommonEditor = props => {
|
|
|
82
95
|
const handleEditorChange = newValue => {
|
|
83
96
|
setValue(newValue);
|
|
84
97
|
const isAstChange = editor.operations.some(op => "set_selection" !== op.type);
|
|
85
|
-
if (isAstChange && onSave) {
|
|
98
|
+
if (isAstChange && onSave && timeoutInMS === 0) {
|
|
86
99
|
// send the value to onSave api
|
|
87
|
-
|
|
100
|
+
updateChanges(newValue);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
const updateChanges = newValue => {
|
|
104
|
+
const stringify = JSON.stringify(newValue);
|
|
105
|
+
if (stringify !== lastUpdated) {
|
|
106
|
+
onSave(stringify, {
|
|
107
|
+
text: serialize(newValue)
|
|
108
|
+
});
|
|
109
|
+
setLastUpdated(stringify);
|
|
88
110
|
}
|
|
89
111
|
};
|
|
90
112
|
const customProps = {
|
|
@@ -129,52 +151,55 @@ const CommonEditor = props => {
|
|
|
129
151
|
}, [chars, editor, target, mentions, setMentions]);
|
|
130
152
|
const isReadOnly = readOnly === "readonly";
|
|
131
153
|
const Overlay = collaborativeEditor && !isReadOnly ? RemoteCursorOverlay : React.Fragment;
|
|
132
|
-
return /*#__PURE__*/_jsx(
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
154
|
+
return /*#__PURE__*/_jsx(DialogWrapper, {
|
|
155
|
+
...props,
|
|
156
|
+
children: /*#__PURE__*/_jsx("div", {
|
|
157
|
+
style: {
|
|
158
|
+
display: "flex",
|
|
159
|
+
flexDirection: "column",
|
|
160
|
+
padding: "0 8px"
|
|
161
|
+
},
|
|
162
|
+
children: /*#__PURE__*/_jsxs(Slate, {
|
|
163
|
+
editor: editor,
|
|
164
|
+
initialValue: value,
|
|
165
|
+
onChange: handleEditorChange,
|
|
166
|
+
children: [/*#__PURE__*/_jsxs(Overlay, {
|
|
167
|
+
children: [!isReadOnly ? /*#__PURE__*/_jsx(Toolbar, {
|
|
168
|
+
handleCodeToText: handleCodeToText,
|
|
169
|
+
customProps: customProps
|
|
170
|
+
}) : null, /*#__PURE__*/_jsxs("div", {
|
|
171
|
+
className: "editor-wrapper",
|
|
172
|
+
style: {
|
|
173
|
+
border: "1px solid #f3f3f3",
|
|
174
|
+
background: pageProps?.pageColor || "#FFF",
|
|
175
|
+
color: pageProps?.color || "#000",
|
|
176
|
+
paddingLeft: `${bannerSpacing?.left}px`,
|
|
177
|
+
paddingRight: `${bannerSpacing?.right}px`,
|
|
178
|
+
paddingTop: `${bannerSpacing?.top}px`,
|
|
179
|
+
paddingBottom: `${bannerSpacing?.bottom}px`
|
|
180
|
+
},
|
|
181
|
+
children: [/*#__PURE__*/_jsx(Editable, {
|
|
182
|
+
readOnly: isReadOnly,
|
|
183
|
+
placeholder: "Write something",
|
|
184
|
+
renderElement: renderElement,
|
|
185
|
+
renderLeaf: renderLeaf,
|
|
186
|
+
onKeyDown: onKeyDown
|
|
187
|
+
}), /*#__PURE__*/_jsx(MentionsPopup, {
|
|
188
|
+
mentions: mentions,
|
|
189
|
+
setMentions: setMentions,
|
|
190
|
+
editor: editor,
|
|
191
|
+
target: target,
|
|
192
|
+
index: index,
|
|
193
|
+
chars: chars
|
|
194
|
+
})]
|
|
170
195
|
})]
|
|
196
|
+
}), htmlAction.showInput && /*#__PURE__*/_jsx(CodeToText, {
|
|
197
|
+
...htmlAction,
|
|
198
|
+
handleCodeToText: handleCodeToText
|
|
171
199
|
})]
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
handleCodeToText: handleCodeToText
|
|
175
|
-
})]
|
|
176
|
-
}, id)
|
|
200
|
+
}, id)
|
|
201
|
+
})
|
|
177
202
|
});
|
|
178
203
|
};
|
|
179
|
-
const CHARACTERS = ["Aayla Secura", "Adi Gallia"
|
|
204
|
+
const CHARACTERS = ["Aayla Secura", "Adi Gallia"];
|
|
180
205
|
export default CommonEditor;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Dialog, DialogTitle, DialogContent, DialogActions, IconButton, Grid } from "@mui/material";
|
|
3
|
+
import CloseIcon from "@mui/icons-material/Close";
|
|
4
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
5
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
6
|
+
const DialogWrapper = props => {
|
|
7
|
+
const {
|
|
8
|
+
fullScreen,
|
|
9
|
+
onClose,
|
|
10
|
+
children,
|
|
11
|
+
footer
|
|
12
|
+
} = props;
|
|
13
|
+
return fullScreen ? /*#__PURE__*/_jsxs(Dialog, {
|
|
14
|
+
open: fullScreen,
|
|
15
|
+
fullScreen: fullScreen,
|
|
16
|
+
onClose: onClose,
|
|
17
|
+
children: [/*#__PURE__*/_jsx(DialogTitle, {
|
|
18
|
+
children: /*#__PURE__*/_jsx(Grid, {
|
|
19
|
+
children: /*#__PURE__*/_jsx(Grid, {
|
|
20
|
+
style: {
|
|
21
|
+
display: 'flex',
|
|
22
|
+
justifyContent: 'end'
|
|
23
|
+
},
|
|
24
|
+
children: /*#__PURE__*/_jsx(IconButton, {
|
|
25
|
+
onClick: onClose,
|
|
26
|
+
children: /*#__PURE__*/_jsx(CloseIcon, {})
|
|
27
|
+
})
|
|
28
|
+
})
|
|
29
|
+
})
|
|
30
|
+
}), /*#__PURE__*/_jsx(DialogContent, {
|
|
31
|
+
children: children
|
|
32
|
+
}), /*#__PURE__*/_jsx(DialogActions, {
|
|
33
|
+
children: footer
|
|
34
|
+
})]
|
|
35
|
+
}) : children;
|
|
36
|
+
};
|
|
37
|
+
DialogWrapper.defaultProps = {
|
|
38
|
+
fullScreen: false,
|
|
39
|
+
onClose: () => {},
|
|
40
|
+
children: '',
|
|
41
|
+
footer: ''
|
|
42
|
+
};
|
|
43
|
+
export default DialogWrapper;
|
|
@@ -10,7 +10,6 @@ const UploadSignature = props => {
|
|
|
10
10
|
} = props;
|
|
11
11
|
const [base64, setBase64] = useState(null);
|
|
12
12
|
const [uploading, setUploading] = useState(false);
|
|
13
|
-
console.log(customProps);
|
|
14
13
|
const onChange = async e => {
|
|
15
14
|
const file = e.target.files[0];
|
|
16
15
|
const strImage = await convertBase64(file);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
let t = null;
|
|
3
|
+
const useTimeout = props => {
|
|
4
|
+
const {
|
|
5
|
+
timeoutInMS
|
|
6
|
+
} = props;
|
|
7
|
+
const [count, setCount] = useState(0);
|
|
8
|
+
const onReset = () => {
|
|
9
|
+
clearTimeout(t);
|
|
10
|
+
t = setTimeout(() => {
|
|
11
|
+
setCount(count + 1);
|
|
12
|
+
}, timeoutInMS);
|
|
13
|
+
};
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
if (timeoutInMS) {
|
|
16
|
+
onReset();
|
|
17
|
+
}
|
|
18
|
+
}, [timeoutInMS, count]);
|
|
19
|
+
return [count];
|
|
20
|
+
};
|
|
21
|
+
export default useTimeout;
|
|
@@ -1,38 +1,16 @@
|
|
|
1
|
-
import { Text } from "slate";
|
|
2
|
-
import { getBlock, getMarked } from "./SlateUtilityFunctions.js";
|
|
3
|
-
import ReactDOMServer from "react-dom/server";
|
|
4
|
-
const {
|
|
5
|
-
renderToString
|
|
6
|
-
} = ReactDOMServer;
|
|
7
1
|
export const serialize = node => {
|
|
8
2
|
try {
|
|
9
|
-
if (
|
|
10
|
-
|
|
11
|
-
string = renderToString(string);
|
|
12
|
-
return string;
|
|
3
|
+
if (!node?.type && node?.text) {
|
|
4
|
+
return node?.text;
|
|
13
5
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
});
|
|
19
|
-
block = renderToString(block);
|
|
6
|
+
let n = Array.isArray(node) ? node : node?.children;
|
|
7
|
+
n = n && Array.isArray(n) ? n : n ? [n] : [];
|
|
8
|
+
let block = n.map(m => {
|
|
9
|
+
return serialize(m);
|
|
10
|
+
}).join(' ');
|
|
20
11
|
return block;
|
|
21
12
|
} catch (err) {
|
|
22
13
|
console.log(err);
|
|
23
14
|
return null;
|
|
24
15
|
}
|
|
25
|
-
};
|
|
26
|
-
export const serializer = editorValue => {
|
|
27
|
-
if (editorValue.length > 0) {
|
|
28
|
-
return editorValue.map(n => serialize(n)).join("");
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
export const deserializer = body => {
|
|
32
|
-
console.log(body);
|
|
33
|
-
};
|
|
34
|
-
export const convertToHTML = editorWrapper => {
|
|
35
|
-
if (editorWrapper && editorWrapper?.current) {
|
|
36
|
-
return editorWrapper?.current;
|
|
37
|
-
}
|
|
38
16
|
};
|