@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.
@@ -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, upArrowEvent, downArrowEvent } from "./utils/events";
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 containerBottom = container?.getBoundingClientRect()?.bottom;
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: 200,
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: "#FCFAFF",
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: "#000",
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 classes = STTStyles();
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: "rgba(252, 250, 255, 1)"
15
+ background: theme?.palette?.editor?.aiInputBackground
16
16
  }
17
17
  },
18
18
  AudioVizualizerContainer: {
19
19
  width: "100%",
20
20
  display: "flex",
21
- background: "rgba(252, 250, 255, 1)",
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
  })]
@@ -6,7 +6,7 @@ const EmojiPicker = props => {
6
6
  const {
7
7
  onEmojiSelect,
8
8
  onClose,
9
- theme = 'dark'
9
+ theme = 'light'
10
10
  } = props;
11
11
  return /*#__PURE__*/_jsx(_Fragment, {
12
12
  children: /*#__PURE__*/_jsx(Picker, {
@@ -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
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flozy/editor",
3
- "version": "4.2.8",
3
+ "version": "4.3.0",
4
4
  "description": "An Editor for flozy app brain",
5
5
  "files": [
6
6
  "dist"