@flozy/editor 4.2.2 → 4.2.4

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.
@@ -10,7 +10,7 @@ import { draftToSlate } from "./utils/draftToSlate";
10
10
  import useMentions from "./hooks/useMentions";
11
11
  import MentionsPopup from "./common/MentionsPopup";
12
12
  import { RemoteCursorOverlay } from "./RemoteCursorOverlay/Overlay";
13
- import { mentionsEvent, commands, indentation, escapeEvent, enterEvent } from "./utils/events";
13
+ import { mentionsEvent, commands, indentation, escapeEvent, enterEvent, upArrowEvent, downArrowEvent } from "./utils/events";
14
14
  import withCommon from "./hooks/withCommon";
15
15
  import DialogWrapper from "./DialogWrapper";
16
16
  import { serializeToText } from "./utils/serializeToText";
@@ -379,6 +379,10 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
379
379
  });
380
380
  }
381
381
  }
382
+ } else if (event.key === "ArrowUp" && otherProps?.tagName !== "Pages") {
383
+ upArrowEvent(event, editor);
384
+ } else if (event.key === "ArrowDown" && otherProps?.tagName !== "Pages") {
385
+ downArrowEvent(event, editor);
382
386
  }
383
387
  }, [chars, editor, target, mentions, setMentions, search, type, mentionsRef]);
384
388
  const Overlay = collaborativeEditor && !isReadOnly ? RemoteCursorOverlay : React.Fragment;
@@ -47,14 +47,7 @@ const ToolBar = ({
47
47
  })]
48
48
  }) : null;
49
49
  };
50
- const ImageContent = ({
51
- readOnly,
52
- setOpenSettings,
53
- element,
54
- handleImageClick,
55
- onTouchEnd,
56
- path
57
- }) => {
50
+ const ImageContent = props => {
58
51
  const {
59
52
  alt,
60
53
  url,
@@ -64,8 +57,13 @@ const ImageContent = ({
64
57
  boxShadow,
65
58
  frame = null,
66
59
  objectFit,
67
- webAddress
68
- } = element;
60
+ webAddress,
61
+ readOnly,
62
+ setOpenSettings,
63
+ handleImageClick,
64
+ onTouchEnd,
65
+ path
66
+ } = props;
69
67
  const theme = useTheme();
70
68
  return !url && !readOnly ? /*#__PURE__*/_jsxs(Box, {
71
69
  component: "button",
@@ -278,9 +276,9 @@ const Image = ({
278
276
  onSettings: onSettings,
279
277
  setOpenNav: setOpenNav
280
278
  }), /*#__PURE__*/_jsx(ImageContent, {
279
+ ...element,
281
280
  readOnly: readOnly,
282
281
  setOpenSettings: setOpenSettings,
283
- element: element,
284
282
  handleImageClick: handleImageClick,
285
283
  onTouchEnd: onTouchEnd,
286
284
  path: path
@@ -1,4 +1,4 @@
1
- import React, { useState, useEffect } from "react";
1
+ import React, { useState, useEffect, useCallback } from "react";
2
2
  import { useSlateStatic, ReactEditor } from "slate-react";
3
3
  import { Node, Transforms } from "slate";
4
4
  import { IconButton, Tooltip, Box, useTheme } from "@mui/material";
@@ -13,6 +13,66 @@ import { getEmbedURL } from "../../helper";
13
13
  import { getBreakPointsValue, getTRBLBreakPoints, groupByBreakpoint } from "../../helper/theme";
14
14
  import { jsx as _jsx } from "react/jsx-runtime";
15
15
  import { jsxs as _jsxs } from "react/jsx-runtime";
16
+ const VideoContent = props => {
17
+ const {
18
+ resizing,
19
+ borderColor,
20
+ borderWidth,
21
+ borderStyle,
22
+ bgColor,
23
+ embedURL,
24
+ alt,
25
+ videoSX
26
+ } = props;
27
+ return resizing ? /*#__PURE__*/_jsx("div", {
28
+ style: {
29
+ width: "100%",
30
+ height: "100%",
31
+ border: "2px dashed black",
32
+ display: "flex",
33
+ justifyContent: "center",
34
+ alignItems: "center"
35
+ },
36
+ children: /*#__PURE__*/_jsx(Icon, {
37
+ icon: "videoPlayer"
38
+ })
39
+ }) : /*#__PURE__*/_jsx(Box, {
40
+ component: "iframe",
41
+ className: "embedd-iframe",
42
+ sx: {
43
+ border: "none",
44
+ position: "absolute",
45
+ width: "100%",
46
+ height: "100%",
47
+ maxWidth: "100%",
48
+ left: "0px",
49
+ ...(gradientBorder(borderColor) || {}),
50
+ borderWidth: borderWidth || "1px",
51
+ borderStyle: borderStyle || "solid",
52
+ background: bgColor || "transparent",
53
+ ...videoSX
54
+ },
55
+ src: embedURL,
56
+ title: alt
57
+ });
58
+ };
59
+ const VideoPlaceholder = props => {
60
+ const {
61
+ url,
62
+ readOnly,
63
+ onSettings
64
+ } = props;
65
+ return !url && !readOnly ? /*#__PURE__*/_jsxs(Box, {
66
+ component: "button",
67
+ className: "element-empty-btn",
68
+ onClick: onSettings,
69
+ children: [/*#__PURE__*/_jsx(Icon, {
70
+ icon: "video"
71
+ }), "Embed Video or Other"]
72
+ }) : /*#__PURE__*/_jsx(VideoContent, {
73
+ ...props
74
+ });
75
+ };
16
76
  const Video = ({
17
77
  attributes,
18
78
  element,
@@ -21,17 +81,12 @@ const Video = ({
21
81
  }) => {
22
82
  const theme = useTheme();
23
83
  const {
24
- alt,
25
84
  alignment,
26
85
  borderRadius,
27
- borderWidth,
28
- borderColor,
29
- borderStyle,
30
86
  url,
31
87
  xsHidden,
32
88
  width: oldWidth,
33
- bannerSpacing,
34
- bgColor
89
+ bannerSpacing
35
90
  } = element;
36
91
  const editor = useSlateStatic();
37
92
  const [openSetttings, setOpenSettings] = useState(false);
@@ -124,8 +179,8 @@ const Video = ({
124
179
  const getWidth = () => {
125
180
  if (resizing) {
126
181
  return {
127
- width: `${size.width}px`,
128
- height: url ? `${size.height}px` : "auto"
182
+ width: size.width ? `${size.width}px` : "100%",
183
+ height: url ? `${size.height || 300}px` : "auto"
129
184
  };
130
185
  } else {
131
186
  return {
@@ -149,49 +204,6 @@ const Video = ({
149
204
  ...getTRBLBreakPoints(bannerSpacing)
150
205
  }
151
206
  }, theme);
152
- const VideoContent = () => {
153
- return resizing ? /*#__PURE__*/_jsx("div", {
154
- style: {
155
- width: "100%",
156
- height: "100%",
157
- border: "2px dashed black",
158
- display: "flex",
159
- justifyContent: "center",
160
- alignItems: "center"
161
- },
162
- children: /*#__PURE__*/_jsx(Icon, {
163
- icon: "videoPlayer"
164
- })
165
- }) : /*#__PURE__*/_jsx(Box, {
166
- component: "iframe",
167
- className: "embedd-iframe",
168
- sx: {
169
- border: "none",
170
- position: "absolute",
171
- width: "100%",
172
- height: "100%",
173
- maxWidth: "100%",
174
- left: "0px",
175
- ...(gradientBorder(borderColor) || {}),
176
- borderWidth: borderWidth || "1px",
177
- borderStyle: borderStyle || "solid",
178
- background: bgColor || "transparent",
179
- ...videoSX
180
- },
181
- src: embedURL,
182
- title: alt
183
- });
184
- };
185
- const VideoPlaceholder = () => {
186
- return !url && !readOnly ? /*#__PURE__*/_jsxs(Box, {
187
- component: "button",
188
- className: "element-empty-btn",
189
- onClick: onSettings,
190
- children: [/*#__PURE__*/_jsx(Icon, {
191
- icon: "video"
192
- }), "Embed Video or Other"]
193
- }) : /*#__PURE__*/_jsx(VideoContent, {});
194
- };
195
207
  return /*#__PURE__*/_jsxs(Box, {
196
208
  ...attributes,
197
209
  className: "embed has-hover video dpath",
@@ -224,7 +236,15 @@ const Video = ({
224
236
  ...getWidth(),
225
237
  maxWidth: "100%"
226
238
  },
227
- children: [!readOnly && url && /*#__PURE__*/_jsx(ToolBar, {}), /*#__PURE__*/_jsx(VideoPlaceholder, {}), !readOnly && url ? /*#__PURE__*/_jsx(IconButton, {
239
+ children: [!readOnly && url && /*#__PURE__*/_jsx(ToolBar, {}), /*#__PURE__*/_jsx(VideoPlaceholder, {
240
+ ...element,
241
+ embedURL: embedURL,
242
+ onSettings: onSettings,
243
+ videoSX: videoSX,
244
+ url: url,
245
+ readOnly: readOnly,
246
+ resizing: resizing
247
+ }), !readOnly && url ? /*#__PURE__*/_jsx(IconButton, {
228
248
  onPointerDown: onMouseDown,
229
249
  style: {
230
250
  background: "#FFF"
@@ -401,6 +401,7 @@ const Form = props => {
401
401
  component: "button",
402
402
  onClick: onSubmitClick,
403
403
  disabled: loading,
404
+ contentEditable: false,
404
405
  sx: {
405
406
  background: buttonProps?.bgColor || "rgb(30, 75, 122)",
406
407
  borderWidth: "1px",
@@ -495,6 +496,7 @@ const Form = props => {
495
496
  open: anchorEl !== null,
496
497
  anchorEl: anchorEl,
497
498
  onClose: handleClose,
499
+ contentEditable: false,
498
500
  children: [/*#__PURE__*/_jsx(MenuItem, {
499
501
  onClick: onMenuClick("edit"),
500
502
  children: /*#__PURE__*/_jsx(Tooltip, {
@@ -465,15 +465,15 @@ const FreeGrid = props => {
465
465
  className: "freegrid-container freegrid-container-parent",
466
466
  sx: {
467
467
  ...classes.root,
468
- ...freegridSX
468
+ ...freegridSX,
469
+ background: sectionBgColor,
470
+ backgroundImage: sectionBackgroundImage ? `url('${sectionBackgroundImage}')` : "",
471
+ backgroundSize: "cover"
469
472
  },
470
473
  "data-path": path.join("|"),
471
474
  style: {
472
475
  "--cols": `100%`,
473
- "--rows": `repeat(${repeatTimes}, ${ROW_HEIGHT}px)`,
474
- background: sectionBgColor,
475
- backgroundImage: sectionBackgroundImage ? `url('${sectionBackgroundImage}')` : "",
476
- backgroundSize: "cover"
476
+ "--rows": `repeat(${repeatTimes}, ${ROW_HEIGHT}px)`
477
477
  },
478
478
  children: [children, !readOnly ? /*#__PURE__*/_jsx("span", {
479
479
  placeholder: `Section (${sectionName || "Welcome"})`,
@@ -23,7 +23,7 @@ const TableRow = props => {
23
23
  return /*#__PURE__*/_jsx("tr", {
24
24
  ...attributes,
25
25
  style: {
26
- backgroundColor: bgColor,
26
+ background: bgColor,
27
27
  border: rowBorderColor ? `1px solid ${rowBorderColor}` : ""
28
28
  },
29
29
  children: children
@@ -3,6 +3,6 @@ const mentions = props => {
3
3
  CHARACTERS,
4
4
  search
5
5
  } = props;
6
- return CHARACTERS.filter(c => c.name.toLowerCase().startsWith(search?.toLowerCase())).slice(0, 10);
6
+ return CHARACTERS.filter(c => c?.name?.toLowerCase()?.startsWith(search?.toLowerCase())).slice(0, 10);
7
7
  };
8
8
  export default mentions;
@@ -101,9 +101,6 @@ const withHtml = editor => {
101
101
  return element.type === "image" ? true : isVoid(element);
102
102
  };
103
103
  editor.insertData = data => {
104
- if (editor.isChatEditor) {
105
- return;
106
- }
107
104
  const slateHTML = data?.getData("application/x-slate-fragment");
108
105
  const html = data?.getData("text/html");
109
106
  const currentEl = getCurrentElement(editor);
@@ -117,6 +114,23 @@ const withHtml = editor => {
117
114
  const defaultInsert = loopChildren(decoded, true);
118
115
  if (defaultInsert) {
119
116
  insertData(data);
117
+ // } else if (editor.isChatEditor) {
118
+ // // Only convert table to paragraphs if in chat editor mode
119
+ // const paragraphs = decoded.map(row =>
120
+ // row.children.map(cell =>
121
+ // cell.children.map(paragraph =>
122
+ // paragraph.children.map(textNode => textNode.text).join('')
123
+ // ).join(' ')
124
+ // ).join(' ')
125
+ // ).join('\n'); // Joining with a newline for separate paragraphs
126
+
127
+ // // Insert text as paragraphs
128
+ // const textNodes = paragraphs.split('\n').map(text => ({
129
+ // type: 'paragraph',
130
+ // children: [{ text }]
131
+ // }));
132
+
133
+ // Transforms.insertNodes(editor, textNodes);
120
134
  } else {
121
135
  // do not paste table, grid inside table cell
122
136
  // only plain text for internal paste
@@ -141,6 +155,15 @@ const withHtml = editor => {
141
155
  }
142
156
  const fragment = deserialize(parsed.body);
143
157
  const formattedFragment = formatFragment[eltype] ? formatFragment[eltype](fragment) : fragment;
158
+ let is_img_table = false;
159
+ formattedFragment.map(f => {
160
+ if (f.type === 'image' || f.type === 'table') {
161
+ is_img_table = true;
162
+ }
163
+ });
164
+ if (editor.isChatEditor && is_img_table) {
165
+ return;
166
+ }
144
167
  handleInsert(editor, () => Transforms.insertFragment(editor, formattedFragment), formattedFragment);
145
168
  return;
146
169
  } else {
@@ -1,9 +1,6 @@
1
1
  import { Editor, Transforms, Element as SlateElement } from "slate";
2
2
  import { Box } from "@mui/material";
3
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
4
  import Mentions from "../../Elements/Mentions/Mentions";
8
5
  import CheckList from "../../Elements/List/CheckList";
9
6
  import { isEmptyTextNode } from "../../helper";
@@ -340,26 +337,6 @@ export const getBlock = props => {
340
337
  ...props,
341
338
  isEmpty: isEmpty
342
339
  });
343
- case "table":
344
- return /*#__PURE__*/_jsx(Table, {
345
- ...props
346
- });
347
- case "table-head":
348
- return /*#__PURE__*/_jsx("thead", {
349
- children: children
350
- });
351
- case "table-body":
352
- return /*#__PURE__*/_jsx("tbody", {
353
- children: children
354
- });
355
- case "table-row":
356
- return /*#__PURE__*/_jsx(TableRow, {
357
- ...props
358
- });
359
- case "table-cell":
360
- return /*#__PURE__*/_jsx(TableCell, {
361
- ...props
362
- });
363
340
  case "mention":
364
341
  return /*#__PURE__*/_jsx(Mentions, {
365
342
  ...props
@@ -5,6 +5,7 @@ import { insertAccordion } from "./accordion";
5
5
  import { isListItem } from "./helper";
6
6
  import RnDCtrlCmds from "./RnD/RnDCtrlCmds";
7
7
  import EDITORCMDS from "../common/EditorCmds";
8
+ import { ReactEditor } from "slate-react";
8
9
  const HOTKEYS = {
9
10
  b: "bold",
10
11
  i: "italic",
@@ -284,4 +285,40 @@ export const enterEvent = (e, editor, isMobile) => {
284
285
  } catch (err) {
285
286
  console.log(err);
286
287
  }
288
+ };
289
+ export const upArrowEvent = (e, editor) => {
290
+ try {
291
+ const {
292
+ selection
293
+ } = editor;
294
+ if (!selection) return;
295
+ const prevNodePath = Editor.before(editor, selection, {
296
+ unit: "line"
297
+ });
298
+ if (prevNodePath) {
299
+ e.preventDefault();
300
+ Transforms.select(editor, prevNodePath);
301
+ ReactEditor.focus(editor);
302
+ }
303
+ } catch (err) {
304
+ console.log(err);
305
+ }
306
+ };
307
+ export const downArrowEvent = (e, editor) => {
308
+ try {
309
+ const {
310
+ selection
311
+ } = editor;
312
+ if (!selection) return;
313
+ const nextNodePath = Editor.after(editor, selection, {
314
+ unit: "line"
315
+ });
316
+ if (nextNodePath) {
317
+ e.preventDefault();
318
+ Transforms.select(editor, nextNodePath);
319
+ ReactEditor.focus(editor);
320
+ }
321
+ } catch (err) {
322
+ console.log(err);
323
+ }
287
324
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flozy/editor",
3
- "version": "4.2.2",
3
+ "version": "4.2.4",
4
4
  "description": "An Editor for flozy app brain",
5
5
  "files": [
6
6
  "dist"