@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,241 @@
1
+ import { useContext, useState } from "react";
2
+ import { GlobalContext } from "../../reducers";
3
+ import classNames from "../../utils/classNames";
4
+ import { Modal, Tabs } from "antd";
5
+
6
+ import { deepClone } from "../../utils/helpers";
7
+ import ColorPicker from "../ColorPicker";
8
+ import PaddingSettings from "./PaddingSettings";
9
+ import useStyleLayout from "../../utils/useStyleLayout";
10
+ import useDataSource from "../../configs/useDataSource";
11
+ import useTranslation from "../../translation";
12
+
13
+ const ColumnStyleSettings = () => {
14
+ const { currentItem, previewMode } = useContext(GlobalContext);
15
+ const { t } = useTranslation();
16
+ const [isModalOpen, setIsModalOpen] = useState(false);
17
+ const [currentColumnType, setCurrentColumnType] = useState(null);
18
+ const { findStyleItem, cardItemElement, updateItemStyles, colorChange, paddingChange } = useStyleLayout();
19
+ const { columnsSetting } = useDataSource();
20
+
21
+ const columnChange = (type) => () => {
22
+ if (currentItem.data.children.length > columnsSetting[type].children.length) {
23
+ setIsModalOpen(true);
24
+ setCurrentColumnType(type);
25
+ return;
26
+ }
27
+ const newColumnConfig = columnsSetting[type];
28
+ const newData = {
29
+ ...currentItem.data,
30
+ ...newColumnConfig,
31
+ children: newColumnConfig.children.map((item, index) => {
32
+ let newItem = item;
33
+ if (currentItem.data.children[index]) {
34
+ newItem = { ...currentItem.data.children[index], width: item.width };
35
+ }
36
+ return { ...newItem };
37
+ }),
38
+ };
39
+ updateItemStyles(newData);
40
+ };
41
+
42
+ const handleOk = () => {
43
+ const newColumnConfig = columnsSetting[currentColumnType];
44
+ const newData = {
45
+ ...currentItem.data,
46
+ ...newColumnConfig,
47
+ children: newColumnConfig.children.map((item, index) => {
48
+ let newItem = item;
49
+ if (currentItem.data.children[index]) {
50
+ newItem = { ...currentItem.data.children[index], width: item.width };
51
+ }
52
+ return { ...newItem };
53
+ }),
54
+ };
55
+ updateItemStyles(newData);
56
+ setIsModalOpen(false);
57
+ setCurrentColumnType(null);
58
+ };
59
+
60
+ const handleCancel = () => {
61
+ setIsModalOpen(false);
62
+ };
63
+
64
+ const columnList = [
65
+ {
66
+ key: "full",
67
+ widths: ["100%"],
68
+ },
69
+ {
70
+ key: "1-1",
71
+ widths: ["50%", "50%"],
72
+ },
73
+ {
74
+ key: "1-1-1",
75
+ widths: ["33.33%", "33.33%", "33.33%"],
76
+ },
77
+ {
78
+ key: "1-1-1-1",
79
+ widths: ["25%", "25%", "25%", "25%"],
80
+ },
81
+ {
82
+ key: "1-2",
83
+ widths: ["33.33%", "66.66%"],
84
+ },
85
+ {
86
+ key: "2-1",
87
+ widths: ["66.66%", "33.33%"],
88
+ },
89
+ {
90
+ key: "2-4-2-4",
91
+ widths: ["16.66%", "33.33%", "16.66%", "33.33%"],
92
+ },
93
+ {
94
+ key: "4-2-4-2",
95
+ widths: ["33.33%", "16.66%", "33.33%", "16.66%"],
96
+ },
97
+ ];
98
+
99
+ const changeColumnList = (key, index) => (value) => {
100
+ const newData = deepClone(currentItem.data);
101
+ newData.children[index].styles[previewMode][key] = value;
102
+ updateItemStyles(newData);
103
+ };
104
+
105
+ const changePaddingStyle = (index) => (padding) => {
106
+ const newData = deepClone(currentItem.data);
107
+ newData.children[index].styles[previewMode] = {
108
+ ...newData.children[index].styles[previewMode],
109
+ ...padding,
110
+ };
111
+ updateItemStyles(newData);
112
+ };
113
+
114
+ const columnListElement = () => {
115
+ return (
116
+ <>
117
+ <div className="right-setting-block-item-title"> {t("columns")}</div>
118
+ <div>
119
+ {columnList.map((item, index) => {
120
+ return (
121
+ <div
122
+ className={classNames(currentItem.data.type === item.key ? "column-item-active" : "column-item-un_active", "column-item")}
123
+ key={index}
124
+ onClick={columnChange(item.key)}
125
+ >
126
+ {item.widths.map((width, index) => {
127
+ const isLast = index === item.widths.length - 1;
128
+ return (
129
+ <span
130
+ key={index}
131
+ style={{ width }}
132
+ className={classNames(
133
+ isLast ? "" : "column-item-border-right",
134
+ currentItem.data.type === item.key ? "column-item-active" : "column-item-un_active",
135
+ "height-full"
136
+ )}
137
+ ></span>
138
+ );
139
+ })}
140
+ </div>
141
+ );
142
+ })}
143
+ </div>
144
+ </>
145
+ );
146
+ };
147
+
148
+ const columnContentElement = () => {
149
+ return (
150
+ <>
151
+ <div className="right-setting-block-item-title"> {t("column_settings")}</div>
152
+ <Tabs
153
+ defaultActiveKey="1"
154
+ animated={{
155
+ inkBar: true,
156
+ tabPane: true,
157
+ }}
158
+ items={currentItem.data.children.map((item, index) => {
159
+ const key = index + 1;
160
+ const backgroundColor = findStyleItem(item.styles, "backgroundColor");
161
+ return {
162
+ label: `${t("column")} ${key}`,
163
+ key: key,
164
+ children: (
165
+ <>
166
+ {cardItemElement(
167
+ t("content_background_color"),
168
+ <ColorPicker color={backgroundColor} setColor={({ hex }) => changeColumnList("backgroundColor", index)(hex)} />
169
+ )}
170
+ <PaddingSettings
171
+ padding={{
172
+ paddingTop: findStyleItem(item.styles, "paddingTop"),
173
+ paddingRight: findStyleItem(item.styles, "paddingRight"),
174
+ paddingLeft: findStyleItem(item.styles, "paddingLeft"),
175
+ paddingBottom: findStyleItem(item.styles, "paddingBottom"),
176
+ }}
177
+ setPadding={changePaddingStyle(index)}
178
+ />
179
+ </>
180
+ ),
181
+ };
182
+ })}
183
+ />
184
+ </>
185
+ );
186
+ };
187
+
188
+ const columnStylesElement = () => {
189
+ const backgroundColor = findStyleItem(currentItem.data.styles, "backgroundColor");
190
+ const contentBackground = findStyleItem(currentItem.data.styles, "contentBackground");
191
+ return (
192
+ <>
193
+ <div className="right-setting-block-item-title"> {t("column_styles")}</div>
194
+ {cardItemElement(t("background_color"), <ColorPicker color={backgroundColor} setColor={colorChange("backgroundColor")} />)}
195
+ {cardItemElement(t("content_background_color"), <ColorPicker color={contentBackground} setColor={colorChange("contentBackground")} />)}
196
+ <PaddingSettings
197
+ padding={{
198
+ paddingTop: findStyleItem(currentItem.data.styles, "paddingTop"),
199
+ paddingRight: findStyleItem(currentItem.data.styles, "paddingRight"),
200
+ paddingLeft: findStyleItem(currentItem.data.styles, "paddingLeft"),
201
+ paddingBottom: findStyleItem(currentItem.data.styles, "paddingBottom"),
202
+ }}
203
+ setPadding={paddingChange}
204
+ />
205
+ </>
206
+ );
207
+ };
208
+
209
+ return (
210
+ <>
211
+ <div className="margin-y-30">
212
+ {columnListElement()}
213
+ {columnContentElement()}
214
+ {columnStylesElement()}
215
+ </div>
216
+ <Modal
217
+ title={t("column_delete")}
218
+ open={isModalOpen}
219
+ onOk={handleOk}
220
+ onCancel={handleCancel}
221
+ width={400}
222
+ okText={t("confirm")}
223
+ cancelText={t("cancel")}
224
+ wrapClassName="ee-modal-dark"
225
+ >
226
+ <p
227
+ className="margin-y-30"
228
+ dangerouslySetInnerHTML={{
229
+ __html: t("column_delete_desc", {
230
+ count: `<span class="column-modal-context">
231
+ ${currentColumnType ? currentItem.data.children.length - columnsSetting[currentColumnType].children.length : 0}
232
+ </span>`,
233
+ }),
234
+ }}
235
+ ></p>
236
+ </Modal>
237
+ </>
238
+ );
239
+ };
240
+
241
+ export default ColumnStyleSettings;
@@ -0,0 +1,111 @@
1
+ import { useContext } from "react";
2
+ import { GlobalContext } from "../../reducers";
3
+ import classNames from "../../utils/classNames";
4
+ import { InputNumber, Select, Slider } from "antd";
5
+ import { deepClone } from "../../utils/helpers";
6
+ import ColorPicker from "../ColorPicker";
7
+ import PaddingSettings from "./PaddingSettings";
8
+ import useLayout from "../../utils/useStyleLayout";
9
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
10
+ import { faAlignCenter, faAlignLeft, faAlignRight, faAlignJustify } from "@fortawesome/free-solid-svg-icons";
11
+ import useTranslation from "../../translation";
12
+
13
+ const DividerStyleSettings = () => {
14
+ const { currentItem, previewMode } = useContext(GlobalContext);
15
+ const { t } = useTranslation();
16
+
17
+ const { findStyleItem, cardItemElement, colorChange, updateItemStyles, inputChange } = useLayout();
18
+
19
+ const updateContentStylesPadding = (padding) => {
20
+ const newData = deepClone(currentItem.data);
21
+ newData.contentStyles[previewMode] = {
22
+ ...newData.contentStyles[previewMode],
23
+ ...padding,
24
+ };
25
+ updateItemStyles(newData);
26
+ };
27
+
28
+ const updateContentTextAlign = (textAlign) => {
29
+ const newData = deepClone(currentItem.data);
30
+ newData.contentStyles[previewMode] = {
31
+ ...newData.contentStyles[previewMode],
32
+ textAlign,
33
+ };
34
+ updateItemStyles(newData);
35
+ };
36
+
37
+ const dividerStyleSettings = () => {
38
+ const textAlign = findStyleItem(currentItem.data.contentStyles, "textAlign");
39
+ const width = findStyleItem(currentItem.data.styles, "width");
40
+ const borderTopColor = findStyleItem(currentItem.data.styles, "borderTopColor");
41
+ const borderTopWidth = findStyleItem(currentItem.data.styles, "borderTopWidth");
42
+ const borderTopStyle = findStyleItem(currentItem.data.styles, "borderTopStyle");
43
+ const dividerType = [
44
+ { label: t("solid"), value: "solid" },
45
+ { label: t("dotted"), value: "dotted" },
46
+ { label: t("dashed"), value: "dashed" },
47
+ ];
48
+
49
+ return (
50
+ <>
51
+ <div className="right-setting-block-item-title"> {t("divider_styles")}</div>
52
+ {cardItemElement(
53
+ t("divider_type"),
54
+ <Select
55
+ className="input-width"
56
+ value={borderTopStyle}
57
+ onChange={inputChange("borderTopStyle")}
58
+ getPopupContainer={() => document.querySelector(".right-settings") || document.body}
59
+ >
60
+ {dividerType.map((item) => (
61
+ <Select.Option key={item.value} value={item.value}>
62
+ {item.label}
63
+ </Select.Option>
64
+ ))}
65
+ </Select>
66
+ )}
67
+ {cardItemElement(
68
+ t("height"),
69
+ <InputNumber min={0} className="input-width" addonAfter="px" value={borderTopWidth} onChange={inputChange("borderTopWidth")} />
70
+ )}
71
+ {cardItemElement(t("divider_color"), <ColorPicker color={borderTopColor} setColor={colorChange("borderTopColor")} />)}
72
+ <div className="card-item-title">{t("width")}</div>
73
+ <Slider value={Number(width.replace("%", ""))} onChange={(value) => inputChange("width")(value + "%")} />
74
+ {cardItemElement(
75
+ t("align"),
76
+ <div className="flex justify-center items-center">
77
+ {[
78
+ { icon: faAlignLeft, value: "left" },
79
+ { icon: faAlignCenter, value: "center" },
80
+ { icon: faAlignRight, value: "right" },
81
+ { icon: faAlignJustify, value: "justify" },
82
+ ].map(({ icon, value }) => {
83
+ return (
84
+ <div
85
+ key={value}
86
+ className={classNames(textAlign === value ? "align-style-item-active" : "align-style-item-un_active", "align-style-item")}
87
+ onClick={() => updateContentTextAlign(value)}
88
+ >
89
+ <FontAwesomeIcon icon={icon} className="tag-style-size" />
90
+ </div>
91
+ );
92
+ })}
93
+ </div>
94
+ )}
95
+ <div className="card-item-title"> {t("padding_settings")}</div>
96
+ <PaddingSettings
97
+ padding={{
98
+ paddingTop: findStyleItem(currentItem.data.contentStyles, "paddingTop"),
99
+ paddingRight: findStyleItem(currentItem.data.contentStyles, "paddingRight"),
100
+ paddingLeft: findStyleItem(currentItem.data.contentStyles, "paddingLeft"),
101
+ paddingBottom: findStyleItem(currentItem.data.contentStyles, "paddingBottom"),
102
+ }}
103
+ setPadding={updateContentStylesPadding}
104
+ />
105
+ </>
106
+ );
107
+ };
108
+ return <div className="margin-y-30">{dividerStyleSettings()}</div>;
109
+ };
110
+
111
+ export default DividerStyleSettings;
@@ -0,0 +1,162 @@
1
+ import { useContext } from "react";
2
+ import { GlobalContext } from "../../reducers";
3
+ import classNames from "../../utils/classNames";
4
+ import { InputNumber, Select } from "antd";
5
+
6
+ import ColorPicker from "../ColorPicker";
7
+ import PaddingSettings from "./PaddingSettings";
8
+ import useLayout from "../../utils/useStyleLayout";
9
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
10
+ import { faAlignCenter, faAlignLeft, faAlignRight, faAlignJustify } from "@fortawesome/free-solid-svg-icons";
11
+ import useTranslation from "../../translation";
12
+
13
+ const HeadingStyleSettings = () => {
14
+ const { currentItem } = useContext(GlobalContext);
15
+ const { t } = useTranslation();
16
+ const { findStyleItem, cardItemElement, colorChange, paddingChange, otherStylesChange, inputChange, updateItemStyles } = useLayout();
17
+
18
+ const PaddingStylesElement = () => {
19
+ return (
20
+ <>
21
+ <div className="right-setting-block-item-title"> {t("padding_settings")}</div>
22
+ <PaddingSettings
23
+ padding={{
24
+ paddingTop: findStyleItem(currentItem.data.styles, "paddingTop"),
25
+ paddingRight: findStyleItem(currentItem.data.styles, "paddingRight"),
26
+ paddingLeft: findStyleItem(currentItem.data.styles, "paddingLeft"),
27
+ paddingBottom: findStyleItem(currentItem.data.styles, "paddingBottom"),
28
+ }}
29
+ setPadding={paddingChange}
30
+ />
31
+ </>
32
+ );
33
+ };
34
+
35
+ const headingTypeChange = (type) => () => {
36
+ let fontSize = currentItem.data.styles.desktop.fontSize;
37
+ switch (type) {
38
+ case "h1":
39
+ fontSize = 22;
40
+ break;
41
+ case "h2":
42
+ fontSize = 20;
43
+ break;
44
+ case "h3":
45
+ fontSize = 18;
46
+ break;
47
+ case "h4":
48
+ fontSize = 16;
49
+ break;
50
+ default:
51
+ break;
52
+ }
53
+ let newConfig = {
54
+ ...currentItem.data,
55
+ type,
56
+ styles: {
57
+ ...currentItem.data.styles,
58
+ desktop: {
59
+ ...currentItem.data.styles.desktop,
60
+ fontSize,
61
+ },
62
+ },
63
+ };
64
+ updateItemStyles(newConfig);
65
+ };
66
+
67
+ const textStylesElement = () => {
68
+ const { type } = currentItem.data;
69
+ const color = findStyleItem(currentItem.data.styles, "color");
70
+ const textAlign = findStyleItem(currentItem.data.styles, "textAlign");
71
+ const fontFamily = findStyleItem(currentItem.data.styles, "fontFamily");
72
+ const fontSize = findStyleItem(currentItem.data.styles, "fontSize");
73
+ const lineHeight = findStyleItem(currentItem.data.styles, "lineHeight");
74
+ const fontFamilyList = ["sans-serif", "Arial", "Verdana", "Times New Roman", "Garamond", "Georgia", "Courier New", "cursive"];
75
+
76
+ return (
77
+ <>
78
+ <div className="right-setting-block-item-title">{t("text_styles")}</div>
79
+ {cardItemElement(
80
+ t("heading_type"),
81
+ <div className="flex justify-center items-center">
82
+ {[
83
+ { name: "H1", value: "h1" },
84
+ { name: "H2", value: "h2" },
85
+ { name: "H3", value: "h3" },
86
+ { name: "H4", value: "h4" },
87
+ ].map(({ name, value }) => {
88
+ return (
89
+ <div
90
+ key={value}
91
+ className={classNames(type === value ? "align-style-item-active" : "align-style-item-un_active", "align-style-item")}
92
+ onClick={headingTypeChange(value)}
93
+ >
94
+ {name}
95
+ </div>
96
+ );
97
+ })}
98
+ </div>
99
+ )}
100
+ {cardItemElement(t("font_color"), <ColorPicker color={color} setColor={colorChange("color")} />)}
101
+ {cardItemElement(
102
+ t("text_align"),
103
+ <div className="flex justify-center items-center">
104
+ {[
105
+ { icon: faAlignLeft, value: "left" },
106
+ { icon: faAlignCenter, value: "center" },
107
+ { icon: faAlignRight, value: "right" },
108
+ { icon: faAlignJustify, value: "justify" },
109
+ ].map(({ icon, value }) => {
110
+ return (
111
+ <div
112
+ key={value}
113
+ className={classNames(textAlign === value ? "align-style-item-active" : "align-style-item-un_active", "align-style-item")}
114
+ onClick={() => otherStylesChange("textAlign", value)}
115
+ >
116
+ <FontAwesomeIcon icon={icon} className="tag-style-size" />
117
+ </div>
118
+ );
119
+ })}
120
+ </div>
121
+ )}
122
+ {cardItemElement(
123
+ t("font_family"),
124
+ <Select
125
+ className="input-width"
126
+ value={fontFamily}
127
+ onChange={inputChange("fontFamily")}
128
+ getPopupContainer={() => document.querySelector(".right-settings") || document.body}
129
+ >
130
+ {fontFamilyList.map((item) => (
131
+ <Select.Option key={item} value={item}>
132
+ {item}
133
+ </Select.Option>
134
+ ))}
135
+ </Select>
136
+ )}
137
+ {cardItemElement(
138
+ t("font_size"),
139
+ <InputNumber min={0} className="input-width" addonAfter="px" value={fontSize} onChange={inputChange("fontSize")} />
140
+ )}
141
+ {cardItemElement(
142
+ t("line_height"),
143
+ <InputNumber
144
+ className="input-width"
145
+ addonAfter="%"
146
+ min={0}
147
+ value={Number(lineHeight.replace("%", ""))}
148
+ onChange={(value) => inputChange("lineHeight")(value + "%")}
149
+ />
150
+ )}
151
+ </>
152
+ );
153
+ };
154
+ return (
155
+ <div className="margin-y-30">
156
+ {textStylesElement()}
157
+ {PaddingStylesElement()}
158
+ </div>
159
+ );
160
+ };
161
+
162
+ export default HeadingStyleSettings;