@flozy/editor 1.2.7 → 1.2.9
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/dist/Editor/CommonEditor.js +19 -10
- package/dist/Editor/Elements/Button/ButtonPopup.js +3 -1
- package/dist/Editor/Elements/Button/EditorButton.js +34 -5
- package/dist/Editor/Elements/Embed/Embed.js +2 -1
- package/dist/Editor/Elements/ImageText/ImageText.js +29 -2
- package/dist/Editor/Elements/Link/LinkButton.js +2 -3
- package/dist/Editor/Elements/NewLine/NewLineButton.js +8 -6
- package/dist/Editor/common/StyleBuilder/buttonStyle.js +8 -4
- package/dist/Editor/common/StyleBuilder/embedImageStyle.js +0 -8
- package/dist/Editor/common/StyleBuilder/fieldTypes/buttonLink.js +113 -0
- package/dist/Editor/common/StyleBuilder/fieldTypes/index.js +3 -1
- package/dist/Editor/plugins/withEmbeds.js +1 -0
- package/dist/Editor/service/actionTrigger.js +16 -0
- package/dist/Editor/utils/button.js +4 -1
- package/package.json +1 -1
|
@@ -75,15 +75,23 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
75
75
|
}));
|
|
76
76
|
}, [id, content]);
|
|
77
77
|
useEffect(() => {
|
|
78
|
-
if (editorWrapper && editorWrapper?.current && loadedValue !== deboundedValue && isInteracted) {
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
});
|
|
78
|
+
if (editorWrapper && editorWrapper?.current && loadedValue !== deboundedValue && isInteracted && onSave) {
|
|
79
|
+
const {
|
|
80
|
+
value: strVal,
|
|
81
|
+
...restVal
|
|
82
|
+
} = getOnSaveData(deboundedValue);
|
|
83
|
+
onSave(strVal, restVal);
|
|
85
84
|
}
|
|
86
85
|
}, [deboundedValue]);
|
|
86
|
+
const getOnSaveData = val => {
|
|
87
|
+
const text = serialize(val);
|
|
88
|
+
const title = val?.find(f => f.type === "title");
|
|
89
|
+
return {
|
|
90
|
+
value: JSON.stringify(val),
|
|
91
|
+
text: text,
|
|
92
|
+
title: serialize(title?.children) || "Untitled"
|
|
93
|
+
};
|
|
94
|
+
};
|
|
87
95
|
const getPreviewImage = async (needBackground = false, options = {}) => {
|
|
88
96
|
ReactEditor.blur(editor);
|
|
89
97
|
const dom = needBackground ? editorWrapper?.current : editorWrapper?.current.getElementsByClassName("innert-editor-textbox")[0];
|
|
@@ -119,7 +127,7 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
119
127
|
return editor;
|
|
120
128
|
},
|
|
121
129
|
getContent() {
|
|
122
|
-
return
|
|
130
|
+
return getOnSaveData(deboundedValue);
|
|
123
131
|
},
|
|
124
132
|
insertFragments(fragments) {
|
|
125
133
|
editor.insertNode(fragments);
|
|
@@ -150,8 +158,10 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
150
158
|
setIsInteracted(true);
|
|
151
159
|
}
|
|
152
160
|
};
|
|
161
|
+
const isReadOnly = readOnly === "readonly";
|
|
153
162
|
const customProps = {
|
|
154
|
-
...(otherProps || {})
|
|
163
|
+
...(otherProps || {}),
|
|
164
|
+
readOnly: isReadOnly
|
|
155
165
|
};
|
|
156
166
|
const renderElement = useCallback(props => {
|
|
157
167
|
return /*#__PURE__*/_jsx(Element, {
|
|
@@ -190,7 +200,6 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
190
200
|
});
|
|
191
201
|
}
|
|
192
202
|
}, [chars, editor, target, mentions, setMentions]);
|
|
193
|
-
const isReadOnly = readOnly === "readonly";
|
|
194
203
|
const Overlay = collaborativeEditor && !isReadOnly ? RemoteCursorOverlay : React.Fragment;
|
|
195
204
|
return /*#__PURE__*/_jsx(DialogWrapper, {
|
|
196
205
|
...props,
|
|
@@ -6,6 +6,7 @@ const ButtonPopup = props => {
|
|
|
6
6
|
const {
|
|
7
7
|
element,
|
|
8
8
|
onSave,
|
|
9
|
+
customProps,
|
|
9
10
|
onClose
|
|
10
11
|
} = props;
|
|
11
12
|
return /*#__PURE__*/_jsx(StyleBuilder, {
|
|
@@ -14,7 +15,8 @@ const ButtonPopup = props => {
|
|
|
14
15
|
element: element,
|
|
15
16
|
onSave: onSave,
|
|
16
17
|
onClose: onClose,
|
|
17
|
-
renderTabs: buttonStyle
|
|
18
|
+
renderTabs: buttonStyle,
|
|
19
|
+
customProps: customProps
|
|
18
20
|
});
|
|
19
21
|
};
|
|
20
22
|
export default ButtonPopup;
|
|
@@ -3,6 +3,7 @@ import { Transforms } from "slate";
|
|
|
3
3
|
import { ReactEditor, useSlateStatic } from "slate-react";
|
|
4
4
|
import { Menu, MenuItem } from "@mui/material";
|
|
5
5
|
import ButtonPopup from "./ButtonPopup";
|
|
6
|
+
import { actionButtonRedirect } from "../../service/actionTrigger";
|
|
6
7
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
7
8
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
8
9
|
const EditorButton = props => {
|
|
@@ -12,7 +13,8 @@ const EditorButton = props => {
|
|
|
12
13
|
customProps
|
|
13
14
|
} = props;
|
|
14
15
|
const {
|
|
15
|
-
readOnly
|
|
16
|
+
readOnly,
|
|
17
|
+
metadata
|
|
16
18
|
} = customProps;
|
|
17
19
|
const editor = useSlateStatic();
|
|
18
20
|
const path = ReactEditor.findPath(editor, element);
|
|
@@ -25,8 +27,13 @@ const EditorButton = props => {
|
|
|
25
27
|
bannerSpacing,
|
|
26
28
|
textColor,
|
|
27
29
|
url,
|
|
28
|
-
borderColor
|
|
30
|
+
borderColor,
|
|
31
|
+
buttonLink
|
|
29
32
|
} = element;
|
|
33
|
+
const {
|
|
34
|
+
linkType,
|
|
35
|
+
redirectOnURLResult
|
|
36
|
+
} = buttonLink || {};
|
|
30
37
|
const {
|
|
31
38
|
topLeft,
|
|
32
39
|
topRight,
|
|
@@ -39,13 +46,34 @@ const EditorButton = props => {
|
|
|
39
46
|
right,
|
|
40
47
|
bottom
|
|
41
48
|
} = bannerSpacing || {};
|
|
42
|
-
const onClick = e => {
|
|
43
|
-
|
|
49
|
+
const onClick = async e => {
|
|
50
|
+
if (readOnly) {
|
|
51
|
+
if (metadata?.buttonLink?.handler) {
|
|
52
|
+
metadata.buttonLink.handler("click");
|
|
53
|
+
} else if (linkType === "actionTrigger") {
|
|
54
|
+
if (redirectOnURLResult) {
|
|
55
|
+
// call api and redirect based on api result
|
|
56
|
+
const apiResult = await actionButtonRedirect({}, {
|
|
57
|
+
url: buttonLink?.url
|
|
58
|
+
});
|
|
59
|
+
window.open(apiResult, "_blank").focus();
|
|
60
|
+
} else {
|
|
61
|
+
const refUrl = buttonLink?.url ? buttonLink?.url.includes("http") ? buttonLink?.url : `//${buttonLink?.url}` : "Link";
|
|
62
|
+
window.open(refUrl, "_blank").focus();
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
const refUrl = url ? url.includes("http") ? url : `//${url}` : "Link";
|
|
66
|
+
window.open(refUrl, "_blank").focus();
|
|
67
|
+
}
|
|
68
|
+
} else {
|
|
69
|
+
setAnchorEl(e.currentTarget);
|
|
70
|
+
}
|
|
44
71
|
};
|
|
45
72
|
const handleClose = () => {
|
|
46
73
|
setAnchorEl(null);
|
|
47
74
|
};
|
|
48
75
|
const onMenuClick = val => () => {
|
|
76
|
+
console.log(val, url);
|
|
49
77
|
switch (val) {
|
|
50
78
|
case "open":
|
|
51
79
|
const refUrl = url ? url.includes("http") ? url : `//${url}` : "Link";
|
|
@@ -117,7 +145,8 @@ const EditorButton = props => {
|
|
|
117
145
|
}), edit && /*#__PURE__*/_jsx(ButtonPopup, {
|
|
118
146
|
element: element,
|
|
119
147
|
onSave: onSave,
|
|
120
|
-
onClose: onClose
|
|
148
|
+
onClose: onClose,
|
|
149
|
+
customProps: customProps
|
|
121
150
|
})]
|
|
122
151
|
});
|
|
123
152
|
};
|
|
@@ -68,6 +68,7 @@ const Embed = ({
|
|
|
68
68
|
[e.target.name]: e.target.value
|
|
69
69
|
});
|
|
70
70
|
};
|
|
71
|
+
const imageURL = formData?.url === "none" || !formData?.url ? "" : formData?.url;
|
|
71
72
|
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
72
73
|
children: [/*#__PURE__*/_jsx(IconButton, {
|
|
73
74
|
className: isBlockActive(editor, format) ? "active" : "",
|
|
@@ -127,7 +128,7 @@ const Embed = ({
|
|
|
127
128
|
size: "small",
|
|
128
129
|
fullWidth: true,
|
|
129
130
|
onChange: handleChange,
|
|
130
|
-
value:
|
|
131
|
+
value: imageURL || ""
|
|
131
132
|
})
|
|
132
133
|
}), /*#__PURE__*/_jsx(Uploader, {
|
|
133
134
|
value: formData,
|
|
@@ -1,14 +1,41 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import { IconButton } from "@mui/material";
|
|
3
|
+
import DeleteIcon from "@mui/icons-material/Delete";
|
|
4
|
+
import { Transforms } from "slate";
|
|
5
|
+
import { ReactEditor, useSlateStatic } from "slate-react";
|
|
2
6
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
7
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
8
|
const ImageText = props => {
|
|
4
9
|
const {
|
|
5
10
|
attributes,
|
|
11
|
+
element,
|
|
6
12
|
children
|
|
7
13
|
} = props;
|
|
8
|
-
|
|
14
|
+
const editor = useSlateStatic();
|
|
15
|
+
const onDelete = () => {
|
|
16
|
+
const path = ReactEditor.findPath(editor, element);
|
|
17
|
+
Transforms.removeNodes(editor, {
|
|
18
|
+
at: [...path]
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
return /*#__PURE__*/_jsxs("div", {
|
|
9
22
|
className: "image-text",
|
|
10
23
|
...attributes,
|
|
11
|
-
|
|
24
|
+
style: {
|
|
25
|
+
position: "relative"
|
|
26
|
+
},
|
|
27
|
+
children: [children, /*#__PURE__*/_jsx("div", {
|
|
28
|
+
children: /*#__PURE__*/_jsx(IconButton, {
|
|
29
|
+
onClick: onDelete,
|
|
30
|
+
style: {
|
|
31
|
+
background: "#FFF",
|
|
32
|
+
position: "absolute",
|
|
33
|
+
right: "0px",
|
|
34
|
+
top: "0px"
|
|
35
|
+
},
|
|
36
|
+
children: /*#__PURE__*/_jsx(DeleteIcon, {})
|
|
37
|
+
})
|
|
38
|
+
})]
|
|
12
39
|
});
|
|
13
40
|
};
|
|
14
41
|
export default ImageText;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { useRef, useState } from "react";
|
|
2
2
|
import { Transforms } from "slate";
|
|
3
|
-
import { Dialog, DialogActions, DialogContent, DialogTitle, FormControl, FormControlLabel, Grid, TextField, Button, IconButton, Typography } from "@mui/material";
|
|
3
|
+
import { Dialog, DialogActions, DialogContent, DialogTitle, FormControl, FormControlLabel, Grid, TextField, Button, IconButton, Typography, Checkbox } from "@mui/material";
|
|
4
4
|
import CloseIcon from "@mui/icons-material/Close";
|
|
5
|
-
import { CheckBox } from "@mui/icons-material";
|
|
6
5
|
import { insertLink } from "../../utils/link";
|
|
7
6
|
import Icon from "../../common/Icon";
|
|
8
7
|
import { isBlockActive } from "../../utils/SlateUtilityFunctions";
|
|
@@ -112,7 +111,7 @@ const LinkButton = props => {
|
|
|
112
111
|
},
|
|
113
112
|
children: /*#__PURE__*/_jsx(FormControl, {
|
|
114
113
|
children: /*#__PURE__*/_jsx(FormControlLabel, {
|
|
115
|
-
control: /*#__PURE__*/_jsx(
|
|
114
|
+
control: /*#__PURE__*/_jsx(Checkbox, {
|
|
116
115
|
checked: showInNewTab,
|
|
117
116
|
onChange: handleInputChange
|
|
118
117
|
}),
|
|
@@ -2,9 +2,9 @@ import React from "react";
|
|
|
2
2
|
import { IconButton } from "@mui/material";
|
|
3
3
|
import KeyboardReturnIcon from "@mui/icons-material/KeyboardReturn";
|
|
4
4
|
import { Transforms } from "slate";
|
|
5
|
-
import { useSlateStatic } from "slate-react";
|
|
5
|
+
import { ReactEditor, useSlateStatic } from "slate-react";
|
|
6
6
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
7
|
-
const NewLineButton =
|
|
7
|
+
const NewLineButton = () => {
|
|
8
8
|
const editor = useSlateStatic();
|
|
9
9
|
const onAddNewLine = () => {
|
|
10
10
|
Transforms.insertNodes(editor, [{
|
|
@@ -13,17 +13,19 @@ const NewLineButton = props => {
|
|
|
13
13
|
text: ""
|
|
14
14
|
}]
|
|
15
15
|
}], {
|
|
16
|
-
at: [editor.children.length]
|
|
16
|
+
at: [editor.children.length],
|
|
17
|
+
select: true
|
|
17
18
|
});
|
|
19
|
+
ReactEditor.focus(editor);
|
|
18
20
|
};
|
|
19
21
|
return /*#__PURE__*/_jsx(IconButton, {
|
|
20
22
|
title: "New Line",
|
|
21
23
|
onClick: onAddNewLine,
|
|
22
24
|
children: /*#__PURE__*/_jsx(KeyboardReturnIcon, {
|
|
23
25
|
sx: {
|
|
24
|
-
fill:
|
|
25
|
-
width:
|
|
26
|
-
height:
|
|
26
|
+
fill: "#64748B",
|
|
27
|
+
width: "18px",
|
|
28
|
+
height: "18px"
|
|
27
29
|
}
|
|
28
30
|
})
|
|
29
31
|
});
|
|
@@ -5,10 +5,14 @@ const buttonStyle = [{
|
|
|
5
5
|
label: "Button Text",
|
|
6
6
|
key: "label",
|
|
7
7
|
type: "text"
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
}]
|
|
9
|
+
}, {
|
|
10
|
+
tab: "Link",
|
|
11
|
+
value: "link",
|
|
12
|
+
fields: [{
|
|
13
|
+
label: "Button Link",
|
|
14
|
+
key: "buttonLink",
|
|
15
|
+
type: "buttonLink"
|
|
12
16
|
}]
|
|
13
17
|
}, {
|
|
14
18
|
tab: "Banner Spacing",
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { FormControl, FormLabel, RadioGroup, FormControlLabel, Grid, Radio, TextField, Select, MenuItem } from "@mui/material";
|
|
3
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
4
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
5
|
+
const ButtonLink = props => {
|
|
6
|
+
const {
|
|
7
|
+
value,
|
|
8
|
+
data,
|
|
9
|
+
elementProps,
|
|
10
|
+
customProps,
|
|
11
|
+
onChange
|
|
12
|
+
} = props;
|
|
13
|
+
const {
|
|
14
|
+
key
|
|
15
|
+
} = data;
|
|
16
|
+
const {
|
|
17
|
+
metadata
|
|
18
|
+
} = customProps || {
|
|
19
|
+
metadata: {}
|
|
20
|
+
};
|
|
21
|
+
const {
|
|
22
|
+
buttonLink
|
|
23
|
+
} = metadata || {
|
|
24
|
+
actionTrigger: {}
|
|
25
|
+
};
|
|
26
|
+
const {
|
|
27
|
+
actionTrigger
|
|
28
|
+
} = buttonLink || {};
|
|
29
|
+
const {
|
|
30
|
+
options,
|
|
31
|
+
onClick
|
|
32
|
+
} = actionTrigger || {
|
|
33
|
+
options: []
|
|
34
|
+
};
|
|
35
|
+
const optSelected = options.filter(f => f.selected) || [];
|
|
36
|
+
const handleChange = e => {
|
|
37
|
+
onChange({
|
|
38
|
+
[key]: {
|
|
39
|
+
...value,
|
|
40
|
+
[e.target.name]: e.target.value,
|
|
41
|
+
onClick: onClick || {}
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
const onURLChange = e => {
|
|
46
|
+
onChange({
|
|
47
|
+
url: e.target.value
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
const renderLinkTypeFields = () => {
|
|
51
|
+
if (value?.linkType === "webAddress") {
|
|
52
|
+
return /*#__PURE__*/_jsx(Grid, {
|
|
53
|
+
item: true,
|
|
54
|
+
xs: 12,
|
|
55
|
+
children: /*#__PURE__*/_jsx(TextField, {
|
|
56
|
+
fullWidth: true,
|
|
57
|
+
size: "small",
|
|
58
|
+
placeholder: "https://",
|
|
59
|
+
onChange: onURLChange,
|
|
60
|
+
value: elementProps?.url
|
|
61
|
+
})
|
|
62
|
+
});
|
|
63
|
+
} else if (value?.linkType === "actionTrigger") {
|
|
64
|
+
return /*#__PURE__*/_jsx(Grid, {
|
|
65
|
+
item: true,
|
|
66
|
+
xs: 12,
|
|
67
|
+
children: /*#__PURE__*/_jsx(Select, {
|
|
68
|
+
name: "actionStep",
|
|
69
|
+
size: "small",
|
|
70
|
+
fullWidth: true,
|
|
71
|
+
value: optSelected[0]?.value || "",
|
|
72
|
+
children: optSelected.map(m => {
|
|
73
|
+
return /*#__PURE__*/_jsx(MenuItem, {
|
|
74
|
+
value: m.value,
|
|
75
|
+
children: m.label
|
|
76
|
+
}, `bl_tr_opt_${m.value}`);
|
|
77
|
+
})
|
|
78
|
+
})
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
return /*#__PURE__*/_jsxs(Grid, {
|
|
83
|
+
container: true,
|
|
84
|
+
padding: 4,
|
|
85
|
+
spacing: 1,
|
|
86
|
+
children: [/*#__PURE__*/_jsx(Grid, {
|
|
87
|
+
item: true,
|
|
88
|
+
xs: 12,
|
|
89
|
+
children: /*#__PURE__*/_jsxs(FormControl, {
|
|
90
|
+
children: [/*#__PURE__*/_jsx(FormLabel, {
|
|
91
|
+
id: "demo-radio-buttons-group-label",
|
|
92
|
+
children: "Where do you want to Link?"
|
|
93
|
+
}), /*#__PURE__*/_jsxs(RadioGroup, {
|
|
94
|
+
row: true,
|
|
95
|
+
"aria-labelledby": "demo-radio-buttons-group-label",
|
|
96
|
+
value: value?.linkType || "",
|
|
97
|
+
name: "linkType",
|
|
98
|
+
onChange: handleChange,
|
|
99
|
+
children: [/*#__PURE__*/_jsx(FormControlLabel, {
|
|
100
|
+
value: "actionTrigger",
|
|
101
|
+
control: /*#__PURE__*/_jsx(Radio, {}),
|
|
102
|
+
label: "Action Trigger"
|
|
103
|
+
}), /*#__PURE__*/_jsx(FormControlLabel, {
|
|
104
|
+
value: "webAddress",
|
|
105
|
+
control: /*#__PURE__*/_jsx(Radio, {}),
|
|
106
|
+
label: "Web Address"
|
|
107
|
+
})]
|
|
108
|
+
})]
|
|
109
|
+
})
|
|
110
|
+
}), renderLinkTypeFields()]
|
|
111
|
+
});
|
|
112
|
+
};
|
|
113
|
+
export default ButtonLink;
|
|
@@ -8,6 +8,7 @@ import GridSize from "./gridSize";
|
|
|
8
8
|
import ElementSize from "./elementSize";
|
|
9
9
|
import ImageTexts from "./imageTexts";
|
|
10
10
|
import MenusArray from "./menusArray";
|
|
11
|
+
import ButtonLink from "./buttonLink";
|
|
11
12
|
const FieldMap = {
|
|
12
13
|
text: Text,
|
|
13
14
|
bannerSpacing: BannerSpacing,
|
|
@@ -18,6 +19,7 @@ const FieldMap = {
|
|
|
18
19
|
gridSize: GridSize,
|
|
19
20
|
elementSize: ElementSize,
|
|
20
21
|
imageTexts: ImageTexts,
|
|
21
|
-
menusArray: MenusArray
|
|
22
|
+
menusArray: MenusArray,
|
|
23
|
+
buttonLink: ButtonLink
|
|
22
24
|
};
|
|
23
25
|
export default FieldMap;
|
|
@@ -16,6 +16,7 @@ const withEmbeds = editor => {
|
|
|
16
16
|
editor.insertBreak = (...args) => {
|
|
17
17
|
const parentPath = Path.parent(editor.selection.focus.path);
|
|
18
18
|
const parentNode = Node.get(editor, parentPath);
|
|
19
|
+
console.log(parentNode, parentPath, args);
|
|
19
20
|
if (editor.isVoid(parentNode)) {
|
|
20
21
|
const nextPath = Path.next(parentPath);
|
|
21
22
|
Transforms.insertNodes(editor, {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const actionButtonRedirect = async (formData, props) => {
|
|
2
|
+
try {
|
|
3
|
+
const response = await fetch(`${props.url}`, {
|
|
4
|
+
method: "POST",
|
|
5
|
+
headers: {
|
|
6
|
+
"Content-Type": "application/json"
|
|
7
|
+
},
|
|
8
|
+
body: JSON.stringify(formData)
|
|
9
|
+
});
|
|
10
|
+
const result = await response.json();
|
|
11
|
+
return result.data;
|
|
12
|
+
} catch (err) {
|
|
13
|
+
console.log(err);
|
|
14
|
+
return err;
|
|
15
|
+
}
|
|
16
|
+
};
|