easy-email-pro-theme 1.50.19 → 1.51.0

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.
package/lib/index.js CHANGED
@@ -54,7 +54,7 @@ var __async = (__this, __arguments, generator) => {
54
54
  step((generator = generator.apply(__this, __arguments)).next());
55
55
  });
56
56
  };
57
- import { classnames, useEditorActions, useDragNodePath, useStandaloneElementEditing, useEditorProps, useRefState, isDOMElement, useMergeTagsData, useLockState, useEventCallback, useSelectedNodePath, useSelectedNode, useSetSelectedNodePath, useSetHoverNodePath, useUniversalElementEditing, useUniversalElementPath, useStandaloneElementPath, useStandaloneElement, useActiveTab, ActiveTabKeys, toggleFormat, TextFormat, useUniversalElement, isFormatActive, validation, CustomEvent, getDynamicImagePlaceholder, EmailEditorProvider, EmailEditor, useForceUpdate, IframeComponent, useEditorState, HtmlStringToReactNodes, useStandaloneElementSaveButton, useEqualState, ExternalComponents, useDragoverDirection } from "easy-email-pro-editor";
57
+ import { classnames, useEditorActions, useDragNodePath, useStandaloneElementEditing, useEditorProps, useRefState, isDOMElement, useMergeTagsData, useLockState, useEventCallback, useSelectedNodePath, useSelectedNode, useSetSelectedNodePath, useSetHoverNodePath, useUniversalElementEditing, useUniversalElementPath, useStandaloneElementPath, useStandaloneElement, useActiveTab, ActiveTabKeys, toggleFormat, TextFormat, useUniversalElement, isFormatActive, validation, CustomEvent, getDynamicImagePlaceholder, EmailEditorProvider, EmailEditor, useEditorState, useForceUpdate, useEqualState, IframeComponent, HtmlStringToReactNodes, useStandaloneElementSaveButton, ExternalComponents, useDragoverDirection } from "easy-email-pro-editor";
58
58
  import { useSlate, ReactEditor, useSlateStatic, useSelected } from "slate-react";
59
59
  import * as React$2 from "react";
60
60
  import React__default, { useRef, useState, useEffect, useCallback, useMemo, createContext, useContext, useLayoutEffect, memo, useReducer, cloneElement, forwardRef, Suspense, Component, createElement } from "react";
@@ -63,7 +63,7 @@ import { cloneDeep, get, isEqual, set, omit as omit$2, merge as merge$1, debounc
63
63
  import { Editor, Range, Node, Transforms, Path, Text as Text$2, createEditor } from "slate";
64
64
  import { nanoid } from "nanoid";
65
65
  import { Form, Input, Modal, Collapse, Space, Empty, Card, Grid, Button as Button$2, Drawer, Switch, Typography as Typography$1, Tabs, Radio, Divider as Divider$2, Alert, Popconfirm, Tooltip, Message, PageHeader, Spin, Layout as Layout$2, Popover, Select as Select$1, Slider, InputNumber, Tag, Link as Link$3, List as List$1, Skeleton, Trigger } from "@arco-design/web-react";
66
- import { IconPlus, IconDelete, IconEdit, IconLeft, IconCopy, IconUndo, IconRedo, IconMinus, IconEye, IconSubscribeAdd, IconClose, IconCheckCircleFill, IconDragArrow, IconLock, IconUnlock, IconQuestionCircle, IconLink, IconCloud, IconDragDotVertical, IconSend, IconDown } from "@arco-design/web-react/icon";
66
+ import { IconPlus, IconDelete, IconEdit, IconLeft, IconCopy, IconUndo, IconRedo, IconMinus, IconEye, IconSubscribeAdd, IconClose, IconCheckCircleFill, IconDragArrow, IconPalette, IconLock, IconUnlock, IconImage, IconQuestionCircle, IconLink, IconCloud, IconDragDotVertical, IconSend, IconDown } from "@arco-design/web-react/icon";
67
67
  import { unstable_batchedUpdates, createPortal } from "react-dom";
68
68
  import mjml from "mjml-browser";
69
69
  import { HistoryEditor } from "slate-history";
@@ -6964,7 +6964,7 @@ const action = "_action_14paa_43";
6964
6964
  const itemTitle = "_itemTitle_14paa_60";
6965
6965
  const itemCollapse = "_itemCollapse_14paa_66";
6966
6966
  const itemChildren = "_itemChildren_14paa_87";
6967
- const styles$3 = {
6967
+ const styles$4 = {
6968
6968
  item: item$2,
6969
6969
  itemContent,
6970
6970
  itemActions,
@@ -7154,7 +7154,7 @@ function SortableComponentItem({
7154
7154
  const isVoid = BlockManager.getBlockByType(component.block.type).void;
7155
7155
  const hasBlockChildren = !isVoid && component.block.children.every((child) => NodeUtils.isBlockElement(child));
7156
7156
  const hideWhenDragging = isDraggingLevel && !isCurrentDragging;
7157
- return /* @__PURE__ */ React__default.createElement("div", { ref: setNodeRef, style, className: styles$3.sortableItem }, /* @__PURE__ */ React__default.createElement(
7157
+ return /* @__PURE__ */ React__default.createElement("div", { ref: setNodeRef, style, className: styles$4.sortableItem }, /* @__PURE__ */ React__default.createElement(
7158
7158
  ComponentItem,
7159
7159
  {
7160
7160
  component,
@@ -7164,7 +7164,7 @@ function SortableComponentItem({
7164
7164
  onToggleCollapse,
7165
7165
  dragHandleProps: __spreadValues(__spreadValues({}, attributes), listeners)
7166
7166
  }
7167
- ), hasBlockChildren && !isCollapsed && !isDragging && !hideWhenDragging && /* @__PURE__ */ React__default.createElement("div", { className: styles$3.itemChildren }, /* @__PURE__ */ React__default.createElement(
7167
+ ), hasBlockChildren && !isCollapsed && !isDragging && !hideWhenDragging && /* @__PURE__ */ React__default.createElement("div", { className: styles$4.itemChildren }, /* @__PURE__ */ React__default.createElement(
7168
7168
  ElementList,
7169
7169
  {
7170
7170
  blocks: component.block.children,
@@ -7229,10 +7229,10 @@ function ComponentItem({
7229
7229
  }
7230
7230
  return text;
7231
7231
  }, [component.block, label]);
7232
- return /* @__PURE__ */ React__default.createElement("div", { className: styles$3.item, onClick }, /* @__PURE__ */ React__default.createElement("div", { className: styles$3.itemContent }, /* @__PURE__ */ React__default.createElement("div", { className: styles$3.itemTitle }, /* @__PURE__ */ React__default.createElement(
7232
+ return /* @__PURE__ */ React__default.createElement("div", { className: styles$4.item, onClick }, /* @__PURE__ */ React__default.createElement("div", { className: styles$4.itemContent }, /* @__PURE__ */ React__default.createElement("div", { className: styles$4.itemTitle }, /* @__PURE__ */ React__default.createElement(
7233
7233
  "div",
7234
7234
  {
7235
- className: styles$3.itemCollapse,
7235
+ className: styles$4.itemCollapse,
7236
7236
  style: { opacity: hasBlockChildren ? 1 : 0 },
7237
7237
  onClick: handleCollapseClick
7238
7238
  },
@@ -7246,27 +7246,27 @@ function ComponentItem({
7246
7246
  },
7247
7247
  collapseIcon
7248
7248
  )
7249
- ), /* @__PURE__ */ React__default.createElement("div", { className: styles$3.itemLabelWrapper }, /* @__PURE__ */ React__default.createElement(
7249
+ ), /* @__PURE__ */ React__default.createElement("div", { className: styles$4.itemLabelWrapper }, /* @__PURE__ */ React__default.createElement(
7250
7250
  SharedComponents.ElementIcon,
7251
7251
  {
7252
7252
  type: component.block.type,
7253
7253
  width: 16,
7254
7254
  height: 16
7255
7255
  }
7256
- ), /* @__PURE__ */ React__default.createElement("div", { className: styles$3.itemLabel }, displayLabel))), /* @__PURE__ */ React__default.createElement(
7256
+ ), /* @__PURE__ */ React__default.createElement("div", { className: styles$4.itemLabel }, displayLabel))), /* @__PURE__ */ React__default.createElement(
7257
7257
  "div",
7258
7258
  {
7259
- className: styles$3.itemActions,
7259
+ className: styles$4.itemActions,
7260
7260
  onClick: (e) => e.stopPropagation()
7261
7261
  },
7262
- /* @__PURE__ */ React__default.createElement("div", { className: styles$3.action, onClick: onRemove }, /* @__PURE__ */ React__default.createElement(IconDelete, null)),
7262
+ /* @__PURE__ */ React__default.createElement("div", { className: styles$4.action, onClick: onRemove }, /* @__PURE__ */ React__default.createElement(IconDelete, null)),
7263
7263
  /* @__PURE__ */ React__default.createElement(
7264
7264
  "div",
7265
7265
  __spreadValues({
7266
7266
  style: {
7267
7267
  cursor: "grab"
7268
7268
  },
7269
- className: styles$3.action
7269
+ className: styles$4.action
7270
7270
  }, dragHandleProps),
7271
7271
  /* @__PURE__ */ React__default.createElement("svg", { viewBox: "0 0 20 20", width: "12" }, /* @__PURE__ */ React__default.createElement("path", { d: "M7 2a2 2 0 1 0 .001 4.001A2 2 0 0 0 7 2zm0 6a2 2 0 1 0 .001 4.001A2 2 0 0 0 7 8zm0 6a2 2 0 1 0 .001 4.001A2 2 0 0 0 7 14zm6-8a2 2 0 1 0-.001-4.001A2 2 0 0 0 13 6zm0 2a2 2 0 1 0 .001 4.001A2 2 0 0 0 13 8zm0 6a2 2 0 1 0 .001 4.001A2 2 0 0 0 13 14z" }))
7272
7272
  )
@@ -7948,7 +7948,7 @@ const TabHeader = (props) => {
7948
7948
  ));
7949
7949
  };
7950
7950
  const hoverUnderline = "_hoverUnderline_8d8dl_1";
7951
- const styles$2 = {
7951
+ const styles$3 = {
7952
7952
  hoverUnderline
7953
7953
  };
7954
7954
  function BlockPaths({
@@ -8010,7 +8010,7 @@ function BlockPaths({
8010
8010
  /* @__PURE__ */ React__default.createElement(
8011
8011
  "span",
8012
8012
  {
8013
- className: styles$2.hoverUnderline,
8013
+ className: styles$3.hoverUnderline,
8014
8014
  onClick: () => setSelectedNodePath(item2.path)
8015
8015
  },
8016
8016
  item2.name
@@ -26663,7 +26663,7 @@ const directionAdapter = {
26663
26663
  };
26664
26664
  const transparentIcon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAABAElEQVRIie2WwW7CMBBEZ8NKOJd8CPRABVVJ+fxUUEgQPbT9kBziFAWbU4FkjXCBICExtxk9Z7KxZYWSJLFoiJmbEYwxMMaI/JC1dv+oQmvE8QTWWvDo5VUs/FwtHSUWvmxTwUniQhHRdUuIyJm3Oslf6dVLmtMQEfhjNhVgFEUiq6oCvmye5zXPSnUF1Os/iSxLF/BlZ9P3mm9tTw4/231uvKuo9RIA4MHzUITHrgpfNgxDFFrv/E0meZT8S/zz/SXCsvyVIDP82U7dr9cSGsdvIsvSBXzZm10rj5KzJf99AGTpXGRB4H4fF6uUgi7LfYnrCLq18eSAqtpAddXObwEoMVtvVloS0QAAAABJRU5ErkJggg==";
26665
26665
  const transparentColor$1 = "rgba(0,0,0,0)";
26666
- function ColorPicker$1(props) {
26666
+ const ColorPickerContainer = (props) => {
26667
26667
  const {
26668
26668
  value = "",
26669
26669
  onChange,
@@ -26793,10 +26793,13 @@ function ColorPicker$1(props) {
26793
26793
  placeholder: placeholder == null ? void 0 : placeholder.replace("#", "")
26794
26794
  }
26795
26795
  ));
26796
- }
26796
+ };
26797
+ const ColorPicker$1 = (props) => {
26798
+ return /* @__PURE__ */ React__default.createElement(ColorProvider, null, /* @__PURE__ */ React__default.createElement(ColorPickerContainer, __spreadValues({}, props)));
26799
+ };
26797
26800
  const DefaultColorPicker = enhancer(ColorPicker$1);
26798
26801
  const ColorPickerField = (props) => {
26799
- return /* @__PURE__ */ React__default.createElement(ColorProvider, null, /* @__PURE__ */ React__default.createElement(
26802
+ return /* @__PURE__ */ React__default.createElement(
26800
26803
  DefaultColorPicker,
26801
26804
  __spreadProps(__spreadValues({}, props), {
26802
26805
  formItem: __spreadValues(__spreadProps(__spreadValues({}, colorAdapter), {
@@ -26818,7 +26821,7 @@ const ColorPickerField = (props) => {
26818
26821
  ]
26819
26822
  }), props.formItem)
26820
26823
  })
26821
- ));
26824
+ );
26822
26825
  };
26823
26826
  const idMap = /* @__PURE__ */ new Map();
26824
26827
  function reorder(list, startIndex, endIndex) {
@@ -27137,7 +27140,7 @@ const cardItemLeft = "_cardItemLeft_8uw8m_71";
27137
27140
  const cardItemRight = "_cardItemRight_8uw8m_85";
27138
27141
  const selectImage = "_selectImage_8uw8m_93";
27139
27142
  const exportFreeImage = "_exportFreeImage_8uw8m_110";
27140
- const styles$1 = {
27143
+ const styles$2 = {
27141
27144
  container,
27142
27145
  error,
27143
27146
  item,
@@ -27356,7 +27359,7 @@ function ImageUploader(props) {
27356
27359
  );
27357
27360
  const content = useMemo(() => {
27358
27361
  if (isUploading) {
27359
- return /* @__PURE__ */ React__default.createElement("div", { className: styles$1["item"] }, /* @__PURE__ */ React__default.createElement("div", { className: classnames$1(styles$1["info"]) }, /* @__PURE__ */ React__default.createElement(Spin, { size: 60 }), /* @__PURE__ */ React__default.createElement("div", { className: styles$1["btn-wrap"] })));
27362
+ return /* @__PURE__ */ React__default.createElement("div", { className: styles$2["item"] }, /* @__PURE__ */ React__default.createElement("div", { className: classnames$1(styles$2["info"]) }, /* @__PURE__ */ React__default.createElement(Spin, { size: 60 }), /* @__PURE__ */ React__default.createElement("div", { className: styles$2["btn-wrap"] })));
27360
27363
  }
27361
27364
  if (!props.value) {
27362
27365
  return /* @__PURE__ */ React__default.createElement("div", null, /* @__PURE__ */ React__default.createElement(
@@ -27377,10 +27380,10 @@ function ImageUploader(props) {
27377
27380
  lineHeight: "22px"
27378
27381
  }
27379
27382
  },
27380
- unsplashClientId ? /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement("div", { className: styles$1.selectImage, onClick: onUpload }, t("Select image")), /* @__PURE__ */ React__default.createElement(
27383
+ unsplashClientId ? /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement("div", { className: styles$2.selectImage, onClick: onUpload }, t("Select image")), /* @__PURE__ */ React__default.createElement(
27381
27384
  "div",
27382
27385
  {
27383
- className: styles$1.exportFreeImage,
27386
+ className: styles$2.exportFreeImage,
27384
27387
  onClick: () => setUnsplashVisible(true)
27385
27388
  },
27386
27389
  t("Export free images")
@@ -27426,7 +27429,7 @@ function ImageUploader(props) {
27426
27429
  triggerProps: {
27427
27430
  popupStyle: { display: "inline-flex" }
27428
27431
  },
27429
- triggerElement: /* @__PURE__ */ React__default.createElement("span", { className: styles$1.actionItem }, t("Replace"))
27432
+ triggerElement: /* @__PURE__ */ React__default.createElement("span", { className: styles$2.actionItem }, t("Replace"))
27430
27433
  },
27431
27434
  /* @__PURE__ */ React__default.createElement(Select$1.Option, { value: "1", onClick: onUpload }, t("Select image")),
27432
27435
  /* @__PURE__ */ React__default.createElement(
@@ -27437,10 +27440,10 @@ function ImageUploader(props) {
27437
27440
  },
27438
27441
  t("Export free images")
27439
27442
  )
27440
- ) : /* @__PURE__ */ React__default.createElement("span", { className: styles$1.actionItem, onClick: onUpload }, t("Replace")), enablePreview && /* @__PURE__ */ React__default.createElement("span", null, " ∙ "), enablePreview && /* @__PURE__ */ React__default.createElement(
27443
+ ) : /* @__PURE__ */ React__default.createElement("span", { className: styles$2.actionItem, onClick: onUpload }, t("Replace")), enablePreview && /* @__PURE__ */ React__default.createElement("span", null, " ∙ "), enablePreview && /* @__PURE__ */ React__default.createElement(
27441
27444
  "span",
27442
27445
  {
27443
- className: styles$1.actionItem,
27446
+ className: styles$2.actionItem,
27444
27447
  onClick: () => setPreview(true)
27445
27448
  },
27446
27449
  t("Preview")
@@ -27908,11 +27911,621 @@ function PixelField(props) {
27908
27911
  })
27909
27912
  );
27910
27913
  }
27914
+ const controlSection = "_controlSection_1t3ne_1";
27915
+ const controlGroup = "_controlGroup_1t3ne_7";
27916
+ const colorHeader = "_colorHeader_1t3ne_11";
27917
+ const colorList = "_colorList_1t3ne_18";
27918
+ const colorItem = "_colorItem_1t3ne_34";
27919
+ const positionControl = "_positionControl_1t3ne_44";
27920
+ const percentSign = "_percentSign_1t3ne_50";
27921
+ const deleteButton = "_deleteButton_1t3ne_55";
27922
+ const sizeInputs = "_sizeInputs_1t3ne_62";
27923
+ const styles$1 = {
27924
+ controlSection,
27925
+ controlGroup,
27926
+ colorHeader,
27927
+ colorList,
27928
+ colorItem,
27929
+ positionControl,
27930
+ percentSign,
27931
+ deleteButton,
27932
+ sizeInputs
27933
+ };
27934
+ const MAX_COLORS = 4;
27935
+ const MIN_COLORS = 2;
27936
+ const GRADIENT_PRESETS = [
27937
+ {
27938
+ value: "1",
27939
+ colors: [
27940
+ { color: "#2CD8D5", position: 0 },
27941
+ { color: "#C5C1FF", position: 56 },
27942
+ { color: "#FFBAC3", position: 100 }
27943
+ ],
27944
+ label: "Prism"
27945
+ },
27946
+ {
27947
+ value: "2",
27948
+ colors: [
27949
+ { color: "#00C6FB", position: 0 },
27950
+ { color: "#005BEA", position: 100 }
27951
+ ],
27952
+ label: "Ocean"
27953
+ },
27954
+ {
27955
+ value: "3",
27956
+ colors: [
27957
+ { color: "#F6D365", position: 0 },
27958
+ { color: "#FDA085", position: 100 }
27959
+ ],
27960
+ label: "Sun"
27961
+ },
27962
+ {
27963
+ value: "4",
27964
+ colors: [
27965
+ { color: "#21D4FD", position: 0 },
27966
+ { color: "#B721FF", position: 100 }
27967
+ ],
27968
+ label: "Purple"
27969
+ },
27970
+ {
27971
+ value: "5",
27972
+ colors: [
27973
+ { color: "#3EECAC", position: 0 },
27974
+ { color: "#EE74E1", position: 100 }
27975
+ ],
27976
+ label: "Aurora"
27977
+ },
27978
+ {
27979
+ value: "6",
27980
+ colors: [
27981
+ { color: "#FA8BFF", position: 0 },
27982
+ { color: "#2BD2FF", position: 52 },
27983
+ { color: "#2BFF88", position: 100 }
27984
+ ],
27985
+ label: "Rainbow"
27986
+ },
27987
+ {
27988
+ value: "7",
27989
+ colors: [
27990
+ { color: "#08AEEA", position: 0 },
27991
+ { color: "#2AF598", position: 100 }
27992
+ ],
27993
+ label: "Mint"
27994
+ },
27995
+ {
27996
+ value: "8",
27997
+ colors: [
27998
+ { color: "#FBAB7E", position: 0 },
27999
+ { color: "#F7CE68", position: 100 }
28000
+ ],
28001
+ label: "Amber"
28002
+ },
28003
+ {
28004
+ value: "9",
28005
+ colors: [
28006
+ { color: "#85FFBD", position: 0 },
28007
+ { color: "#FFFB7D", position: 100 }
28008
+ ],
28009
+ label: "Lime"
28010
+ },
28011
+ {
28012
+ value: "10",
28013
+ colors: [
28014
+ { color: "#FF3CAC", position: 0 },
28015
+ { color: "#784BA0", position: 50 },
28016
+ { color: "#2B86C5", position: 100 }
28017
+ ],
28018
+ label: "Dream"
28019
+ },
28020
+ {
28021
+ value: "11",
28022
+ colors: [
28023
+ { color: "#0093E9", position: 0 },
28024
+ { color: "#80D0C7", position: 100 }
28025
+ ],
28026
+ label: "Aqua"
28027
+ },
28028
+ {
28029
+ value: "12",
28030
+ colors: [
28031
+ { color: "#D9AFD9", position: 0 },
28032
+ { color: "#97D9E1", position: 100 }
28033
+ ],
28034
+ label: "Lilac"
28035
+ },
28036
+ {
28037
+ value: "13",
28038
+ colors: [
28039
+ { color: "#8BC6EC", position: 0 },
28040
+ { color: "#9599E2", position: 100 }
28041
+ ],
28042
+ label: "Violet"
28043
+ },
28044
+ {
28045
+ value: "14",
28046
+ colors: [
28047
+ { color: "#A9C9FF", position: 0 },
28048
+ { color: "#FFBBEC", position: 100 }
28049
+ ],
28050
+ label: "Pink"
28051
+ },
28052
+ {
28053
+ value: "15",
28054
+ colors: [
28055
+ { color: "#FEE140", position: 0 },
28056
+ { color: "#FA709A", position: 100 }
28057
+ ],
28058
+ label: "Peach"
28059
+ },
28060
+ {
28061
+ value: "16",
28062
+ colors: [
28063
+ { color: "#00DBDE", position: 0 },
28064
+ { color: "#FC00FF", position: 100 }
28065
+ ],
28066
+ label: "Neon"
28067
+ },
28068
+ {
28069
+ value: "17",
28070
+ colors: [
28071
+ { color: "#4158D0", position: 0 },
28072
+ { color: "#C850C0", position: 46 },
28073
+ { color: "#FFCC70", position: 100 }
28074
+ ],
28075
+ label: "Sunset"
28076
+ },
28077
+ {
28078
+ value: "18",
28079
+ colors: [
28080
+ { color: "#0BA360", position: 0 },
28081
+ { color: "#3CBA92", position: 100 }
28082
+ ],
28083
+ label: "Jade"
28084
+ },
28085
+ {
28086
+ value: "19",
28087
+ colors: [
28088
+ { color: "#FFDEE9", position: 0 },
28089
+ { color: "#B5FFFC", position: 100 }
28090
+ ],
28091
+ label: "Candy"
28092
+ },
28093
+ {
28094
+ value: "20",
28095
+ colors: [
28096
+ { color: "#74EBD5", position: 0 },
28097
+ { color: "#9FACE6", position: 100 }
28098
+ ],
28099
+ label: "Dawn"
28100
+ }
28101
+ ];
28102
+ function GradientGenerator(props) {
28103
+ const [loading, setLoading] = useState(false);
28104
+ const { setLock } = useEditorState();
28105
+ const canvasRef = useRef(null);
28106
+ const { isOpen, setIsOpen } = props;
28107
+ const { resetSelectedNode } = useElementInteract();
28108
+ const { lastSelectedNode, isChanged } = useLastSelectedNode();
28109
+ const changeRef = useRefState(isChanged);
28110
+ const { selectedNode } = useSelectedNode();
28111
+ const data = props.data;
28112
+ const colors = data.colors;
28113
+ const lock = useLockState();
28114
+ const onChangeRef = useRefState(props.onChange);
28115
+ const setData = useCallback(
28116
+ (val) => {
28117
+ onChangeRef.current(val);
28118
+ },
28119
+ [onChangeRef]
28120
+ );
28121
+ const addColor = () => {
28122
+ if (colors.length >= MAX_COLORS) {
28123
+ Message.warning(t(`Maximum 4 colors allowed`));
28124
+ return;
28125
+ }
28126
+ const newColor = {
28127
+ id: nanoid(),
28128
+ color: "#ffffff",
28129
+ position: 50
28130
+ };
28131
+ setData(__spreadProps(__spreadValues({}, data), {
28132
+ colors: [...colors, newColor].sort((a, b) => a.position - b.position)
28133
+ }));
28134
+ };
28135
+ const previewRef = useRefState(props.onPreview);
28136
+ const removeColor = (index2) => {
28137
+ const newColors = cloneDeep(colors).filter((_, i) => i !== index2);
28138
+ setData(__spreadProps(__spreadValues({}, data), {
28139
+ colors: newColors.sort((a, b) => a.position - b.position)
28140
+ }));
28141
+ };
28142
+ const generateGradientBlob = useCallback(
28143
+ (params) => __async(this, null, function* () {
28144
+ const { colors: colors2, gradientAngle, gradientSize, gradientType } = params;
28145
+ const canvas = canvasRef.current;
28146
+ if (!canvas)
28147
+ return;
28148
+ const ctx = canvas.getContext("2d");
28149
+ if (!ctx)
28150
+ return;
28151
+ const size = gradientSize;
28152
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
28153
+ canvas.width = size.width;
28154
+ canvas.height = size.height;
28155
+ let gradient;
28156
+ if (gradientType === "linear") {
28157
+ const canvasAngle = (360 - gradientAngle + 90) % 360 * Math.PI / 180;
28158
+ const x1 = size.width / 2 - Math.cos(canvasAngle) * size.width / 2;
28159
+ const y1 = size.height / 2 - Math.sin(canvasAngle) * size.height / 2;
28160
+ const x2 = size.width / 2 + Math.cos(canvasAngle) * size.width / 2;
28161
+ const y2 = size.height / 2 + Math.sin(canvasAngle) * size.height / 2;
28162
+ gradient = ctx.createLinearGradient(x1, y1, x2, y2);
28163
+ } else {
28164
+ gradient = ctx.createRadialGradient(
28165
+ size.width / 2,
28166
+ size.height / 2,
28167
+ 0,
28168
+ size.width / 2,
28169
+ size.height / 2,
28170
+ Math.min(size.width, size.height) / 2
28171
+ );
28172
+ }
28173
+ colors2.forEach((color2) => {
28174
+ gradient.addColorStop(color2.position / 100, color2.color);
28175
+ });
28176
+ ctx.fillStyle = gradient;
28177
+ ctx.fillRect(0, 0, size.width, size.height);
28178
+ const blob = yield new Promise((resolve) => {
28179
+ canvas.toBlob((blob2) => {
28180
+ resolve(blob2);
28181
+ });
28182
+ });
28183
+ return blob;
28184
+ }),
28185
+ []
28186
+ );
28187
+ const generatePreview = useCallback(
28188
+ debounce$2(
28189
+ (params) => {
28190
+ generateGradientBlob(params).then((blob) => {
28191
+ var _a;
28192
+ if (!blob)
28193
+ return;
28194
+ const url = URL.createObjectURL(blob);
28195
+ (_a = previewRef.current) == null ? void 0 : _a.call(previewRef, url);
28196
+ });
28197
+ },
28198
+ 100
28199
+ ),
28200
+ [generateGradientBlob, previewRef]
28201
+ );
28202
+ const handelSave = () => __async(this, null, function* () {
28203
+ var _a;
28204
+ const canvas = canvasRef.current;
28205
+ if (!canvas)
28206
+ return;
28207
+ try {
28208
+ setLoading(true);
28209
+ const blob = yield generateGradientBlob({
28210
+ colors,
28211
+ gradientAngle: data.angle,
28212
+ gradientSize: { width: data.width, height: data.height },
28213
+ gradientType: data.type
28214
+ });
28215
+ if (!blob)
28216
+ return;
28217
+ yield (_a = props.onSave) == null ? void 0 : _a.call(props, data, blob);
28218
+ handleClose();
28219
+ } catch (error2) {
28220
+ console.error(error2);
28221
+ Message.error(t(`Save failed`));
28222
+ } finally {
28223
+ setLoading(false);
28224
+ }
28225
+ });
28226
+ useEffect(() => {
28227
+ if (!isOpen)
28228
+ return;
28229
+ if (!changeRef.current)
28230
+ return;
28231
+ generatePreview({
28232
+ colors,
28233
+ gradientAngle: data.angle,
28234
+ gradientSize: {
28235
+ width: data.width,
28236
+ height: data.height
28237
+ },
28238
+ gradientType: data.type
28239
+ });
28240
+ return () => {
28241
+ generatePreview.cancel();
28242
+ };
28243
+ }, [
28244
+ colors,
28245
+ generatePreview,
28246
+ data.angle,
28247
+ data.width,
28248
+ data.height,
28249
+ data.type,
28250
+ isOpen,
28251
+ changeRef
28252
+ ]);
28253
+ useEffect(() => {
28254
+ if (lastSelectedNode.current && !isEqual(lastSelectedNode.current, selectedNode)) {
28255
+ console.log("set lock");
28256
+ setLock(true);
28257
+ } else {
28258
+ resetSelectedNode();
28259
+ setLock(false);
28260
+ }
28261
+ }, [lastSelectedNode, selectedNode, setLock, resetSelectedNode]);
28262
+ const handleClose = () => {
28263
+ lastSelectedNode.current = null;
28264
+ setIsOpen(false);
28265
+ setLock(false);
28266
+ };
28267
+ return /* @__PURE__ */ React__default.createElement(
28268
+ Drawer,
28269
+ {
28270
+ className: "GradientGeneratorDrawer",
28271
+ bodyStyle: {
28272
+ paddingLeft: 0,
28273
+ paddingRight: 0,
28274
+ paddingTop: 0,
28275
+ paddingBottom: 60
28276
+ },
28277
+ closable: false,
28278
+ width: "100%",
28279
+ visible: isOpen && props.enable,
28280
+ getPopupContainer: () => {
28281
+ return document.body.querySelector("#ConfigurationDrawer") || document.body;
28282
+ },
28283
+ title: /* @__PURE__ */ React__default.createElement("div", { style: { textAlign: "left" } }, /* @__PURE__ */ React__default.createElement(Space, null, /* @__PURE__ */ React__default.createElement(
28284
+ Button$2,
28285
+ {
28286
+ type: "text",
28287
+ icon: /* @__PURE__ */ React__default.createElement(IconLeft, null),
28288
+ disabled: lock,
28289
+ onClick: handleClose
28290
+ }
28291
+ ), /* @__PURE__ */ React__default.createElement(IconPalette, null), " ", t(`Gradient Generator`))),
28292
+ okButtonProps: {
28293
+ type: "primary",
28294
+ onClick: handelSave,
28295
+ loading
28296
+ },
28297
+ okText: t(`Generate`),
28298
+ cancelText: t(`Cancel`),
28299
+ onCancel: handleClose,
28300
+ cancelButtonProps: {
28301
+ disabled: lock
28302
+ }
28303
+ },
28304
+ /* @__PURE__ */ React__default.createElement("div", { key: isOpen.toString() }, isChanged && lock && /* @__PURE__ */ React__default.createElement(
28305
+ Alert,
28306
+ {
28307
+ type: "warning",
28308
+ content: /* @__PURE__ */ React__default.createElement("div", null, /* @__PURE__ */ React__default.createElement("span", null, t(`Content has been modified. Please save before leaving.`)), " ", /* @__PURE__ */ React__default.createElement(
28309
+ Popconfirm,
28310
+ {
28311
+ focusLock: true,
28312
+ title: t("Do you want to discard?"),
28313
+ okText: t("Discard"),
28314
+ cancelText: t("Cancel"),
28315
+ style: { zIndex: 9999 },
28316
+ getPopupContainer: () => document.body,
28317
+ okButtonProps: {
28318
+ status: "danger"
28319
+ },
28320
+ onOk: () => {
28321
+ resetSelectedNode();
28322
+ handleClose();
28323
+ }
28324
+ },
28325
+ /* @__PURE__ */ React__default.createElement(
28326
+ "span",
28327
+ {
28328
+ style: {
28329
+ color: "rgb(var(--danger-6))",
28330
+ cursor: "pointer"
28331
+ }
28332
+ },
28333
+ t("Discard")
28334
+ )
28335
+ ))
28336
+ }
28337
+ ), /* @__PURE__ */ React__default.createElement("div", { className: styles$1.controlSection }, /* @__PURE__ */ React__default.createElement("div", { className: styles$1.controlGroup }, /* @__PURE__ */ React__default.createElement(
28338
+ Form.Item,
28339
+ {
28340
+ label: /* @__PURE__ */ React__default.createElement("div", null, /* @__PURE__ */ React__default.createElement(
28341
+ "div",
28342
+ {
28343
+ style: {
28344
+ display: "flex",
28345
+ alignItems: "center",
28346
+ gap: "4px"
28347
+ }
28348
+ },
28349
+ /* @__PURE__ */ React__default.createElement(
28350
+ "div",
28351
+ {
28352
+ style: {
28353
+ width: "20px",
28354
+ height: "20px",
28355
+ display: "flex",
28356
+ alignItems: "center",
28357
+ justifyContent: "center",
28358
+ borderRadius: "4px",
28359
+ backgroundImage: "linear-gradient(to right, rgb(99, 102, 241), rgb(168, 85, 247))",
28360
+ color: "white"
28361
+ }
28362
+ },
28363
+ /* @__PURE__ */ React__default.createElement(IconPalette, { color: "white" })
28364
+ ),
28365
+ /* @__PURE__ */ React__default.createElement("span", null, "Preset")
28366
+ )),
28367
+ layout: "vertical"
28368
+ },
28369
+ /* @__PURE__ */ React__default.createElement(
28370
+ Select$1,
28371
+ {
28372
+ style: { width: "100%" },
28373
+ onChange: (value) => {
28374
+ const preset = GRADIENT_PRESETS.find(
28375
+ (p) => p.value === value
28376
+ );
28377
+ if (preset) {
28378
+ setData(__spreadProps(__spreadValues({}, data), {
28379
+ colors: preset.colors.map((c) => __spreadProps(__spreadValues({}, c), {
28380
+ id: nanoid()
28381
+ }))
28382
+ }));
28383
+ }
28384
+ }
28385
+ },
28386
+ GRADIENT_PRESETS.map((preset) => /* @__PURE__ */ React__default.createElement(Select$1.Option, { key: preset.value, value: preset.value }, /* @__PURE__ */ React__default.createElement(
28387
+ "div",
28388
+ {
28389
+ style: {
28390
+ display: "flex",
28391
+ alignItems: "center",
28392
+ gap: "12px",
28393
+ width: "100%"
28394
+ }
28395
+ },
28396
+ /* @__PURE__ */ React__default.createElement(
28397
+ "div",
28398
+ {
28399
+ style: {
28400
+ width: `calc(100% - 80px)`,
28401
+ height: "24px",
28402
+ borderRadius: "4px",
28403
+ backgroundImage: `linear-gradient(to right, ${preset.colors.map((c) => `${c.color} ${c.position}%`).join(", ")})`,
28404
+ flexShrink: 0
28405
+ }
28406
+ }
28407
+ ),
28408
+ /* @__PURE__ */ React__default.createElement(
28409
+ "div",
28410
+ {
28411
+ style: {
28412
+ fontSize: "12px",
28413
+ whiteSpace: "nowrap",
28414
+ overflow: "hidden",
28415
+ textOverflow: "ellipsis"
28416
+ }
28417
+ },
28418
+ preset.label
28419
+ )
28420
+ )))
28421
+ )
28422
+ )), /* @__PURE__ */ React__default.createElement(Divider$2, { style: { margin: "0px 0 10px 0" } }), /* @__PURE__ */ React__default.createElement("div", { className: styles$1.controlGroup }, /* @__PURE__ */ React__default.createElement(Form.Item, { label: t(`Gradient Type`), layout: "vertical" }, /* @__PURE__ */ React__default.createElement(
28423
+ Select$1,
28424
+ {
28425
+ style: { width: "100%" },
28426
+ options: [
28427
+ {
28428
+ label: t(`Linear Gradient`),
28429
+ value: "linear"
28430
+ },
28431
+ {
28432
+ label: t(`Radial Gradient`),
28433
+ value: "radial"
28434
+ }
28435
+ ],
28436
+ value: data.type,
28437
+ onChange: (value) => {
28438
+ setData(__spreadProps(__spreadValues({}, data), {
28439
+ type: value
28440
+ }));
28441
+ }
28442
+ }
28443
+ ))), /* @__PURE__ */ React__default.createElement("div", { className: styles$1.controlGroup }, /* @__PURE__ */ React__default.createElement(Grid.Row, null, /* @__PURE__ */ React__default.createElement(Grid.Col, { span: 11 }, /* @__PURE__ */ React__default.createElement(Form.Item, { label: t(`Width`), layout: "vertical" }, /* @__PURE__ */ React__default.createElement(
28444
+ InputNumber,
28445
+ {
28446
+ style: { width: "100%" },
28447
+ value: data.width,
28448
+ onChange: (value) => {
28449
+ setData(__spreadProps(__spreadValues({}, data), { width: value }));
28450
+ }
28451
+ }
28452
+ ))), /* @__PURE__ */ React__default.createElement(Grid.Col, { offset: 2, span: 11 }, /* @__PURE__ */ React__default.createElement(Form.Item, { label: t(`Height`), layout: "vertical" }, /* @__PURE__ */ React__default.createElement(
28453
+ InputNumber,
28454
+ {
28455
+ style: { width: "100%" },
28456
+ value: data.height,
28457
+ onChange: (value) => {
28458
+ setData(__spreadProps(__spreadValues({}, data), { height: value }));
28459
+ }
28460
+ }
28461
+ ))))), /* @__PURE__ */ React__default.createElement(Divider$2, null), data.type === "linear" && /* @__PURE__ */ React__default.createElement("div", { className: styles$1.controlGroup }, /* @__PURE__ */ React__default.createElement(Form.Item, { label: t(`Angle`), layout: "vertical" }, /* @__PURE__ */ React__default.createElement(
28462
+ Slider,
28463
+ {
28464
+ value: data.angle,
28465
+ onChange: (value) => {
28466
+ setData(__spreadProps(__spreadValues({}, data), { angle: value }));
28467
+ },
28468
+ style: { width: "100%" },
28469
+ max: 360,
28470
+ min: 0,
28471
+ step: 1,
28472
+ showInput: true
28473
+ }
28474
+ ))), /* @__PURE__ */ React__default.createElement(Divider$2, null), /* @__PURE__ */ React__default.createElement("div", { className: styles$1.controlGroup }, /* @__PURE__ */ React__default.createElement("div", { className: styles$1.colorHeader }, /* @__PURE__ */ React__default.createElement("div", { className: styles$1.label }, t(`Colors`), " (", colors.length, "/", MAX_COLORS, ")"), /* @__PURE__ */ React__default.createElement(
28475
+ Button$2,
28476
+ {
28477
+ type: "text",
28478
+ icon: /* @__PURE__ */ React__default.createElement(IconPlus, null),
28479
+ onClick: addColor,
28480
+ size: "small",
28481
+ disabled: colors.length >= MAX_COLORS
28482
+ },
28483
+ t(`Add Color`)
28484
+ )), /* @__PURE__ */ React__default.createElement("div", { className: styles$1.colorList }, colors.map((color2, index2) => /* @__PURE__ */ React__default.createElement("div", { key: color2.id, className: styles$1.colorItem }, /* @__PURE__ */ React__default.createElement("div", { className: styles$1.colorInputs }, /* @__PURE__ */ React__default.createElement(
28485
+ ColorPicker$1,
28486
+ {
28487
+ value: color2.color,
28488
+ onChange: (value) => {
28489
+ setData(__spreadProps(__spreadValues({}, data), {
28490
+ colors: data.colors.map(
28491
+ (c, i) => i === index2 ? __spreadProps(__spreadValues({}, c), { color: value }) : c
28492
+ )
28493
+ }));
28494
+ }
28495
+ }
28496
+ )), /* @__PURE__ */ React__default.createElement("div", { className: styles$1.positionControl }, /* @__PURE__ */ React__default.createElement(
28497
+ InputNumber,
28498
+ {
28499
+ value: color2.position,
28500
+ onChange: (value) => {
28501
+ setData(__spreadProps(__spreadValues({}, data), {
28502
+ colors: data.colors.map(
28503
+ (c, i) => i === index2 ? __spreadProps(__spreadValues({}, c), { position: value }) : c
28504
+ )
28505
+ }));
28506
+ },
28507
+ style: { width: "80px" },
28508
+ min: 0,
28509
+ max: 100
28510
+ }
28511
+ ), /* @__PURE__ */ React__default.createElement("span", { className: styles$1.percentSign }, "%"), colors.length > MIN_COLORS && /* @__PURE__ */ React__default.createElement(
28512
+ Button$2,
28513
+ {
28514
+ type: "text",
28515
+ icon: /* @__PURE__ */ React__default.createElement(IconDelete, null),
28516
+ onClick: () => removeColor(index2),
28517
+ className: styles$1.deleteButton
28518
+ }
28519
+ )))))))),
28520
+ /* @__PURE__ */ React__default.createElement("canvas", { ref: canvasRef, style: { display: "none" } })
28521
+ );
28522
+ }
27911
28523
  const TextField = enhancer(Input);
27912
28524
  enhancer(Input.Search);
27913
28525
  const TextAreaField = enhancer(Input.TextArea);
27914
28526
  const NumberField = enhancer(InputNumber);
27915
28527
  const SelectField = enhancer(Select);
28528
+ const GradientGeneratorField = enhancer(GradientGenerator);
27916
28529
  function BackgroundColor(props) {
27917
28530
  const { label = t("Background color") } = props;
27918
28531
  return useMemo(() => {
@@ -28843,11 +29456,73 @@ const backgroundSizeOptions = [
28843
29456
  }
28844
29457
  ];
28845
29458
  function BackgroundImage(props) {
28846
- const { getFieldValue } = useEditorContext();
28847
- const isEnabledImage = getFieldValue(
29459
+ const { getFieldValue: useGetFieldValue, setFieldValue } = useEditorContext();
29460
+ const editor = useSlateStatic();
29461
+ const { enabledGradientImage } = useEditorProps();
29462
+ const isEnabledImage = useGetFieldValue(
28848
29463
  props.path,
28849
29464
  props.name + ".background-image-enabled"
28850
29465
  );
29466
+ const hasGradient = useGetFieldValue(props.path, "data.gradient");
29467
+ const isEnabledGradient = useGetFieldValue(
29468
+ props.path,
29469
+ "data.gradient.enabled"
29470
+ );
29471
+ const handleChangeEnabledGradient = useCallback(
29472
+ (value) => {
29473
+ if (hasGradient) {
29474
+ setFieldValue(
29475
+ props.path,
29476
+ "data.gradient.enabled",
29477
+ value === "gradient"
29478
+ );
29479
+ } else {
29480
+ let width = 600;
29481
+ let height = 400;
29482
+ const domNode = ReactEditor.toDOMNode(
29483
+ editor,
29484
+ Node.get(editor, props.path)
29485
+ );
29486
+ try {
29487
+ width = domNode.offsetWidth;
29488
+ height = parseInt((domNode.offsetHeight * 1.5).toString());
29489
+ } catch (error2) {
29490
+ console.log("error", error2);
29491
+ }
29492
+ const gradient = {
29493
+ enabled: true,
29494
+ colors: [
29495
+ {
29496
+ id: nanoid(),
29497
+ color: "#4a90e2",
29498
+ position: 0
29499
+ },
29500
+ {
29501
+ id: nanoid(),
29502
+ color: "#c6dffb",
29503
+ position: 30
29504
+ },
29505
+ {
29506
+ id: nanoid(),
29507
+ color: "#ffffff",
29508
+ position: 100
29509
+ }
29510
+ ],
29511
+ angle: 45,
29512
+ type: "linear",
29513
+ width,
29514
+ height
29515
+ };
29516
+ setFieldValue(props.path, "data.gradient", gradient);
29517
+ setFieldValue(
29518
+ props.path,
29519
+ props.name + ".background-url",
29520
+ "https://cdn.shopify.com/s/files/1/0863/8971/9346/files/vt4tumq_4aorkduqi2c-s_nwiysq709yi-nbxh-c8sk.png"
29521
+ );
29522
+ }
29523
+ },
29524
+ [editor, hasGradient, props.name, props.path, setFieldValue]
29525
+ );
28851
29526
  return useMemo(() => {
28852
29527
  return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(
28853
29528
  AttributeField.SwitchField,
@@ -28856,7 +29531,52 @@ function BackgroundImage(props) {
28856
29531
  label: t("Image"),
28857
29532
  name: props.name + ".background-image-enabled"
28858
29533
  }
28859
- ), isEnabledImage && /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(
29534
+ ), isEnabledImage && /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, enabledGradientImage && /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(Grid.Row, null, /* @__PURE__ */ React__default.createElement(Grid.Col, { span: 20, offset: 4 }, /* @__PURE__ */ React__default.createElement(
29535
+ Radio.Group,
29536
+ {
29537
+ type: "button",
29538
+ value: isEnabledGradient ? "gradient" : "image",
29539
+ onChange: handleChangeEnabledGradient,
29540
+ options: [
29541
+ {
29542
+ value: "image",
29543
+ label: /* @__PURE__ */ React__default.createElement(
29544
+ Space,
29545
+ {
29546
+ align: "center",
29547
+ style: {
29548
+ minWidth: "100px",
29549
+ justifyContent: "center"
29550
+ }
29551
+ },
29552
+ /* @__PURE__ */ React__default.createElement(IconImage, null),
29553
+ t("Image")
29554
+ )
29555
+ },
29556
+ {
29557
+ value: "gradient",
29558
+ label: /* @__PURE__ */ React__default.createElement(
29559
+ Space,
29560
+ {
29561
+ align: "center",
29562
+ style: {
29563
+ minWidth: "100px",
29564
+ justifyContent: "center"
29565
+ }
29566
+ },
29567
+ /* @__PURE__ */ React__default.createElement(IconPalette, null),
29568
+ t("Gradient")
29569
+ )
29570
+ }
29571
+ ]
29572
+ }
29573
+ ))), /* @__PURE__ */ React__default.createElement(Divider$2, null)), isEnabledGradient ? /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(
29574
+ AttributeField.BackgroundGradient,
29575
+ __spreadProps(__spreadValues({}, props), {
29576
+ targetName: props.name + ".background-url",
29577
+ formItem: __spreadValues({ layout: "vertical" }, props.formItem)
29578
+ })
29579
+ )) : /* @__PURE__ */ React__default.createElement(
28860
29580
  AttributeField.ImageUrl,
28861
29581
  __spreadProps(__spreadValues({}, props), {
28862
29582
  name: props.name + ".background-url",
@@ -28876,7 +29596,13 @@ function BackgroundImage(props) {
28876
29596
  name: props.name + ".background-position"
28877
29597
  })
28878
29598
  )));
28879
- }, [isEnabledImage, props]);
29599
+ }, [
29600
+ enabledGradientImage,
29601
+ handleChangeEnabledGradient,
29602
+ isEnabledGradient,
29603
+ isEnabledImage,
29604
+ props
29605
+ ]);
28880
29606
  }
28881
29607
  function ImageUrl(props) {
28882
29608
  const { onUpload } = useEditorProps();
@@ -30237,6 +30963,76 @@ const MergeTagSelectInputField = (props) => {
30237
30963
  ))
30238
30964
  ));
30239
30965
  };
30966
+ function BackgroundGradient(props) {
30967
+ const { onUpload } = useEditorProps();
30968
+ const { getFieldValue, setFieldValue } = useEditorContext();
30969
+ const editor = useSlateStatic();
30970
+ const fieldName = "data.gradient";
30971
+ const gradient = useEqualState(getFieldValue(props.path, fieldName));
30972
+ const [isOpen, setIsOpen] = useState(false);
30973
+ const handelSave = useCallback(
30974
+ (val, blob) => __async(this, null, function* () {
30975
+ if (!onUpload)
30976
+ return;
30977
+ const gradientUrl = yield onUpload(blob);
30978
+ setFieldValue(props.path, props.targetName, gradientUrl);
30979
+ }),
30980
+ [onUpload, props.path, props.targetName, setFieldValue]
30981
+ );
30982
+ const handelPreview = useCallback(
30983
+ (url) => {
30984
+ HistoryEditor.withoutSaving(editor, () => {
30985
+ setFieldValue(props.path, props.targetName, url);
30986
+ });
30987
+ },
30988
+ [editor, props.path, props.targetName, setFieldValue]
30989
+ );
30990
+ const handleChange = useCallback(
30991
+ (val) => {
30992
+ setFieldValue(props.path, fieldName, val);
30993
+ },
30994
+ [props.path, fieldName, setFieldValue]
30995
+ );
30996
+ const enableGradient = useEqualState(
30997
+ getFieldValue(props.path, `${fieldName}.enabled`)
30998
+ );
30999
+ return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, isOpen && /* @__PURE__ */ React__default.createElement(
31000
+ GradientGenerator,
31001
+ {
31002
+ data: gradient,
31003
+ onSave: handelSave,
31004
+ onPreview: handelPreview,
31005
+ onChange: handleChange,
31006
+ enable: enableGradient,
31007
+ isOpen,
31008
+ setIsOpen
31009
+ }
31010
+ ), /* @__PURE__ */ React__default.createElement(Form.Item, { wrapperCol: { offset: 8, span: 14 } }, /* @__PURE__ */ React__default.createElement(
31011
+ Button$2,
31012
+ {
31013
+ onClick: () => setIsOpen(true),
31014
+ type: "primary",
31015
+ size: "large",
31016
+ icon: /* @__PURE__ */ React__default.createElement(IconPalette, null),
31017
+ style: {
31018
+ width: "100%",
31019
+ border: "none",
31020
+ borderRadius: "6px",
31021
+ fontWeight: "500",
31022
+ background: "linear-gradient(to right, #9333ea, #db2777)",
31023
+ transition: "background 0.3s ease",
31024
+ marginBottom: "10px"
31025
+ },
31026
+ onMouseEnter: (e) => {
31027
+ e.currentTarget.style.background = "linear-gradient(to right, #7e22ce, #be185d)";
31028
+ },
31029
+ onMouseLeave: (e) => {
31030
+ e.currentTarget.style.background = "linear-gradient(to right, #9333ea, #db2777)";
31031
+ }
31032
+ },
31033
+ t("Create gradient")
31034
+ )));
31035
+ }
30240
31036
  const defaultAttributeFields = {
30241
31037
  // Basic Form Field
30242
31038
  WatchField,
@@ -30264,6 +31060,7 @@ const defaultAttributeFields = {
30264
31060
  TextAreaField,
30265
31061
  Link: Link$2,
30266
31062
  BackgroundImage,
31063
+ BackgroundGradient,
30267
31064
  DisplayOptions,
30268
31065
  Columns,
30269
31066
  BackgroundColor,
@@ -30292,7 +31089,8 @@ const defaultAttributeFields = {
30292
31089
  ButtonCategory,
30293
31090
  WebFonts,
30294
31091
  RichTextField,
30295
- FieldItem
31092
+ FieldItem,
31093
+ GradientGeneratorField
30296
31094
  };
30297
31095
  const AttributeField = __spreadValues({}, defaultAttributeFields);
30298
31096
  const index$5 = "";
package/lib/style.css CHANGED
@@ -1319,6 +1319,71 @@ THEMES:
1319
1319
  }
1320
1320
  .presetColorItem:hover {
1321
1321
  border-color: #000;
1322
+ }._controlSection_1t3ne_1 {
1323
+ display: flex;
1324
+ flex-direction: column;
1325
+ padding: 24px;
1326
+ }
1327
+
1328
+ ._controlGroup_1t3ne_7 {
1329
+ width: 100%;
1330
+ }
1331
+
1332
+ ._colorHeader_1t3ne_11 {
1333
+ display: flex;
1334
+ justify-content: space-between;
1335
+ align-items: center;
1336
+ margin-bottom: 12px;
1337
+ }
1338
+
1339
+ ._colorList_1t3ne_18 {
1340
+ display: flex;
1341
+ flex-direction: column;
1342
+ gap: 12px;
1343
+ max-height: 320px;
1344
+ overflow-y: auto;
1345
+ padding-right: 8px;
1346
+ }
1347
+ ._colorList_1t3ne_18::-webkit-scrollbar {
1348
+ width: 6px;
1349
+ }
1350
+ ._colorList_1t3ne_18::-webkit-scrollbar-thumb {
1351
+ background-color: var(--color-fill-3);
1352
+ border-radius: 3px;
1353
+ }
1354
+
1355
+ ._colorItem_1t3ne_34 {
1356
+ display: flex;
1357
+ align-items: center;
1358
+ gap: 12px;
1359
+ padding: 12px;
1360
+ border-radius: 8px;
1361
+ background-color: var(--color-bg-2);
1362
+ border: 1px solid var(--color-border-2);
1363
+ }
1364
+
1365
+ ._positionControl_1t3ne_44 {
1366
+ display: flex;
1367
+ align-items: center;
1368
+ gap: 8px;
1369
+ }
1370
+
1371
+ ._percentSign_1t3ne_50 {
1372
+ color: var(--color-text-3);
1373
+ font-size: 12px;
1374
+ }
1375
+
1376
+ ._deleteButton_1t3ne_55 {
1377
+ color: rgb(var(--red-6));
1378
+ }
1379
+ ._deleteButton_1t3ne_55:hover {
1380
+ color: rgb(var(--red-7));
1381
+ }
1382
+
1383
+ ._sizeInputs_1t3ne_62 {
1384
+ display: grid;
1385
+ grid-template-columns: 1fr 1fr;
1386
+ gap: 12px;
1322
1387
  }.ResponsiveTabsItem {
1323
1388
  width: 95px;
1324
1389
  height: 95px;
@@ -0,0 +1,9 @@
1
+ import { EnhancerProps } from "../../../../components/Form/enhancer";
2
+ import React from "react";
3
+ import { Path } from "slate";
4
+ export declare function BackgroundGradient(props: Omit<EnhancerProps, "label"> & {
5
+ label?: React.ReactNode;
6
+ path: Path;
7
+ targetName: string;
8
+ hideBackgroundSize?: boolean;
9
+ }): React.JSX.Element;
@@ -1,6 +1,10 @@
1
1
  import { EnhancerProps } from "../../../../components/Form/enhancer";
2
2
  import React from "react";
3
3
  import { Path } from "slate";
4
+ export declare const gradientAdapter: {
5
+ formatter(active: boolean): "gradient" | "image";
6
+ normalize(type: "gradient" | "image"): boolean;
7
+ };
4
8
  export declare function BackgroundImage(props: Omit<EnhancerProps, "label"> & {
5
9
  label?: React.ReactNode;
6
10
  path: Path;
@@ -36,6 +36,7 @@ import { Preheader } from "./Preheader";
36
36
  import { ButtonContent } from "./ButtonContent";
37
37
  import { RTLDirection } from "./RTLDirection";
38
38
  import { TableLayout } from "./TableLayout";
39
+ import { BackgroundGradient } from "./BackgroundGradient";
39
40
  export declare const defaultAttributeFields: {
40
41
  WatchField: (props: import("../../../Form/WatchField").WatchFieldProps) => import("react").JSX.Element;
41
42
  SyncChildrenField: (props: import("../../../Form/SyncChildrenField").SyncChildrenFieldProps) => import("react").JSX.Element;
@@ -84,6 +85,7 @@ export declare const defaultAttributeFields: {
84
85
  TextAreaField: (props: import("../../../Form/enhancer").EnhancerProps & Omit<import("@arco-design/web-react").TextAreaProps & import("react").RefAttributes<import("@arco-design/web-react/es/Input").RefTextAreaType>, "onChange" | "value">) => import("react").JSX.Element;
85
86
  Link: typeof Link;
86
87
  BackgroundImage: typeof BackgroundImage;
88
+ BackgroundGradient: typeof BackgroundGradient;
87
89
  DisplayOptions: ({ enabledResponsive, }: {
88
90
  enabledResponsive: boolean;
89
91
  }) => import("react").JSX.Element | null;
@@ -124,5 +126,6 @@ export declare const defaultAttributeFields: {
124
126
  height: string;
125
127
  }, "onChange" | "value">) => import("react").JSX.Element;
126
128
  FieldItem: typeof FieldItem;
129
+ GradientGeneratorField: (props: import("../../../Form/enhancer").EnhancerProps & Omit<import("../../../Form/GradientGenerator").GradientGeneratorProps, "onChange" | "value">) => import("react").JSX.Element;
127
130
  };
128
131
  export declare const AttributeField: AttributeFieldsMap;
@@ -9,6 +9,7 @@ export interface ColorPickerProps extends PopoverProps {
9
9
  showInput?: boolean;
10
10
  placeholder?: string;
11
11
  }
12
+ declare const ColorPicker: (props: ColorPickerProps) => React.JSX.Element;
12
13
  declare const DefaultColorPicker: (props: import("../enhancer").EnhancerProps & Omit<ColorPickerProps, "onChange" | "value">) => React.JSX.Element;
13
14
  export declare const ColorPickerField: (props: ComponentProps<typeof DefaultColorPicker>) => React.JSX.Element;
14
- export {};
15
+ export { ColorPicker };
@@ -0,0 +1,13 @@
1
+ import React from "react";
2
+ import { GradientConfigData } from "easy-email-pro-core";
3
+ export interface GradientGeneratorProps {
4
+ onSave: (val: GradientConfigData, blob: Blob) => Promise<void>;
5
+ onChange: (val: GradientConfigData) => void;
6
+ onPreview: (url: string) => void;
7
+ children?: React.ReactNode;
8
+ data: GradientConfigData;
9
+ enable: boolean;
10
+ isOpen: boolean;
11
+ setIsOpen: (isOpen: boolean) => void;
12
+ }
13
+ export declare function GradientGenerator(props: GradientGeneratorProps): React.JSX.Element;
@@ -24,4 +24,5 @@ export declare const SelectField: (props: import("./enhancer").EnhancerProps & O
24
24
  export declare const TreeSelectField: (props: import("./enhancer").EnhancerProps & Omit<import("@arco-design/web-react").TreeSelectProps & {
25
25
  children?: import("react").ReactNode;
26
26
  } & import("react").RefAttributes<import("@arco-design/web-react/es/TreeSelect").RefTreeSelectType>, "onChange" | "value">) => import("react").JSX.Element;
27
+ export declare const GradientGeneratorField: (props: import("./enhancer").EnhancerProps & Omit<import("./GradientGenerator").GradientGeneratorProps, "onChange" | "value">) => import("react").JSX.Element;
27
28
  export { enhancer, SwitchField, ButtonField, ButtonGroupField, WatchField, SyncChildrenField, ColorPickerField, ImageUploaderField, EditPanelListField, EditPanelTabsField, RichTextField, SliderField, PixelField, };
@@ -139,6 +139,7 @@ export interface PluginsCustomEditorTypes {
139
139
  showInsertTips?: boolean;
140
140
  enabledHtmlBlockNodeAlign?: boolean;
141
141
  enabledPreviewEmailSubjectEdit?: boolean;
142
+ enabledGradientImage?: boolean;
142
143
  hideSectionBackgroundImage?: boolean;
143
144
  layerConfig?: {
144
145
  scrollWhenSelect?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "easy-email-pro-theme",
3
- "version": "1.50.19",
3
+ "version": "1.51.0",
4
4
  "description": "",
5
5
  "files": [
6
6
  "lib"