@flozy/editor 1.2.7 → 1.2.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 text = serialize(deboundedValue);
80
- const title = deboundedValue?.find(f => f.type === "title");
81
- onSave(JSON.stringify(deboundedValue), {
82
- text: text,
83
- title: serialize(title?.children) || "Untitled"
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 value;
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
- setAnchorEl(e.currentTarget);
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: formData?.url || ""
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
- return /*#__PURE__*/_jsx("div", {
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
- children: children
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(CheckBox, {
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 = props => {
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: '#64748B',
25
- width: '18px',
26
- height: '18px'
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
- label: "Button URL",
10
- type: "text",
11
- key: "url"
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",
@@ -1,12 +1,4 @@
1
1
  const embedImageStyle = [{
2
- tab: "Image Texts",
3
- value: "imageTexts",
4
- fields: [{
5
- label: "Image Texts",
6
- key: "imageTexts",
7
- type: "imageTexts"
8
- }]
9
- }, {
10
2
  tab: "Banner Spacing",
11
3
  value: "bannerSpacing",
12
4
  fields: [{
@@ -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
+ };
@@ -4,7 +4,10 @@ export const insertButton = editor => {
4
4
  type: "button",
5
5
  children: [{
6
6
  text: ""
7
- }]
7
+ }],
8
+ buttonLink: {
9
+ linkType: "webAddress"
10
+ }
8
11
  };
9
12
  Transforms.insertNodes(editor, button);
10
13
  Transforms.move(editor);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flozy/editor",
3
- "version": "1.2.7",
3
+ "version": "1.2.9",
4
4
  "description": "An Editor for flozy app brain",
5
5
  "files": [
6
6
  "dist"