@flozy/editor 4.0.3 → 4.0.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 +85 -13
- package/dist/Editor/DialogWrapper.js +4 -3
- package/dist/Editor/Editor.css +28 -2
- package/dist/Editor/Elements/AI/AIInput.js +31 -33
- package/dist/Editor/Elements/AI/CustomSelect.js +19 -12
- package/dist/Editor/Elements/AI/PopoverAIInput.js +124 -133
- package/dist/Editor/Elements/AI/Styles.js +2 -2
- package/dist/Editor/Elements/AI/VoiceToText/AudioWave.js +73 -0
- package/dist/Editor/Elements/AI/VoiceToText/index.js +184 -0
- package/dist/Editor/Elements/AI/VoiceToText/style.js +40 -0
- package/dist/Editor/Elements/AI/helper.js +5 -3
- package/dist/Editor/Elements/AppHeader/AppHeader.js +36 -23
- package/dist/Editor/Elements/Button/EditorButton.js +23 -16
- package/dist/Editor/Elements/Carousel/CarouselButton.js +2 -2
- package/dist/Editor/Elements/Color Picker/ColorButtons.js +1 -1
- package/dist/Editor/Elements/Color Picker/Styles.js +1 -0
- package/dist/Editor/Elements/Embed/Image.js +15 -14
- package/dist/Editor/Elements/Embed/Video.js +12 -8
- package/dist/Editor/Elements/Emoji/EmojiButton.js +11 -7
- package/dist/Editor/Elements/Form/Form.js +43 -27
- package/dist/Editor/Elements/Form/FormField.js +21 -10
- package/dist/Editor/Elements/Form/Workflow/index.js +5 -2
- package/dist/Editor/Elements/FreeGrid/FreeGrid.js +437 -0
- package/dist/Editor/Elements/FreeGrid/FreeGridBox.js +206 -0
- package/dist/Editor/Elements/FreeGrid/FreeGridButton.js +23 -0
- package/dist/Editor/Elements/FreeGrid/FreeGridItem.js +236 -0
- package/dist/Editor/Elements/FreeGrid/Options/AddElement.js +44 -0
- package/dist/Editor/Elements/FreeGrid/Options/More.js +24 -0
- package/dist/Editor/Elements/FreeGrid/Options/SectionSettings.js +47 -0
- package/dist/Editor/Elements/FreeGrid/Options/sectionItemOptions.js +19 -0
- package/dist/Editor/Elements/FreeGrid/breakpointConstants.js +75 -0
- package/dist/Editor/Elements/FreeGrid/styles.js +214 -0
- package/dist/Editor/Elements/Grid/Grid.js +12 -8
- package/dist/Editor/Elements/Grid/GridItem.js +31 -21
- package/dist/Editor/Elements/Link/LinkPopup.js +69 -13
- package/dist/Editor/Elements/Link/LinkPopupStyles.js +28 -0
- package/dist/Editor/Elements/NewLine/NewLineButton.js +2 -2
- package/dist/Editor/Elements/Signature/Signature.css +13 -6
- package/dist/Editor/Elements/Signature/SignatureOptions/UploadSignature.js +2 -1
- package/dist/Editor/Elements/Signature/SignaturePopup.js +186 -31
- package/dist/Editor/Elements/SimpleText/index.js +19 -7
- package/dist/Editor/Elements/SimpleText/style.js +44 -1
- package/dist/Editor/ErrorBoundary.js +30 -0
- package/dist/Editor/Styles/EditorStyles.js +28 -0
- package/dist/Editor/Toolbar/FormatTools/Dropdown.js +1 -1
- package/dist/Editor/Toolbar/FormatTools/TextSize.js +2 -2
- package/dist/Editor/Toolbar/Mini/MiniToolbar.js +33 -5
- package/dist/Editor/Toolbar/PopupTool/ButtonTemplatesCard.js +12 -13
- package/dist/Editor/Toolbar/PopupTool/FullViewCard.js +12 -13
- package/dist/Editor/Toolbar/PopupTool/MiniTextFormat/CustomSelectTool.js +3 -0
- package/dist/Editor/Toolbar/PopupTool/MiniTextFormat/SelectSuperSubscript.js +59 -0
- package/dist/Editor/Toolbar/PopupTool/MiniTextFormat/index.js +2 -1
- package/dist/Editor/Toolbar/PopupTool/PopupToolStyle.js +107 -40
- package/dist/Editor/Toolbar/PopupTool/TextFormat.js +57 -61
- package/dist/Editor/Toolbar/PopupTool/index.js +13 -3
- package/dist/Editor/Toolbar/Toolbar.js +7 -0
- package/dist/Editor/Toolbar/toolbarGroups.js +15 -5
- package/dist/Editor/assets/svg/AIIcons.js +153 -1
- package/dist/Editor/common/EditorCmds.js +0 -3
- package/dist/Editor/common/EditorIcons.js +7 -7
- package/dist/Editor/common/Icon.js +39 -30
- package/dist/Editor/common/ImageList.js +16 -3
- package/dist/Editor/common/ImageSelector/ImageSelector.js +30 -9
- package/dist/Editor/common/ImageSelector/Styles.js +2 -1
- package/dist/Editor/common/LinkSettings/index.js +2 -1
- package/dist/Editor/common/LinkSettings/style.js +11 -8
- package/dist/Editor/common/MentionsPopup/Styles.js +1 -1
- package/dist/Editor/common/MentionsPopup/index.js +12 -8
- package/dist/Editor/common/RnD/ContextMenu/CMenus.js +142 -0
- package/dist/Editor/common/RnD/ContextMenu/index.js +38 -0
- package/dist/Editor/common/RnD/ContextMenu/styles.js +21 -0
- package/dist/Editor/common/RnD/DragInfo/index.js +31 -0
- package/dist/Editor/common/RnD/DragInfo/styles.js +15 -0
- package/dist/Editor/common/RnD/DragOver/index.js +55 -0
- package/dist/Editor/common/RnD/DragOver/styles.js +23 -0
- package/dist/Editor/common/RnD/ElementOptions/Actions.js +102 -0
- package/dist/Editor/common/RnD/ElementOptions/Icons/LinkIcon.js +26 -0
- package/dist/Editor/common/RnD/ElementOptions/index.js +95 -0
- package/dist/Editor/common/RnD/ElementOptions/styles.js +41 -0
- package/dist/Editor/common/RnD/ElementSettings/OtherSettings/Link.js +153 -0
- package/dist/Editor/common/RnD/ElementSettings/OtherSettings/SaveAsTemplate.js +36 -0
- package/dist/Editor/common/RnD/ElementSettings/OtherSettings/Settings.js +60 -0
- package/dist/Editor/common/RnD/ElementSettings/OtherSettings/index.js +9 -0
- package/dist/Editor/common/RnD/ElementSettings/Settings/AppHeaderSettings.js +47 -0
- package/dist/Editor/common/RnD/ElementSettings/Settings/BoxSettings.js +47 -0
- package/dist/Editor/common/RnD/ElementSettings/Settings/ButtonSettings.js +47 -0
- package/dist/Editor/common/RnD/ElementSettings/Settings/FormSettings.js +48 -0
- package/dist/Editor/common/RnD/ElementSettings/Settings/ImageSettings.js +47 -0
- package/dist/Editor/common/RnD/ElementSettings/Settings/TextSettings.js +30 -0
- package/dist/Editor/common/RnD/ElementSettings/Settings/VideoSettings.js +47 -0
- package/dist/Editor/common/RnD/ElementSettings/Settings/index.js +17 -0
- package/dist/Editor/common/RnD/ElementSettings/index.js +17 -0
- package/dist/Editor/common/RnD/ElementSettings/settingsConstants.js +18 -0
- package/dist/Editor/common/RnD/ElementSettings/styles.js +94 -0
- package/dist/Editor/common/RnD/GuideLines/BoundaryLine.js +52 -0
- package/dist/Editor/common/RnD/GuideLines/index.js +33 -0
- package/dist/Editor/common/RnD/GuideLines/styles.js +62 -0
- package/dist/Editor/common/RnD/OptionsPopup/index.js +50 -0
- package/dist/Editor/common/RnD/OptionsPopup/style.js +36 -0
- package/dist/Editor/common/RnD/RnDCopy.js +23 -0
- package/dist/Editor/common/RnD/ShadowElement.js +34 -0
- package/dist/Editor/common/RnD/SwitchViewport/SwitchViewport.js +40 -0
- package/dist/Editor/common/RnD/SwitchViewport/styles.js +24 -0
- package/dist/Editor/common/RnD/Theme/ViewportStimulator.js +63 -0
- package/dist/Editor/common/RnD/TransformHandles/CornerHandle.js +19 -0
- package/dist/Editor/common/RnD/TransformHandles/Icons/BottomRightIcon.js +13 -0
- package/dist/Editor/common/RnD/TransformHandles/SizeHandle.js +20 -0
- package/dist/Editor/common/RnD/TransformHandles/index.js +67 -0
- package/dist/Editor/common/RnD/Utils/alignmentDetection.js +26 -0
- package/dist/Editor/common/RnD/Utils/calculateDropItem.js +98 -0
- package/dist/Editor/common/RnD/Utils/collisionDetection.js +52 -0
- package/dist/Editor/common/RnD/Utils/gridDropItem.js +181 -0
- package/dist/Editor/common/RnD/Utils/index.js +251 -0
- package/dist/Editor/common/RnD/VirtualElement/index.js +77 -0
- package/dist/Editor/common/RnD/VirtualElement/styles.js +27 -0
- package/dist/Editor/common/RnD/VirtualElement/updateAutoProps.js +28 -0
- package/dist/Editor/common/RnD/index.js +567 -0
- package/dist/Editor/common/RnD/styles.js +4 -0
- package/dist/Editor/common/Section/index.js +21 -12
- package/dist/Editor/common/Section/styles.js +7 -4
- package/dist/Editor/common/Shorthands/elements.js +21 -9
- package/dist/Editor/common/StyleBuilder/boxStyle.js +30 -0
- package/dist/Editor/common/StyleBuilder/fieldTypes/bannerSpacing.js +18 -10
- package/dist/Editor/common/StyleBuilder/fieldTypes/saveAsTemplate.js +18 -5
- package/dist/Editor/common/StyleBuilder/fieldTypes/text.js +4 -2
- package/dist/Editor/common/StyleBuilder/index.js +6 -4
- package/dist/Editor/common/StyleBuilder/sectionStyle.js +13 -2
- package/dist/Editor/common/iconListV2.js +843 -0
- package/dist/Editor/commonStyle.js +6 -0
- package/dist/Editor/helper/RnD/focusOnNewItem.js +39 -0
- package/dist/Editor/helper/RnD/scrollToNewSection.js +24 -0
- package/dist/Editor/helper/breakpoint.js +5 -0
- package/dist/Editor/helper/index.js +139 -0
- package/dist/Editor/helper/theme.js +50 -1
- package/dist/Editor/hooks/useBreakpoints.js +34 -0
- package/dist/Editor/hooks/useMouseMove.js +36 -8
- package/dist/Editor/hooks/useWindowMessage.js +10 -7
- package/dist/Editor/hooks/withCommon.js +2 -1
- package/dist/Editor/hooks/withErrorHandling.js +14 -0
- package/dist/Editor/utils/RnD/RnDCtrlCmds.js +197 -0
- package/dist/Editor/utils/SlateUtilityFunctions.js +36 -4
- package/dist/Editor/utils/events.js +5 -0
- package/dist/Editor/utils/form.js +7 -2
- package/dist/Editor/utils/formfield.js +1 -1
- package/dist/Editor/utils/freegrid.js +91 -0
- package/dist/Editor/utils/helper.js +43 -0
- package/dist/Editor/utils/insertAppHeader.js +47 -40
- package/package.json +6 -2
|
@@ -1,26 +1,33 @@
|
|
|
1
1
|
import { useEffect, useRef, useState } from "react";
|
|
2
2
|
import { useEditorContext } from "../../hooks/useMouseMove";
|
|
3
3
|
import Styles from "./Styles";
|
|
4
|
-
import {
|
|
4
|
+
import { Fade, Paper, Popper } from "@mui/material";
|
|
5
5
|
import AIInput from "./AIInput";
|
|
6
6
|
import { ReactEditor, useSlate } from "slate-react";
|
|
7
|
-
import {
|
|
8
|
-
import useWindowResize from "../../hooks/useWindowResize";
|
|
7
|
+
import { Node, Transforms } from "slate";
|
|
9
8
|
import { MODES } from "./helper";
|
|
10
9
|
import { getSelectedText } from "../../utils/helper";
|
|
10
|
+
import { VoiceToText } from "./VoiceToText";
|
|
11
|
+
import deserialize from "../../helper/deserialize";
|
|
11
12
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
12
13
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
|
-
const scrollToAIInput =
|
|
14
|
+
const scrollToAIInput = editor => {
|
|
14
15
|
try {
|
|
15
16
|
setTimeout(() => {
|
|
16
17
|
const slateWrapper = document.getElementById("slate-wrapper-scroll-container");
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
let selectionRect;
|
|
19
|
+
if (getSelectedText(editor)) {
|
|
20
|
+
selectionRect = window.getSelection().getRangeAt(0).getBoundingClientRect();
|
|
21
|
+
} else {
|
|
22
|
+
selectionRect = ReactEditor.toDOMRange(editor, getNextLine(editor).at).getBoundingClientRect();
|
|
23
|
+
}
|
|
24
|
+
const selectionScrollBottom = selectionRect.bottom;
|
|
25
|
+
|
|
26
|
+
// if the cursor or selection top position is greater than 80
|
|
27
|
+
if (selectionScrollBottom > 80) {
|
|
28
|
+
// scroll to top of the slateWrapper
|
|
22
29
|
slateWrapper.scrollTo({
|
|
23
|
-
top: slateWrapper.scrollTop +
|
|
30
|
+
top: slateWrapper.scrollTop + selectionScrollBottom - 80,
|
|
24
31
|
behavior: "smooth"
|
|
25
32
|
});
|
|
26
33
|
}
|
|
@@ -29,80 +36,94 @@ const scrollToAIInput = () => {
|
|
|
29
36
|
console.log(err);
|
|
30
37
|
}
|
|
31
38
|
};
|
|
39
|
+
const insertText = (editor, text, options) => {
|
|
40
|
+
const parsed = new DOMParser().parseFromString(text, "text/html");
|
|
41
|
+
const fragment = deserialize(parsed.body);
|
|
42
|
+
Transforms.insertFragment(editor, fragment, options);
|
|
43
|
+
};
|
|
32
44
|
const insertAtNextLine = (editor, text) => {
|
|
33
45
|
const nextLine = getNextLine(editor);
|
|
34
|
-
|
|
46
|
+
insertText(editor, text, {
|
|
35
47
|
at: nextLine.at
|
|
36
48
|
});
|
|
37
|
-
Transforms.
|
|
38
|
-
type: "paragraph",
|
|
39
|
-
children: [{
|
|
40
|
-
text
|
|
41
|
-
}]
|
|
42
|
-
}, {
|
|
49
|
+
Transforms.splitNodes(editor, {
|
|
43
50
|
at: nextLine.at
|
|
44
51
|
});
|
|
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
52
|
};
|
|
53
53
|
const getNextLine = editor => {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
54
|
+
try {
|
|
55
|
+
const {
|
|
56
|
+
selection
|
|
57
|
+
} = editor;
|
|
58
|
+
const {
|
|
59
|
+
focus
|
|
60
|
+
} = selection;
|
|
61
|
+
if (focus?.path?.length > 0) {
|
|
62
|
+
const {
|
|
63
|
+
text = ""
|
|
64
|
+
} = Node.get(editor, focus.path);
|
|
65
|
+
let nextLineIndex = 0;
|
|
66
|
+
let indexOfNextLine = 0;
|
|
67
|
+
if (text?.length) {
|
|
68
|
+
// split the text based on caret position
|
|
69
|
+
const textBeforeCaret = text.substring(0, focus.offset);
|
|
70
|
+
const textAfterCaret = text.substring(focus.offset);
|
|
69
71
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
72
|
+
// getting the index of the next line after the caret position
|
|
73
|
+
indexOfNextLine = textAfterCaret?.indexOf("\n");
|
|
74
|
+
if (indexOfNextLine >= 0) {
|
|
75
|
+
// index of next line
|
|
76
|
+
nextLineIndex = textBeforeCaret?.length + indexOfNextLine;
|
|
77
|
+
} else {
|
|
78
|
+
nextLineIndex = text?.length;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const data = {
|
|
82
|
+
...focus,
|
|
83
|
+
offset: nextLineIndex
|
|
84
|
+
};
|
|
85
|
+
const at = {
|
|
86
|
+
anchor: data,
|
|
87
|
+
focus: data
|
|
88
|
+
};
|
|
89
|
+
return {
|
|
90
|
+
at,
|
|
91
|
+
indexOfNextLine
|
|
92
|
+
};
|
|
77
93
|
}
|
|
94
|
+
return null;
|
|
95
|
+
} catch (err) {
|
|
96
|
+
console.log(err);
|
|
97
|
+
return null;
|
|
78
98
|
}
|
|
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
99
|
};
|
|
92
|
-
const updateAnchorEl = (setAnchorEl, editor) => {
|
|
100
|
+
const updateAnchorEl = (setAnchorEl, editor, openAI) => {
|
|
93
101
|
try {
|
|
94
102
|
if (!editor.selection) {
|
|
95
103
|
return;
|
|
96
104
|
}
|
|
97
105
|
const selection = window.getSelection();
|
|
106
|
+
if (openAI === "fromToolBar" && selection.anchorOffset !== selection.focusOffset) {
|
|
107
|
+
// to fix some issue in Drag n Drop
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
98
110
|
if (selection.rangeCount) {
|
|
99
111
|
let caret;
|
|
100
112
|
if (getSelectedText(editor)) {
|
|
101
113
|
// selected text as caret
|
|
102
114
|
caret = selection.getRangeAt(0);
|
|
103
115
|
} else {
|
|
104
|
-
|
|
116
|
+
const sel = getNextLine(editor);
|
|
117
|
+
if (sel) {
|
|
118
|
+
const domElement = ReactEditor.toDOMRange(editor, sel.at);
|
|
119
|
+
const {
|
|
120
|
+
textContent,
|
|
121
|
+
parentElement
|
|
122
|
+
} = domElement?.commonAncestorContainer || {};
|
|
123
|
+
caret = textContent ? domElement : parentElement; // in mobile, if textContent in not available, it is pointing some <br> tag (getBoundingClientRect not working correctly for <br>), to avoid that, we are pointing the parent element as caret
|
|
124
|
+
}
|
|
105
125
|
}
|
|
126
|
+
|
|
106
127
|
const getBoundingClientRect = () => {
|
|
107
128
|
const editorContainer = document.querySelector("#slate-wrapper-scroll-container")?.getBoundingClientRect();
|
|
108
129
|
const editorEle = document.querySelector(".ed-section-inner")?.getBoundingClientRect();
|
|
@@ -144,10 +165,8 @@ function PopoverAIInput({
|
|
|
144
165
|
const [generatedText, setGeneratedText] = useState("");
|
|
145
166
|
const [inputValue, setInputValue] = useState("");
|
|
146
167
|
const [selectedOption, setSelectedOption] = useState();
|
|
147
|
-
const targetRef = useRef();
|
|
148
168
|
const classes = Styles();
|
|
149
169
|
const editor = useSlate();
|
|
150
|
-
const [size] = useWindowResize();
|
|
151
170
|
const onClickOutside = () => {
|
|
152
171
|
setAnchorEl(null);
|
|
153
172
|
setOpenAI("");
|
|
@@ -160,11 +179,11 @@ function PopoverAIInput({
|
|
|
160
179
|
};
|
|
161
180
|
const editorElement = document.querySelector(".ed-section-inner");
|
|
162
181
|
useEffect(() => {
|
|
163
|
-
updateAnchorEl(setAnchorEl, editor);
|
|
182
|
+
updateAnchorEl(setAnchorEl, editor, openAI);
|
|
164
183
|
}, [openAI, editor.selection]);
|
|
165
184
|
useEffect(() => {
|
|
166
|
-
if (openAI
|
|
167
|
-
scrollToAIInput();
|
|
185
|
+
if (openAI) {
|
|
186
|
+
scrollToAIInput(editor);
|
|
168
187
|
}
|
|
169
188
|
}, [openAI]);
|
|
170
189
|
const onSend = async (type, option) => {
|
|
@@ -172,12 +191,35 @@ function PopoverAIInput({
|
|
|
172
191
|
onClickOutside();
|
|
173
192
|
return;
|
|
174
193
|
}
|
|
194
|
+
if (type === "done") {
|
|
195
|
+
// Get the current selection point
|
|
196
|
+
const {
|
|
197
|
+
anchor
|
|
198
|
+
} = editor.selection;
|
|
199
|
+
const {
|
|
200
|
+
path
|
|
201
|
+
} = anchor;
|
|
202
|
+
const {
|
|
203
|
+
text: selectText
|
|
204
|
+
} = Node.get(editor, path);
|
|
205
|
+
if (selectText?.length) {
|
|
206
|
+
insertAtNextLine(editor, generatedText);
|
|
207
|
+
} else {
|
|
208
|
+
insertText(editor, generatedText);
|
|
209
|
+
}
|
|
210
|
+
onClickOutside();
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
175
213
|
if (type === "replace_selection") {
|
|
176
214
|
// replace generated text
|
|
177
|
-
|
|
215
|
+
insertText(editor, generatedText);
|
|
178
216
|
onClickOutside();
|
|
179
217
|
return;
|
|
180
218
|
}
|
|
219
|
+
if (type === "speech_to_text") {
|
|
220
|
+
setGeneratedText(option.text);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
181
223
|
if (type === "try_again") {
|
|
182
224
|
// resetting the previous option and try again
|
|
183
225
|
option = selectedOption;
|
|
@@ -188,7 +230,7 @@ function PopoverAIInput({
|
|
|
188
230
|
setLoading(true);
|
|
189
231
|
const payload = {
|
|
190
232
|
mode: option.mode || 0,
|
|
191
|
-
query: inputValue
|
|
233
|
+
query: option?.inputValue || inputValue
|
|
192
234
|
};
|
|
193
235
|
if (option.mode === MODES.translate || option.mode === MODES.rephraseTone) {
|
|
194
236
|
payload.textOptionInput = type;
|
|
@@ -214,47 +256,7 @@ function PopoverAIInput({
|
|
|
214
256
|
}
|
|
215
257
|
return;
|
|
216
258
|
}
|
|
217
|
-
|
|
218
|
-
// Get the current selection point
|
|
219
|
-
const {
|
|
220
|
-
anchor
|
|
221
|
-
} = editor.selection;
|
|
222
|
-
const {
|
|
223
|
-
path
|
|
224
|
-
} = anchor;
|
|
225
|
-
const {
|
|
226
|
-
text: selectText
|
|
227
|
-
} = Node.get(editor, path);
|
|
228
|
-
const insertInNewLine = option.isSendBtn && selectText?.length || type === "continue_writing";
|
|
229
|
-
if (insertInNewLine) {
|
|
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
|
-
}
|
|
246
|
-
} else {
|
|
247
|
-
Transforms.insertText(editor, text);
|
|
248
|
-
}
|
|
249
|
-
const range = {
|
|
250
|
-
...editor.selection,
|
|
251
|
-
anchor: {
|
|
252
|
-
...anchor,
|
|
253
|
-
offset: openAI === "fromToolBar" ? anchor.offset : 0
|
|
254
|
-
}
|
|
255
|
-
};
|
|
256
|
-
ReactEditor.focus(editor);
|
|
257
|
-
Transforms.select(editor, range);
|
|
259
|
+
insertText(editor, text);
|
|
258
260
|
|
|
259
261
|
// scrollToAIInput();
|
|
260
262
|
};
|
|
@@ -263,21 +265,7 @@ function PopoverAIInput({
|
|
|
263
265
|
setInputValue(e.target.value);
|
|
264
266
|
};
|
|
265
267
|
return /*#__PURE__*/_jsxs("div", {
|
|
266
|
-
children: [
|
|
267
|
-
component: "div",
|
|
268
|
-
sx: classes.mobileAIInputWrapper,
|
|
269
|
-
ref: targetRef,
|
|
270
|
-
children: /*#__PURE__*/_jsx(AIInput, {
|
|
271
|
-
loading: loading,
|
|
272
|
-
onSend: onSend,
|
|
273
|
-
generatedText: generatedText,
|
|
274
|
-
anchorEl: anchorEl,
|
|
275
|
-
openAI: openAI,
|
|
276
|
-
inputValue: inputValue,
|
|
277
|
-
onInputChange: onInputChange,
|
|
278
|
-
onClickOutside: onClickOutside
|
|
279
|
-
})
|
|
280
|
-
}) : /*#__PURE__*/_jsx(Popper, {
|
|
268
|
+
children: [/*#__PURE__*/_jsx(Popper, {
|
|
281
269
|
open: Boolean(openAI),
|
|
282
270
|
anchorEl: anchorEl,
|
|
283
271
|
transition: true,
|
|
@@ -286,7 +274,6 @@ function PopoverAIInput({
|
|
|
286
274
|
...classes.aiPopper,
|
|
287
275
|
width: editorElement?.offsetWidth || 400
|
|
288
276
|
},
|
|
289
|
-
ref: targetRef,
|
|
290
277
|
children: ({
|
|
291
278
|
TransitionProps
|
|
292
279
|
}) => /*#__PURE__*/_jsx(Fade, {
|
|
@@ -296,21 +283,25 @@ function PopoverAIInput({
|
|
|
296
283
|
sx: getSelectedText(editor) ? {
|
|
297
284
|
marginTop: "6px"
|
|
298
285
|
} : {},
|
|
299
|
-
children: /*#__PURE__*/_jsx(
|
|
300
|
-
|
|
286
|
+
children: /*#__PURE__*/_jsx(VoiceToText, {
|
|
287
|
+
otherProps: otherProps,
|
|
301
288
|
onSend: onSend,
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
289
|
+
children: /*#__PURE__*/_jsx(AIInput, {
|
|
290
|
+
loading: loading,
|
|
291
|
+
onSend: onSend,
|
|
292
|
+
generatedText: generatedText,
|
|
293
|
+
anchorEl: anchorEl,
|
|
294
|
+
openAI: openAI,
|
|
295
|
+
inputValue: inputValue,
|
|
296
|
+
onInputChange: onInputChange,
|
|
297
|
+
onClickOutside: onClickOutside
|
|
298
|
+
})
|
|
308
299
|
})
|
|
309
300
|
})
|
|
310
301
|
})
|
|
311
302
|
}), openAI ? /*#__PURE__*/_jsx("div", {
|
|
312
303
|
style: {
|
|
313
|
-
height:
|
|
304
|
+
height: "100vh",
|
|
314
305
|
background: "transparent"
|
|
315
306
|
}
|
|
316
307
|
}) : null]
|
|
@@ -91,7 +91,6 @@ const Styles = theme => ({
|
|
|
91
91
|
},
|
|
92
92
|
generatedText: {
|
|
93
93
|
margin: "8px",
|
|
94
|
-
maxHeight: "100px",
|
|
95
94
|
overflow: "auto",
|
|
96
95
|
fontSize: "inherit"
|
|
97
96
|
},
|
|
@@ -167,7 +166,8 @@ const Styles = theme => ({
|
|
|
167
166
|
sendIconContainer: {
|
|
168
167
|
alignSelf: "flex-end",
|
|
169
168
|
display: "flex",
|
|
170
|
-
alignItems: "center"
|
|
169
|
+
alignItems: "center",
|
|
170
|
+
gap: "6px"
|
|
171
171
|
}
|
|
172
172
|
});
|
|
173
173
|
export default Styles;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { Box } from "@mui/material";
|
|
2
|
+
import { useEffect, useRef, useState } from "react";
|
|
3
|
+
import WaveSurfer from "wavesurfer.js";
|
|
4
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
5
|
+
const SoundWave = props => {
|
|
6
|
+
const {
|
|
7
|
+
audioChunks = null
|
|
8
|
+
} = props; // Initialize to null if not provided
|
|
9
|
+
const waveContent = useRef(null);
|
|
10
|
+
const wavesurfer = useRef(null);
|
|
11
|
+
const [playOnce, setPlayOnce] = useState(false);
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
if (waveContent.current) {
|
|
14
|
+
if (wavesurfer.current) {
|
|
15
|
+
wavesurfer.current.destroy();
|
|
16
|
+
}
|
|
17
|
+
wavesurfer.current = WaveSurfer.create({
|
|
18
|
+
container: waveContent.current,
|
|
19
|
+
waveColor: "#2563EB",
|
|
20
|
+
progressColor: "#2563EB",
|
|
21
|
+
cursorWidth: 0,
|
|
22
|
+
// Disable the cursor
|
|
23
|
+
barWidth: 2,
|
|
24
|
+
barGap: 1,
|
|
25
|
+
barRadius: 2,
|
|
26
|
+
scrollParent: false,
|
|
27
|
+
// Prevent scrolling
|
|
28
|
+
height: waveContent.current.clientHeight // Set height to fit container
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// Fit the waveform to the container width
|
|
32
|
+
const resize = () => {
|
|
33
|
+
if (wavesurfer.current) {
|
|
34
|
+
const containerWidth = waveContent.current.clientWidth;
|
|
35
|
+
const duration = wavesurfer.current.getDuration();
|
|
36
|
+
if (duration > 0) {
|
|
37
|
+
const newZoom = containerWidth / duration;
|
|
38
|
+
wavesurfer.current.zoom(newZoom);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
window.addEventListener("resize", resize);
|
|
43
|
+
resize();
|
|
44
|
+
return () => {
|
|
45
|
+
window.removeEventListener("resize", resize);
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}, []);
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
if (wavesurfer.current && audioChunks) {
|
|
51
|
+
const audioBlob = new Blob(audioChunks, {
|
|
52
|
+
type: "audio/webm"
|
|
53
|
+
});
|
|
54
|
+
const recordedUrl = URL.createObjectURL(audioBlob);
|
|
55
|
+
wavesurfer.current.load(recordedUrl).then().catch(e => console.error("Error loading audio: ", e));
|
|
56
|
+
if (!playOnce) {
|
|
57
|
+
setPlayOnce(true);
|
|
58
|
+
}
|
|
59
|
+
} else if (wavesurfer.current && !audioChunks) {
|
|
60
|
+
// Clear the waveform when audioChunks is null
|
|
61
|
+
wavesurfer.current.empty();
|
|
62
|
+
}
|
|
63
|
+
}, [audioChunks, playOnce]);
|
|
64
|
+
return /*#__PURE__*/_jsx(Box, {
|
|
65
|
+
ref: waveContent,
|
|
66
|
+
style: {
|
|
67
|
+
width: "100%",
|
|
68
|
+
height: "100%",
|
|
69
|
+
overflow: "hidden"
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
};
|
|
73
|
+
export const AudioWave = SoundWave;
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { useState, useEffect, useRef, cloneElement } from "react";
|
|
2
|
+
import PropTypes from "prop-types";
|
|
3
|
+
import STTStyles from "./style";
|
|
4
|
+
import { Grid, IconButton, Box } from "@mui/material";
|
|
5
|
+
import { AudioWave } from "./AudioWave";
|
|
6
|
+
import { CloseGreyCircle, PauseRecordingIcon, TickBlueCircle } from "../../../assets/svg/AIIcons";
|
|
7
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
8
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
9
|
+
function STT(props) {
|
|
10
|
+
const {
|
|
11
|
+
otherProps,
|
|
12
|
+
onSend,
|
|
13
|
+
setIsRecording
|
|
14
|
+
} = props;
|
|
15
|
+
const {
|
|
16
|
+
services
|
|
17
|
+
} = otherProps;
|
|
18
|
+
const classes = STTStyles();
|
|
19
|
+
const [mediaRecorder, setMediaRecorder] = useState(null);
|
|
20
|
+
const [audioChunks, setAudioChunks] = useState([]);
|
|
21
|
+
const [chunkIndex, setChunkIndex] = useState(0);
|
|
22
|
+
const audioChunksRef = useRef([]);
|
|
23
|
+
const [transcription, setTranscription] = useState("");
|
|
24
|
+
const [showPause, setShowPause] = useState(true);
|
|
25
|
+
const setChunk = event => {
|
|
26
|
+
if (event.data.size > 0) {
|
|
27
|
+
setAudioChunks(prev => {
|
|
28
|
+
const updatedChunks = [...prev, event.data];
|
|
29
|
+
audioChunksRef.current = updatedChunks; // Update ref manually
|
|
30
|
+
return updatedChunks;
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
const sendChunck = async (isLast = false) => {
|
|
35
|
+
if (audioChunksRef.current.length > 0) {
|
|
36
|
+
const audioBlob = new Blob(audioChunksRef.current, {
|
|
37
|
+
type: "audio/webm"
|
|
38
|
+
});
|
|
39
|
+
const formData = new FormData();
|
|
40
|
+
formData.append("audio", audioBlob, `audio_chunk_${chunkIndex}.wav`);
|
|
41
|
+
formData.append("chunkIndex", chunkIndex); // Send chunk index to the backend
|
|
42
|
+
if (isLast) {
|
|
43
|
+
formData.append("isLastChunk", true); // Send chunk index to the backend
|
|
44
|
+
} else {
|
|
45
|
+
formData.append("isLastChunk", false);
|
|
46
|
+
setChunkIndex(prevIndex => prevIndex + 1);
|
|
47
|
+
}
|
|
48
|
+
const result = await services("speechToText", {
|
|
49
|
+
formData
|
|
50
|
+
});
|
|
51
|
+
setTranscription(result?.data || "");
|
|
52
|
+
await sendChunck();
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
const handleStopRecording = () => {
|
|
56
|
+
sendChunck(true);
|
|
57
|
+
setAudioChunks([]);
|
|
58
|
+
};
|
|
59
|
+
const startRecording = async () => {
|
|
60
|
+
setTranscription("");
|
|
61
|
+
const stream = await navigator.mediaDevices.getUserMedia({
|
|
62
|
+
audio: true
|
|
63
|
+
});
|
|
64
|
+
const recorder = new MediaRecorder(stream);
|
|
65
|
+
setMediaRecorder(recorder);
|
|
66
|
+
recorder.ondataavailable = setChunk;
|
|
67
|
+
recorder.onstop = handleStopRecording;
|
|
68
|
+
recorder.start(100);
|
|
69
|
+
setIsRecording(true);
|
|
70
|
+
setTimeout(() => {
|
|
71
|
+
sendChunck();
|
|
72
|
+
}, 2000);
|
|
73
|
+
};
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
startRecording();
|
|
76
|
+
}, []);
|
|
77
|
+
const stopRecording = () => {
|
|
78
|
+
if (mediaRecorder) {
|
|
79
|
+
mediaRecorder.stop();
|
|
80
|
+
|
|
81
|
+
// Stop all tracks to release the microphone
|
|
82
|
+
if (mediaRecorder.stream) {
|
|
83
|
+
mediaRecorder.stream.getTracks().forEach(track => track.stop());
|
|
84
|
+
}
|
|
85
|
+
setChunkIndex(0);
|
|
86
|
+
setShowPause(false);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
const sendToInfiniti = async () => {
|
|
90
|
+
setIsRecording(false);
|
|
91
|
+
await onSend("", {
|
|
92
|
+
inputValue: transcription
|
|
93
|
+
});
|
|
94
|
+
stopRecording();
|
|
95
|
+
setShowPause(true);
|
|
96
|
+
};
|
|
97
|
+
const closeRecording = () => {
|
|
98
|
+
setAudioChunks([]);
|
|
99
|
+
stopRecording();
|
|
100
|
+
setIsRecording(false);
|
|
101
|
+
setShowPause(true);
|
|
102
|
+
setTranscription("");
|
|
103
|
+
};
|
|
104
|
+
useEffect(() => {
|
|
105
|
+
audioChunksRef.current = audioChunks;
|
|
106
|
+
}, [audioChunks]);
|
|
107
|
+
const transcriptionText = typeof transcription === "string" && transcription?.replace(/\s+/g, "")?.length; // Remove all whitespace characters like \n \t
|
|
108
|
+
|
|
109
|
+
return /*#__PURE__*/_jsxs(Grid, {
|
|
110
|
+
xs: 12,
|
|
111
|
+
sx: classes.AudioVizualizerContainer,
|
|
112
|
+
children: [transcriptionText ? /*#__PURE__*/_jsx(Grid, {
|
|
113
|
+
xs: 12,
|
|
114
|
+
sx: classes.TranscriptionContainer,
|
|
115
|
+
children: /*#__PURE__*/_jsx("pre", {
|
|
116
|
+
style: {
|
|
117
|
+
whiteSpace: "pre-wrap",
|
|
118
|
+
wordWrap: "break-word",
|
|
119
|
+
fontFamily: "inherit",
|
|
120
|
+
margin: 0
|
|
121
|
+
},
|
|
122
|
+
children: transcription
|
|
123
|
+
})
|
|
124
|
+
}) : null, /*#__PURE__*/_jsxs(Grid, {
|
|
125
|
+
xs: 12,
|
|
126
|
+
sx: classes.AudioVizualizerContent,
|
|
127
|
+
children: [/*#__PURE__*/_jsx(Box, {
|
|
128
|
+
children: /*#__PURE__*/_jsx(IconButton, {
|
|
129
|
+
onClick: closeRecording,
|
|
130
|
+
children: /*#__PURE__*/_jsx(CloseGreyCircle, {})
|
|
131
|
+
})
|
|
132
|
+
}), /*#__PURE__*/_jsx(Box, {
|
|
133
|
+
sx: classes.AudioVisualiser,
|
|
134
|
+
children: /*#__PURE__*/_jsx(AudioWave, {
|
|
135
|
+
audioChunks: audioChunks
|
|
136
|
+
})
|
|
137
|
+
}), /*#__PURE__*/_jsx(Box, {
|
|
138
|
+
children: showPause ? /*#__PURE__*/_jsx(IconButton, {
|
|
139
|
+
onClick: stopRecording,
|
|
140
|
+
children: /*#__PURE__*/_jsx(PauseRecordingIcon, {})
|
|
141
|
+
}) : /*#__PURE__*/_jsx(IconButton, {
|
|
142
|
+
onClick: sendToInfiniti,
|
|
143
|
+
disabled: !transcriptionText,
|
|
144
|
+
style: !transcriptionText ? {
|
|
145
|
+
opacity: 0.5
|
|
146
|
+
} : {},
|
|
147
|
+
children: /*#__PURE__*/_jsx(TickBlueCircle, {})
|
|
148
|
+
})
|
|
149
|
+
})]
|
|
150
|
+
})]
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
const withHOC = STT => {
|
|
154
|
+
const Container = props => {
|
|
155
|
+
const classes = STTStyles();
|
|
156
|
+
const {
|
|
157
|
+
children
|
|
158
|
+
} = props;
|
|
159
|
+
const [isRecording, setIsRecording] = useState(false);
|
|
160
|
+
return /*#__PURE__*/_jsx(Grid, {
|
|
161
|
+
xs: 12,
|
|
162
|
+
children: /*#__PURE__*/_jsx(Grid, {
|
|
163
|
+
className: classes.SttContainer,
|
|
164
|
+
children: !isRecording ? /*#__PURE__*/_jsx(Grid, {
|
|
165
|
+
xs: 12,
|
|
166
|
+
children: /*#__PURE__*/cloneElement(children, {
|
|
167
|
+
startRecording: () => setIsRecording(true)
|
|
168
|
+
})
|
|
169
|
+
}) : /*#__PURE__*/_jsx(STT, {
|
|
170
|
+
...props,
|
|
171
|
+
setIsRecording: setIsRecording
|
|
172
|
+
})
|
|
173
|
+
})
|
|
174
|
+
});
|
|
175
|
+
};
|
|
176
|
+
return Container;
|
|
177
|
+
};
|
|
178
|
+
STT.defaultProps = {
|
|
179
|
+
classes: {}
|
|
180
|
+
};
|
|
181
|
+
STT.propTypes = {
|
|
182
|
+
classes: PropTypes.object
|
|
183
|
+
};
|
|
184
|
+
export const VoiceToText = withHOC(STT);
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const styles = () => ({
|
|
2
|
+
SttContainer: {
|
|
3
|
+
display: "flex",
|
|
4
|
+
width: "100%",
|
|
5
|
+
padding: "12px",
|
|
6
|
+
zIndex: 1
|
|
7
|
+
},
|
|
8
|
+
STTInput: {
|
|
9
|
+
width: "100%",
|
|
10
|
+
borderRadius: "8px",
|
|
11
|
+
"&& .MuiOutlinedInput-root .MuiOutlinedInput-notchedOutline": {
|
|
12
|
+
borderColor: "#2563EB"
|
|
13
|
+
},
|
|
14
|
+
"&& .MuiOutlinedInput-root": {
|
|
15
|
+
background: "rgba(252, 250, 255, 1)"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
AudioVizualizerContainer: {
|
|
19
|
+
width: "100%",
|
|
20
|
+
display: "flex",
|
|
21
|
+
background: "rgba(252, 250, 255, 1)",
|
|
22
|
+
borderRadius: "8px",
|
|
23
|
+
border: "1px solid #2563EB",
|
|
24
|
+
alignItems: "center",
|
|
25
|
+
flexWrap: "wrap"
|
|
26
|
+
},
|
|
27
|
+
AudioVizualizerContent: {
|
|
28
|
+
display: "flex",
|
|
29
|
+
height: "50px",
|
|
30
|
+
width: "100%"
|
|
31
|
+
},
|
|
32
|
+
AudioVisualiser: {
|
|
33
|
+
flexGrow: "1",
|
|
34
|
+
height: "100%"
|
|
35
|
+
},
|
|
36
|
+
TranscriptionContainer: {
|
|
37
|
+
padding: "12px"
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
export default styles;
|