@markopolo_ai_inc/markopolo-email-editor 1.0.3

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 (91) hide show
  1. package/README.md +63 -0
  2. package/build/asset-manifest.json +12 -0
  3. package/build/favicon.ico +0 -0
  4. package/build/index.html +1 -0
  5. package/build/logo192.png +0 -0
  6. package/build/logo512.png +0 -0
  7. package/build/manifest.json +25 -0
  8. package/build/robots.txt +3 -0
  9. package/build/static/css/main.588cb535.css +9 -0
  10. package/build/static/js/206.a4343501.chunk.js +1 -0
  11. package/build/static/js/main.053d366a.js +2 -0
  12. package/build/static/js/main.053d366a.js.LICENSE.txt +56 -0
  13. package/package.json +64 -0
  14. package/public/favicon.ico +0 -0
  15. package/public/index.html +50 -0
  16. package/public/logo192.png +0 -0
  17. package/public/logo512.png +0 -0
  18. package/public/manifest.json +25 -0
  19. package/public/robots.txt +3 -0
  20. package/src/App.js +15 -0
  21. package/src/components/EmailEditor/assets/App.css +339 -0
  22. package/src/components/EmailEditor/assets/Columns.css +309 -0
  23. package/src/components/EmailEditor/assets/Header.css +174 -0
  24. package/src/components/EmailEditor/assets/ImageBlock.css +12 -0
  25. package/src/components/EmailEditor/assets/Preview.css +30 -0
  26. package/src/components/EmailEditor/assets/RichText.css +199 -0
  27. package/src/components/EmailEditor/assets/RightSettings.css +520 -0
  28. package/src/components/EmailEditor/assets/Sidebar.css +195 -0
  29. package/src/components/EmailEditor/components/BlockItems/ButtonBlock.js +25 -0
  30. package/src/components/EmailEditor/components/BlockItems/DividerBlock.js +19 -0
  31. package/src/components/EmailEditor/components/BlockItems/HeadingBlock.js +16 -0
  32. package/src/components/EmailEditor/components/BlockItems/ImageBlock.js +28 -0
  33. package/src/components/EmailEditor/components/BlockItems/MenuBlock.js +52 -0
  34. package/src/components/EmailEditor/components/BlockItems/SocialLinkBlocks.js +26 -0
  35. package/src/components/EmailEditor/components/BlockItems/SpacerBlock.js +23 -0
  36. package/src/components/EmailEditor/components/BlockItems/TextBlock.js +16 -0
  37. package/src/components/EmailEditor/components/BlockItems/index.js +25 -0
  38. package/src/components/EmailEditor/components/ColorPicker/index.js +26 -0
  39. package/src/components/EmailEditor/components/Column/index.js +253 -0
  40. package/src/components/EmailEditor/components/Header/index.js +243 -0
  41. package/src/components/EmailEditor/components/LeftSideBar/index.js +253 -0
  42. package/src/components/EmailEditor/components/Main/index.js +281 -0
  43. package/src/components/EmailEditor/components/Preview/index.js +97 -0
  44. package/src/components/EmailEditor/components/RichText/Bold.js +37 -0
  45. package/src/components/EmailEditor/components/RichText/FontColor.js +39 -0
  46. package/src/components/EmailEditor/components/RichText/InsertOrderedList.js +36 -0
  47. package/src/components/EmailEditor/components/RichText/InsertUnorderedList.js +36 -0
  48. package/src/components/EmailEditor/components/RichText/Italic.js +36 -0
  49. package/src/components/EmailEditor/components/RichText/Link.js +99 -0
  50. package/src/components/EmailEditor/components/RichText/RichTextLayout.js +53 -0
  51. package/src/components/EmailEditor/components/RichText/Strikethrough.js +36 -0
  52. package/src/components/EmailEditor/components/RichText/TextAlign.js +58 -0
  53. package/src/components/EmailEditor/components/RichText/Underline.js +36 -0
  54. package/src/components/EmailEditor/components/RichText/index.js +210 -0
  55. package/src/components/EmailEditor/components/RightSetting/index.js +126 -0
  56. package/src/components/EmailEditor/components/StyleSettings/ButtonStyleSettings.js +141 -0
  57. package/src/components/EmailEditor/components/StyleSettings/ColumnStyleSettings.js +241 -0
  58. package/src/components/EmailEditor/components/StyleSettings/DividerStyleSettings.js +111 -0
  59. package/src/components/EmailEditor/components/StyleSettings/HeadingStyleSettings.js +162 -0
  60. package/src/components/EmailEditor/components/StyleSettings/ImageStyleSettings.js +217 -0
  61. package/src/components/EmailEditor/components/StyleSettings/MenuStyleSettings.js +177 -0
  62. package/src/components/EmailEditor/components/StyleSettings/PaddingSettings.js +30 -0
  63. package/src/components/EmailEditor/components/StyleSettings/SocialLinkSettings.js +250 -0
  64. package/src/components/EmailEditor/components/StyleSettings/SpacerStyleSettings.js +38 -0
  65. package/src/components/EmailEditor/components/StyleSettings/TextStyleSettings.js +108 -0
  66. package/src/components/EmailEditor/components/StyleSettings/index.js +32 -0
  67. package/src/components/EmailEditor/configs/getBlockConfigsList.js +263 -0
  68. package/src/components/EmailEditor/configs/getColumnConfigFunc.js +59 -0
  69. package/src/components/EmailEditor/configs/getColumnsSettings.js +246 -0
  70. package/src/components/EmailEditor/configs/useDataSource.js +19 -0
  71. package/src/components/EmailEditor/index.js +93 -0
  72. package/src/components/EmailEditor/reducers/index.js +173 -0
  73. package/src/components/EmailEditor/translation/en.js +166 -0
  74. package/src/components/EmailEditor/translation/index.js +39 -0
  75. package/src/components/EmailEditor/translation/zh.js +166 -0
  76. package/src/components/EmailEditor/utils/classNames.js +5 -0
  77. package/src/components/EmailEditor/utils/dataToHTML.js +323 -0
  78. package/src/components/EmailEditor/utils/exportValidation.js +296 -0
  79. package/src/components/EmailEditor/utils/helpers.js +48 -0
  80. package/src/components/EmailEditor/utils/pexels.js +20 -0
  81. package/src/components/EmailEditor/utils/useSection.js +24 -0
  82. package/src/components/EmailEditor/utils/useStyleLayout.js +82 -0
  83. package/src/index.css +99 -0
  84. package/src/index.js +15 -0
  85. package/src/logo.svg +1 -0
  86. package/src/pages/AppPage/index.js +10 -0
  87. package/src/pages/Dashboard/Header.js +192 -0
  88. package/src/pages/Dashboard/defaultBlockList.json +1758 -0
  89. package/src/pages/Dashboard/index.js +48 -0
  90. package/src/reportWebVitals.js +13 -0
  91. package/src/setupTests.js +5 -0
@@ -0,0 +1,25 @@
1
+ import { useContext } from "react";
2
+ import { GlobalContext } from "../../reducers";
3
+ import RichTextLayout from "../RichText/RichTextLayout";
4
+ import { useMemo } from "react";
5
+
6
+ const ButtonBlock = (props) => {
7
+ const { blockItem, index } = props;
8
+ const { currentItem, previewMode } = useContext(GlobalContext);
9
+
10
+ // TODO: border radius not yet implemented
11
+ const isEdit = currentItem && currentItem.index === index;
12
+ const styles = previewMode === "desktop" ? blockItem.styles.desktop : { ...blockItem.styles.desktop, ...blockItem.styles.mobile };
13
+
14
+ const contentStyles =
15
+ previewMode === "desktop" ? blockItem.contentStyles?.desktop : { ...blockItem.contentStyles?.desktop, ...blockItem.contentStyles?.mobile };
16
+
17
+ const richTextElement = useMemo(() => <RichTextLayout {...props} />, [props]);
18
+ return (
19
+ <div style={{ ...contentStyles }}>
20
+ {isEdit ? richTextElement : <div style={{ ...styles }} dangerouslySetInnerHTML={{ __html: blockItem.text }}></div>}
21
+ </div>
22
+ );
23
+ };
24
+
25
+ export default ButtonBlock;
@@ -0,0 +1,19 @@
1
+ import { useContext } from "react";
2
+ import { GlobalContext } from "../../reducers";
3
+
4
+ const DividerBlock = ({ blockItem }) => {
5
+ const { previewMode } = useContext(GlobalContext);
6
+ const styles = previewMode === "desktop" ? blockItem.styles.desktop : { ...blockItem.styles.desktop, ...blockItem.styles.mobile };
7
+ const contentStyles =
8
+ previewMode === "desktop" ? blockItem.contentStyles?.desktop : { ...blockItem.contentStyles?.desktop, ...blockItem.contentStyles?.mobile };
9
+
10
+ return (
11
+ <div className="relative">
12
+ <div style={{ ...contentStyles }}>
13
+ <div style={{ ...styles }}></div>
14
+ </div>
15
+ </div>
16
+ );
17
+ };
18
+
19
+ export default DividerBlock;
@@ -0,0 +1,16 @@
1
+ import { useContext } from "react";
2
+ import { GlobalContext } from "../../reducers";
3
+ import RichTextLayout from "../RichText/RichTextLayout";
4
+ import { useMemo } from "react";
5
+
6
+ const HeadingBlock = (props) => {
7
+ const { index, blockItem } = props;
8
+ const { currentItem, previewMode } = useContext(GlobalContext);
9
+ const styles = previewMode === "desktop" ? blockItem.styles.desktop : { ...blockItem.styles.desktop, ...blockItem.styles.mobile };
10
+ const isEdit = currentItem && currentItem.index === index;
11
+ const richTextElement = useMemo(() => <RichTextLayout {...props} />, [props]);
12
+
13
+ return isEdit ? richTextElement : <div style={{ ...styles }} dangerouslySetInnerHTML={{ __html: blockItem.text }}></div>;
14
+ };
15
+
16
+ export default HeadingBlock;
@@ -0,0 +1,28 @@
1
+ import { useContext } from "react";
2
+ import { GlobalContext } from "../../reducers";
3
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
4
+ import { faImage } from "@fortawesome/free-solid-svg-icons";
5
+
6
+ const ImageBlock = ({ blockItem }) => {
7
+ const { src, alt } = blockItem;
8
+ const { previewMode } = useContext(GlobalContext);
9
+ const styles = previewMode === "desktop" ? blockItem.styles.desktop : { ...blockItem.styles.desktop, ...blockItem.styles.mobile };
10
+ const contentStyles =
11
+ previewMode === "desktop" ? blockItem.contentStyles?.desktop : { ...blockItem.contentStyles?.desktop, ...blockItem.contentStyles?.mobile };
12
+
13
+ return (
14
+ <div className="relative">
15
+ <div style={{ ...contentStyles }}>
16
+ {src ? (
17
+ <img src={src} style={styles} alt={alt} className="inline-block" />
18
+ ) : (
19
+ <div className="empty-image" style={{ ...styles, width: styles.width === "auto" ? "100%" : styles.width }}>
20
+ <FontAwesomeIcon icon={faImage} className="empty-image-icon" />
21
+ </div>
22
+ )}
23
+ </div>
24
+ </div>
25
+ );
26
+ };
27
+
28
+ export default ImageBlock;
@@ -0,0 +1,52 @@
1
+ import { useContext } from "react";
2
+ import { GlobalContext } from "../../reducers";
3
+
4
+ const MenuBlock = ({ blockItem }) => {
5
+ const { previewMode } = useContext(GlobalContext);
6
+ const { list = [], separator = " | " } = blockItem;
7
+ const styles = previewMode === "desktop" ? blockItem.styles.desktop : { ...blockItem.styles.desktop, ...blockItem.styles.mobile };
8
+ const contentStyles =
9
+ previewMode === "desktop" ? blockItem.contentStyles?.desktop : { ...blockItem.contentStyles?.desktop, ...blockItem.contentStyles?.mobile };
10
+
11
+ const linkStyle = {
12
+ fontSize: styles.fontSize != null ? `${styles.fontSize}px` : "14px",
13
+ fontFamily: styles.fontFamily || "sans-serif",
14
+ color: styles.linkColor || styles.color || "#2faade",
15
+ fontWeight: styles.fontWeight || "normal",
16
+ letterSpacing: styles.letterSpacing != null ? `${styles.letterSpacing}px` : "0px",
17
+ textDecoration: "none",
18
+ paddingLeft: styles.paddingLeft != null ? `${styles.paddingLeft}px` : "8px",
19
+ paddingRight: styles.paddingRight != null ? `${styles.paddingRight}px` : "8px",
20
+ paddingTop: styles.paddingTop != null ? `${styles.paddingTop}px` : "4px",
21
+ paddingBottom: styles.paddingBottom != null ? `${styles.paddingBottom}px` : "4px",
22
+ };
23
+
24
+ const separatorStyle = {
25
+ fontSize: styles.fontSize != null ? `${styles.fontSize}px` : "14px",
26
+ color: styles.color || "#333",
27
+ paddingLeft: 4,
28
+ paddingRight: 4,
29
+ };
30
+
31
+ return (
32
+ <div className="relative">
33
+ <div style={{ ...contentStyles, display: "flex", flexWrap: "wrap", alignItems: "center", justifyContent: contentStyles.textAlign || "center" }}>
34
+ {list.map((item, index) => (
35
+ <span key={index} style={{ display: "inline-flex", alignItems: "center" }}>
36
+ {index > 0 && <span style={separatorStyle}>{separator}</span>}
37
+ <a
38
+ href={item.url ? (item.url.startsWith("http") ? item.url : `https://${item.url}`) : "#"}
39
+ target={item.target === "_blank" ? "_blank" : "_self"}
40
+ rel={item.target === "_blank" ? "noopener noreferrer" : undefined}
41
+ style={linkStyle}
42
+ >
43
+ {item.label || "Link"}
44
+ </a>
45
+ </span>
46
+ ))}
47
+ </div>
48
+ </div>
49
+ );
50
+ };
51
+
52
+ export default MenuBlock;
@@ -0,0 +1,26 @@
1
+ import { useContext } from "react";
2
+ import { GlobalContext } from "../../reducers";
3
+
4
+ const SocialLinkBlocks = ({ blockItem }) => {
5
+ const { previewMode } = useContext(GlobalContext);
6
+ const { list, imageWidth } = blockItem;
7
+ const styles = previewMode === "desktop" ? blockItem.styles.desktop : { ...blockItem.styles.desktop, ...blockItem.styles.mobile };
8
+ const contentStyles =
9
+ previewMode === "desktop" ? blockItem.contentStyles?.desktop : { ...blockItem.contentStyles?.desktop, ...blockItem.contentStyles?.mobile };
10
+ return (
11
+ <div className="relative">
12
+ <div style={contentStyles}>
13
+ {list.map((socialLinkItem, index) => {
14
+ const { image, title } = socialLinkItem;
15
+ return (
16
+ <div key={index} style={{ ...styles, display: "inline-block" }}>
17
+ <img src={image} alt={title} style={{ width: imageWidth }} />
18
+ </div>
19
+ );
20
+ })}
21
+ </div>
22
+ </div>
23
+ );
24
+ };
25
+
26
+ export default SocialLinkBlocks;
@@ -0,0 +1,23 @@
1
+ import { useContext } from "react";
2
+ import { GlobalContext } from "../../reducers";
3
+
4
+ const SpacerBlock = ({ blockItem }) => {
5
+ const { previewMode } = useContext(GlobalContext);
6
+ const styles = previewMode === "desktop" ? blockItem.styles.desktop : { ...blockItem.styles.desktop, ...blockItem.styles.mobile };
7
+ const contentStyles =
8
+ previewMode === "desktop" ? blockItem.contentStyles?.desktop : { ...blockItem.contentStyles?.desktop, ...blockItem.contentStyles?.mobile };
9
+
10
+ return (
11
+ <div className="relative" style={{ ...contentStyles }}>
12
+ <div
13
+ style={{
14
+ width: "100%",
15
+ height: typeof styles.height === "number" ? `${styles.height}px` : styles.height || "16px",
16
+ display: styles.display || "block",
17
+ }}
18
+ />
19
+ </div>
20
+ );
21
+ };
22
+
23
+ export default SpacerBlock;
@@ -0,0 +1,16 @@
1
+ import { useContext } from "react";
2
+ import { GlobalContext } from "../../reducers";
3
+ import RichTextLayout from "../RichText/RichTextLayout";
4
+ import { useMemo } from "react";
5
+
6
+ const TextBlock = (props) => {
7
+ const { index, blockItem } = props;
8
+ const { currentItem, previewMode } = useContext(GlobalContext);
9
+ const styles = previewMode === "desktop" ? blockItem.styles.desktop : { ...blockItem.styles.desktop, ...blockItem.styles.mobile };
10
+ const isEdit = currentItem && currentItem.index === index;
11
+ const richTextElement = useMemo(() => <RichTextLayout {...props} />, [props]);
12
+
13
+ return isEdit ? richTextElement : <div style={{ ...styles }} dangerouslySetInnerHTML={{ __html: blockItem.text }}></div>;
14
+ };
15
+
16
+ export default TextBlock;
@@ -0,0 +1,25 @@
1
+ import TextBlock from "./TextBlock";
2
+ import HeadingBlock from "./HeadingBlock";
3
+ import ButtonBlock from "./ButtonBlock";
4
+ import DividerBlock from "./DividerBlock";
5
+ import SpacerBlock from "./SpacerBlock";
6
+ import MenuBlock from "./MenuBlock";
7
+ import ImageBlock from "./ImageBlock";
8
+ import SocialLinkBlocks from "./SocialLinkBlocks";
9
+
10
+ const BlockItems = ({ blockItem, index }) => {
11
+ return (
12
+ <>
13
+ {blockItem && blockItem.key === "text" && <TextBlock blockItem={blockItem} index={index} />}
14
+ {blockItem && blockItem.key === "heading" && <HeadingBlock blockItem={blockItem} index={index} />}
15
+ {blockItem && blockItem.key === "button" && <ButtonBlock blockItem={blockItem} index={index} />}
16
+ {blockItem && blockItem.key === "divider" && <DividerBlock blockItem={blockItem} index={index} />}
17
+ {blockItem && blockItem.key === "spacer" && <SpacerBlock blockItem={blockItem} index={index} />}
18
+ {blockItem && blockItem.key === "menu" && <MenuBlock blockItem={blockItem} index={index} />}
19
+ {blockItem && blockItem.key === "image" && <ImageBlock blockItem={blockItem} index={index} />}
20
+ {blockItem && blockItem.key === "social_link" && <SocialLinkBlocks blockItem={blockItem} index={index} />}
21
+ </>
22
+ );
23
+ };
24
+
25
+ export default BlockItems;
@@ -0,0 +1,26 @@
1
+ import { useState } from "react";
2
+ import { Popover } from "antd";
3
+ import { ChromePicker } from "react-color";
4
+
5
+ const ColorPicker = ({ color, setColor }) => {
6
+ const [popoverOpen, setPopoverOpen] = useState(false);
7
+
8
+ return (
9
+ <Popover
10
+ zIndex={1070}
11
+ getPopupContainer={() => document.querySelector(".right-settings") || document.body}
12
+ content={
13
+ <div className="select-none ee-color-picker-popover">
14
+ <ChromePicker color={color} style={{ boxShadow: "none" }} onChange={setColor} />
15
+ </div>
16
+ }
17
+ trigger="click"
18
+ open={popoverOpen}
19
+ onOpenChange={setPopoverOpen}
20
+ >
21
+ <button className="color-picker-button" style={{ background: color }}></button>
22
+ </Popover>
23
+ );
24
+ };
25
+
26
+ export default ColorPicker;
@@ -0,0 +1,253 @@
1
+ import { Fragment, useContext } from "react";
2
+ import { GlobalContext } from "../../reducers";
3
+ import classNames from "../../utils/classNames";
4
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
5
+ import { faArrowsAlt, faTrash } from "@fortawesome/free-solid-svg-icons";
6
+ import { deepClone } from "../../utils/helpers";
7
+ import BlockItems from "../BlockItems";
8
+ import useTranslation from "../../translation";
9
+
10
+ const Column = (props) => {
11
+ const { block, blockIndex, clearStyles } = props;
12
+ const { t } = useTranslation();
13
+ const { previewMode, blockList, currentItem, setBlockList, setCurrentItem, setIsDragStart, isDragStart, bodySettings, setActionType } =
14
+ useContext(GlobalContext);
15
+
16
+ let columnStyles = previewMode === "desktop" ? block.styles.desktop : { ...block.styles.desktop, ...block.styles.mobile };
17
+ const { contentBackground, ...newStyles } = columnStyles;
18
+
19
+ const deleteBlock = (event) => {
20
+ event.preventDefault();
21
+ event.stopPropagation();
22
+ const newBlockList = deepClone(blockList);
23
+ newBlockList.splice(blockIndex, 1);
24
+ setBlockList(newBlockList, "delete");
25
+ setCurrentItem(null);
26
+ };
27
+
28
+ const deleteBlockItem = (index) => (event) => {
29
+ event.preventDefault();
30
+ event.stopPropagation();
31
+ const newBlockList = deepClone(blockList);
32
+ const indexArr = index.split("-");
33
+ const blockIndex = indexArr[0];
34
+ const contentIndex = indexArr[1];
35
+ const itemIndex = indexArr[2];
36
+ const item = newBlockList[blockIndex].children[contentIndex].children;
37
+ item.splice(itemIndex, 1);
38
+ if (item.length === 0) {
39
+ item.push({
40
+ name: t("drag_block_here"),
41
+ key: "empty",
42
+ width: "100%",
43
+ styles: {
44
+ desktop: {
45
+ backgroundColor: "transparent",
46
+ paddingTop: 0,
47
+ paddingLeft: 0,
48
+ paddingRight: 0,
49
+ paddingBottom: 0,
50
+ },
51
+ mobile: {},
52
+ },
53
+ });
54
+ }
55
+ setBlockList(newBlockList, "delete");
56
+ setCurrentItem(null);
57
+ };
58
+
59
+ const dragStart = () => {
60
+ setIsDragStart(true);
61
+ setCurrentItem({ ...currentItem, type: "move" });
62
+ setActionType("move");
63
+ };
64
+
65
+ const dragEnd = (event) => {
66
+ event.preventDefault();
67
+ event.stopPropagation();
68
+ // Parent onDrop/onDragOver use 30ms delay; delay 50ms here so styles are cleared after blockList/currentItem update
69
+ setTimeout(() => {
70
+ event.target.style.border = "";
71
+ event.target.children[0] && event.target.children[0].classList.remove("sidebar-block-move");
72
+ setIsDragStart(false);
73
+ clearStyles();
74
+ }, 50);
75
+ };
76
+
77
+ const blockItemElement = (item, index) => {
78
+ const nextIndex = index
79
+ .split("-")
80
+ .map((item, itemIndex) => {
81
+ if (itemIndex === 2) {
82
+ return Number(item) + 1;
83
+ } else {
84
+ return item;
85
+ }
86
+ })
87
+ .join("-");
88
+ return (
89
+ <>
90
+ {item.key === "empty" ? (
91
+ <div className="block-empty-content p-4 h-32 relative width-full">
92
+ {isDragStart && currentItem && currentItem.data.key !== "column" && (
93
+ <div className="block-empty-content-tools" onDragOver={preventDefault} data-index={index} data-type="empty-block-item">
94
+ {t("drag_block_here")}
95
+ </div>
96
+ )}
97
+ {item.name}
98
+ </div>
99
+ ) : (
100
+ <>
101
+ <div className="relative block-content-drag-label-content" data-index={index} data-type="block-item">
102
+ <div className="absolute block-move-top">
103
+ <span className="block-tools-drag_here">{t("drag_block_here")}</span>
104
+ </div>
105
+ </div>
106
+ <div className="block-item">
107
+ <div className={classNames("relative", currentItem && currentItem.index === index && "block-item-focus")}>
108
+ <div
109
+ className="block-item-tools"
110
+ onDragOver={preventDefault}
111
+ onClick={(event) => {
112
+ event.preventDefault();
113
+ event.stopPropagation();
114
+ setCurrentItem({ data: item, type: "edit", index });
115
+ setActionType("edit");
116
+ }}
117
+ >
118
+ {isDragStart && currentItem && currentItem.data.key !== "column" && (
119
+ <>
120
+ <div
121
+ className="block-move-content-top"
122
+ data-name="dragTools"
123
+ data-position="top"
124
+ data-index={index}
125
+ data-type="block-item-move"
126
+ ></div>
127
+ <div
128
+ className="block-move-content-bottom"
129
+ data-name="dragTools"
130
+ data-position="bottom"
131
+ data-index={nextIndex}
132
+ data-type="block-item-move"
133
+ ></div>
134
+ </>
135
+ )}
136
+ <span className="absolute block-item-delete" onClick={deleteBlockItem(index)}>
137
+ <FontAwesomeIcon icon={faTrash} />
138
+ </span>
139
+ <span
140
+ className="absolute block-item-move current-move-block-arrows"
141
+ draggable="true"
142
+ onDragEnd={dragEnd}
143
+ data-index={index}
144
+ onDragStart={dragStart}
145
+ >
146
+ <FontAwesomeIcon icon={faArrowsAlt} />
147
+ </span>
148
+ </div>
149
+ <BlockItems blockItem={item} index={index} />
150
+ </div>
151
+ </div>
152
+ </>
153
+ )}
154
+ </>
155
+ );
156
+ };
157
+
158
+ const preventDefault = (event) => {
159
+ event.preventDefault();
160
+ };
161
+
162
+ return (
163
+ <>
164
+ <div className="relative block-drag-label-content" data-index={blockIndex} data-position="top">
165
+ <div className="absolute block-move-top">
166
+ <span className="block-tools-drag_here">{t("drag_block_here")}</span>
167
+ </div>
168
+ <div
169
+ className={classNames(
170
+ "relative block",
171
+ currentItem && currentItem.index === blockIndex && "block-focus",
172
+ previewMode === "mobile" && "mobile-block-focus"
173
+ )}
174
+ onClick={(event) => {
175
+ event.preventDefault();
176
+ event.stopPropagation();
177
+ setCurrentItem({ data: block, type: "edit", index: blockIndex });
178
+ }}
179
+ >
180
+ <div className="hover-visible">
181
+ <span className="absolute block-delete" onClick={deleteBlock}>
182
+ <FontAwesomeIcon icon={faTrash} />
183
+ </span>
184
+ <span
185
+ className="absolute block-move current-move-block-arrows"
186
+ draggable="true"
187
+ onDragEnd={dragEnd}
188
+ data-index={blockIndex}
189
+ onDragStart={dragStart}
190
+ >
191
+ <FontAwesomeIcon icon={faArrowsAlt} />
192
+ </span>
193
+ </div>
194
+
195
+ <div className="width-full height-full absolute" onDragOver={preventDefault}>
196
+ {isDragStart && currentItem.data.key === "column" && (
197
+ <>
198
+ <div
199
+ className="block-move-content-top"
200
+ data-name="dragTools"
201
+ data-type="drag-over-column"
202
+ data-position="top"
203
+ data-index={blockIndex}
204
+ ></div>
205
+ <div
206
+ className="block-move-content-bottom"
207
+ data-name="dragTools"
208
+ data-type="drag-over-column"
209
+ data-position="bottom"
210
+ data-index={blockIndex + 1}
211
+ ></div>
212
+ </>
213
+ )}
214
+ </div>
215
+ <div className="column margin-auto" style={{ ...newStyles, maxWidth: "100%" }}>
216
+ <div className="block-content" style={{ background: contentBackground, width: bodySettings.contentWidth }} data-index={blockIndex}>
217
+ {block.children.map((content, index) => {
218
+ let contentStyles = previewMode === "desktop" ? content.styles.desktop : { ...content.styles.desktop, ...content.styles.mobile };
219
+ return (
220
+ <Fragment key={index}>
221
+ <div
222
+ id={`block-content-${blockIndex}-${index}`}
223
+ style={{ ...contentStyles, width: previewMode === "mobile" ? "100%" : content.width }}
224
+ >
225
+ {content.children.map((item, itemIndex) => {
226
+ const blockItemIndex = `${blockIndex}-${index}-${itemIndex}`;
227
+ const isLastKid = itemIndex === content.children.length - 1 && item.key !== "empty";
228
+ return (
229
+ <Fragment key={itemIndex}>
230
+ {blockItemElement(item, blockItemIndex)}
231
+ {isLastKid && (
232
+ <div className="relative block-content-drag-label-content" data-index={`${blockIndex}-${index}-${itemIndex + 1}`}>
233
+ <div className="absolute block-move-bottom">
234
+ <span className="block-tools-drag_here">{t("drag_block_here")}</span>
235
+ </div>
236
+ </div>
237
+ )}
238
+ </Fragment>
239
+ );
240
+ })}
241
+ </div>
242
+ </Fragment>
243
+ );
244
+ })}
245
+ </div>
246
+ </div>
247
+ </div>
248
+ </div>
249
+ </>
250
+ );
251
+ };
252
+
253
+ export default Column;