@flozy/editor 3.6.0 → 3.6.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,10 +2,10 @@ import React, { useState, forwardRef, useImperativeHandle } from "react";
2
2
  import { useSlateStatic, ReactEditor } from "slate-react";
3
3
  import { Paper, Popover } from "@mui/material";
4
4
  import data from "@emoji-mart/data";
5
+ import Picker from "@emoji-mart/react";
5
6
  import { insertEmoji } from "../../utils/emoji";
6
7
  import ToolbarIcon from "../../common/ToolbarIcon";
7
8
  import Icon from "../../common/Icon";
8
- import EmojiPicker from "./EmojiPicker";
9
9
  import { jsx as _jsx } from "react/jsx-runtime";
10
10
  import { Fragment as _Fragment } from "react/jsx-runtime";
11
11
  import { jsxs as _jsxs } from "react/jsx-runtime";
@@ -61,7 +61,7 @@ const EmojiButton = /*#__PURE__*/forwardRef((props, ref) => {
61
61
  },
62
62
  onClose: handleClose,
63
63
  children: /*#__PURE__*/_jsx(Paper, {
64
- children: /*#__PURE__*/_jsx(EmojiPicker, {
64
+ children: /*#__PURE__*/_jsx(Picker, {
65
65
  data: data,
66
66
  onEmojiSelect: onEmojiSelect
67
67
  })
@@ -1,16 +0,0 @@
1
- import data from "@emoji-mart/data";
2
- import Picker from "@emoji-mart/react";
3
- import { jsx as _jsx } from "react/jsx-runtime";
4
- import { Fragment as _Fragment } from "react/jsx-runtime";
5
- const EmojiPicker = props => {
6
- const {
7
- onEmojiSelect
8
- } = props;
9
- return /*#__PURE__*/_jsx(_Fragment, {
10
- children: /*#__PURE__*/_jsx(Picker, {
11
- data: data,
12
- onEmojiSelect: onEmojiSelect
13
- })
14
- });
15
- };
16
- export default EmojiPicker;
@@ -243,7 +243,7 @@ export const handleLinkType = (url, linkType, readOnly, openInNewTab, onClick =
243
243
  const [page, section] = url?.split("#") || [];
244
244
  const sec = section ? `#${section}` : "";
245
245
  const currentUserPage = getCurrentUserPage();
246
- props.href = isHomePage(page) ? `./${currentUserPage}${sec}` : `./${url}`;
246
+ props.href = isCurrentPage(page) ? `./${currentUserPage}${sec}` : `./${url}`;
247
247
  if (openInNewTab) {
248
248
  if (isCurrentPage(page)) {
249
249
  // temp fix, if user is presented in current page, open in new tab option is restricted, we will scroll to the element in current page
@@ -1,34 +1,22 @@
1
1
  import { renderToString } from "react-dom/server";
2
- import { getBlock } from "./chatEditor/SlateUtilityFunctions";
2
+ import { getBlock } from "./SlateUtilityFunctions";
3
3
  const serializeToHTML = nodes => {
4
4
  try {
5
- const htmlString = nodes.map(node => {
6
- // Render function for each node
7
- const renderNode = node => {
5
+ const htmlString = nodes.map(n => {
6
+ if (n) {
8
7
  const props = {
9
- element: node,
10
- children: node.children?.map(child => {
11
- // Render each child node
12
- if (child.text !== undefined) {
13
- // For text nodes, return the text
14
- return child.text;
15
- }
16
- // For other nodes, render them recursively
17
- return renderNode(child);
18
- }) || []
8
+ element: n,
9
+ children: n?.children
19
10
  };
20
- return getBlock(props);
21
- };
22
-
23
- // Render root node to HTML string
24
- const reactElement = renderNode(node);
25
- return renderToString(reactElement);
26
- }).join(''); // Combine all HTML strings
27
-
28
- return htmlString;
11
+ const reactString = renderToString(getBlock(props));
12
+ return reactString;
13
+ } else {
14
+ return "";
15
+ }
16
+ });
17
+ console.log(htmlString);
29
18
  } catch (err) {
30
- console.error('Error serializing to HTML:', err);
31
- return '';
19
+ console.log(err);
32
20
  }
33
21
  };
34
22
  export default serializeToHTML;
package/dist/index.js CHANGED
@@ -2,11 +2,7 @@ import Collaborative from "./Editor/CollaborativeEditor";
2
2
  import CommonEditor from "./Editor/CommonEditor";
3
3
  import Mini from "./Editor/MiniEditor";
4
4
  import EditorInFrame from "./Editor/IframeEditor";
5
- import Chat from "./Editor/ChatEditor";
6
- import Emoji from "./Editor/Elements/Emoji/EmojiPicker";
7
5
  export const Editor = CommonEditor;
8
6
  export const MiniEditor = Mini;
9
7
  export const CollaborativeEditor = Collaborative;
10
- export const IframeEditor = EditorInFrame;
11
- export const ChatEditor = Chat;
12
- export const EmojiPicker = Emoji;
8
+ export const IframeEditor = EditorInFrame;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flozy/editor",
3
- "version": "3.6.0",
3
+ "version": "3.6.2",
4
4
  "description": "An Editor for flozy app brain",
5
5
  "files": [
6
6
  "dist"
@@ -1,195 +0,0 @@
1
- import React, { useCallback, useMemo, useRef, useState, useEffect, useImperativeHandle, forwardRef } from "react";
2
- import { Editable, Slate } from 'slate-react';
3
- import { createEditor } from 'slate';
4
- import { useDebounce } from "use-debounce";
5
- import withCommon from "./hooks/withCommon";
6
- import { getBlock, getMarked } from "./utils/chatEditor/SlateUtilityFunctions";
7
- import MiniTextFormat from "./Toolbar/PopupTool/MiniTextFormat";
8
- import { commands, mentionsEvent } from "./utils/events";
9
- import { insertEmoji } from "./utils/emoji";
10
- import { draftToSlate } from "./utils/draftToSlate";
11
- import MentionsPopup from "./common/MentionsPopup";
12
- import { serializeToText } from "./utils/serializeToText";
13
- import useMentions from "./hooks/useMentions";
14
- import Shorthands from "./common/Shorthands";
15
- import usePopupStyle from "./Toolbar/PopupTool/PopupToolStyle";
16
- import { EditorProvider } from "./hooks/useMouseMove";
17
- import { jsx as _jsx } from "react/jsx-runtime";
18
- import { jsxs as _jsxs } from "react/jsx-runtime";
19
- const ChatEditor = /*#__PURE__*/forwardRef((props, ref) => {
20
- const {
21
- id,
22
- theme,
23
- content,
24
- readOnly,
25
- otherProps,
26
- needLayout = false,
27
- toolBar = true,
28
- onSave,
29
- onsubmit
30
- } = props;
31
- const classes = usePopupStyle(theme);
32
- const convertedContent = draftToSlate({
33
- data: content
34
- });
35
- const [isInteracted, setIsInteracted] = useState(false);
36
- const [value, setValue] = useState(convertedContent);
37
- const [loadedValue] = useState(value);
38
- const [deboundedValue] = useDebounce(value, 500);
39
- const editor = useMemo(() => {
40
- return withCommon(createEditor(), {
41
- needLayout
42
- });
43
- }, []);
44
- const isReadOnly = readOnly === "readonly";
45
- useImperativeHandle(ref, () => ({
46
- emojiClick: emoji => {
47
- insertEmoji(editor, emoji?.native, editor.selection);
48
- }
49
- }));
50
- useEffect(() => {
51
- setValue(draftToSlate({
52
- data: content
53
- }));
54
- }, [id, content]);
55
- useEffect(() => {
56
- if (JSON.stringify(loadedValue) !== JSON.stringify(deboundedValue) && isInteracted && onSave) {
57
- const {
58
- value: strVal,
59
- ...restVal
60
- } = getOnSaveData(deboundedValue);
61
- onSave(strVal, restVal);
62
- }
63
- }, [deboundedValue]);
64
- const getOnSaveData = val => {
65
- const text = serializeToText(val);
66
- const title = val?.find(f => f.type === "title");
67
- return {
68
- value: JSON.stringify(val),
69
- text: text,
70
- title: serializeToText(title?.children) || "Untitled"
71
- };
72
- };
73
- const {
74
- CHARACTERS = [],
75
- hideTools
76
- // needLayout = true,
77
- } = otherProps || {};
78
- const mentionsRef = useRef();
79
- const customProps = {
80
- ...(otherProps || {}),
81
- readOnly: isReadOnly,
82
- editorPlaceholder: "Write Something",
83
- page_id: 1
84
- };
85
- const [mentions, setMentions] = useMentions({
86
- editor,
87
- selection: editor?.selection
88
- });
89
- const {
90
- search,
91
- target,
92
- index
93
- } = mentions;
94
- let {
95
- type
96
- } = mentions;
97
- if (type && type === "elements" && hideTools.indexOf("slash") > -1) {
98
- type = null;
99
- }
100
- const chars = type ? Shorthands[type]({
101
- ...mentions,
102
- CHARACTERS,
103
- hideTools: hideTools
104
- }) : [];
105
- const Leaf = ({
106
- attributes,
107
- children,
108
- leaf
109
- }) => {
110
- children = getMarked(leaf, children);
111
- return /*#__PURE__*/_jsx("span", {
112
- ...attributes,
113
- children: children
114
- });
115
- };
116
- const handleEditorChange = newValue => {
117
- setValue(newValue);
118
- if (!isInteracted) {
119
- setIsInteracted(true);
120
- }
121
- };
122
- const Element = props => {
123
- return getBlock(props);
124
- };
125
- const renderElement = useCallback(props => {
126
- return /*#__PURE__*/_jsx(Element, {
127
- ...props,
128
- customProps: customProps
129
- });
130
- }, []);
131
- const renderLeaf = useCallback(props => {
132
- return /*#__PURE__*/_jsx(Leaf, {
133
- ...props,
134
- customProps: customProps
135
- });
136
- }, []);
137
- const onKeyDown = useCallback(event => {
138
- const isMetaKey = event.metaKey && event.keyCode >= 65 && event.keyCode <= 90;
139
- const isCtrlKey = event.ctrlKey || isMetaKey;
140
- if (target && chars.length > 0 && !isCtrlKey) {
141
- mentionsEvent({
142
- event,
143
- mentions,
144
- setMentions,
145
- chars,
146
- target,
147
- editor,
148
- type,
149
- mentionsRef
150
- });
151
- } else if (isCtrlKey) {
152
- commands({
153
- event,
154
- editor
155
- });
156
- } else if (event.key === "Enter") {
157
- onsubmit();
158
- }
159
- }, [chars, editor, target, mentions, setMentions, search, type, mentionsRef]);
160
- const handleClose = () => {};
161
- return /*#__PURE__*/_jsx(EditorProvider, {
162
- theme: theme,
163
- editor: editor,
164
- children: /*#__PURE__*/_jsxs(Slate, {
165
- editor: editor,
166
- initialValue: value,
167
- onChange: handleEditorChange,
168
- children: [toolBar && /*#__PURE__*/_jsx(MiniTextFormat, {
169
- classes: classes,
170
- editor: editor,
171
- closeMainPopup: handleClose
172
- }), /*#__PURE__*/_jsx(Editable, {
173
- className: "chatEditorRoot",
174
- renderElement: renderElement,
175
- renderLeaf: renderLeaf,
176
- placeholder: "Start typing ...",
177
- spellCheck: true,
178
- autoFocus: true,
179
- onKeyDown: onKeyDown
180
- }), !readOnly ? /*#__PURE__*/_jsx(MentionsPopup, {
181
- ref: mentionsRef,
182
- mentions: mentions,
183
- setMentions: setMentions,
184
- editor: editor,
185
- target: target,
186
- index: index,
187
- chars: chars,
188
- type: type,
189
- theme: theme
190
- }) : null]
191
- }, id)
192
- });
193
- });
194
- ChatEditor.displayName = "ChatEditor";
195
- export default ChatEditor;
@@ -1,361 +0,0 @@
1
- import { Editor, Transforms, Element as SlateElement } from "slate";
2
- import { Box } from "@mui/material";
3
- import { fontFamilyMap, sizeMap } from "../font";
4
- import Table from "../../Elements/Table/Table";
5
- import TableRow from "../../Elements/Table/TableRow";
6
- import TableCell from "../../Elements/Table/TableCell";
7
- import Mentions from "../../Elements/Mentions/Mentions";
8
- import CheckList from "../../Elements/List/CheckList";
9
- import { isEmptyTextNode } from "../../helper";
10
- import { getBreakPointsValue } from "../../helper/theme";
11
- import insertNewLine from "../insertNewLine";
12
- import { getBorderColor } from "../helper";
13
- import { jsx as _jsx } from "react/jsx-runtime";
14
- const alignment = ["alignLeft", "alignRight", "alignCenter"];
15
- const list_types = ["orderedList", "unorderedList"];
16
- const LIST_FORMAT_TYPE = {
17
- orderedList: "list-item",
18
- unorderedList: "list-item"
19
- };
20
- const NEWLINESAFTER = ["headingOne", "headingTwo", "headingThree"];
21
- export const toggleBlock = (editor, format, selection = true, attr = {}) => {
22
- const isActive = isBlockActive(editor, format);
23
- const isList = list_types.includes(format);
24
- const isIndent = alignment.includes(format);
25
- const isAligned = alignment.some(alignmentType => isBlockActive(editor, alignmentType));
26
-
27
- /*If the node is already aligned and change in indent is called we should unwrap it first and split the node to prevent
28
- messy, nested DOM structure and bugs due to that.*/
29
- if (isAligned && isIndent) {
30
- Transforms.unwrapNodes(editor, {
31
- match: n => alignment.includes(!Editor.isEditor(n) && SlateElement.isElement(n) && n.type),
32
- split: true
33
- });
34
- }
35
-
36
- /* Wraping the nodes for alignment, to allow it to co-exist with other block level operations*/
37
- if (isIndent) {
38
- Transforms.wrapNodes(editor, {
39
- type: format,
40
- children: []
41
- });
42
- return;
43
- }
44
- Transforms.unwrapNodes(editor, {
45
- match: n => list_types.includes(!Editor.isEditor(n) && SlateElement.isElement(n) && n.type),
46
- split: true
47
- });
48
-
49
- // inserting blocks from "/"" commands remove searched word
50
- if (!selection) {
51
- Transforms.insertText(editor, "");
52
- }
53
- Transforms.setNodes(editor, {
54
- type: isActive ? "paragraph" : isList ? LIST_FORMAT_TYPE[format] : format,
55
- ...attr
56
- });
57
- if (isList && !isActive) {
58
- Transforms.wrapNodes(editor, {
59
- type: format,
60
- children: []
61
- });
62
- }
63
- if (NEWLINESAFTER.indexOf(format) > -1) {
64
- insertNewLine(editor);
65
- }
66
- };
67
- export const addMarkData = (editor, data) => {
68
- try {
69
- Editor.addMark(editor, data.format, data.value);
70
- } catch (err) {
71
- console.log(err);
72
- }
73
- };
74
- export const toggleMark = (editor, format) => {
75
- const isActive = isMarkActive(editor, format);
76
- if (isActive) {
77
- Editor.removeMark(editor, format);
78
- } else {
79
- Editor.addMark(editor, format, true);
80
- }
81
- };
82
- export const isMarkActive = (editor, format) => {
83
- try {
84
- const marks = Editor.marks(editor);
85
- return marks ? marks[format] === true : false;
86
- } catch (err) {
87
- console.log(err);
88
- return null;
89
- }
90
- };
91
- export const isBlockActive = (editor, format) => {
92
- const [match] = Editor.nodes(editor, {
93
- match: n => !Editor.isEditor(n) && SlateElement.isElement(n) && n.type === format
94
- });
95
- return !!match;
96
- };
97
- export const getBlockActive = (editor, format) => {
98
- const [match] = Editor.nodes(editor, {
99
- match: n => !Editor.isEditor(n) && SlateElement.isElement(n) && n.type === format
100
- });
101
- return {
102
- isActive: !!match,
103
- props: match && match[0]
104
- };
105
- };
106
- export const upateBlockActive = (editor, format, attr = {}) => {
107
- const [match] = Editor.nodes(editor, {
108
- match: n => !Editor.isEditor(n) && SlateElement.isElement(n) && n.type === format
109
- });
110
- if (match && match[1] !== undefined) {
111
- Transforms.setNodes(editor, attr, {
112
- at: match[1]
113
- });
114
- }
115
- };
116
- export const activeMark = (editor, format) => {
117
- const defaultMarkData = {
118
- color: "#000000",
119
- bgColor: "#FFFFFF",
120
- fontSize: "normal",
121
- fontFamily: "PoppinsRegular",
122
- fontWeight: "normal"
123
- };
124
- try {
125
- const marks = Editor.marks(editor);
126
- const defaultValue = defaultMarkData[format];
127
- return marks?.[format] ?? defaultValue;
128
- } catch (err) {
129
- console.log(err);
130
- return null;
131
- }
132
- };
133
- export const getMarked = (leaf, children) => {
134
- const className = leaf?.doublequote ? "doublequote" : "";
135
- if (leaf.bold) {
136
- children = /*#__PURE__*/_jsx("strong", {
137
- children: children
138
- });
139
- }
140
- if (leaf.code) {
141
- children = /*#__PURE__*/_jsx("code", {
142
- children: children
143
- });
144
- }
145
- if (leaf.italic) {
146
- children = /*#__PURE__*/_jsx("em", {
147
- children: children
148
- });
149
- }
150
- if (leaf.strikethrough) {
151
- children = /*#__PURE__*/_jsx("span", {
152
- style: {
153
- textDecoration: "line-through"
154
- },
155
- children: children
156
- });
157
- }
158
- if (leaf.underline) {
159
- children = /*#__PURE__*/_jsx("u", {
160
- children: children
161
- });
162
- }
163
- if (leaf.superscript) {
164
- children = /*#__PURE__*/_jsx("sup", {
165
- children: children
166
- });
167
- }
168
- if (leaf.subscript) {
169
- children = /*#__PURE__*/_jsx("sub", {
170
- children: children
171
- });
172
- }
173
- // cover under single span
174
- if (leaf.color || leaf.bgColor || leaf.fontSize || leaf.fontFamily || leaf.fontWeight || className) {
175
- const family = fontFamilyMap[leaf?.fontFamily];
176
- const textStyles = leaf?.color?.indexOf("gradient") >= 0 ? {
177
- background: leaf?.color?.concat("text"),
178
- WebkitBackgroundClip: "text",
179
- WebkitTextFillColor: "transparent"
180
- } : {
181
- color: leaf.color
182
- };
183
- children = /*#__PURE__*/_jsx("span", {
184
- style: {
185
- background: leaf.bgColor
186
- },
187
- children: /*#__PURE__*/_jsx(Box, {
188
- className: className,
189
- component: "span",
190
- sx: {
191
- fontSize: {
192
- lg: sizeMap[leaf.fontSize] || leaf.fontSize,
193
- ...getBreakPointsValue(leaf.fontSize, null, "overrideText")
194
- },
195
- ...textStyles,
196
- fontFamily: family,
197
- fontWeight: leaf.fontWeight
198
- },
199
- children: children
200
- })
201
- });
202
- }
203
- if (leaf.decoration === "link") {
204
- children = /*#__PURE__*/_jsx("a", {
205
- style: {
206
- cursor: "pointer"
207
- },
208
- rel: "noreferrer",
209
- target: "_blank",
210
- href: leaf.text,
211
- children: children
212
- });
213
- }
214
- return children;
215
- };
216
- export const getBlock = props => {
217
- const {
218
- element,
219
- children
220
- } = props;
221
- const attributes = props.attributes ?? {};
222
- const isEmpty = isEmptyTextNode(element);
223
- switch (element.type) {
224
- case "paragraph":
225
- return /*#__PURE__*/_jsx("p", {
226
- ...attributes,
227
- ...element.attr,
228
- className: `content-editable ${isEmpty ? "empty" : ""}`
229
- // placeholder="paragraph"
230
- ,
231
- children: children
232
- });
233
- case "headingOne":
234
- return /*#__PURE__*/_jsx("h1", {
235
- ...attributes,
236
- ...element.attr,
237
- className: `content-editable ${isEmpty ? "empty" : ""}`
238
- // placeholder="Heading 1"
239
- ,
240
- children: children
241
- });
242
- case "headingTwo":
243
- return /*#__PURE__*/_jsx("h2", {
244
- ...attributes,
245
- ...element.attr,
246
- className: `content-editable ${isEmpty ? "empty" : ""}`
247
- // placeholder="Heading 2"
248
- ,
249
- children: children
250
- });
251
- case "headingThree":
252
- return /*#__PURE__*/_jsx("h3", {
253
- ...attributes,
254
- ...element.attr,
255
- className: `content-editable ${isEmpty ? "empty" : ""}`
256
- // placeholder="Heading 3"
257
- ,
258
- children: children
259
- });
260
- case "blockquote":
261
- return /*#__PURE__*/_jsx("blockquote", {
262
- ...attributes,
263
- ...element.attr,
264
- style: {
265
- // borderColor: element?.color || "transparent",
266
- ...getBorderColor(element?.color || "transparent", 3),
267
- background: element?.bgColor || "none",
268
- padding: `${element?.bgColor ? "16px" : "0px"} 8px`,
269
- borderRadius: `${element?.color ? "0px" : "12px"} 12px 12px ${element?.color ? "0px" : "12px"}`,
270
- margin: `${element?.bgColor ? "16px" : "0px"} 0px`,
271
- width: element?.bgColor ? "calc(100% - 16px)" : "100%",
272
- borderWidth: element?.color ? "0px 0px 0px 3px" : "0px"
273
- },
274
- children: children
275
- });
276
- case "alignLeft":
277
- return /*#__PURE__*/_jsx("div", {
278
- ...attributes,
279
- ...element.attr,
280
- children: children
281
- });
282
- case "alignCenter":
283
- return /*#__PURE__*/_jsx("div", {
284
- style: {
285
- display: "flex",
286
- alignItems: "center",
287
- flexDirection: "column",
288
- textAlign: "center"
289
- },
290
- ...attributes,
291
- ...element.attr,
292
- children: children
293
- });
294
- case "alignRight":
295
- return /*#__PURE__*/_jsx("div", {
296
- style: {
297
- display: "flex",
298
- alignItems: "flex-end",
299
- flexDirection: "column",
300
- textAlign: "right"
301
- },
302
- ...attributes,
303
- ...element.attr,
304
- children: children
305
- });
306
- case "list-item":
307
- const firstChildren = element.children[0] || {};
308
- return /*#__PURE__*/_jsx("li", {
309
- ...attributes,
310
- ...element.attr,
311
- className: `content-editable ${isEmpty ? "empty" : ""}`,
312
- placeholder: "List",
313
- style: {
314
- color: firstChildren?.color
315
- },
316
- children: children
317
- });
318
- case "orderedList":
319
- return /*#__PURE__*/_jsx("ol", {
320
- type: "1",
321
- ...attributes,
322
- children: children
323
- });
324
- case "unorderedList":
325
- return /*#__PURE__*/_jsx("ul", {
326
- ...attributes,
327
- children: children
328
- });
329
- case "check-list-item":
330
- return /*#__PURE__*/_jsx(CheckList, {
331
- ...props,
332
- isEmpty: isEmpty
333
- });
334
- case "table":
335
- return /*#__PURE__*/_jsx(Table, {
336
- ...props
337
- });
338
- case "table-head":
339
- return /*#__PURE__*/_jsx("thead", {
340
- children: children
341
- });
342
- case "table-body":
343
- return /*#__PURE__*/_jsx("tbody", {
344
- children: children
345
- });
346
- case "table-row":
347
- return /*#__PURE__*/_jsx(TableRow, {
348
- ...props
349
- });
350
- case "table-cell":
351
- return /*#__PURE__*/_jsx(TableCell, {
352
- ...props
353
- });
354
- case "mention":
355
- return /*#__PURE__*/_jsx(Mentions, {
356
- ...props
357
- });
358
- default:
359
- return;
360
- }
361
- };