@flozy/editor 9.1.0 → 9.1.2

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.
@@ -189,6 +189,17 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
189
189
  title: serializeToText(title?.children) || "Untitled"
190
190
  };
191
191
  };
192
+ const getTitleSaveData = title => {
193
+ const val = debouncedValue.current;
194
+ const data = {
195
+ text: serializeToText(val),
196
+ title: title
197
+ };
198
+ if (customProps.onSaveTitle) {
199
+ const isTitleChanged = true;
200
+ customProps.onSaveTitle(JSON.stringify(val), data, isTitleChanged);
201
+ }
202
+ };
192
203
  const getPreviewImage = async (needBackground = false, options = {}) => {
193
204
  ReactEditor.blur(editor);
194
205
  const dom = needBackground ? editorWrapper?.current : editorWrapper?.current.getElementsByClassName("innert-editor-textbox")[0];
@@ -333,7 +344,8 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
333
344
  page_title: page_title,
334
345
  isIframe: isIframe,
335
346
  onDrawerOpen: onDrawerOpen,
336
- ICON_API: "https://assets.agenciflow.com"
347
+ ICON_API: "https://assets.agenciflow.com",
348
+ getTitleSaveData
337
349
  };
338
350
  const lineH = getBreakpointLineSpacing(lineHeight, breakpoint);
339
351
  const renderElement = useCallback(props => {
@@ -1280,8 +1280,8 @@ blockquote {
1280
1280
  }
1281
1281
  @media (max-width: 899px) {
1282
1282
  /* Qa validation required */
1283
- /* .MuiPopover-root {
1284
- z-index: 1302 !important;
1283
+ /* .MuiPopover-root {
1284
+ z-index: 1302 !important;
1285
1285
  } */
1286
1286
 
1287
1287
  canvas {
@@ -5,7 +5,7 @@ import { Box } from "@mui/material";
5
5
  import { isTextSelected } from "../../utils/helper";
6
6
  import { useEditorContext } from "../../hooks/useMouseMove";
7
7
  import SimpleTextStyle from "./style";
8
- import { getBreakpointLineSpacing } from "../../helper/theme";
8
+ // import { getBreakpointLineSpacing } from "../../helper/theme";
9
9
  import { jsx as _jsx } from "react/jsx-runtime";
10
10
  import { Fragment as _Fragment } from "react/jsx-runtime";
11
11
  import { jsxs as _jsxs } from "react/jsx-runtime";
@@ -1,10 +1,16 @@
1
- import React from "react";
1
+ import React, { useEffect, useState } from "react";
2
+ import { Editor } from "slate";
3
+ import { useSlate } from "slate-react";
4
+ import { getNodeText } from "../../utils/helper";
2
5
  import { jsx as _jsx } from "react/jsx-runtime";
3
6
  const Title = props => {
4
7
  const {
5
8
  attributes,
6
- children
9
+ children,
10
+ element,
11
+ customProps
7
12
  } = props;
13
+ useDetectExitFromTitle(element, customProps?.getTitleSaveData);
8
14
  return /*#__PURE__*/_jsx("div", {
9
15
  ...attributes,
10
16
  style: {
@@ -14,4 +20,28 @@ const Title = props => {
14
20
  children: children
15
21
  });
16
22
  };
17
- export default Title;
23
+ export default Title;
24
+ const useDetectExitFromTitle = (titleNode, onSaveTitle) => {
25
+ const editor = useSlate();
26
+ const [wasInsideTitle, setWasInsideTitle] = useState(false);
27
+ useEffect(() => {
28
+ if (!editor.selection) return;
29
+
30
+ // Get the current node where the cursor is
31
+ const [nodeEntry] = Editor.nodes(editor, {
32
+ at: editor.selection,
33
+ match: n => n.type === "title"
34
+ });
35
+ if (nodeEntry) {
36
+ setWasInsideTitle(true); // User was inside the title
37
+ } else if (wasInsideTitle) {
38
+ // User exited the title node
39
+ const text = getNodeText(titleNode) || "";
40
+ if (text?.trim() && text !== "Untitled" && onSaveTitle) {
41
+ onSaveTitle(text);
42
+ }
43
+ setWasInsideTitle(false);
44
+ }
45
+ }, [editor.selection]);
46
+ return null;
47
+ };
@@ -33,17 +33,14 @@ const TextFormat = props => {
33
33
  const [anchorEl, setAnchorEl] = useState(null);
34
34
  const [type, setType] = useState(null);
35
35
  const open = Boolean(anchorEl);
36
- const {
37
- element: pageSt
38
- } = getPageSettings(editor) || {};
36
+
37
+ // const { element: pageSt } = getPageSettings(editor) || {};
39
38
  // const pageSettingLine = pageSt?.pageProps?.lineHeight;
40
39
  const {
41
40
  fontFamilies,
42
41
  theme
43
42
  } = useEditorContext();
44
- const {
45
- activeBreakPoint
46
- } = useEditorContext();
43
+ // const { activeBreakPoint } = useEditorContext();
47
44
  // const breakpoint = activeBreakPoint === "" ? "lg" : activeBreakPoint;
48
45
  const fontWeight = allTools.find(f => f.format === "fontWeight");
49
46
  const fontStyle = allTools.filter(f => f.type === "mark" && f.format !== "strikethrough" && f.format !== "superscript" && f.format !== "subscript");
@@ -14,7 +14,6 @@ import { jsx as _jsx } from "react/jsx-runtime";
14
14
  const PopupTool = props => {
15
15
  const {
16
16
  theme,
17
- setIsTextSelected,
18
17
  customProps,
19
18
  editorWrapper
20
19
  } = props;
@@ -35,6 +34,9 @@ const PopupTool = props => {
35
34
  const [size] = useWindowResize();
36
35
  const updateAnchorEl = isScroll => {
37
36
  try {
37
+ const {
38
+ selection
39
+ } = editor;
38
40
  const isHavingSelection = selection && !Range.isCollapsed(selection);
39
41
  if (isHavingSelection && event === "end") {
40
42
  const domRange = ReactEditor.toDOMRange(editor, editor.selection);
@@ -74,29 +76,33 @@ const PopupTool = props => {
74
76
  if (!isCarouselEdit) {
75
77
  setOpen(true);
76
78
  setPopupType("textFormat");
77
- setIsTextSelected(true);
79
+ // setIsTextSelected(true);
78
80
  }
79
81
  } else if (!anchorEl) {
80
82
  setOpen(false);
81
83
  setPopupType("");
82
- setIsTextSelected(false);
84
+ // setIsTextSelected(false);
83
85
  }
84
86
  }, [event, anchorEl]);
85
87
  useEffect(() => {
88
+ console.log("Editor useEffect", selection);
86
89
  if (!selection || Range.isCollapsed(selection) || Editor.string(editor, selection) === "" || selectedElement?.enable === 1) {
87
90
  setAnchorEl(null);
88
91
  } else {
92
+ console.log("Editor updateAnchorEl", selection);
89
93
  updateAnchorEl();
90
94
  hideSlateSelection(); // removes slate selection background, when there is no selection
91
95
  }
92
96
  }, [selection, event, selectedElement?.enable]);
93
97
  const handleClose = () => {
98
+ console.log("Editor closing");
94
99
  // setAnchorEl(null);
95
100
  setOpen(false);
96
101
  setPopupType("");
97
102
  };
98
103
  return open && !openAI ? /*#__PURE__*/_jsx(ClickAwayListener, {
99
104
  onClickAway: e => {
105
+ console.log("ClickAwayListener", e.target, document.body, e.target !== document.body);
100
106
  // close the mini toolbar, if user clicks outside the editor (in Flozy app.)
101
107
  if (e.target !== document.body) {
102
108
  // e.target returns body, if the user clicks material ui select popup inside the tool bar, on that time, we don't need to close
@@ -19,7 +19,7 @@ const Upload = props => {
19
19
  xs: 12,
20
20
  sx: {
21
21
  padding: "10px",
22
- height: '100%'
22
+ height: "100%"
23
23
  },
24
24
  className: "ims-right",
25
25
  children: /*#__PURE__*/_jsx(Uploader, {
@@ -5,9 +5,9 @@ const UploadStyles = theme => ({
5
5
  borderRadius: "11px",
6
6
  boxShadow: "0px 4px 10px rgba(0, 0, 0, 0.16)",
7
7
  background: theme?.palette?.editor?.uploadFileBg,
8
- height: '100%',
9
- minHeight: '150px',
10
- height: 'inherit'
8
+ height: "100%",
9
+ minHeight: "150px",
10
+ height: "inherit"
11
11
  },
12
12
  uploadField: {
13
13
  width: "100%",
@@ -19,21 +19,21 @@ const UploadStyles = theme => ({
19
19
  backgroundColor: theme?.palette?.editor?.uploadFileInnerBg,
20
20
  borderRadius: "9px",
21
21
  border: "1px dashed #2563EB",
22
- minHeight: '150px'
22
+ minHeight: "150px"
23
23
  },
24
24
  uploadIcon: {
25
25
  display: "grid !important",
26
26
  "& svg": {
27
- display: 'flex',
28
- width: '100%',
27
+ display: "flex",
28
+ width: "100%",
29
29
  "& path": {
30
30
  stroke: "#2563EB"
31
31
  }
32
32
  },
33
- '& span': {
34
- display: 'flex',
35
- width: '100%',
36
- marginTop: '5px'
33
+ "& span": {
34
+ display: "flex",
35
+ width: "100%",
36
+ marginTop: "5px"
37
37
  }
38
38
  }
39
39
  });
@@ -58,6 +58,7 @@ const useElementSettingsStyle = theme => ({
58
58
  maxHeight: "500px",
59
59
  overflowX: "hidden",
60
60
  overflowY: "auto",
61
+ paddingLeft: "4px",
61
62
  background: theme?.palette?.editor?.background,
62
63
  paddingLeft: "4px",
63
64
  "& .MuiTypography-root, .MuiInputBase-root, input": {
@@ -1,26 +1,20 @@
1
- import { useEffect, useState } from "react";
1
+ import { useCallback, useEffect, useState } from "react";
2
2
  const useDrag = () => {
3
3
  const [event, setEvent] = useState("");
4
- useEffect(() => {
5
- addListener();
6
- return () => {
7
- removeListener();
8
- };
9
- }, []);
10
- const onMouseDown = () => {
4
+ const onMouseDown = useCallback(() => {
11
5
  setEvent("start");
12
- };
13
- const onMouseUp = () => {
6
+ }, []);
7
+ const onMouseUp = useCallback(() => {
14
8
  setEvent("end");
15
- };
16
- const addListener = () => {
9
+ }, []);
10
+ useEffect(() => {
17
11
  document.addEventListener("pointerdown", onMouseDown);
18
12
  document.addEventListener("pointerup", onMouseUp);
19
- };
20
- const removeListener = () => {
21
- document.removeEventListener("pointerdown", onMouseDown);
22
- document.removeEventListener("pointerup", onMouseUp);
23
- };
13
+ return () => {
14
+ document.removeEventListener("pointerdown", onMouseDown);
15
+ document.removeEventListener("pointerup", onMouseUp);
16
+ };
17
+ }, []);
24
18
  return [event];
25
19
  };
26
20
  export default useDrag;
@@ -4,6 +4,7 @@ function useEditorScroll(editorWrapper = {
4
4
  }, callback) {
5
5
  useEffect(() => {
6
6
  const handleScroll = () => {
7
+ console.log("Editor debug useEditorScroll ====>", editorWrapper, callback);
7
8
  if (editorWrapper.current) {
8
9
  callback("scroll");
9
10
  }
@@ -100,6 +100,14 @@ export const getSelectedText = editor => {
100
100
  return "";
101
101
  }
102
102
  };
103
+ export const getNodeText = node => {
104
+ try {
105
+ return Node.string(node);
106
+ } catch (err) {
107
+ console.log(err);
108
+ return "";
109
+ }
110
+ };
103
111
  export const isEmptyNode = (editor, children, path) => {
104
112
  try {
105
113
  const isEmptyText = Node.string(Node.get(editor, path))?.length === 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flozy/editor",
3
- "version": "9.1.0",
3
+ "version": "9.1.2",
4
4
  "description": "An Editor for flozy app brain",
5
5
  "files": [
6
6
  "dist"
@@ -61,7 +61,7 @@
61
61
  "scripts": {
62
62
  "prepare": "husky install .husky",
63
63
  "analyze": "source-map-explorer build/static/js/*.js",
64
- "lint": "./node_modules/.bin/eslint --ignore-path .gitignore .",
64
+ "lint": "./node_modules/. bin/eslint --ignore-path .gitignore .",
65
65
  "start": "craco start",
66
66
  "build": "NODE_OPTIONS='--max_old_space_size=4096' craco build",
67
67
  "test": "craco test --passWithNoTests",