@flozy/editor 10.6.5 → 10.6.7

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.
Files changed (69) hide show
  1. package/dist/Editor/CommonEditor.js +17 -1
  2. package/dist/Editor/Editor.css +26 -0
  3. package/dist/Editor/Elements/Accordion/Accordion.js +46 -9
  4. package/dist/Editor/Elements/Accordion/AccordionSummary.js +2 -25
  5. package/dist/Editor/Elements/AppHeader/AppHeader.js +7 -2
  6. package/dist/Editor/Elements/Button/EditorButton.js +2 -2
  7. package/dist/Editor/Elements/Carousel/CarouselItem.js +2 -1
  8. package/dist/Editor/Elements/DataView/Layouts/DataTypes/Components/SelectV1.js +510 -0
  9. package/dist/Editor/Elements/DataView/Layouts/DataTypes/MultiSelectType.js +10 -10
  10. package/dist/Editor/Elements/DataView/Layouts/DataTypes/SelectType.js +28 -9
  11. package/dist/Editor/Elements/DataView/Layouts/Options/AddOptions.js +12 -5
  12. package/dist/Editor/Elements/DataView/Layouts/Options/EditOption.js +44 -18
  13. package/dist/Editor/Elements/Divider/Divider.js +1 -1
  14. package/dist/Editor/Elements/Embed/Embed.css +4 -0
  15. package/dist/Editor/Elements/Form/Form.js +3 -3
  16. package/dist/Editor/Elements/Form/FormElements/FormTextArea.js +0 -1
  17. package/dist/Editor/Elements/FreeGrid/FreeGrid.js +4 -1
  18. package/dist/Editor/Elements/FreeGrid/FreeGridItem.js +1 -0
  19. package/dist/Editor/Elements/Grid/Grid.js +14 -2
  20. package/dist/Editor/Elements/Signature/Signature.css +2 -1
  21. package/dist/Editor/Elements/Signature/SignatureOptions/DrawSignature.js +18 -5
  22. package/dist/Editor/Elements/Signature/SignatureOptions/UploadSignature.js +16 -3
  23. package/dist/Editor/Elements/Table/AddRowCol.js +8 -2
  24. package/dist/Editor/Elements/Table/DragButton.js +0 -1
  25. package/dist/Editor/Elements/Table/Draggable.js +6 -2
  26. package/dist/Editor/Elements/Table/Styles.js +7 -0
  27. package/dist/Editor/Elements/Table/TableCell.js +24 -5
  28. package/dist/Editor/Elements/Title/title.js +2 -5
  29. package/dist/Editor/Toolbar/PopupTool/PopupToolStyle.js +4 -4
  30. package/dist/Editor/Toolbar/PopupTool/index.js +7 -3
  31. package/dist/Editor/common/Checkbox/index.js +46 -0
  32. package/dist/Editor/common/Checkbox/styles.js +45 -0
  33. package/dist/Editor/common/ColorPickerButton.js +3 -0
  34. package/dist/Editor/common/LinkSettings/NavComponents.js +45 -65
  35. package/dist/Editor/common/LinkSettings/index.js +17 -28
  36. package/dist/Editor/common/LinkSettings/navOptions.js +2 -2
  37. package/dist/Editor/common/LinkSettings/style.js +164 -244
  38. package/dist/Editor/common/RadioGroup/index.js +48 -0
  39. package/dist/Editor/common/RadioGroup/styles.js +29 -0
  40. package/dist/Editor/common/RnD/ElementOptions/Actions.js +4 -5
  41. package/dist/Editor/common/RnD/ElementSettings/OtherSettings/Signature.js +4 -3
  42. package/dist/Editor/common/RnD/ElementSettings/styles.js +0 -1
  43. package/dist/Editor/common/RnD/OptionsPopup/style.js +0 -1
  44. package/dist/Editor/common/RnD/Utils/gridDropItem.js +0 -1
  45. package/dist/Editor/common/RnD/Utils/index.js +55 -24
  46. package/dist/Editor/common/RnD/VirtualElement/helper.js +3 -2
  47. package/dist/Editor/common/RnD/index.js +30 -27
  48. package/dist/Editor/common/Select/index.js +44 -7
  49. package/dist/Editor/common/Select/styles.js +30 -2
  50. package/dist/Editor/common/StyleBuilder/accordionTitleBtnStyle.js +2 -2
  51. package/dist/Editor/common/StyleBuilder/accordionTitleStyle.js +12 -9
  52. package/dist/Editor/common/SwipeableDrawer/style.js +14 -12
  53. package/dist/Editor/common/iconListV2.js +76 -0
  54. package/dist/Editor/commonStyle.js +12 -0
  55. package/dist/Editor/helper/deserialize/index.js +6 -4
  56. package/dist/Editor/helper/index.js +4 -0
  57. package/dist/Editor/hooks/useTable.js +5 -4
  58. package/dist/Editor/plugins/withCustomDeleteBackward.js +6 -1
  59. package/dist/Editor/plugins/withHTML.js +11 -4
  60. package/dist/Editor/utils/SlateUtilityFunctions.js +21 -32
  61. package/dist/Editor/utils/accordion.js +129 -39
  62. package/dist/Editor/utils/customHooks/useTableResize.js +49 -9
  63. package/dist/Editor/utils/events.js +17 -5
  64. package/dist/Editor/utils/formfield.js +1 -0
  65. package/dist/Editor/utils/helper.js +53 -9
  66. package/dist/Editor/utils/insertAppHeader.js +1 -1
  67. package/dist/Editor/utils/signature.js +2 -9
  68. package/dist/Editor/utils/updateFormName.js +22 -0
  69. package/package.json +1 -1
@@ -4,7 +4,7 @@ import { decodeAndParseBase64 } from "../utils/helper";
4
4
  import convertMDToHTML from "../helper/markdown";
5
5
  const avoidDefaultInsert = ["table", "grid"];
6
6
  const NON_TEXT_TAGS = ["ol", "ul", "img", "table", "video", "a", "button", "GOOGLE-SHEETS-HTML-ORIGIN"];
7
- const ALLOWED_TEXT_NODES = ["paragraph", "title", "headingOne", "headingTwo", "headingThree"];
7
+ const ALLOWED_TEXT_NODES = ["paragraph", "title", "headingOne", "headingTwo", "headingThree", "headingFour", "headingFive", "headingSix"];
8
8
  const parseCopiedHTML = html => {
9
9
  const parsed = new DOMParser().parseFromString(html, "text/html");
10
10
 
@@ -18,7 +18,8 @@ const parseCopiedHTML = html => {
18
18
  });
19
19
 
20
20
  // to handle google docs list
21
- parsed.querySelectorAll("li p, li div").forEach(element => {
21
+ // 'col' tag added to resolve formatting issues with table data copied from Microsoft Excel
22
+ parsed.querySelectorAll("li p, li div, col").forEach(element => {
22
23
  const parent = element.parentNode;
23
24
  // Move all child nodes of <p> or <div> to its parent <li>
24
25
  while (element.firstChild) {
@@ -134,7 +135,7 @@ const formatFragment = {
134
135
  },
135
136
  "check-list-item": fragment => {
136
137
  return fragment.map(a => {
137
- a.type = "check-list-item";
138
+ // a.type = "check-list-item";
138
139
  return a;
139
140
  });
140
141
  }
@@ -274,7 +275,13 @@ const withHtml = editor => {
274
275
  // }
275
276
 
276
277
  if (isTitlePath && isNonText) {
277
- insertAtNextNode(editor, formattedFragment);
278
+ const firstNodePasted = formattedFragment[0];
279
+ const isAllowedTextNode = ALLOWED_TEXT_NODES.includes(firstNodePasted?.type || "");
280
+ if (isAllowedTextNode) {
281
+ Transforms.insertFragment(editor, formattedFragment);
282
+ } else {
283
+ insertAtNextNode(editor, formattedFragment);
284
+ }
278
285
  return;
279
286
  }
280
287
  const currentText = getCurrentElementText(editor);
@@ -49,7 +49,6 @@ import ColumnView from "../Elements/DataView/Layouts/ColumnView";
49
49
  import SearchAttachment from "../Elements/Search/SearchAttachment";
50
50
  // import { wrapThemeBreakpoints } from "../Elements/FreeGrid/breakpointConstants";
51
51
  import { jsx as _jsx } from "react/jsx-runtime";
52
- import { jsxs as _jsxs } from "react/jsx-runtime";
53
52
  const alignment = ["alignLeft", "alignRight", "alignCenter", "alignJustify"];
54
53
  const list_types = ["orderedList", "unorderedList"];
55
54
  const LIST_FORMAT_TYPE = {
@@ -305,64 +304,52 @@ export const getBlock = props => {
305
304
  const selectedLineHeight = getBreakpointLineSpacing(lineH, breakpoint);
306
305
  switch (element.type) {
307
306
  case "headingOne":
308
- return /*#__PURE__*/_jsxs("h1", {
307
+ return /*#__PURE__*/_jsx("h1", {
309
308
  ...attributes,
310
309
  ...element.attr,
311
- className: `edt-headings content-editable ${isEmpty ? "empty" : ""}`,
310
+ className: `edt-headings content-editable ${isEmpty ? "empty" : ""} disablePointerEvent`,
312
311
  placeholder: translation("Heading 1"),
313
- children: [children, /*#__PURE__*/_jsx("span", {
314
- contentEditable: false
315
- })]
312
+ children: children
316
313
  });
317
314
  case "headingTwo":
318
- return /*#__PURE__*/_jsxs("h2", {
315
+ return /*#__PURE__*/_jsx("h2", {
319
316
  ...attributes,
320
317
  ...element.attr,
321
- className: `edt-headings content-editable ${isEmpty ? "empty" : ""}`,
318
+ className: `edt-headings content-editable ${isEmpty ? "empty" : ""} disablePointerEvent`,
322
319
  placeholder: translation("Heading 2"),
323
- children: [children, /*#__PURE__*/_jsx("span", {
324
- contentEditable: false
325
- })]
320
+ children: children
326
321
  });
327
322
  case "headingThree":
328
- return /*#__PURE__*/_jsxs("h3", {
323
+ return /*#__PURE__*/_jsx("h3", {
329
324
  ...attributes,
330
325
  ...element.attr,
331
- className: `edt-headings content-editable ${isEmpty ? "empty" : ""}`,
326
+ className: `edt-headings content-editable ${isEmpty ? "empty" : ""} disablePointerEvent`,
332
327
  placeholder: translation("Heading 3"),
333
- children: [children, /*#__PURE__*/_jsx("span", {
334
- contentEditable: false
335
- })]
328
+ children: children
336
329
  });
337
330
  case "headingFour":
338
- return /*#__PURE__*/_jsxs("h4", {
331
+ return /*#__PURE__*/_jsx("h4", {
339
332
  ...attributes,
340
333
  ...element.attr,
341
- className: `edt-headings content-editable ${isEmpty ? "empty" : ""}`,
334
+ className: `edt-headings content-editable ${isEmpty ? "empty" : ""} disablePointerEvent`,
342
335
  placeholder: translation("Heading 4"),
343
- children: [children, /*#__PURE__*/_jsx("span", {
344
- contentEditable: false
345
- })]
336
+ children: children
346
337
  });
347
338
  case "headingFive":
348
- return /*#__PURE__*/_jsxs("h5", {
339
+ return /*#__PURE__*/_jsx("h5", {
349
340
  ...attributes,
350
341
  ...element.attr,
351
- className: `edt-headings content-editable ${isEmpty ? "empty" : ""}`,
342
+ className: `edt-headings content-editable ${isEmpty ? "empty" : ""} disablePointerEvent`,
352
343
  placeholder: translation("Heading 5"),
353
- children: [children, /*#__PURE__*/_jsx("span", {
354
- contentEditable: false
355
- })]
344
+ children: children
356
345
  });
357
346
  case "headingSix":
358
- return /*#__PURE__*/_jsxs("h6", {
347
+ return /*#__PURE__*/_jsx("h6", {
359
348
  ...attributes,
360
349
  ...element.attr,
361
- className: `edt-headings content-editable ${isEmpty ? "empty" : ""}`,
350
+ className: `edt-headings content-editable ${isEmpty ? "empty" : ""} disablePointerEvent`,
362
351
  placeholder: translation("Heading 6"),
363
- children: [children, /*#__PURE__*/_jsx("span", {
364
- contentEditable: false
365
- })]
352
+ children: children
366
353
  });
367
354
  case "blockquote":
368
355
  return /*#__PURE__*/_jsx("blockquote", {
@@ -672,8 +659,10 @@ export const getQueryStrings = urlString => {
672
659
  const newUrl = new URL(urlString);
673
660
  var youCode = newUrl.searchParams.get("v");
674
661
  if (!youCode) {
675
- youCode = newUrl.pathname.replace("/", "");
662
+ const parts = newUrl.pathname.split("/");
663
+ youCode = parts[parts.length - 1]; // video ID
676
664
  }
665
+
677
666
  return `https://www.youtube.com/embed/${youCode}`;
678
667
  } else {
679
668
  return urlString;
@@ -1,47 +1,137 @@
1
- import { Transforms } from "slate";
1
+ import { Editor, Element, Path, Transforms } from "slate";
2
2
  import insertNewLine from "./insertNewLine";
3
- import { getSelectedText } from "./helper";
3
+ import { ALLOWED_TEXT_NODES, getNode, getNodeText, getNodeWithType } from "./helper";
4
+ import { isMobileWindow } from "../helper";
5
+ import { removeAccordion } from "./events";
6
+ import { ReactEditor } from "slate-react";
7
+ const focusAccordion = (editor, upPath) => {
8
+ Transforms.select(editor, {
9
+ path: upPath,
10
+ offset: 0
11
+ });
12
+ };
4
13
  export const insertAccordion = (editor, path) => {
5
14
  try {
6
- const selectedText = getSelectedText(editor);
7
- const accordion = {
8
- type: "accordion",
9
- children: [{
10
- type: "accordion-summary",
11
- children: [{
12
- type: "paragraph",
15
+ const {
16
+ selection
17
+ } = editor;
18
+ if (selection) {
19
+ const selectedNodes = Array.from(Editor.nodes(editor, {
20
+ at: selection,
21
+ match: n => Element.isElement(n),
22
+ mode: "lowest" // use 'lowest' to get individual blocks
23
+ }));
24
+
25
+ for (const [node, path] of selectedNodes) {
26
+ const accordion = {
27
+ type: "accordion",
13
28
  children: [{
14
- text: selectedText || ""
29
+ type: "accordion-summary",
30
+ children: [node]
31
+ }, {
32
+ type: "accordion-details",
33
+ children: [{
34
+ type: "paragraph",
35
+ children: [{
36
+ text: ""
37
+ }]
38
+ }]
15
39
  }]
16
- }]
17
- }, {
18
- type: "accordion-details",
19
- children: [{
20
- type: "paragraph",
21
- children: [{
22
- text: ""
23
- }]
24
- }]
25
- }]
26
- };
27
- const props = path ? {
28
- at: path,
29
- select: true
30
- } : {
31
- select: true
32
- };
33
- Transforms.insertNodes(editor, accordion, props);
34
- const curPath = [...editor?.selection?.anchor?.path];
35
- const upPath = [...curPath];
36
- // get title index
37
- const summaryIndex = upPath.length - 3;
38
- upPath[summaryIndex] = upPath[summaryIndex] === 0 ? 0 : upPath[summaryIndex] - 1;
39
- // select accordion title by default
40
- Transforms.select(editor, {
41
- path: upPath,
42
- offset: 0
43
- });
44
- insertNewLine(editor);
40
+ };
41
+ Transforms.removeNodes(editor, {
42
+ at: path
43
+ });
44
+ Transforms.insertNodes(editor, accordion, {
45
+ at: path
46
+ });
47
+ }
48
+ const lastNode = selectedNodes[selectedNodes.length - 1];
49
+ const lastNodePath = lastNode[1];
50
+ const accordionPath = [...lastNodePath, 0, 0, 0];
51
+ if (isMobileWindow()) {
52
+ // timeout to resolve focus issue in mobile
53
+ setTimeout(() => focusAccordion(editor, accordionPath), 0);
54
+ } else {
55
+ focusAccordion(editor, accordionPath);
56
+ }
57
+ insertNewLine(editor);
58
+ }
59
+ } catch (err) {
60
+ console.log(err);
61
+ }
62
+ };
63
+ export const onDeleteBackwardAccordion = editor => {
64
+ try {
65
+ let preventDefault = false;
66
+ const {
67
+ selection
68
+ } = editor;
69
+ const {
70
+ path: currentPath,
71
+ offset
72
+ } = selection.anchor || {};
73
+ const isCursorAtStart = offset === 0;
74
+ if (isCursorAtStart) {
75
+ // If the cursor is at the start of the accordion-summary and backspace is pressed,
76
+ // unwrap the accordion by removing both the summary and details,
77
+ // and insert their contents as regular nodes without the accordion wrapper.
78
+ const [accordionSummary] = getNodeWithType(editor, "accordion-summary");
79
+ const [accordionTitle, accordionTitlePath] = accordionSummary || [];
80
+ if (accordionTitle) {
81
+ const accordionPath = Path.parent(accordionTitlePath);
82
+ removeAccordion(editor, accordionPath);
83
+ preventDefault = true;
84
+ return;
85
+ }
86
+ const parentPath = Path.parent(currentPath);
87
+ const parentNode = getNode(editor, parentPath);
88
+ const isTextNode = ALLOWED_TEXT_NODES.includes(parentNode?.type);
89
+ if (isTextNode) {
90
+ const prevEntry = Editor.previous(editor, {
91
+ at: parentPath,
92
+ match: n => n.type === "accordion"
93
+ });
94
+ if (prevEntry) {
95
+ const [accordionNode, accordionPath] = prevEntry;
96
+ const dom = ReactEditor.toDOMNode(editor, accordionNode);
97
+ const aContent = dom.querySelector(".accordion-content");
98
+ const isContentVisible = aContent.style.display !== "none";
99
+ if (!isContentVisible) {
100
+ // If the accordion content is not visible and backspace is pressed,
101
+ // the content from the current node should be merged with the accordion title,
102
+ // and the cursor should move to the title.
103
+ // Otherwise, Slate will by default merge the current node into the hidden details section,
104
+ // which makes the content invisible.
105
+
106
+ let targetPath = [...accordionPath, 0, 0];
107
+ const targetNodeEntry = getNode(editor, targetPath);
108
+ if (targetNodeEntry) {
109
+ const nodeText = getNodeText(parentNode);
110
+ const endPath = Editor.end(editor, targetPath);
111
+
112
+ // Move current paragraph text into the end of the target block
113
+ Transforms.select(editor, Editor.start(editor, parentPath));
114
+ Transforms.delete(editor, {
115
+ at: parentPath
116
+ });
117
+ Transforms.insertText(editor, nodeText, {
118
+ at: endPath
119
+ });
120
+
121
+ // move the focus and cursor to the inserted node
122
+ Transforms.select(editor, {
123
+ anchor: endPath,
124
+ focus: endPath
125
+ });
126
+ ReactEditor.focus(editor);
127
+ preventDefault = true;
128
+ return;
129
+ }
130
+ }
131
+ }
132
+ }
133
+ }
134
+ return preventDefault;
45
135
  } catch (err) {
46
136
  console.log(err);
47
137
  }
@@ -1,9 +1,10 @@
1
- import { useState } from "react";
1
+ import { useRef, useState } from "react";
2
2
  const useTableResize = ({
3
3
  parentDOM,
4
4
  size: defaultSize,
5
5
  onDone,
6
- minMaxProps = {}
6
+ minMaxProps = {},
7
+ isMobile
7
8
  }) => {
8
9
  const {
9
10
  width
@@ -18,6 +19,10 @@ const useTableResize = ({
18
19
  });
19
20
  const [resizing, setResizing] = useState(false);
20
21
  const [isDone, setIsDone] = useState(0);
22
+ const lastTouch = useRef({
23
+ x: 0,
24
+ y: 0
25
+ });
21
26
  const onLoad = defaultSize => {
22
27
  setSize({
23
28
  widthInPercent: 100,
@@ -25,29 +30,64 @@ const useTableResize = ({
25
30
  ...defaultSize
26
31
  });
27
32
  };
33
+ const handleEventListeners = type => {
34
+ const listener = type === "add" ? document.addEventListener : document.removeEventListener;
35
+ const onMoveListener = isMobile ? "touchmove" : "pointermove";
36
+ const onEndListener = isMobile ? "touchend" : "pointerup";
37
+ listener(onMoveListener, onMouseMove);
38
+ listener(onEndListener, onMouseUp);
39
+ };
40
+ const updateLastTouch = ({
41
+ clientX,
42
+ clientY
43
+ }) => {
44
+ lastTouch.current.x = clientX;
45
+ lastTouch.current.y = clientY;
46
+ };
28
47
  const onMouseDown = e => {
29
- e.preventDefault();
30
- document.addEventListener("pointermove", onMouseMove);
31
- document.addEventListener("pointerup", onMouseUp);
48
+ if (isMobile) {
49
+ updateLastTouch(e.touches[0]);
50
+ } else {
51
+ e.preventDefault();
52
+ }
53
+ handleEventListeners("add");
32
54
  setResizing(true);
33
55
  setIsDone(0);
34
56
  };
35
57
  const onMouseUp = () => {
36
- document.removeEventListener("pointermove", onMouseMove);
37
- document.removeEventListener("pointerup", onMouseUp);
58
+ handleEventListeners("remove");
38
59
  setResizing(false);
39
60
  setIsDone(1);
40
61
  };
41
62
  const onMouseMove = e => {
63
+ let {
64
+ movementX,
65
+ movementY
66
+ } = e || {};
67
+ if (e.type === "touchmove") {
68
+ // for mobile
69
+ const {
70
+ x,
71
+ y
72
+ } = lastTouch.current || {};
73
+ const touches = e.touches[0];
74
+ const {
75
+ clientX,
76
+ clientY
77
+ } = touches;
78
+ movementX = clientX - x;
79
+ movementY = clientY - y;
80
+ updateLastTouch(touches);
81
+ }
42
82
  const {
43
83
  minWidth
44
84
  } = minMaxProps || {};
45
85
  setSize(currentSize => {
46
86
  const width = currentSize?.width || parentDOM?.clientWidth;
47
- const calcWidth = width + e.movementX;
87
+ const calcWidth = width + movementX;
48
88
  return {
49
89
  width: minWidth && calcWidth < minWidth ? minWidth : calcWidth,
50
- height: currentSize.height + e.movementY,
90
+ height: currentSize.height + movementY,
51
91
  widthInPercent: calcWidth / width * 100
52
92
  };
53
93
  });
@@ -2,7 +2,7 @@ import { Editor, Transforms, Element, Node, Path, Range } from "slate";
2
2
  import { toggleBlock } from "./SlateUtilityFunctions";
3
3
  import insertNewLine from "./insertNewLine";
4
4
  import { insertAccordion } from "./accordion";
5
- import { isListItem } from "./helper";
5
+ import { getNode, isListItem } from "./helper";
6
6
  import RnDCtrlCmds from "./RnD/RnDCtrlCmds";
7
7
  import EDITORCMDS from "../common/EditorCmds";
8
8
  const HOTKEYS = {
@@ -183,6 +183,20 @@ const checkListEnterEvent = (editor, type) => {
183
183
  insertNewLine(editor);
184
184
  }
185
185
  };
186
+ export const removeAccordion = (editor, accordionPath) => {
187
+ const accordion = getNode(editor, accordionPath);
188
+ Transforms.removeNodes(editor, {
189
+ at: accordionPath
190
+ });
191
+ const insertNodes = [];
192
+ accordion.children.forEach(a => {
193
+ a.children.forEach(n => insertNodes.push(n));
194
+ });
195
+ Transforms.insertNodes(editor, insertNodes, {
196
+ at: accordionPath,
197
+ select: true
198
+ });
199
+ };
186
200
  export const enterEvent = (e, editor, isMobile) => {
187
201
  try {
188
202
  const ele = isListItem(editor);
@@ -225,9 +239,7 @@ export const enterEvent = (e, editor, isMobile) => {
225
239
  e.preventDefault();
226
240
  if (!text) {
227
241
  const accordionIndex = ele[1].slice(0, Math.max(ele[1].length - 1));
228
- Transforms.removeNodes(editor, {
229
- at: accordionIndex
230
- });
242
+ removeAccordion(editor, accordionIndex);
231
243
  } else {
232
244
  const nextPath = Path.next(Path.parent(ele[1]));
233
245
  insertAccordion(editor, nextPath);
@@ -348,7 +360,7 @@ export const upDownArrowKeyEvents = (e, editor) => {
348
360
  }
349
361
  Transforms.move(editor, {
350
362
  distance: 0,
351
- unit: 'offset',
363
+ unit: "offset",
352
364
  reverse: false
353
365
  });
354
366
  Transforms.select(editor, {
@@ -7,6 +7,7 @@ export const formField = data => {
7
7
  name: `field_${new Date().getTime()}`,
8
8
  key: `field_${new Date().getTime()}`,
9
9
  label: `field_${new Date().getTime()}`,
10
+ uid: `field_${new Date().getTime()}`,
10
11
  placeholder: "Placeholder...",
11
12
  children: [{
12
13
  text: ""
@@ -2,6 +2,7 @@ import { Editor, Node, Transforms, Element, Path, Range, Text } from "slate";
2
2
  import { ReactEditor } from "slate-react";
3
3
  import insertNewLine from "./insertNewLine";
4
4
  import { getDevice } from "../helper/theme";
5
+ import { getCurrentElementText } from "../plugins/withHTML";
5
6
  export const windowVar = {};
6
7
  let ST_TIMEOUT = null;
7
8
  const BLOCKS = ["grid", "dataView"];
@@ -333,7 +334,9 @@ const handleLinkBtnClick = (e, props, isMobilePreview, metadata) => {
333
334
  }
334
335
  }
335
336
  };
336
- export const handleLinkType = (url, linkType, readOnly, openInNewTab, onClick = () => {}, metadata = {}) => {
337
+ export const handleLinkType = (url, linkType, readOnly, openInNewTab, onClick = () => {}, isEditMode, isCustomMobile,
338
+ // for drawer in App Header
339
+ metadata = {}) => {
337
340
  const props = {};
338
341
  if (!readOnly) {
339
342
  return {
@@ -365,6 +368,9 @@ export const handleLinkType = (url, linkType, readOnly, openInNewTab, onClick =
365
368
  case "page":
366
369
  const [page = "", section] = url?.split("#") || [];
367
370
  const sec = section ? `#${section}` : "";
371
+ if (isEditMode) {
372
+ break;
373
+ }
368
374
  if (page === "_currentPage") {
369
375
  props.component = "button";
370
376
  props.onClick = () => {
@@ -385,11 +391,12 @@ export const handleLinkType = (url, linkType, readOnly, openInNewTab, onClick =
385
391
  const currentUserPage = getCurrentUserPage();
386
392
  props.href = isCurrentPage(page) ? `./${currentUserPage}${sec}` : `./${url}`;
387
393
  if (openInNewTab) {
388
- if (isCurrentPage(page)) {
389
- // 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
390
- } else {
391
- props.target = "_blank";
392
- }
394
+ // if (isCurrentPage(page)) {
395
+ // // 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
396
+ // } else {
397
+ // props.target = "_blank";
398
+ // }
399
+ props.target = "_blank";
393
400
  }
394
401
  }
395
402
  break;
@@ -424,7 +431,7 @@ export const handleLinkType = (url, linkType, readOnly, openInNewTab, onClick =
424
431
 
425
432
  // for iphone fix
426
433
  if (props.component === "a" && props.href) {
427
- const isMobile = getDevice(window.innerWidth) === "xs";
434
+ const isMobile = isCustomMobile || getDevice(window.innerWidth) === "xs";
428
435
  if (isMobile) {
429
436
  props.component = "button"; // iphone is opening two tabs, on open in new tab because of a tag.
430
437
  }
@@ -834,6 +841,24 @@ export const hideSlateSelection = () => {
834
841
  export function handleNegativeInteger(val) {
835
842
  return val < 0 ? 0 : val;
836
843
  }
844
+ export const insertSlashNode = (editor, insertNode) => {
845
+ try {
846
+ // Delete the currently selected text
847
+ editor.deleteFragment();
848
+ const currentText = getCurrentElementText(editor);
849
+ const currentPath = editor?.selection?.anchor?.path;
850
+ let insertAt = currentPath;
851
+ if (currentText?.trim()) {
852
+ const parentPath = Path.parent(currentPath);
853
+ insertAt = Path.next(parentPath);
854
+ }
855
+ Transforms.insertNodes(editor, insertNode, {
856
+ at: insertAt
857
+ });
858
+ } catch (err) {
859
+ console.log(err);
860
+ }
861
+ };
837
862
  export const isEverythingSelected = editor => {
838
863
  const {
839
864
  selection
@@ -864,6 +889,19 @@ export const getCurrentNodeText = editor => {
864
889
  console.log("Error:", error);
865
890
  }
866
891
  };
892
+ export const isHavingColor = color => {
893
+ if (!color) {
894
+ return false;
895
+ }
896
+ if (color.includes("rgba")) {
897
+ const match = color.match(/rgba?\((\d+),\s*(\d+),\s*(\d+),?\s*(\d*\.?\d+)?\)/);
898
+ if (!match) return false; // Invalid format
899
+
900
+ const alpha = match[4] !== undefined ? parseFloat(match[4]) : 1; // Default alpha = 1
901
+ return alpha !== 0;
902
+ }
903
+ return true;
904
+ };
867
905
  const handleCopiedList = (el, domRange) => {
868
906
  // Ensure you're working with an Element, not a Text node
869
907
  const startEl = domRange.startContainer.nodeType === Node.ELEMENT_NODE ? domRange.startContainer : domRange.startContainer.parentElement;
@@ -883,11 +921,15 @@ const handleCopiedList = (el, domRange) => {
883
921
  el.insertAdjacentText("afterbegin", "- ");
884
922
  }
885
923
  };
924
+ const cleanCopiedDOM = container => {
925
+ container.querySelectorAll('[style*="display: none"], [contenteditable="false"]').forEach(el => el.remove());
926
+ return container;
927
+ };
886
928
  const getCopiedTextFormat = domRange => {
887
929
  const contents = domRange.cloneContents();
888
930
  const div = document.createElement("div");
889
931
  div.appendChild(contents);
890
-
932
+ cleanCopiedDOM(div);
891
933
  // Replace <br> with newlines
892
934
  div.querySelectorAll("br").forEach(br => br.replaceWith("\n"));
893
935
  const BLOCK_TAGS = ["DIV", "P", "LI", "H1", "H2", "H3", "H4", "H5", "H6"];
@@ -915,6 +957,7 @@ const getCopiedHTMLFormat = domRange => {
915
957
  const htmlContents = domRange.cloneContents();
916
958
  const container = document.createElement("div");
917
959
  container.appendChild(htmlContents);
960
+ cleanCopiedDOM(container);
918
961
  const html = container.innerHTML;
919
962
  return html;
920
963
  };
@@ -939,4 +982,5 @@ export const handleCopy = (event, editor) => {
939
982
  event.clipboardData?.setData("text/html", html);
940
983
  event.clipboardData?.setData("text/plain", text);
941
984
  event.clipboardData?.setData("application/x-slate-fragment", encodedFragment);
942
- };
985
+ };
986
+ export const ALLOWED_TEXT_NODES = ["paragraph", "title", "headingOne", "headingTwo", "headingThree", "headingFour", "headingFive", "headingSix", "blockquote"];
@@ -51,7 +51,7 @@ export const createAppHeaderNode = ({
51
51
  children: [{
52
52
  type: "grid-item",
53
53
  grid: 12,
54
- children: [...appHeaderNode({
54
+ children: [appHeaderNode({
55
55
  menus
56
56
  })],
57
57
  bgColor: "rgba(255, 255, 255, 0)",
@@ -1,9 +1,5 @@
1
- import { Path, Transforms } from "slate";
2
- import insertNewLine from "./insertNewLine";
3
- import { getCurrentElementText } from "../plugins/withHTML";
1
+ import { insertSlashNode } from "./helper";
4
2
  export const insertSignature = editor => {
5
- const hasText = getCurrentElementText(editor);
6
- const insertPath = hasText ? Path.next(Path.parent(editor?.selection.focus.path)) : editor.selection.anchor.path;
7
3
  const signature = {
8
4
  type: "signature",
9
5
  alignment: "center",
@@ -17,8 +13,5 @@ export const insertSignature = editor => {
17
13
  text: " "
18
14
  }]
19
15
  };
20
- Transforms.insertNodes(editor, signature, {
21
- at: insertPath
22
- });
23
- insertNewLine(editor);
16
+ insertSlashNode(editor, signature);
24
17
  };
@@ -0,0 +1,22 @@
1
+ const updateFormName = node => {
2
+ try {
3
+ if (!node || typeof node !== "object") return node;
4
+ let updatedNode = {
5
+ ...node
6
+ };
7
+ if (updatedNode.type === "form") {
8
+ const timeStamp = Date.now();
9
+ const newFormName = `form_${timeStamp}`;
10
+ updatedNode.formName = newFormName;
11
+ updatedNode.uid = newFormName;
12
+ }
13
+ if (Array.isArray(updatedNode.children)) {
14
+ updatedNode.children = updatedNode.children.map(child => updateFormName(child));
15
+ }
16
+ return updatedNode;
17
+ } catch (err) {
18
+ console.warn("Error inside updateFormName", err);
19
+ return node;
20
+ }
21
+ };
22
+ export default updateFormName;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flozy/editor",
3
- "version": "10.6.5",
3
+ "version": "10.6.7",
4
4
  "description": "An Editor for flozy app brain",
5
5
  "files": [
6
6
  "dist"