@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.
- package/dist/Editor/CommonEditor.js +1 -3
- package/dist/Editor/Elements/AI/AIInput.js +4 -5
- package/dist/Editor/Elements/AI/PopoverAIInput.js +78 -62
- package/dist/Editor/Elements/AI/Styles.js +1 -0
- package/dist/Editor/Elements/Button/EditorButton.js +2 -1
- package/dist/Editor/Elements/Embed/EmbedPopup.js +7 -1
- package/dist/Editor/Elements/FreeGrid/styles.js +1 -1
- package/dist/Editor/Elements/Link/Link.js +73 -37
- package/dist/Editor/Elements/Link/LinkButton.js +37 -25
- package/dist/Editor/MiniEditor.js +19 -12
- package/dist/Editor/Styles/EditorStyles.js +1 -1
- package/dist/Editor/Toolbar/Basic/index.js +10 -8
- package/dist/Editor/Toolbar/PopupTool/MiniTextFormat/index.js +8 -4
- package/dist/Editor/Toolbar/PopupTool/TextFormat.js +4 -2
- package/dist/Editor/Toolbar/Toolbar.js +2 -1
- package/dist/Editor/common/LinkSettings/index.js +3 -2
- package/dist/Editor/common/LinkSettings/navOptions.js +5 -1
- package/dist/Editor/common/RnD/ElementSettings/OtherSettings/Link.js +12 -6
- package/dist/Editor/common/RnD/ElementSettings/OtherSettings/SaveAsTemplate.js +0 -1
- package/dist/Editor/common/RnD/ElementSettings/OtherSettings/Settings.js +1 -1
- package/dist/Editor/common/RnD/Utils/gridDropItem.js +5 -3
- package/dist/Editor/common/StyleBuilder/embedVideoStyle.js +1 -1
- package/dist/Editor/plugins/withCustomDeleteBackward.js +13 -0
- package/dist/Editor/utils/Decorators/highlightSelection.js +22 -0
- package/dist/Editor/utils/Decorators/index.js +3 -2
- package/dist/Editor/utils/SlateUtilityFunctions.js +9 -0
- package/dist/Editor/utils/helper.js +1 -1
- package/dist/Editor/utils/link.js +9 -4
- 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:
|
|
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
|
-
}),
|
|
129
|
+
}), /*#__PURE__*/_jsxs(Box, {
|
|
131
130
|
component: "div",
|
|
132
131
|
style: classes.sendIconContainer,
|
|
133
132
|
className: "icons-elements",
|
|
134
|
-
children: [
|
|
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
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
|
203
|
-
|
|
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 =
|
|
215
|
+
payload.textData = textData;
|
|
216
|
+
} else if (selectedText && Number(payload.mode) === 0) {
|
|
217
|
+
payload.query = `${selectedText} \n ${payload.query}`;
|
|
253
218
|
}
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
};
|
|
@@ -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 :
|
|
27
|
+
renderTabs: format === "image" ? embedImageStyle : videoStyles,
|
|
22
28
|
customProps: customProps,
|
|
23
29
|
onDelete: onDelete
|
|
24
30
|
});
|
|
@@ -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 {
|
|
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
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
|
|
50
|
-
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(
|
|
78
|
-
|
|
79
|
-
|
|
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(
|
|
100
|
-
href: absLink,
|
|
123
|
+
children: [/*#__PURE__*/_jsx(Box, {
|
|
101
124
|
...attributes,
|
|
102
125
|
...element.attr,
|
|
103
|
-
|
|
126
|
+
sx: classes.linkBtn,
|
|
127
|
+
...buttonProps,
|
|
104
128
|
children: children
|
|
105
|
-
}), /*#__PURE__*/_jsx(Toolbar, {}), /*#__PURE__*/_jsx(
|
|
106
|
-
open: showInput,
|
|
107
|
-
linkData: linkData,
|
|
129
|
+
}), /*#__PURE__*/_jsx(Toolbar, {}), showInput ? /*#__PURE__*/_jsx(LinkSettings, {
|
|
108
130
|
handleClose: handleClose,
|
|
109
|
-
|
|
110
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
44
|
-
showInNewTab:
|
|
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(
|
|
76
|
-
open: showInput,
|
|
77
|
-
linkData: linkData,
|
|
74
|
+
}), showInput ? /*#__PURE__*/_jsx(LinkSettings, {
|
|
78
75
|
handleClose: handleClose,
|
|
79
|
-
|
|
80
|
-
|
|
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__*/
|
|
133
|
+
return /*#__PURE__*/_jsx(EditorProvider, {
|
|
132
134
|
editor: editor,
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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";
|
|
@@ -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:
|
|
38
|
+
format: "color",
|
|
38
39
|
value: color
|
|
39
40
|
});
|
|
40
41
|
};
|
|
41
42
|
return /*#__PURE__*/_jsxs(Box, {
|
|
42
|
-
component:
|
|
43
|
+
component: "div",
|
|
43
44
|
className: "basic-toolbar",
|
|
44
45
|
children: [/*#__PURE__*/_jsxs(Grid, {
|
|
45
46
|
container: true,
|
|
46
47
|
sx: {
|
|
47
|
-
padding:
|
|
48
|
+
padding: "10px"
|
|
48
49
|
},
|
|
49
|
-
alignItems:
|
|
50
|
-
justifyContent:
|
|
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:
|
|
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:
|
|
39
|
-
openInNewTab:
|
|
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
|
};
|
|
@@ -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(
|
|
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();
|
|
@@ -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: {
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { Editor, Transforms, Path, Range, Element } from "slate";
|
|
2
|
-
|
|
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
|
-
|
|
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)) {
|