@flozy/editor 4.7.4 → 4.7.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. package/dist/Editor/CommonEditor.js +1 -3
  2. package/dist/Editor/Elements/AI/AIInput.js +4 -5
  3. package/dist/Editor/Elements/AI/PopoverAIInput.js +78 -62
  4. package/dist/Editor/Elements/AI/Styles.js +1 -0
  5. package/dist/Editor/Elements/Button/EditorButton.js +2 -1
  6. package/dist/Editor/Elements/Embed/EmbedPopup.js +7 -1
  7. package/dist/Editor/Elements/FreeGrid/styles.js +1 -1
  8. package/dist/Editor/Elements/Link/Link.js +73 -37
  9. package/dist/Editor/Elements/Link/LinkButton.js +37 -25
  10. package/dist/Editor/MiniEditor.js +19 -12
  11. package/dist/Editor/Styles/EditorStyles.js +1 -1
  12. package/dist/Editor/Toolbar/Basic/index.js +10 -8
  13. package/dist/Editor/Toolbar/PopupTool/MiniTextFormat/index.js +8 -4
  14. package/dist/Editor/Toolbar/PopupTool/TextFormat.js +4 -2
  15. package/dist/Editor/Toolbar/Toolbar.js +2 -1
  16. package/dist/Editor/common/LinkSettings/index.js +3 -2
  17. package/dist/Editor/common/LinkSettings/navOptions.js +5 -1
  18. package/dist/Editor/common/RnD/ElementSettings/OtherSettings/Link.js +12 -6
  19. package/dist/Editor/common/RnD/ElementSettings/OtherSettings/SaveAsTemplate.js +0 -1
  20. package/dist/Editor/common/RnD/ElementSettings/OtherSettings/Settings.js +1 -1
  21. package/dist/Editor/common/RnD/Utils/gridDropItem.js +5 -3
  22. package/dist/Editor/common/StyleBuilder/embedVideoStyle.js +1 -1
  23. package/dist/Editor/plugins/withCustomDeleteBackward.js +13 -0
  24. package/dist/Editor/utils/Decorators/highlightSelection.js +22 -0
  25. package/dist/Editor/utils/Decorators/index.js +3 -2
  26. package/dist/Editor/utils/SlateUtilityFunctions.js +9 -0
  27. package/dist/Editor/utils/helper.js +1 -1
  28. package/dist/Editor/utils/link.js +9 -4
  29. package/package.json +1 -1
@@ -534,7 +534,7 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
534
534
  readOnly: isReadOnly,
535
535
  renderElement: renderElement,
536
536
  renderLeaf: renderLeaf,
537
- decorate: decorators,
537
+ decorate: d => decorators(d, editor),
538
538
  onKeyDown: onKeyDown,
539
539
  onSelect: () => handleCursorScroll(editorWrapper.current)
540
540
  }), !readOnly ? /*#__PURE__*/_jsx(MentionsPopup, {
@@ -584,8 +584,6 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
584
584
  }), htmlAction.showInput && /*#__PURE__*/_jsx(CodeToText, {
585
585
  ...htmlAction,
586
586
  handleCodeToText: handleCodeToText
587
- }), /*#__PURE__*/_jsx(FontLoader, {
588
- ...props
589
587
  })]
590
588
  }, id)
591
589
  })
@@ -90,6 +90,7 @@ function AIInput({
90
90
  children: [/*#__PURE__*/_jsxs(Box, {
91
91
  component: "div",
92
92
  sx: classes.aiContainer,
93
+ ref: refs[0],
93
94
  children: [generatedText ? /*#__PURE__*/_jsx(Typography, {
94
95
  sx: classes.generatedText,
95
96
  style: {
@@ -104,7 +105,6 @@ function AIInput({
104
105
  onSubmit: e => {
105
106
  e.preventDefault();
106
107
  },
107
- ref: refs[0],
108
108
  children: [/*#__PURE__*/_jsx("div", {
109
109
  className: "icon-container icons-elements",
110
110
  ref: inputWrapperRef,
@@ -116,22 +116,21 @@ function AIInput({
116
116
  children: /*#__PURE__*/_jsx(WaveLoading, {})
117
117
  }) : /*#__PURE__*/_jsx(TextareaAutosize, {
118
118
  className: "ai-input",
119
- placeholder: fromToolBar ? "" : "Ask AI to write anything...",
119
+ placeholder: "Ask AI to write anything...",
120
120
  ref: inputRef,
121
121
  value: inputValue,
122
122
  onChange: onInputChange,
123
- disabled: fromToolBar,
124
123
  onKeyDown: event => {
125
124
  if (event.key === "Enter" && !event.shiftKey) {
126
125
  event.preventDefault();
127
126
  handleSendBtnClick();
128
127
  }
129
128
  }
130
- }), fromToolBar ? null : /*#__PURE__*/_jsxs(Box, {
129
+ }), /*#__PURE__*/_jsxs(Box, {
131
130
  component: "div",
132
131
  style: classes.sendIconContainer,
133
132
  className: "icons-elements",
134
- children: [isMobile ? null : /*#__PURE__*/_jsx(IconButton, {
133
+ children: [/*#__PURE__*/_jsx(IconButton, {
135
134
  disabled: loading,
136
135
  onClick: () => startRecording(),
137
136
  children: /*#__PURE__*/_jsx(ChatMicIcon, {})
@@ -40,9 +40,11 @@ const scrollToAIInput = editor => {
40
40
  }, 200);
41
41
  };
42
42
  const insertText = (editor, text, options) => {
43
- const parsed = new DOMParser().parseFromString(text, "text/html");
44
- const fragment = deserialize(parsed.body);
45
- Transforms.insertFragment(editor, fragment, options);
43
+ if (text?.length) {
44
+ const parsed = new DOMParser().parseFromString(text, "text/html");
45
+ const fragment = deserialize(parsed.body);
46
+ Transforms.insertFragment(editor, fragment, options);
47
+ }
46
48
  };
47
49
  const insertAtNextLine = (editor, text) => {
48
50
  const nextLine = getNextLine(editor);
@@ -199,81 +201,95 @@ function PopoverAIInput({
199
201
  useEffect(() => {
200
202
  selectedEleRef.current = selectedElement;
201
203
  }, [selectedElement]);
202
- const onSend = async (type, option) => {
203
- if (type === "close") {
204
- onClickOutside();
205
- return;
206
- }
207
- if (type === "done") {
208
- // Get the current selection point
209
- const {
210
- anchor
211
- } = editor.selection;
212
- const {
213
- path
214
- } = anchor;
215
- const {
216
- text: selectText
217
- } = Node.get(editor, path);
218
- if (selectText?.length) {
219
- insertAtNextLine(editor, generatedText);
220
- } else {
221
- insertText(editor, generatedText);
222
- }
223
- onClickOutside();
224
- return;
225
- }
226
- if (type === "replace_selection") {
227
- // replace generated text
228
- insertText(editor, generatedText);
229
- onClickOutside();
230
- return;
231
- }
232
- if (type === "speech_to_text") {
233
- setGeneratedText(option.text);
234
- return;
235
- }
236
- if (type === "try_again") {
237
- // resetting the previous option and try again
238
- option = selectedOption;
239
- type = selectedOption.value;
240
- } else {
241
- setSelectedOption(option);
242
- }
243
- setLoading(true);
244
- const payload = {
204
+ const framePayload = (type, option) => {
205
+ let payload = {
245
206
  mode: option.mode || 0,
246
207
  query: option?.inputValue || inputValue
247
208
  };
248
209
  if (option.mode === MODES.translate || option.mode === MODES.rephraseTone) {
249
210
  payload.textOptionInput = type;
250
211
  }
212
+ const selectedText = getSelectedText(editor);
213
+ const textData = generatedText || selectedText;
251
214
  if (option.mode) {
252
- payload.textData = generatedText || window.getSelection().toString();
215
+ payload.textData = textData;
216
+ } else if (selectedText && Number(payload.mode) === 0) {
217
+ payload.query = `${selectedText} \n ${payload.query}`;
253
218
  }
254
- const result = await services("infinityAI", payload);
255
- setLoading(false);
256
- setInputValue("");
257
- let {
258
- data: text
259
- } = result || {};
260
- if (!text) {
261
- onClickOutside();
262
- return;
219
+ const tryAgain = type === "try_again";
220
+ if (tryAgain) {
221
+ // resetting previous payload
222
+ const prevPayload = selectedOption?.payload || {};
223
+ payload = prevPayload;
263
224
  }
264
- if (!option.replace) {
225
+ return payload;
226
+ };
227
+ const onSend = async (type, option) => {
228
+ try {
229
+ if (type === "close") {
230
+ onClickOutside();
231
+ return;
232
+ }
233
+ if (type === "done") {
234
+ // Get the current selection point
235
+ const {
236
+ anchor
237
+ } = editor.selection;
238
+ const {
239
+ path
240
+ } = anchor;
241
+ const {
242
+ text: selectText
243
+ } = Node.get(editor, path);
244
+ if (selectText?.length) {
245
+ insertAtNextLine(editor, generatedText);
246
+ } else {
247
+ insertText(editor, generatedText);
248
+ }
249
+ onClickOutside();
250
+ return;
251
+ }
252
+ if (type === "replace_selection") {
253
+ // replace generated text
254
+ insertText(editor, generatedText);
255
+ onClickOutside();
256
+ return;
257
+ }
258
+ setLoading(true);
259
+ const payload = framePayload(type, option);
260
+ setSelectedOption({
261
+ ...option,
262
+ payload
263
+ });
264
+ const result = await services("infinityAI", payload);
265
+ setLoading(false);
266
+ setInputValue("");
267
+ let {
268
+ data: text
269
+ } = result || {};
270
+ if (!text) {
271
+ onClickOutside();
272
+ return;
273
+ }
274
+
275
+ // if (!option.replace) {
265
276
  if (type === "continue_writing") {
266
277
  setGeneratedText(generatedText + text);
267
278
  } else {
268
279
  setGeneratedText(text);
269
280
  }
270
- return;
271
- }
272
- insertText(editor, text);
273
281
 
274
- // scrollToAIInput();
275
- };
282
+ // return;
283
+ // }
276
284
 
285
+ // ** we are not using this insertText right now, AI returned response will not insert into the editor immediately, so option.replace will be false always
286
+ // insertText(editor, text);
287
+
288
+ // scrollToAIInput();
289
+ } catch (err) {
290
+ console.error("Error on sending/inserting text", err);
291
+ }
292
+ };
277
293
  const onInputChange = e => {
278
294
  setInputValue(e.target.value);
279
295
  };
@@ -102,6 +102,7 @@ const Styles = theme => ({
102
102
  customSelectWrapper: {
103
103
  width: "fit-content",
104
104
  marginTop: "4px",
105
+ position: "absolute",
105
106
  "@media only screen and (max-width: 600px)": {
106
107
  marginBottom: "4px"
107
108
  }
@@ -325,7 +325,8 @@ const EditorButton = props => {
325
325
  navType: element?.buttonLink?.linkType,
326
326
  navValue: element?.url,
327
327
  openInNewTab: element?.openInNewTab,
328
- customProps: customProps
328
+ customProps: customProps,
329
+ allowTrigger: true
329
330
  }) : null]
330
331
  });
331
332
  };
@@ -12,13 +12,19 @@ const EmbedPopup = props => {
12
12
  format,
13
13
  onDelete
14
14
  } = props;
15
+ const videoStyles = embedVideoStyle?.filter(f => {
16
+ if (f?.value === "AspectRatio" && format !== "video") {
17
+ return false;
18
+ }
19
+ return true;
20
+ });
15
21
  return /*#__PURE__*/_jsx(StyleBuilder, {
16
22
  title: format === "image" ? "Image" : format === "video" ? "video" : format === "calendly" ? "calendly" : "Embed",
17
23
  type: format === "image" ? "embedImageStyle" : "embedVideoStyle",
18
24
  element: element,
19
25
  onSave: onSave,
20
26
  onClose: onClose,
21
- renderTabs: format === "image" ? embedImageStyle : embedVideoStyle,
27
+ renderTabs: format === "image" ? embedImageStyle : videoStyles,
22
28
  customProps: customProps,
23
29
  onDelete: onDelete
24
30
  });
@@ -323,7 +323,7 @@ const useFreeGridStyles = ({
323
323
  },
324
324
  "&.rnd-dragOver": {
325
325
  "&:before": {
326
- content: '"Attact to this Section"',
326
+ content: '"Attach to this Section"',
327
327
  position: "absolute",
328
328
  top: 0,
329
329
  left: 0,
@@ -1,22 +1,43 @@
1
1
  import React, { useState } from "react";
2
2
  import { Node, Transforms } from "slate";
3
3
  import { ReactEditor, useFocused, useSelected, useSlateStatic } from "slate-react";
4
- import { IconButton, Tooltip } from "@mui/material";
4
+ import { Box, IconButton, Tooltip } from "@mui/material";
5
5
  import OpenInNewIcon from "@mui/icons-material/OpenInNew";
6
6
  import EditIcon from "@mui/icons-material/Edit";
7
7
  import LinkOffIcon from "@mui/icons-material/LinkOff";
8
8
  import { removeLink } from "../../utils/link";
9
- import LinkPopup from "./LinkPopup";
10
9
  import "./styles.css";
11
- import { absoluteLink } from "../../utils/helper";
10
+ import { getLinkType, handleLinkType } from "../../utils/helper";
11
+ import LinkSettings from "../../common/LinkSettings";
12
12
  import { jsx as _jsx } from "react/jsx-runtime";
13
13
  import { jsxs as _jsxs } from "react/jsx-runtime";
14
+ const linkStyles = () => ({
15
+ linkBtn: {
16
+ border: "none",
17
+ outline: "none",
18
+ background: "none",
19
+ fontSize: "inherit",
20
+ fontWeight: "inherit",
21
+ fontFamily: "inherit",
22
+ color: "rgb(85, 26, 139)",
23
+ textDecoration: "underline",
24
+ padding: 0,
25
+ margin: 0,
26
+ "&:hover": {
27
+ color: "rgb(65, 15, 110);"
28
+ }
29
+ }
30
+ });
14
31
  const Link = props => {
15
32
  const {
16
33
  attributes,
17
34
  element,
18
- children
35
+ children,
36
+ customProps
19
37
  } = props;
38
+ const {
39
+ readOnly
40
+ } = customProps;
20
41
  const editor = useSlateStatic();
21
42
  const selected = useSelected();
22
43
  const focused = useFocused();
@@ -24,59 +45,60 @@ const Link = props => {
24
45
  const [linkData, setLinkData] = useState({
25
46
  name: "",
26
47
  url: "",
27
- showInNewTab: true
48
+ showInNewTab: true,
49
+ linkType: ""
28
50
  });
29
51
  const path = ReactEditor.findPath(editor, element);
30
52
  const urlPath = element.url || element.href;
31
- const absLink = absoluteLink(urlPath);
32
- const updateLink = () => {
33
- Transforms.setNodes(editor, {
34
- href: linkData?.url,
35
- showInNewTab: linkData?.showInNewTab
36
- }, {
53
+ const showInNewTab = element?.showInNewTab || element?.target;
54
+ const linkType = element?.linkType;
55
+ const classes = linkStyles();
56
+ const updateLink = data => {
57
+ Transforms.setNodes(editor, data, {
37
58
  at: path
38
59
  });
39
60
  setLinkData({
40
61
  name: "",
41
62
  url: "",
42
- showInNewTab: true
63
+ showInNewTab: true,
64
+ linkType: ""
43
65
  });
44
66
  setShowInput(false);
45
67
  };
46
68
  const onEditLink = () => {
47
69
  setLinkData({
48
70
  name: Node.string(element),
49
- url: urlPath || "",
50
- showInNewTab: element?.showInNewTab
71
+ href: urlPath || "",
72
+ showInNewTab: showInNewTab,
73
+ linkType: element?.linkType
51
74
  });
52
75
  setShowInput(true);
53
76
  };
54
- const handleInputChange = ({
55
- target
56
- }) => {
57
- let val = target.type === "checkbox" ? target.checked : target.value;
58
- setLinkData({
59
- ...linkData,
60
- [target.name]: val
61
- });
62
- };
63
77
  const handleClose = () => {
64
78
  setShowInput(false);
65
79
  };
66
80
  const Toolbar = () => {
81
+ const btnProps = handleLinkType(urlPath, linkType, true, showInNewTab === "_blank");
82
+ const navType = getLinkType(linkType, urlPath);
83
+ const hideOpenLink = navType === "page" || !navType;
84
+ console.log("linkType", linkType, navType, hideOpenLink);
67
85
  return selected && focused ? /*#__PURE__*/_jsxs("div", {
68
86
  className: "element-toolbar hr",
69
87
  contentEditable: false,
70
88
  style: {
71
89
  width: "150px",
72
90
  top: "100%",
73
- left: "0px"
91
+ left: "0px",
92
+ display: "flex"
74
93
  },
75
- children: [/*#__PURE__*/_jsx(Tooltip, {
94
+ children: [hideOpenLink ? null : /*#__PURE__*/_jsx(Tooltip, {
76
95
  title: "Open",
77
- children: /*#__PURE__*/_jsx(IconButton, {
78
- href: absLink,
79
- target: "_blank",
96
+ children: /*#__PURE__*/_jsx(Box, {
97
+ sx: {
98
+ display: "inline-flex",
99
+ color: "rgba(0, 0, 0, 0.54)"
100
+ },
101
+ ...btnProps,
80
102
  children: /*#__PURE__*/_jsx(OpenInNewIcon, {})
81
103
  })
82
104
  }), /*#__PURE__*/_jsx(Tooltip, {
@@ -94,21 +116,35 @@ const Link = props => {
94
116
  })]
95
117
  }) : null;
96
118
  };
119
+ const buttonProps = handleLinkType(urlPath, linkType, readOnly, showInNewTab === "_blank");
120
+ console.log("buttonProps===>", buttonProps);
97
121
  return /*#__PURE__*/_jsxs("div", {
98
122
  className: "link",
99
- children: [/*#__PURE__*/_jsx("a", {
100
- href: absLink,
123
+ children: [/*#__PURE__*/_jsx(Box, {
101
124
  ...attributes,
102
125
  ...element.attr,
103
- target: element.target,
126
+ sx: classes.linkBtn,
127
+ ...buttonProps,
104
128
  children: children
105
- }), /*#__PURE__*/_jsx(Toolbar, {}), /*#__PURE__*/_jsx(LinkPopup, {
106
- open: showInput,
107
- linkData: linkData,
129
+ }), /*#__PURE__*/_jsx(Toolbar, {}), showInput ? /*#__PURE__*/_jsx(LinkSettings, {
108
130
  handleClose: handleClose,
109
- handleInputChange: handleInputChange,
110
- handleInsertLink: updateLink
111
- })]
131
+ onSave: ({
132
+ linkType,
133
+ navValue,
134
+ openInNewTab
135
+ }) => {
136
+ updateLink({
137
+ linkType,
138
+ url: navValue,
139
+ target: openInNewTab ? "_blank" : "_self"
140
+ });
141
+ handleClose();
142
+ },
143
+ navType: getLinkType(linkType, urlPath),
144
+ navValue: urlPath,
145
+ openInNewTab: linkData.showInNewTab === "_blank",
146
+ customProps: customProps
147
+ }) : null]
112
148
  });
113
149
  };
114
150
  export default Link;
@@ -4,34 +4,41 @@ import { IconButton, Tooltip } from "@mui/material";
4
4
  import { insertLink } from "../../utils/link";
5
5
  import Icon from "../../common/Icon";
6
6
  import { getBlockActive } from "../../utils/SlateUtilityFunctions";
7
- import LinkPopup from "./LinkPopup";
7
+ import { getLinkType } from "../../utils/helper";
8
+ import LinkSettings from "../../common/LinkSettings";
8
9
  import { jsx as _jsx } from "react/jsx-runtime";
9
10
  import { jsxs as _jsxs } from "react/jsx-runtime";
10
11
  const LinkButton = props => {
11
12
  const {
12
- editor
13
+ editor,
14
+ customProps
13
15
  } = props;
14
16
  const linkInputRef = useRef(null);
15
17
  const [showInput, setShowInput] = useState(false);
16
18
  const [linkData, setLinkData] = useState({
17
19
  name: "",
18
20
  url: "",
19
- showInNewTab: true
21
+ showInNewTab: true,
22
+ linkType: ""
20
23
  });
21
24
  const [selection, setSelection] = useState();
22
25
  const {
23
26
  isActive,
24
27
  props: blockProps
25
28
  } = getBlockActive(editor, "link");
26
- const handleInsertLink = () => {
29
+ const urlPath = blockProps?.url || blockProps?.href;
30
+ const showInNewTab = blockProps?.showInNewTab || blockProps?.target;
31
+ const {
32
+ linkType
33
+ } = linkData || {};
34
+ const handleInsertLink = linkData => {
27
35
  Transforms.select(editor, selection);
28
- insertLink(editor, {
29
- ...linkData
30
- });
36
+ insertLink(editor, linkData);
31
37
  setLinkData({
32
38
  name: "",
33
39
  url: "",
34
- showInNewTab: true
40
+ showInNewTab: true,
41
+ linkType: ""
35
42
  });
36
43
  setShowInput(false);
37
44
  };
@@ -40,21 +47,13 @@ const LinkButton = props => {
40
47
  if (editor.selection) {
41
48
  setLinkData({
42
49
  name: Editor.string(editor, editor.selection),
43
- url: blockProps?.href || "",
44
- showInNewTab: true
50
+ href: urlPath || "",
51
+ showInNewTab: showInNewTab,
52
+ linkType: blockProps?.linkType
45
53
  });
46
54
  setShowInput(true);
47
55
  }
48
56
  };
49
- const handleInputChange = ({
50
- target
51
- }) => {
52
- let val = target.type === "checkbox" ? target.checked : target.value;
53
- setLinkData({
54
- ...linkData,
55
- [target.name]: val
56
- });
57
- };
58
57
  const handleClose = () => {
59
58
  setShowInput(false);
60
59
  };
@@ -72,13 +71,26 @@ const LinkButton = props => {
72
71
  icon: "link"
73
72
  })
74
73
  })
75
- }), /*#__PURE__*/_jsx(LinkPopup, {
76
- open: showInput,
77
- linkData: linkData,
74
+ }), showInput ? /*#__PURE__*/_jsx(LinkSettings, {
78
75
  handleClose: handleClose,
79
- handleInputChange: handleInputChange,
80
- handleInsertLink: handleInsertLink
81
- })]
76
+ onSave: ({
77
+ linkType,
78
+ navValue,
79
+ openInNewTab
80
+ }) => {
81
+ handleInsertLink({
82
+ name: linkData?.name,
83
+ linkType,
84
+ url: navValue,
85
+ showInNewTab: openInNewTab ? "_blank" : "_self"
86
+ });
87
+ handleClose();
88
+ },
89
+ navType: getLinkType(linkType, urlPath),
90
+ navValue: urlPath,
91
+ openInNewTab: linkData.showInNewTab === "_blank",
92
+ customProps: customProps
93
+ }) : null]
82
94
  });
83
95
  };
84
96
  export default LinkButton;
@@ -10,6 +10,7 @@ import BasicToolbar from "./Toolbar/Basic";
10
10
  import withCommon from "./hooks/withCommon";
11
11
  import { serializeToText } from "./utils/serializeToText";
12
12
  import "./Editor.css";
13
+ import { EditorProvider } from "./hooks/useMouseMove";
13
14
  import { jsx as _jsx } from "react/jsx-runtime";
14
15
  import { jsxs as _jsxs } from "react/jsx-runtime";
15
16
  const MiniEditor = props => {
@@ -23,7 +24,8 @@ const MiniEditor = props => {
23
24
  miniEditorPlaceholder,
24
25
  className,
25
26
  otherProps,
26
- onSave
27
+ onSave,
28
+ theme
27
29
  } = props;
28
30
  const {
29
31
  CHARACTERS = []
@@ -128,18 +130,23 @@ const MiniEditor = props => {
128
130
  handleEditorChange(newVal);
129
131
  setValue(newVal);
130
132
  };
131
- return /*#__PURE__*/_jsxs(Slate, {
133
+ return /*#__PURE__*/_jsx(EditorProvider, {
132
134
  editor: editor,
133
- initialValue: content,
134
- onChange: onChange,
135
- children: [/*#__PURE__*/_jsx(BasicToolbar, {
136
- ...props
137
- }), /*#__PURE__*/_jsx(Editable, {
138
- className: className || "mini-editor-cls",
139
- renderElement: renderElement,
140
- renderLeaf: renderLeaf,
141
- onKeyDown: onKeyDown
142
- })]
135
+ theme: theme,
136
+ children: /*#__PURE__*/_jsxs(Slate, {
137
+ editor: editor,
138
+ initialValue: content,
139
+ onChange: onChange,
140
+ children: [/*#__PURE__*/_jsx(BasicToolbar, {
141
+ ...props,
142
+ customProps: customProps
143
+ }), /*#__PURE__*/_jsx(Editable, {
144
+ className: className || "mini-editor-cls",
145
+ renderElement: renderElement,
146
+ renderLeaf: renderLeaf,
147
+ onKeyDown: onKeyDown
148
+ })]
149
+ })
143
150
  });
144
151
  };
145
152
  MiniEditor.displayName = "MiniEditor";
@@ -286,7 +286,7 @@ const editorStyles = ({
286
286
  }
287
287
  },
288
288
  "& ::selection": {
289
- color: "black",
289
+ color: "inherit",
290
290
  background: "#EAEBFE"
291
291
  }
292
292
  },
@@ -25,7 +25,8 @@ const BasicToolbar = props => {
25
25
  hideTextColor = false,
26
26
  hideResetIcon = true,
27
27
  onResetClick = () => {}
28
- }
28
+ },
29
+ customProps
29
30
  } = props;
30
31
  // state
31
32
  const [activeColor, setActiveColor] = useState("#000000");
@@ -34,25 +35,25 @@ const BasicToolbar = props => {
34
35
  const handleTextColor = color => {
35
36
  setActiveColor(color);
36
37
  addMarkData(editor, {
37
- format: 'color',
38
+ format: "color",
38
39
  value: color
39
40
  });
40
41
  };
41
42
  return /*#__PURE__*/_jsxs(Box, {
42
- component: 'div',
43
+ component: "div",
43
44
  className: "basic-toolbar",
44
45
  children: [/*#__PURE__*/_jsxs(Grid, {
45
46
  container: true,
46
47
  sx: {
47
- padding: '10px'
48
+ padding: "10px"
48
49
  },
49
- alignItems: 'center',
50
- justifyContent: 'space-between',
50
+ alignItems: "center",
51
+ justifyContent: "space-between",
51
52
  children: [/*#__PURE__*/_jsx(Grid, {
52
53
  item: true,
53
54
  children: /*#__PURE__*/_jsxs(Grid, {
54
55
  container: true,
55
- alignItems: 'center',
56
+ alignItems: "center",
56
57
  children: [/*#__PURE__*/_jsx(Grid, {
57
58
  item: true,
58
59
  children: fontStyle?.map((m, i) => {
@@ -65,7 +66,8 @@ const BasicToolbar = props => {
65
66
  item: true,
66
67
  children: /*#__PURE__*/_jsx(LinkButton, {
67
68
  active: isBlockActive(editor, link.format),
68
- editor: editor
69
+ editor: editor,
70
+ customProps: customProps
69
71
  }, link.id)
70
72
  }), !hideTextColor && /*#__PURE__*/_jsx(Grid, {
71
73
  item: true,
@@ -13,6 +13,7 @@ import PopperHeader from "../PopperHeader";
13
13
  import MiniColorPicker from "./MiniColorPicker";
14
14
  import SelectAlignment from "./SelectAlignment";
15
15
  import SelectFontSize from "./SelectFontSize";
16
+ import InfinityAITool from "./InfinityAITool";
16
17
  import { jsx as _jsx } from "react/jsx-runtime";
17
18
  import { jsxs as _jsxs } from "react/jsx-runtime";
18
19
  const DEFAULT_COLOR = {
@@ -26,7 +27,8 @@ const MiniTextFormat = props => {
26
27
  const {
27
28
  classes,
28
29
  editor,
29
- closeMainPopup
30
+ closeMainPopup,
31
+ customProps
30
32
  } = props;
31
33
  const [anchorEl, setAnchorEl] = useState(null);
32
34
  const open = Boolean(anchorEl);
@@ -48,7 +50,7 @@ const MiniTextFormat = props => {
48
50
  xs: 12,
49
51
  children: /*#__PURE__*/_jsxs("div", {
50
52
  className: "toolWrapper",
51
- children: [/*#__PURE__*/_jsx(SelectTypography, {
53
+ children: [customProps?.hideTools?.includes("infinityAI") ? null : /*#__PURE__*/_jsx(InfinityAITool, {}), /*#__PURE__*/_jsx(SelectTypography, {
52
54
  classes: classes,
53
55
  editor: editor,
54
56
  closeMainPopup: closeMainPopup
@@ -91,7 +93,8 @@ const MiniTextFormat = props => {
91
93
  className: "verticalLine ml-1 mr-1"
92
94
  }), /*#__PURE__*/_jsx(LinkButton, {
93
95
  active: isBlockActive(editor, link.format),
94
- editor: editor
96
+ editor: editor,
97
+ customProps: customProps
95
98
  }, link.id), /*#__PURE__*/_jsx(Button, {
96
99
  onClick: e => setAnchorEl(document.getElementById("mini-text-editor-wrapper")),
97
100
  className: "textSettingsIcon",
@@ -119,7 +122,8 @@ const MiniTextFormat = props => {
119
122
  }), /*#__PURE__*/_jsx(TextFormat, {
120
123
  editor: editor,
121
124
  classes: classes,
122
- closeMainPopup: closeMainPopup
125
+ closeMainPopup: closeMainPopup,
126
+ customProps: customProps
123
127
  })]
124
128
  })
125
129
  })
@@ -25,7 +25,8 @@ const TextFormat = props => {
25
25
  classes,
26
26
  editor,
27
27
  onClose,
28
- closeMainPopup
28
+ closeMainPopup,
29
+ customProps
29
30
  } = props;
30
31
  const [anchorEl, setAnchorEl] = useState(null);
31
32
  const [type, setType] = useState(null);
@@ -344,7 +345,8 @@ const TextFormat = props => {
344
345
  closeMainPopup: closeMainPopup || onClose
345
346
  }), /*#__PURE__*/_jsx(LinkButton, {
346
347
  active: isBlockActive(editor, link.format),
347
- editor: editor
348
+ editor: editor,
349
+ customProps: customProps
348
350
  }, link.id)]
349
351
  })]
350
352
  }), /*#__PURE__*/_jsx(Grid, {
@@ -86,7 +86,8 @@ export const RenderToolbarIcon = props => {
86
86
  case "link":
87
87
  return /*#__PURE__*/_jsx(LinkButton, {
88
88
  active: isBlockActive(editor, "link"),
89
- editor: editor
89
+ editor: editor,
90
+ customProps: customProps
90
91
  }, element.id);
91
92
  case "embed":
92
93
  return /*#__PURE__*/_jsx(Embed, {
@@ -38,13 +38,14 @@ export default function LinkSettings(props) {
38
38
  handleClose,
39
39
  onSave,
40
40
  customProps,
41
- navType
41
+ navType,
42
+ allowTrigger
42
43
  } = props;
43
44
  const {
44
45
  isMobile,
45
46
  tagName
46
47
  } = customProps;
47
- const navOptions = getNavOptions(customProps.hideTools, tagName);
48
+ const navOptions = getNavOptions(customProps.hideTools, tagName, allowTrigger);
48
49
  const classes = LinkSettingsStyles(theme);
49
50
  const [nav, setNav] = useState(getNav(navType, navOptions));
50
51
  const [navValue, setNavValue] = useState(props?.navValue || "");
@@ -1,4 +1,4 @@
1
- export const getNavOptions = (hideTools = [], tagName = "") => {
1
+ export const getNavOptions = (hideTools = [], tagName = "", allowTrigger) => {
2
2
  let navOptions = [{
3
3
  label: "None",
4
4
  value: ""
@@ -33,6 +33,10 @@ export const getNavOptions = (hideTools = [], tagName = "") => {
33
33
  placeholder: "phone"
34
34
  }];
35
35
  navOptions = navOptions.filter(n => !hideTools.includes(n.value));
36
+ if (!allowTrigger) {
37
+ const triggerValues = ["nextTrigger", "prevTrigger"];
38
+ navOptions = navOptions.filter(n => !triggerValues.includes(n.value));
39
+ }
36
40
  if (tagName !== "Pages") {
37
41
  navOptions = navOptions.filter(n => n.value !== "page");
38
42
  }
@@ -4,6 +4,7 @@ import { ReactEditor } from "slate-react";
4
4
  import LinkSettings from "../../../LinkSettings";
5
5
  import { insertLink, removeLink } from "../../../../utils/link";
6
6
  import { getBlockActive, isBlockActive, upateBlockActive } from "../../../../utils/SlateUtilityFunctions";
7
+ import { getLinkType } from "../../../../utils/helper";
7
8
  import { jsx as _jsx } from "react/jsx-runtime";
8
9
  import { Fragment as _Fragment } from "react/jsx-runtime";
9
10
  const Link = props => {
@@ -32,11 +33,13 @@ const Link = props => {
32
33
  if (childType === "text") {
33
34
  selectTextNode();
34
35
  const p = getBlockActive(editor, "link")?.props || {};
36
+ const url = p?.href || p?.url;
37
+ const showInNewTab = p?.target || p?.showInNewTab;
35
38
  const bp = {
36
39
  name: Editor.string(editor, editor.selection),
37
- navType: "webAddress",
38
- navValue: p?.href,
39
- openInNewTab: p?.target === "_blank"
40
+ navType: getLinkType(p.linkType, url) || "webAddress",
41
+ navValue: url,
42
+ openInNewTab: showInNewTab === "_blank"
40
43
  };
41
44
  setIsActiveTextLink(isBlockActive(editor, "link"));
42
45
  setBlockProps(bp);
@@ -78,7 +81,8 @@ const Link = props => {
78
81
  return {
79
82
  name: Editor.string(editor, editor.selection),
80
83
  url: d?.navValue,
81
- showInNewTab: d?.openInNewTab
84
+ showInNewTab: d?.openInNewTab,
85
+ linkType: d?.linkType
82
86
  };
83
87
  case "image":
84
88
  return {
@@ -108,7 +112,8 @@ const Link = props => {
108
112
  const upData = isActiveTextLink ? {
109
113
  href: data?.url,
110
114
  target: data?.showInNewTab ? "_blank" : "_self",
111
- name: data?.name
115
+ name: data?.name,
116
+ linkType: data?.linkType
112
117
  } : data;
113
118
  if (isActiveTextLink) {
114
119
  // update text link
@@ -151,7 +156,8 @@ const Link = props => {
151
156
  },
152
157
  ...(blockProps || {}),
153
158
  customProps: customProps,
154
- theme: theme
159
+ theme: theme,
160
+ allowTrigger: childType === "button"
155
161
  }) : null
156
162
  });
157
163
  };
@@ -1,5 +1,4 @@
1
1
  import React from "react";
2
- import { Node } from "slate";
3
2
  import { Dialog, DialogContent, DialogTitle, IconButton } from "@mui/material";
4
3
  import SaveAsTemplate from "../../../StyleBuilder/fieldTypes/saveAsTemplate";
5
4
  import { CloseIcon } from "../../../iconslist";
@@ -12,7 +12,7 @@ const Settings = props => {
12
12
  childType,
13
13
  open,
14
14
  anchorEl,
15
- placement,
15
+ // placement,
16
16
  onClose,
17
17
  editor,
18
18
  classes,
@@ -123,8 +123,8 @@ export function onDropItem(props, parentClass) {
123
123
  dragOver,
124
124
  parentPath,
125
125
  path,
126
- diffX,
127
- x: cx,
126
+ // diffX,
127
+ // x: cx,
128
128
  breakpoint
129
129
  // calX,
130
130
  } = props;
@@ -134,7 +134,9 @@ export function onDropItem(props, parentClass) {
134
134
  let newPath = [];
135
135
  newPath = moveTo;
136
136
  const cCalx = isContainerElement(editor, moveTo, props);
137
- const posX = parseInt(cx - window.innerWidth / 2 + MARGIN_OF[breakpoint] - diffX);
137
+ // const posX = parseInt(
138
+ // cx - window.innerWidth / 2 + MARGIN_OF[breakpoint] - diffX
139
+ // );
138
140
  const toSectionNode = Node.get(editor, newPath);
139
141
  const addToSectionDOM = ReactEditor.toDOMNode(editor, toSectionNode);
140
142
  const rect = addToSectionDOM.getBoundingClientRect();
@@ -9,7 +9,7 @@ const embedVideoStyle = [{
9
9
  }]
10
10
  }, {
11
11
  tab: "Aspect Ratio",
12
- value: "Aspect Ratio",
12
+ value: "AspectRatio",
13
13
  hideOnFGS: true,
14
14
  fields: [{
15
15
  label: "Aspect Ratio",
@@ -14,6 +14,19 @@ const withCustomDeleteBackward = editor => {
14
14
  selection
15
15
  } = editor;
16
16
  if (selection) {
17
+ // get the current node
18
+ const [freeGridItemNode] = Editor.nodes(editor, {
19
+ match: n => n.type === "freegridItem" // Adjust based on your list item type
20
+ });
21
+
22
+ // if it is freegrid
23
+ if (freeGridItemNode && freeGridItemNode[0]) {
24
+ const hasText = Node.string(freeGridItemNode[0]);
25
+ if (!hasText) {
26
+ return;
27
+ }
28
+ }
29
+
17
30
  // Check if current node is a list item and is the last one
18
31
  const [node] = Editor.nodes(editor, {
19
32
  match: n => n.type === "list-item" // Adjust based on your list item type
@@ -0,0 +1,22 @@
1
+ import { Editor, Range, Text } from "slate";
2
+ const highlightSelection = ([node, path], editor = {}) => {
3
+ if (Text.isText(node) && editor?.selection) {
4
+ const intersection = Range.intersection(editor.selection, Editor.range(editor, path));
5
+ if (!intersection) {
6
+ return [];
7
+ }
8
+
9
+ // Avoid applying highlight if the range only includes line breaks
10
+ const rangeText = Editor.string(editor, intersection);
11
+ if (!rangeText.trim()) {
12
+ return [];
13
+ }
14
+ const range = {
15
+ highlight: true,
16
+ ...intersection
17
+ };
18
+ return [range];
19
+ }
20
+ return [];
21
+ };
22
+ export default highlightSelection;
@@ -1,5 +1,6 @@
1
+ import highlightSelection from "./highlightSelection";
1
2
  import link from "./link";
2
- const decorators = d => {
3
- return [...link(d)];
3
+ const decorators = (d, editor) => {
4
+ return [...link(d, editor), ...highlightSelection(d, editor)];
4
5
  };
5
6
  export default decorators;
@@ -242,6 +242,15 @@ export const getMarked = (leaf, children, theme) => {
242
242
  })
243
243
  });
244
244
  }
245
+ if (leaf.highlight) {
246
+ children = /*#__PURE__*/_jsx("span", {
247
+ style: {
248
+ background: "#EAEBFE",
249
+ color: "inherit"
250
+ },
251
+ children: children
252
+ });
253
+ }
245
254
  if (leaf.decoration === "link") {
246
255
  children = /*#__PURE__*/_jsx("a", {
247
256
  style: {
@@ -483,7 +483,7 @@ export const isFreeGrid = (nodes, types = ["freegrid", "freegridItem", "freegrid
483
483
  }
484
484
  return false;
485
485
  } catch (err) {
486
- console.log('isFreeGrid error:', err);
486
+ console.log("isFreeGrid error:", err);
487
487
  return false;
488
488
  }
489
489
  };
@@ -1,8 +1,10 @@
1
1
  import { Editor, Transforms, Path, Range, Element } from "slate";
2
- export const createLinkNode = (href, showInNewTab, text) => ({
2
+ import { isBlockActive } from "./SlateUtilityFunctions";
3
+ export const createLinkNode = (href, showInNewTab, text, linkType) => ({
3
4
  type: "link",
4
5
  href,
5
6
  target: showInNewTab ? "_blank" : "_self",
7
+ linkType,
6
8
  children: [{
7
9
  text
8
10
  }]
@@ -10,16 +12,19 @@ export const createLinkNode = (href, showInNewTab, text) => ({
10
12
  export const insertLink = (editor, {
11
13
  url,
12
14
  showInNewTab,
13
- name
15
+ name,
16
+ linkType
14
17
  }) => {
15
18
  if (!url) return;
16
19
  const {
17
20
  selection
18
21
  } = editor;
19
- const link = createLinkNode(url, showInNewTab, name || "Link");
22
+ const link = createLinkNode(url, showInNewTab, name || "Link", linkType);
20
23
  if (!!selection) {
21
24
  const [parent, parentPath] = Editor.parent(editor, selection.focus.path);
22
- if (parent.type === "link") {
25
+ const isActive = isBlockActive(editor, "link"); // on reverse selecting the full text from offset 0 to some point (Note: only on focus-offset is 0), Transforms.wrapNodes is removing that reversely selected full text
26
+
27
+ if (parent.type === "link" || isActive) {
23
28
  removeLink(editor);
24
29
  }
25
30
  if (editor.isVoid(parent)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flozy/editor",
3
- "version": "4.7.4",
3
+ "version": "4.7.5",
4
4
  "description": "An Editor for flozy app brain",
5
5
  "files": [
6
6
  "dist"