@flozy/editor 4.2.8 → 4.3.0
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/Editor/CommonEditor.js +10 -9
- package/dist/Editor/Elements/AI/PopoverAIInput.js +10 -4
- package/dist/Editor/Elements/AI/Styles.js +4 -2
- package/dist/Editor/Elements/AI/VoiceToText/index.js +7 -1
- package/dist/Editor/Elements/AI/VoiceToText/style.js +12 -4
- package/dist/Editor/Elements/Emoji/EmojiButton.js +4 -2
- package/dist/Editor/Elements/Emoji/EmojiPicker.js +1 -1
- package/dist/Editor/Elements/FreeGrid/Options/sectionItemOptions.js +3 -1
- package/dist/Editor/Elements/Variables/VariableButton.js +7 -1
- package/dist/Editor/Toolbar/PopupTool/index.js +29 -26
- package/dist/Editor/assets/svg/AIIcons.js +4 -0
- package/dist/Editor/common/MentionsPopup/index.js +2 -1
- package/dist/Editor/helper/index.js +6 -3
- package/dist/Editor/hooks/useEditorScroll.js +24 -0
- package/dist/Editor/utils/events.js +0 -36
- package/package.json +1 -1
@@ -10,7 +10,7 @@ import { draftToSlate } from "./utils/draftToSlate";
|
|
10
10
|
import useMentions from "./hooks/useMentions";
|
11
11
|
import MentionsPopup from "./common/MentionsPopup";
|
12
12
|
import { RemoteCursorOverlay } from "./RemoteCursorOverlay/Overlay";
|
13
|
-
import { mentionsEvent, commands, indentation, escapeEvent, enterEvent
|
13
|
+
import { mentionsEvent, commands, indentation, escapeEvent, enterEvent } from "./utils/events";
|
14
14
|
import withCommon from "./hooks/withCommon";
|
15
15
|
import DialogWrapper from "./DialogWrapper";
|
16
16
|
import { serializeToText } from "./utils/serializeToText";
|
@@ -379,10 +379,6 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
|
|
379
379
|
});
|
380
380
|
}
|
381
381
|
}
|
382
|
-
} else if (event.key === "ArrowUp" && otherProps?.tagName !== "Pages") {
|
383
|
-
upArrowEvent(event, editor);
|
384
|
-
} else if (event.key === "ArrowDown" && otherProps?.tagName !== "Pages") {
|
385
|
-
downArrowEvent(event, editor);
|
386
382
|
}
|
387
383
|
}, [chars, editor, target, mentions, setMentions, search, type, mentionsRef]);
|
388
384
|
const Overlay = collaborativeEditor && !isReadOnly ? RemoteCursorOverlay : React.Fragment;
|
@@ -447,10 +443,13 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
|
|
447
443
|
const selection = window?.getSelection();
|
448
444
|
if (selection && selection.rangeCount > 0) {
|
449
445
|
const cursorPosition = selection.getRangeAt(0)?.getBoundingClientRect();
|
450
|
-
const
|
446
|
+
const containerRect = container?.getBoundingClientRect();
|
447
|
+
const containerBottom = containerRect?.bottom;
|
451
448
|
if (cursorPosition && cursorPosition.bottom > containerBottom - 250) {
|
449
|
+
// Calculate dynamic scroll based on remaining space
|
450
|
+
const scrollAmount = Math.min(200, cursorPosition.bottom - containerBottom + 250);
|
452
451
|
container?.scrollBy({
|
453
|
-
top:
|
452
|
+
top: scrollAmount,
|
454
453
|
behavior: "smooth"
|
455
454
|
});
|
456
455
|
}
|
@@ -545,7 +544,8 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
|
|
545
544
|
customProps: customProps,
|
546
545
|
theme: theme
|
547
546
|
}) : null, /*#__PURE__*/_jsx(PopoverAIInput, {
|
548
|
-
otherProps: otherProps || {}
|
547
|
+
otherProps: otherProps || {},
|
548
|
+
editorWrapper: editorWrapper
|
549
549
|
}), footer && (fullScreen || readOnly) && /*#__PURE__*/_jsx(Typography, {
|
550
550
|
sx: {
|
551
551
|
color: "rgb(100, 116, 139)",
|
@@ -563,7 +563,8 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
|
|
563
563
|
onDrawerOpen: onDrawerOpen,
|
564
564
|
theme: theme,
|
565
565
|
setIsTextSelected: setIsTextSelected,
|
566
|
-
customProps: customProps
|
566
|
+
customProps: customProps,
|
567
|
+
editorWrapper: editorWrapper
|
567
568
|
}) : null, !readOnly && showViewport ? /*#__PURE__*/_jsx(SwitchViewport, {
|
568
569
|
breakpoint: breakpoint,
|
569
570
|
onChange: b => onSwitchBreakpoint(b)
|
@@ -9,6 +9,7 @@ import { MODES } from "./helper";
|
|
9
9
|
import { getSelectedText } from "../../utils/helper";
|
10
10
|
import { VoiceToText } from "./VoiceToText";
|
11
11
|
import deserialize from "../../helper/deserialize";
|
12
|
+
import useEditorScroll from "../../hooks/useEditorScroll";
|
12
13
|
import { jsx as _jsx } from "react/jsx-runtime";
|
13
14
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
14
15
|
const getInputWidth = selectedElement => {
|
@@ -154,7 +155,10 @@ const updateAnchorEl = (setAnchorEl, editor, openAI, selectedElement) => {
|
|
154
155
|
}
|
155
156
|
};
|
156
157
|
function PopoverAIInput({
|
157
|
-
otherProps
|
158
|
+
otherProps,
|
159
|
+
editorWrapper = {
|
160
|
+
current: null
|
161
|
+
}
|
158
162
|
}) {
|
159
163
|
const {
|
160
164
|
services
|
@@ -171,6 +175,10 @@ function PopoverAIInput({
|
|
171
175
|
const [selectedOption, setSelectedOption] = useState();
|
172
176
|
const classes = Styles();
|
173
177
|
const editor = useSlate();
|
178
|
+
const updateAnchor = () => {
|
179
|
+
updateAnchorEl(setAnchorEl, editor, openAI, selectedElement);
|
180
|
+
};
|
181
|
+
useEditorScroll(editorWrapper, updateAnchor);
|
174
182
|
const onClickOutside = () => {
|
175
183
|
setAnchorEl(null);
|
176
184
|
setOpenAI("");
|
@@ -181,9 +189,7 @@ function PopoverAIInput({
|
|
181
189
|
ReactEditor.focus(editor);
|
182
190
|
Transforms.deselect(editor);
|
183
191
|
};
|
184
|
-
useEffect(
|
185
|
-
updateAnchorEl(setAnchorEl, editor, openAI, selectedElement);
|
186
|
-
}, [openAI, editor.selection]);
|
192
|
+
useEffect(updateAnchor, [openAI, editor.selection]);
|
187
193
|
useEffect(() => {
|
188
194
|
if (openAI) {
|
189
195
|
scrollToAIInput(editor);
|
@@ -1,6 +1,7 @@
|
|
1
1
|
const Styles = theme => ({
|
2
2
|
aiContainer: {
|
3
3
|
background: "#FCFAFF",
|
4
|
+
background: theme?.palette?.editor?.aiInputBackground,
|
4
5
|
border: "1px solid #8360FD",
|
5
6
|
borderRadius: "6px",
|
6
7
|
boxShadow: "0px 4px 10px 0px #00000029"
|
@@ -12,7 +13,7 @@ const Styles = theme => ({
|
|
12
13
|
padding: "0px 4px 0px 12px",
|
13
14
|
minHeight: "36px",
|
14
15
|
position: "relative",
|
15
|
-
background:
|
16
|
+
background: theme?.palette?.editor?.aiInputBackground,
|
16
17
|
borderRadius: "5px",
|
17
18
|
"& .icon-container": {
|
18
19
|
display: "flex",
|
@@ -29,7 +30,7 @@ const Styles = theme => ({
|
|
29
30
|
background: "transparent",
|
30
31
|
resize: "none",
|
31
32
|
alignSelf: "center",
|
32
|
-
color:
|
33
|
+
color: theme?.palette?.editor?.textColor,
|
33
34
|
fontSize: "14px !important",
|
34
35
|
fontFamily: '"Inter", sans-serif',
|
35
36
|
"&:focus-visible": {
|
@@ -81,6 +82,7 @@ const Styles = theme => ({
|
|
81
82
|
},
|
82
83
|
sendBtnDisabled: {
|
83
84
|
background: "#C0C9D6",
|
85
|
+
opacity: "0.5",
|
84
86
|
"&:hover": {
|
85
87
|
background: "#C0C9D6"
|
86
88
|
}
|
@@ -4,6 +4,7 @@ import STTStyles from "./style";
|
|
4
4
|
import { Grid, IconButton, Box } from "@mui/material";
|
5
5
|
import { AudioWave } from "./AudioWave";
|
6
6
|
import { CloseGreyCircle, PauseRecordingIcon, TickBlueCircle } from "../../../assets/svg/AIIcons";
|
7
|
+
import { useEditorContext } from "../../../hooks/useMouseMove";
|
7
8
|
import { jsx as _jsx } from "react/jsx-runtime";
|
8
9
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
9
10
|
function STT(props) {
|
@@ -15,7 +16,10 @@ function STT(props) {
|
|
15
16
|
const {
|
16
17
|
services
|
17
18
|
} = otherProps;
|
18
|
-
const
|
19
|
+
const {
|
20
|
+
theme
|
21
|
+
} = useEditorContext();
|
22
|
+
const classes = STTStyles(theme);
|
19
23
|
const [mediaRecorder, setMediaRecorder] = useState(null);
|
20
24
|
const [audioChunks, setAudioChunks] = useState([]);
|
21
25
|
const [chunkIndex, setChunkIndex] = useState(0);
|
@@ -127,6 +131,7 @@ function STT(props) {
|
|
127
131
|
children: [/*#__PURE__*/_jsx(Box, {
|
128
132
|
children: /*#__PURE__*/_jsx(IconButton, {
|
129
133
|
onClick: closeRecording,
|
134
|
+
className: "ai-icon",
|
130
135
|
children: /*#__PURE__*/_jsx(CloseGreyCircle, {})
|
131
136
|
})
|
132
137
|
}), /*#__PURE__*/_jsx(Box, {
|
@@ -137,6 +142,7 @@ function STT(props) {
|
|
137
142
|
}), /*#__PURE__*/_jsx(Box, {
|
138
143
|
children: showPause ? /*#__PURE__*/_jsx(IconButton, {
|
139
144
|
onClick: stopRecording,
|
145
|
+
className: "ai-icon",
|
140
146
|
children: /*#__PURE__*/_jsx(PauseRecordingIcon, {})
|
141
147
|
}) : /*#__PURE__*/_jsx(IconButton, {
|
142
148
|
onClick: sendToInfiniti,
|
@@ -1,4 +1,4 @@
|
|
1
|
-
const styles =
|
1
|
+
const styles = theme => ({
|
2
2
|
SttContainer: {
|
3
3
|
display: "flex",
|
4
4
|
width: "100%",
|
@@ -12,17 +12,25 @@ const styles = () => ({
|
|
12
12
|
borderColor: "#2563EB"
|
13
13
|
},
|
14
14
|
"&& .MuiOutlinedInput-root": {
|
15
|
-
background:
|
15
|
+
background: theme?.palette?.editor?.aiInputBackground
|
16
16
|
}
|
17
17
|
},
|
18
18
|
AudioVizualizerContainer: {
|
19
19
|
width: "100%",
|
20
20
|
display: "flex",
|
21
|
-
background:
|
21
|
+
background: theme?.palette?.editor?.aiInputBackground,
|
22
22
|
borderRadius: "8px",
|
23
23
|
border: "1px solid #2563EB",
|
24
24
|
alignItems: "center",
|
25
|
-
flexWrap: "wrap"
|
25
|
+
flexWrap: "wrap",
|
26
|
+
"& .ai-icon": {
|
27
|
+
"& circle": {
|
28
|
+
fill: theme?.palette?.editor?.aiInputBackground
|
29
|
+
},
|
30
|
+
"& rect": {
|
31
|
+
fill: theme?.palette?.editor?.aiInputBackground
|
32
|
+
}
|
33
|
+
}
|
26
34
|
},
|
27
35
|
AudioVizualizerContent: {
|
28
36
|
display: "flex",
|
@@ -12,7 +12,8 @@ import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
12
12
|
const EmojiButton = /*#__PURE__*/forwardRef((props, ref) => {
|
13
13
|
const {
|
14
14
|
icoBtnType,
|
15
|
-
selectionTarget
|
15
|
+
selectionTarget,
|
16
|
+
theme = 'light'
|
16
17
|
} = props;
|
17
18
|
const editor = useSlateStatic();
|
18
19
|
const [anchorEl, setAnchorEl] = useState(null);
|
@@ -67,7 +68,8 @@ const EmojiButton = /*#__PURE__*/forwardRef((props, ref) => {
|
|
67
68
|
children: /*#__PURE__*/_jsx(Paper, {
|
68
69
|
children: /*#__PURE__*/_jsx(EmojiPicker, {
|
69
70
|
data: data,
|
70
|
-
onEmojiSelect: onEmojiSelect
|
71
|
+
onEmojiSelect: onEmojiSelect,
|
72
|
+
theme: theme?.palette?.type
|
71
73
|
})
|
72
74
|
})
|
73
75
|
})]
|
@@ -2,6 +2,7 @@ const commonOptions = ["drag", "edit", "settings", "saveAsTemplate", "close"];
|
|
2
2
|
const textOptions = ["edit", "settings", "link", "saveAsTemplate", "close"];
|
3
3
|
const buttonOptions = ["settings", "link", "saveAsTemplate", "close"];
|
4
4
|
const imageOptions = ["settings", "link", "imageFrame", "saveAsTemplate", "close"];
|
5
|
+
const videoOptions = ["settings", "saveAsTemplate", "close"];
|
5
6
|
const boxOptions = ["settings", "link", "saveAsTemplate", "close"];
|
6
7
|
const appHeaderOptions = ["settings", "saveAsTemplate", "close"];
|
7
8
|
const tableOptions = ["drag", "edit", "settings", "saveAsTemplate", "close"];
|
@@ -18,6 +19,7 @@ const itemOptions = {
|
|
18
19
|
form: formOptions,
|
19
20
|
section: sectionOptions,
|
20
21
|
table: tableOptions,
|
21
|
-
embedScript: embedScriptOptions
|
22
|
+
embedScript: embedScriptOptions,
|
23
|
+
video: videoOptions
|
22
24
|
};
|
23
25
|
export default itemOptions;
|
@@ -26,7 +26,13 @@ const VariableButton = props => {
|
|
26
26
|
onChange: updateVariable,
|
27
27
|
IconComponent: () => /*#__PURE__*/_jsx(KeyboardArrowDownIcon, {}),
|
28
28
|
MenuProps: {
|
29
|
-
sx: classes.variableMenuItem
|
29
|
+
sx: classes.variableMenuItem,
|
30
|
+
PaperProps: {
|
31
|
+
style: {
|
32
|
+
maxHeight: 300,
|
33
|
+
overflowY: "auto"
|
34
|
+
}
|
35
|
+
}
|
30
36
|
},
|
31
37
|
children: [/*#__PURE__*/_jsx(MenuItem, {
|
32
38
|
value: "",
|
@@ -8,12 +8,14 @@ import useWindowResize from "../../hooks/useWindowResize";
|
|
8
8
|
import MiniTextFormat from "./MiniTextFormat";
|
9
9
|
import { useEditorContext } from "../../hooks/useMouseMove";
|
10
10
|
import usePopupStyles from "../PopupTool/PopupToolStyle";
|
11
|
+
import useEditorScroll from "../../hooks/useEditorScroll";
|
11
12
|
import { jsx as _jsx } from "react/jsx-runtime";
|
12
13
|
const PopupTool = props => {
|
13
14
|
const {
|
14
15
|
theme,
|
15
16
|
setIsTextSelected,
|
16
|
-
customProps
|
17
|
+
customProps,
|
18
|
+
editorWrapper
|
17
19
|
} = props;
|
18
20
|
const classes = usePopupStyles(theme);
|
19
21
|
const {
|
@@ -33,6 +35,27 @@ const PopupTool = props => {
|
|
33
35
|
const {
|
34
36
|
selectedElement
|
35
37
|
} = useEditorContext();
|
38
|
+
const updateAnchorEl = () => {
|
39
|
+
try {
|
40
|
+
const domSelection = window.getSelection();
|
41
|
+
const domRange = domSelection?.getRangeAt(0);
|
42
|
+
const {
|
43
|
+
startOffset,
|
44
|
+
endOffset
|
45
|
+
} = domRange || {};
|
46
|
+
if (startOffset !== endOffset) {
|
47
|
+
const rect = domRange.getBoundingClientRect();
|
48
|
+
setAnchorEl({
|
49
|
+
clientWidth: rect.width,
|
50
|
+
clientHeight: rect.height,
|
51
|
+
getBoundingClientRect: () => rect
|
52
|
+
});
|
53
|
+
}
|
54
|
+
} catch (err) {
|
55
|
+
console.log(err);
|
56
|
+
}
|
57
|
+
};
|
58
|
+
useEditorScroll(editorWrapper, updateAnchorEl);
|
36
59
|
useEffect(() => {
|
37
60
|
const userStoppedSelection = size?.device === "xs" ? true : event === "end"; // for mobile, when user starts the selection, we are gonna show the popup tool
|
38
61
|
|
@@ -57,36 +80,16 @@ const PopupTool = props => {
|
|
57
80
|
updateAnchorEl();
|
58
81
|
}
|
59
82
|
}, [selection]);
|
60
|
-
useEffect(() => {
|
61
|
-
if (selectedElement?.enable === 1) {
|
62
|
-
setAnchorEl(null);
|
63
|
-
}
|
64
|
-
}, [selection, selectedElement?.path, selectedElement?.enable]);
|
65
|
-
const updateAnchorEl = () => {
|
66
|
-
try {
|
67
|
-
const domSelection = window.getSelection();
|
68
|
-
const domRange = domSelection?.getRangeAt(0);
|
69
|
-
const {
|
70
|
-
startOffset,
|
71
|
-
endOffset
|
72
|
-
} = domRange || {};
|
73
|
-
if (startOffset !== endOffset) {
|
74
|
-
const rect = domRange.getBoundingClientRect();
|
75
|
-
setAnchorEl({
|
76
|
-
clientWidth: rect.width,
|
77
|
-
clientHeight: rect.height,
|
78
|
-
getBoundingClientRect: () => rect
|
79
|
-
});
|
80
|
-
}
|
81
|
-
} catch (err) {
|
82
|
-
console.log(err);
|
83
|
-
}
|
84
|
-
};
|
85
83
|
const handleClose = () => {
|
86
84
|
setAnchorEl(null);
|
87
85
|
setOpen(false);
|
88
86
|
setPopupType("");
|
89
87
|
};
|
88
|
+
useEffect(() => {
|
89
|
+
if (selectedElement?.enable === 1) {
|
90
|
+
setAnchorEl(null);
|
91
|
+
}
|
92
|
+
}, [selection, selectedElement?.path, selectedElement?.enable]);
|
90
93
|
return open && !openAI ? /*#__PURE__*/_jsx(ClickAwayListener, {
|
91
94
|
onClickAway: e => {
|
92
95
|
// close the mini toolbar, if user clicks outside the editor (in Flozy app.)
|
@@ -503,6 +503,10 @@ export const CloseGreyCircle = () => /*#__PURE__*/_jsxs("svg", {
|
|
503
503
|
viewBox: "0 0 30 30",
|
504
504
|
fill: "none",
|
505
505
|
xmlns: "http://www.w3.org/2000/svg",
|
506
|
+
style: {
|
507
|
+
border: "1.3px solid #2563EB",
|
508
|
+
borderRadius: "50%"
|
509
|
+
},
|
506
510
|
children: [/*#__PURE__*/_jsx("rect", {
|
507
511
|
width: "30",
|
508
512
|
height: "30",
|
@@ -87,7 +87,8 @@ const MentionsPopup = /*#__PURE__*/forwardRef((props, ref) => {
|
|
87
87
|
ref: i === index ? papperRef : null,
|
88
88
|
children: char.renderComponent ? char.renderComponent({
|
89
89
|
ref: index === i ? buttonRef : null,
|
90
|
-
selectionTarget: target
|
90
|
+
selectionTarget: target,
|
91
|
+
theme: theme
|
91
92
|
}) : ListElement ? /*#__PURE__*/_jsx(ListElement, {
|
92
93
|
classes: classes,
|
93
94
|
data: char,
|
@@ -299,9 +299,12 @@ export const getTextColor = (color = "") => {
|
|
299
299
|
return color?.indexOf("gradient") >= 0 ? {
|
300
300
|
background: color?.concat("text"),
|
301
301
|
WebkitBackgroundClip: "text",
|
302
|
-
WebkitTextFillColor: "transparent",
|
303
|
-
color: "transparent",
|
304
|
-
caretColor: "black"
|
302
|
+
WebkitTextFillColor: "transparent !important",
|
303
|
+
color: "transparent !important",
|
304
|
+
caretColor: "black",
|
305
|
+
'& span': {
|
306
|
+
color: "transparent !important"
|
307
|
+
}
|
305
308
|
} : {
|
306
309
|
color
|
307
310
|
};
|
@@ -0,0 +1,24 @@
|
|
1
|
+
import { useEffect } from "react";
|
2
|
+
function useEditorScroll(editorWrapper = {
|
3
|
+
current: null
|
4
|
+
}, callback) {
|
5
|
+
useEffect(() => {
|
6
|
+
const handleScroll = () => {
|
7
|
+
if (editorWrapper.current) {
|
8
|
+
callback();
|
9
|
+
}
|
10
|
+
};
|
11
|
+
const currentEditorWrapper = editorWrapper.current;
|
12
|
+
if (currentEditorWrapper) {
|
13
|
+
currentEditorWrapper.addEventListener("scroll", handleScroll);
|
14
|
+
}
|
15
|
+
|
16
|
+
// Cleanup the event listener on component unmount
|
17
|
+
return () => {
|
18
|
+
if (currentEditorWrapper) {
|
19
|
+
currentEditorWrapper.removeEventListener("scroll", handleScroll);
|
20
|
+
}
|
21
|
+
};
|
22
|
+
}, [editorWrapper.current]);
|
23
|
+
}
|
24
|
+
export default useEditorScroll;
|
@@ -285,40 +285,4 @@ export const enterEvent = (e, editor, isMobile) => {
|
|
285
285
|
} catch (err) {
|
286
286
|
console.log(err);
|
287
287
|
}
|
288
|
-
};
|
289
|
-
export const upArrowEvent = (e, editor) => {
|
290
|
-
try {
|
291
|
-
const {
|
292
|
-
selection
|
293
|
-
} = editor;
|
294
|
-
if (!selection) return;
|
295
|
-
const prevNodePath = Editor.before(editor, selection, {
|
296
|
-
unit: "line"
|
297
|
-
});
|
298
|
-
if (prevNodePath) {
|
299
|
-
e.preventDefault();
|
300
|
-
Transforms.select(editor, prevNodePath);
|
301
|
-
ReactEditor.focus(editor);
|
302
|
-
}
|
303
|
-
} catch (err) {
|
304
|
-
console.log(err);
|
305
|
-
}
|
306
|
-
};
|
307
|
-
export const downArrowEvent = (e, editor) => {
|
308
|
-
try {
|
309
|
-
const {
|
310
|
-
selection
|
311
|
-
} = editor;
|
312
|
-
if (!selection) return;
|
313
|
-
const nextNodePath = Editor.after(editor, selection, {
|
314
|
-
unit: "line"
|
315
|
-
});
|
316
|
-
if (nextNodePath) {
|
317
|
-
e.preventDefault();
|
318
|
-
Transforms.select(editor, nextNodePath);
|
319
|
-
ReactEditor.focus(editor);
|
320
|
-
}
|
321
|
-
} catch (err) {
|
322
|
-
console.log(err);
|
323
|
-
}
|
324
288
|
};
|