@flozy/editor 1.1.7 → 1.1.9
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/Editor/CollaborativeEditor.js +4 -3
- package/dist/Editor/CommonEditor.js +75 -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,19 @@ 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
|
+
const text = serialize(newValue);
|
106
|
+
if (stringify !== lastUpdated && count > 0 && text?.trim().length > 3) {
|
107
|
+
onSave(stringify, {
|
108
|
+
text: text
|
109
|
+
});
|
110
|
+
setLastUpdated(stringify);
|
88
111
|
}
|
89
112
|
};
|
90
113
|
const customProps = {
|
@@ -129,52 +152,55 @@ const CommonEditor = props => {
|
|
129
152
|
}, [chars, editor, target, mentions, setMentions]);
|
130
153
|
const isReadOnly = readOnly === "readonly";
|
131
154
|
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
|
-
|
155
|
+
return /*#__PURE__*/_jsx(DialogWrapper, {
|
156
|
+
...props,
|
157
|
+
children: /*#__PURE__*/_jsx("div", {
|
158
|
+
style: {
|
159
|
+
display: "flex",
|
160
|
+
flexDirection: "column",
|
161
|
+
padding: "0 8px"
|
162
|
+
},
|
163
|
+
children: /*#__PURE__*/_jsxs(Slate, {
|
164
|
+
editor: editor,
|
165
|
+
initialValue: value,
|
166
|
+
onChange: handleEditorChange,
|
167
|
+
children: [/*#__PURE__*/_jsxs(Overlay, {
|
168
|
+
children: [!isReadOnly ? /*#__PURE__*/_jsx(Toolbar, {
|
169
|
+
handleCodeToText: handleCodeToText,
|
170
|
+
customProps: customProps
|
171
|
+
}) : null, /*#__PURE__*/_jsxs("div", {
|
172
|
+
className: "editor-wrapper",
|
173
|
+
style: {
|
174
|
+
border: "1px solid #f3f3f3",
|
175
|
+
background: pageProps?.pageColor || "#FFF",
|
176
|
+
color: pageProps?.color || "#000",
|
177
|
+
paddingLeft: `${bannerSpacing?.left}px`,
|
178
|
+
paddingRight: `${bannerSpacing?.right}px`,
|
179
|
+
paddingTop: `${bannerSpacing?.top}px`,
|
180
|
+
paddingBottom: `${bannerSpacing?.bottom}px`
|
181
|
+
},
|
182
|
+
children: [/*#__PURE__*/_jsx(Editable, {
|
183
|
+
readOnly: isReadOnly,
|
184
|
+
placeholder: "Write something",
|
185
|
+
renderElement: renderElement,
|
186
|
+
renderLeaf: renderLeaf,
|
187
|
+
onKeyDown: onKeyDown
|
188
|
+
}), /*#__PURE__*/_jsx(MentionsPopup, {
|
189
|
+
mentions: mentions,
|
190
|
+
setMentions: setMentions,
|
191
|
+
editor: editor,
|
192
|
+
target: target,
|
193
|
+
index: index,
|
194
|
+
chars: chars
|
195
|
+
})]
|
170
196
|
})]
|
197
|
+
}), htmlAction.showInput && /*#__PURE__*/_jsx(CodeToText, {
|
198
|
+
...htmlAction,
|
199
|
+
handleCodeToText: handleCodeToText
|
171
200
|
})]
|
172
|
-
}
|
173
|
-
|
174
|
-
handleCodeToText: handleCodeToText
|
175
|
-
})]
|
176
|
-
}, id)
|
201
|
+
}, id)
|
202
|
+
})
|
177
203
|
});
|
178
204
|
};
|
179
|
-
const CHARACTERS = ["Aayla Secura", "Adi Gallia"
|
205
|
+
const CHARACTERS = ["Aayla Secura", "Adi Gallia"];
|
180
206
|
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(-1);
|
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
|
};
|