@flozy/editor 4.7.4 → 4.7.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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"