@flozy/editor 3.4.1 → 3.4.2
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/Editor/CommonEditor.js +1 -6
- package/dist/Editor/Elements/AI/AIInput.js +15 -11
- package/dist/Editor/Elements/AI/PopoverAIInput.js +96 -20
- package/dist/Editor/Elements/AI/Styles.js +22 -14
- package/dist/Editor/common/MentionsPopup/Styles.js +3 -3
- package/dist/Editor/common/Shorthands/elements.js +1 -1
- package/dist/Editor/hooks/useMouseMove.js +2 -6
- package/dist/Editor/utils/infinityAI.js +1 -20
- package/package.json +1 -1
@@ -98,7 +98,6 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
|
|
98
98
|
});
|
99
99
|
const [isScrolling, setIsScrolling] = useState(false);
|
100
100
|
const [isTextSelected, setIsTextSelected] = useState(false);
|
101
|
-
const [openInfiniti, setOpenInfiniti] = useState(false);
|
102
101
|
const [size] = useWindowResize();
|
103
102
|
const {
|
104
103
|
needDotsBG,
|
@@ -386,7 +385,6 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
|
|
386
385
|
return /*#__PURE__*/_jsx(EditorProvider, {
|
387
386
|
theme: theme,
|
388
387
|
editor: editor,
|
389
|
-
setOpenInfiniti: setOpenInfiniti,
|
390
388
|
children: /*#__PURE__*/_jsx(DialogWrapper, {
|
391
389
|
classes: classes,
|
392
390
|
...props,
|
@@ -416,10 +414,7 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
|
|
416
414
|
handleInsertLastElement(e, editor);
|
417
415
|
},
|
418
416
|
onScroll: handleScroll,
|
419
|
-
style:
|
420
|
-
...editorWrapperStyle,
|
421
|
-
overflowY: openInfiniti ? "hidden" : "auto"
|
422
|
-
},
|
417
|
+
style: editorWrapperStyle,
|
423
418
|
children: /*#__PURE__*/_jsxs(Box, {
|
424
419
|
component: "div",
|
425
420
|
className: "max-content",
|
@@ -94,7 +94,15 @@ function AIInput({
|
|
94
94
|
sx: classes.aiContainer,
|
95
95
|
children: [generatedText ? /*#__PURE__*/_jsx(Typography, {
|
96
96
|
sx: classes.generatedText,
|
97
|
-
children:
|
97
|
+
children: /*#__PURE__*/_jsx("pre", {
|
98
|
+
style: {
|
99
|
+
whiteSpace: "pre-wrap",
|
100
|
+
wordWrap: "break-word",
|
101
|
+
fontFamily: "inherit",
|
102
|
+
margin: 0
|
103
|
+
},
|
104
|
+
children: generatedText
|
105
|
+
})
|
98
106
|
}) : null, /*#__PURE__*/_jsxs(Box, {
|
99
107
|
component: "form",
|
100
108
|
sx: classes.aiInputWrapper,
|
@@ -103,19 +111,14 @@ function AIInput({
|
|
103
111
|
},
|
104
112
|
ref: refs[0],
|
105
113
|
children: [/*#__PURE__*/_jsx("div", {
|
106
|
-
className: "icon-container",
|
114
|
+
className: "icon-container icons-elements",
|
107
115
|
ref: inputWrapperRef,
|
108
116
|
children: /*#__PURE__*/_jsx(Icon, {
|
109
117
|
icon: "infinityIcon"
|
110
118
|
})
|
111
|
-
}), loading ? /*#__PURE__*/
|
119
|
+
}), loading ? /*#__PURE__*/_jsx("div", {
|
112
120
|
className: "loading-container",
|
113
|
-
children:
|
114
|
-
variant: "body1",
|
115
|
-
children: "Infinity Writing"
|
116
|
-
}), /*#__PURE__*/_jsx("div", {
|
117
|
-
children: /*#__PURE__*/_jsx(WaveLoading, {})
|
118
|
-
})]
|
121
|
+
children: /*#__PURE__*/_jsx(WaveLoading, {})
|
119
122
|
}) : /*#__PURE__*/_jsx(TextareaAutosize, {
|
120
123
|
className: "ai-input",
|
121
124
|
placeholder: fromToolBar ? "" : "Ask AI to write anything...",
|
@@ -129,15 +132,16 @@ function AIInput({
|
|
129
132
|
handleSendBtnClick();
|
130
133
|
}
|
131
134
|
}
|
132
|
-
}), /*#__PURE__*/_jsx(Box, {
|
135
|
+
}), fromToolBar ? null : /*#__PURE__*/_jsx(Box, {
|
133
136
|
component: "div",
|
134
137
|
style: classes.sendIconContainer,
|
138
|
+
className: "icons-elements",
|
135
139
|
children: /*#__PURE__*/_jsx(IconButton, {
|
136
140
|
sx: isSendBtnDisabled ? classes.sendBtnDisabled : classes.sendBtn,
|
137
141
|
onClick: () => handleSendBtnClick(),
|
138
142
|
children: /*#__PURE__*/_jsx(IoSend, {
|
139
143
|
color: "#fff",
|
140
|
-
size:
|
144
|
+
size: 14
|
141
145
|
})
|
142
146
|
})
|
143
147
|
})]
|
@@ -4,7 +4,7 @@ import Styles from "./Styles";
|
|
4
4
|
import { Box, Fade, Paper, Popper } from "@mui/material";
|
5
5
|
import AIInput from "./AIInput";
|
6
6
|
import { ReactEditor, useSlate } from "slate-react";
|
7
|
-
import { Node, Path, Transforms } from "slate";
|
7
|
+
import { Editor, Node, Path, Transforms } from "slate";
|
8
8
|
import useWindowResize from "../../hooks/useWindowResize";
|
9
9
|
import { MODES } from "./helper";
|
10
10
|
import { getSelectedText } from "../../utils/helper";
|
@@ -29,6 +29,66 @@ const scrollToAIInput = () => {
|
|
29
29
|
console.log(err);
|
30
30
|
}
|
31
31
|
};
|
32
|
+
const insertAtNextLine = (editor, text) => {
|
33
|
+
const nextLine = getNextLine(editor);
|
34
|
+
Transforms.splitNodes(editor, {
|
35
|
+
at: nextLine.at
|
36
|
+
});
|
37
|
+
Transforms.insertNodes(editor, {
|
38
|
+
type: "paragraph",
|
39
|
+
children: [{
|
40
|
+
text
|
41
|
+
}]
|
42
|
+
}, {
|
43
|
+
at: nextLine.at
|
44
|
+
});
|
45
|
+
const currentPath = Path.parent(nextLine.at.focus.path);
|
46
|
+
const nextPath = Path.next(currentPath);
|
47
|
+
ReactEditor.focus(editor);
|
48
|
+
Transforms.select(editor, {
|
49
|
+
anchor: Editor.start(editor, nextPath),
|
50
|
+
focus: Editor.end(editor, nextPath)
|
51
|
+
});
|
52
|
+
};
|
53
|
+
const getNextLine = editor => {
|
54
|
+
const {
|
55
|
+
selection
|
56
|
+
} = editor;
|
57
|
+
const {
|
58
|
+
focus
|
59
|
+
} = selection;
|
60
|
+
const {
|
61
|
+
text = ""
|
62
|
+
} = Node.get(editor, focus.path);
|
63
|
+
let nextLineIndex = 0;
|
64
|
+
let indexOfNextLine = 0;
|
65
|
+
if (text?.length) {
|
66
|
+
// split the text based on caret position
|
67
|
+
const textBeforeCaret = text.substring(0, focus.offset);
|
68
|
+
const textAfterCaret = text.substring(focus.offset);
|
69
|
+
|
70
|
+
// getting the index of the next line after the caret position
|
71
|
+
indexOfNextLine = textAfterCaret?.indexOf("\n");
|
72
|
+
if (indexOfNextLine >= 0) {
|
73
|
+
// index of next line
|
74
|
+
nextLineIndex = textBeforeCaret?.length + indexOfNextLine;
|
75
|
+
} else {
|
76
|
+
nextLineIndex = text?.length;
|
77
|
+
}
|
78
|
+
}
|
79
|
+
const data = {
|
80
|
+
...focus,
|
81
|
+
offset: nextLineIndex
|
82
|
+
};
|
83
|
+
const at = {
|
84
|
+
anchor: data,
|
85
|
+
focus: data
|
86
|
+
};
|
87
|
+
return {
|
88
|
+
at,
|
89
|
+
indexOfNextLine
|
90
|
+
};
|
91
|
+
};
|
32
92
|
const updateAnchorEl = (setAnchorEl, editor) => {
|
33
93
|
try {
|
34
94
|
if (!editor.selection) {
|
@@ -41,17 +101,19 @@ const updateAnchorEl = (setAnchorEl, editor) => {
|
|
41
101
|
// selected text as caret
|
42
102
|
caret = selection.getRangeAt(0);
|
43
103
|
} else {
|
44
|
-
|
45
|
-
// foccussed DOM as caret
|
46
|
-
caret = ReactEditor.toDOMNode(editor, focussedNode);
|
104
|
+
caret = ReactEditor.toDOMRange(editor, getNextLine(editor).at);
|
47
105
|
}
|
48
106
|
const getBoundingClientRect = () => {
|
49
|
-
const
|
107
|
+
const editorContainer = document.querySelector("#slate-wrapper-scroll-container")?.getBoundingClientRect();
|
108
|
+
const editorEle = document.querySelector(".ed-section-inner")?.getBoundingClientRect();
|
50
109
|
const caretPos = caret.getBoundingClientRect();
|
110
|
+
const isAIInputReachTop = caretPos.height + caretPos.y <= editorContainer.y;
|
111
|
+
const yValue = isAIInputReachTop ? "-500" : caretPos.y; // -500 is to hide the AI input if the toolbar reached the top
|
112
|
+
|
51
113
|
return {
|
52
|
-
y:
|
114
|
+
y: yValue,
|
53
115
|
height: caretPos.height,
|
54
|
-
top:
|
116
|
+
top: yValue,
|
55
117
|
right: caretPos.right,
|
56
118
|
bottom: caretPos.bottom,
|
57
119
|
x: editorEle.x,
|
@@ -140,6 +202,10 @@ function PopoverAIInput({
|
|
140
202
|
let {
|
141
203
|
data: text
|
142
204
|
} = result || {};
|
205
|
+
if (!text) {
|
206
|
+
onClickOutside();
|
207
|
+
return;
|
208
|
+
}
|
143
209
|
if (!option.replace) {
|
144
210
|
if (type === "continue_writing") {
|
145
211
|
setGeneratedText(generatedText + text);
|
@@ -148,8 +214,6 @@ function PopoverAIInput({
|
|
148
214
|
}
|
149
215
|
return;
|
150
216
|
}
|
151
|
-
const currentPath = Path.parent(editor.selection.focus.path);
|
152
|
-
const nextPath = Path.next(currentPath);
|
153
217
|
|
154
218
|
// Get the current selection point
|
155
219
|
const {
|
@@ -157,21 +221,28 @@ function PopoverAIInput({
|
|
157
221
|
} = editor.selection;
|
158
222
|
const {
|
159
223
|
path
|
160
|
-
} =
|
224
|
+
} = anchor;
|
161
225
|
const {
|
162
226
|
text: selectText
|
163
227
|
} = Node.get(editor, path);
|
164
228
|
const insertInNewLine = option.isSendBtn && selectText?.length || type === "continue_writing";
|
165
229
|
if (insertInNewLine) {
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
230
|
+
if (getSelectedText(editor)) {
|
231
|
+
const currentPath = Path.parent(editor.selection.focus.path);
|
232
|
+
const nextPath = Path.next(currentPath);
|
233
|
+
Transforms.insertNodes(editor, {
|
234
|
+
type: "paragraph",
|
235
|
+
children: [{
|
236
|
+
text
|
237
|
+
}]
|
238
|
+
}, {
|
239
|
+
at: nextPath,
|
240
|
+
select: true
|
241
|
+
});
|
242
|
+
} else {
|
243
|
+
insertAtNextLine(editor, text);
|
244
|
+
return;
|
245
|
+
}
|
175
246
|
} else {
|
176
247
|
Transforms.insertText(editor, text);
|
177
248
|
}
|
@@ -184,8 +255,10 @@ function PopoverAIInput({
|
|
184
255
|
};
|
185
256
|
ReactEditor.focus(editor);
|
186
257
|
Transforms.select(editor, range);
|
187
|
-
|
258
|
+
|
259
|
+
// scrollToAIInput();
|
188
260
|
};
|
261
|
+
|
189
262
|
const onInputChange = e => {
|
190
263
|
setInputValue(e.target.value);
|
191
264
|
};
|
@@ -220,6 +293,9 @@ function PopoverAIInput({
|
|
220
293
|
...TransitionProps,
|
221
294
|
timeout: 350,
|
222
295
|
children: /*#__PURE__*/_jsx(Paper, {
|
296
|
+
sx: getSelectedText(editor) ? {
|
297
|
+
marginTop: "6px"
|
298
|
+
} : {},
|
223
299
|
children: /*#__PURE__*/_jsx(AIInput, {
|
224
300
|
loading: loading,
|
225
301
|
onSend: onSend,
|
@@ -2,39 +2,45 @@ const Styles = theme => ({
|
|
2
2
|
aiContainer: {
|
3
3
|
background: "#FCFAFF",
|
4
4
|
border: "1px solid #8360FD",
|
5
|
-
borderRadius: "
|
5
|
+
borderRadius: "6px",
|
6
|
+
boxShadow: "0px 4px 10px 0px #00000029"
|
6
7
|
},
|
7
8
|
aiInputWrapper: {
|
8
9
|
display: "flex",
|
9
10
|
alignItems: "baseline",
|
10
11
|
justifyContent: "space-between",
|
11
|
-
padding: "0px 12px",
|
12
|
+
padding: "0px 4px 0px 12px",
|
12
13
|
minHeight: "36px",
|
13
14
|
position: "relative",
|
14
15
|
background: "#FCFAFF",
|
15
|
-
borderRadius: "
|
16
|
+
borderRadius: "5px",
|
16
17
|
"& .icon-container": {
|
17
18
|
display: "flex",
|
18
|
-
alignItems: "center"
|
19
|
-
|
19
|
+
alignItems: "center"
|
20
|
+
},
|
21
|
+
"& .icons-elements": {
|
22
|
+
height: "40px"
|
20
23
|
},
|
21
24
|
"& .ai-input": {
|
22
|
-
padding: "
|
25
|
+
padding: "8px 4px 8px 18px",
|
23
26
|
border: "none",
|
24
27
|
outline: "none",
|
25
28
|
width: "100%",
|
26
29
|
background: "transparent",
|
27
30
|
resize: "none",
|
28
31
|
alignSelf: "center",
|
29
|
-
color:
|
30
|
-
fontSize: "
|
32
|
+
color: "#000",
|
33
|
+
fontSize: "14px !important",
|
34
|
+
fontFamily: '"Inter", sans-serif',
|
31
35
|
"&::placeholder": {
|
32
36
|
color: "#94A3B8",
|
33
|
-
opacity: 1 /* Firefox
|
37
|
+
opacity: 1 /* Firefox */,
|
38
|
+
fontFamily: '"Inter", sans-serif',
|
39
|
+
fontWeight: 500
|
34
40
|
},
|
35
|
-
|
36
41
|
"&::-ms-input-placeholder": {
|
37
|
-
/* Edge 12-18 */color: "#94A3B8"
|
42
|
+
/* Edge 12-18 */color: "#94A3B8",
|
43
|
+
fontFamily: '"Inter", sans-serif'
|
38
44
|
}
|
39
45
|
},
|
40
46
|
"& .action-btns": {
|
@@ -71,7 +77,10 @@ const Styles = theme => ({
|
|
71
77
|
background: "linear-gradient(331.11deg, #2563EB 7.11%, #8360FD 88.37%)"
|
72
78
|
},
|
73
79
|
sendBtnDisabled: {
|
74
|
-
background: "#C0C9D6"
|
80
|
+
background: "#C0C9D6",
|
81
|
+
"&:hover": {
|
82
|
+
background: "#C0C9D6"
|
83
|
+
}
|
75
84
|
},
|
76
85
|
aiPopper: {
|
77
86
|
zIndex: 9000,
|
@@ -114,7 +123,7 @@ const Styles = theme => ({
|
|
114
123
|
},
|
115
124
|
|
116
125
|
optionBtn: {
|
117
|
-
color: "#373232",
|
126
|
+
color: theme?.palette?.editor?.textColor || "#373232",
|
118
127
|
padding: "8px 12px",
|
119
128
|
textTransform: "none",
|
120
129
|
justifyContent: "space-between",
|
@@ -142,7 +151,6 @@ const Styles = theme => ({
|
|
142
151
|
},
|
143
152
|
sendIconContainer: {
|
144
153
|
alignSelf: "flex-end",
|
145
|
-
height: "48px",
|
146
154
|
display: "flex",
|
147
155
|
alignItems: "center"
|
148
156
|
}
|
@@ -4,7 +4,7 @@ const usePopupStyles = theme => ({
|
|
4
4
|
zIndex: 1300,
|
5
5
|
borderRadius: "10px",
|
6
6
|
padding: "0px",
|
7
|
-
boxShadow: "
|
7
|
+
boxShadow: "0px 4px 10px 0px #00000029",
|
8
8
|
overflow: "hidden"
|
9
9
|
},
|
10
10
|
papper: {
|
@@ -40,10 +40,10 @@ const usePopupStyles = theme => ({
|
|
40
40
|
color: theme?.palette?.editor?.textColor
|
41
41
|
},
|
42
42
|
"&.active": {
|
43
|
-
|
43
|
+
background: "#E9F3FE"
|
44
44
|
},
|
45
45
|
"&:hover": {
|
46
|
-
|
46
|
+
background: "#E9F3FE"
|
47
47
|
},
|
48
48
|
"&.renderComp": {
|
49
49
|
padding: "0px",
|
@@ -19,8 +19,7 @@ export const useEditorSelection = editor => {
|
|
19
19
|
export const EditorProvider = ({
|
20
20
|
editor,
|
21
21
|
theme,
|
22
|
-
children
|
23
|
-
setOpenInfiniti
|
22
|
+
children
|
24
23
|
}) => {
|
25
24
|
const [event] = useMouseMove();
|
26
25
|
const [previous, setPrevious] = useState("");
|
@@ -55,10 +54,7 @@ export const EditorProvider = ({
|
|
55
54
|
popupType,
|
56
55
|
setPopupType,
|
57
56
|
openAI,
|
58
|
-
setOpenAI
|
59
|
-
setOpenAI(value);
|
60
|
-
setOpenInfiniti(!!value);
|
61
|
-
}
|
57
|
+
setOpenAI
|
62
58
|
},
|
63
59
|
children: children
|
64
60
|
});
|
@@ -1,23 +1,4 @@
|
|
1
|
-
import {
|
1
|
+
import { Transforms } from "slate";
|
2
2
|
export const insertInfinityAI = editor => {
|
3
3
|
Transforms.delete(editor, editor.selection);
|
4
|
-
const {
|
5
|
-
path
|
6
|
-
} = editor.selection.anchor;
|
7
|
-
const {
|
8
|
-
text
|
9
|
-
} = Node.get(editor, path);
|
10
|
-
const currentPath = Path.parent(editor.selection.focus.path);
|
11
|
-
const nextPath = Path.next(currentPath);
|
12
|
-
if (text?.length) {
|
13
|
-
Transforms.insertNodes(editor, {
|
14
|
-
type: "paragraph",
|
15
|
-
children: [{
|
16
|
-
text: ""
|
17
|
-
}]
|
18
|
-
}, {
|
19
|
-
at: nextPath,
|
20
|
-
select: true
|
21
|
-
});
|
22
|
-
}
|
23
4
|
};
|