@flozy/editor 4.1.9 → 4.2.1
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/ChatEditor.js +2 -1
- package/dist/Editor/Elements/FreeGrid/FreeGrid.js +3 -2
- package/dist/Editor/Elements/FreeGrid/FreeGridBox.js +3 -2
- package/dist/Editor/Elements/FreeGrid/Options/AddElement.js +53 -39
- package/dist/Editor/Elements/FreeGrid/Options/SectionSettings.js +3 -2
- package/dist/Editor/Styles/EditorStyles.js +1 -0
- package/dist/Editor/common/RnD/OptionsPopup/style.js +4 -1
- package/dist/Editor/common/RnD/VirtualElement/index.js +64 -4
- package/dist/Editor/common/RnD/VirtualElement/styles.js +1 -0
- package/dist/Editor/common/RnD/VirtualElement/updateAutoProps.js +2 -1
- package/dist/Editor/hooks/useMentions.js +39 -13
- package/dist/Editor/hooks/withCommon.js +7 -2
- package/dist/Editor/plugins/withHTML.js +3 -0
- package/dist/Editor/utils/chatEditor/SlateUtilityFunctions.js +1 -1
- package/package.json +1 -1
|
@@ -46,7 +46,8 @@ const ChatEditor = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
46
46
|
const [deboundedValue] = useDebounce(value, 500);
|
|
47
47
|
const editor = useMemo(() => {
|
|
48
48
|
return withCommon(createEditor(), {
|
|
49
|
-
needLayout
|
|
49
|
+
needLayout,
|
|
50
|
+
isChatEditor: true
|
|
50
51
|
});
|
|
51
52
|
}, []);
|
|
52
53
|
const isReadOnly = readOnly === "readonly";
|
|
@@ -449,7 +449,8 @@ const FreeGrid = props => {
|
|
|
449
449
|
props: {
|
|
450
450
|
editor,
|
|
451
451
|
path,
|
|
452
|
-
classes
|
|
452
|
+
classes,
|
|
453
|
+
customProps
|
|
453
454
|
}
|
|
454
455
|
}
|
|
455
456
|
},
|
|
@@ -471,7 +472,7 @@ const FreeGrid = props => {
|
|
|
471
472
|
"--cols": `100%`,
|
|
472
473
|
"--rows": `repeat(${repeatTimes}, ${ROW_HEIGHT}px)`,
|
|
473
474
|
background: sectionBgColor,
|
|
474
|
-
backgroundImage: `url('${sectionBackgroundImage}')
|
|
475
|
+
backgroundImage: sectionBackgroundImage ? `url('${sectionBackgroundImage}')` : "",
|
|
475
476
|
backgroundSize: "cover"
|
|
476
477
|
},
|
|
477
478
|
children: [children, !readOnly ? /*#__PURE__*/_jsx("span", {
|
|
@@ -200,10 +200,11 @@ const FreeGridBox = props => {
|
|
|
200
200
|
...getBreakPointsValue(sectionBorderRadius || {}, null, "overrideBorderRadius", true)
|
|
201
201
|
},
|
|
202
202
|
background: sectionBgColor,
|
|
203
|
-
backgroundImage: `url(${sectionBackgroundImage})
|
|
203
|
+
backgroundImage: sectionBackgroundImage ? `url('${sectionBackgroundImage}')` : "",
|
|
204
204
|
borderColor: borderColor || "transparent",
|
|
205
205
|
borderWidth: borderWidth || "1px",
|
|
206
|
-
borderStyle: borderStyle || "solid"
|
|
206
|
+
borderStyle: borderStyle || "solid",
|
|
207
|
+
backgroundSize: "cover"
|
|
207
208
|
},
|
|
208
209
|
children: children
|
|
209
210
|
})
|
|
@@ -1,51 +1,65 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { Box, List, ListItemButton } from "@mui/material";
|
|
2
|
+
import { Box, List, ListItemButton, ListItemIcon, ListItemText } from "@mui/material";
|
|
3
|
+
import Icon from "../../../common/Icon";
|
|
3
4
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
4
5
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
6
|
+
const FREE_GRID_ELEMENTS = [{
|
|
7
|
+
actionType: "addText",
|
|
8
|
+
label: "Text",
|
|
9
|
+
icon: "text"
|
|
10
|
+
}, {
|
|
11
|
+
actionType: "addButton",
|
|
12
|
+
label: "Button",
|
|
13
|
+
icon: "button"
|
|
14
|
+
}, {
|
|
15
|
+
actionType: "addImage",
|
|
16
|
+
label: "Image",
|
|
17
|
+
icon: "image"
|
|
18
|
+
}, {
|
|
19
|
+
actionType: "addVideo",
|
|
20
|
+
label: "Embed or Video",
|
|
21
|
+
icon: "embed"
|
|
22
|
+
}, {
|
|
23
|
+
actionType: "addBox",
|
|
24
|
+
label: "Box",
|
|
25
|
+
icon: "colorbox"
|
|
26
|
+
}, {
|
|
27
|
+
actionType: "addTable",
|
|
28
|
+
label: "Table",
|
|
29
|
+
icon: "table"
|
|
30
|
+
}, {
|
|
31
|
+
actionType: "addCode",
|
|
32
|
+
label: "Code",
|
|
33
|
+
icon: "embedScript"
|
|
34
|
+
}, {
|
|
35
|
+
actionType: "addForm",
|
|
36
|
+
label: "Form",
|
|
37
|
+
icon: "form"
|
|
38
|
+
}, {
|
|
39
|
+
actionType: "addAppHeader",
|
|
40
|
+
label: "App Header",
|
|
41
|
+
icon: "appHeader"
|
|
42
|
+
}];
|
|
5
43
|
const AddElement = props => {
|
|
6
44
|
const {
|
|
7
45
|
handleClick
|
|
8
46
|
} = props;
|
|
9
47
|
return /*#__PURE__*/_jsx(Box, {
|
|
10
|
-
children: /*#__PURE__*/
|
|
48
|
+
children: /*#__PURE__*/_jsx(List, {
|
|
11
49
|
className: "item-list-wrpr",
|
|
12
|
-
children:
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
})
|
|
25
|
-
className: "item-wrapper",
|
|
26
|
-
onClick: handleClick("addVideo"),
|
|
27
|
-
children: "Embed or Video"
|
|
28
|
-
}), /*#__PURE__*/_jsx(ListItemButton, {
|
|
29
|
-
className: "item-wrapper",
|
|
30
|
-
onClick: handleClick("addTable"),
|
|
31
|
-
children: "Table"
|
|
32
|
-
}), /*#__PURE__*/_jsx(ListItemButton, {
|
|
33
|
-
className: "item-wrapper",
|
|
34
|
-
onClick: handleClick("addCode"),
|
|
35
|
-
children: "Code"
|
|
36
|
-
}), /*#__PURE__*/_jsx(ListItemButton, {
|
|
37
|
-
className: "item-wrapper",
|
|
38
|
-
onClick: handleClick("addBox"),
|
|
39
|
-
children: "Box"
|
|
40
|
-
}), /*#__PURE__*/_jsx(ListItemButton, {
|
|
41
|
-
className: "item-wrapper",
|
|
42
|
-
onClick: handleClick("addForm"),
|
|
43
|
-
children: "Form"
|
|
44
|
-
}), /*#__PURE__*/_jsx(ListItemButton, {
|
|
45
|
-
className: "item-wrapper",
|
|
46
|
-
onClick: handleClick("addAppHeader"),
|
|
47
|
-
children: "App Header"
|
|
48
|
-
})]
|
|
50
|
+
children: FREE_GRID_ELEMENTS.map(m => {
|
|
51
|
+
return /*#__PURE__*/_jsxs(ListItemButton, {
|
|
52
|
+
className: "item-wrapper",
|
|
53
|
+
onClick: handleClick(m.actionType),
|
|
54
|
+
children: [/*#__PURE__*/_jsx(ListItemIcon, {
|
|
55
|
+
children: /*#__PURE__*/_jsx(Icon, {
|
|
56
|
+
icon: m.icon
|
|
57
|
+
})
|
|
58
|
+
}), /*#__PURE__*/_jsx(ListItemText, {
|
|
59
|
+
children: m.label
|
|
60
|
+
})]
|
|
61
|
+
}, m.actionType);
|
|
62
|
+
})
|
|
49
63
|
})
|
|
50
64
|
});
|
|
51
65
|
};
|
|
@@ -8,7 +8,8 @@ const SectionSettings = props => {
|
|
|
8
8
|
const {
|
|
9
9
|
editor,
|
|
10
10
|
path,
|
|
11
|
-
classes
|
|
11
|
+
classes,
|
|
12
|
+
customProps
|
|
12
13
|
} = props;
|
|
13
14
|
const element = Node.get(editor, path);
|
|
14
15
|
const styleMaps = sectionStyle?.filter(f => !f?.hideOnFGS);
|
|
@@ -38,7 +39,7 @@ const SectionSettings = props => {
|
|
|
38
39
|
value: m.value,
|
|
39
40
|
element: element,
|
|
40
41
|
onChange: onChange,
|
|
41
|
-
customProps:
|
|
42
|
+
customProps: customProps,
|
|
42
43
|
handleClose: handleClose
|
|
43
44
|
}, `tab_${m.value}_$${i}`);
|
|
44
45
|
})
|
|
@@ -25,8 +25,11 @@ const useOptionsPopupStyle = () => ({
|
|
|
25
25
|
}
|
|
26
26
|
},
|
|
27
27
|
"& .item-wrapper": {
|
|
28
|
-
padding: "
|
|
28
|
+
padding: "8px",
|
|
29
29
|
fontFamily: "sans-serif",
|
|
30
|
+
"& .MuiListItemIcon-root": {
|
|
31
|
+
minWidth: "30px"
|
|
32
|
+
},
|
|
30
33
|
"&.title": {
|
|
31
34
|
display: "flex",
|
|
32
35
|
fontWeight: "bold",
|
|
@@ -5,6 +5,64 @@ import updateAutoProps from "./updateAutoProps";
|
|
|
5
5
|
import { calculateGridArea } from "../Utils/gridDropItem";
|
|
6
6
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
7
7
|
const ROOT_ITEM_CLASS = ".freegrid-item.path-3";
|
|
8
|
+
|
|
9
|
+
// Function to group items by path and calculate heights
|
|
10
|
+
function groupByPathAndCalculateHeight(data) {
|
|
11
|
+
const root = {};
|
|
12
|
+
const heightData = {};
|
|
13
|
+
|
|
14
|
+
// Step 1: Group items based on their path
|
|
15
|
+
data.forEach(item => {
|
|
16
|
+
const segments = item.path.split("|");
|
|
17
|
+
let current = root;
|
|
18
|
+
segments.forEach((segment, index) => {
|
|
19
|
+
if (!current[segment]) {
|
|
20
|
+
current[segment] = {
|
|
21
|
+
children: {},
|
|
22
|
+
props: {
|
|
23
|
+
height: 0
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
if (index === segments.length - 1) {
|
|
28
|
+
// Assign the properties of the item including height
|
|
29
|
+
current[segment] = {
|
|
30
|
+
...item,
|
|
31
|
+
children: current[segment].children
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
current = current[segment].children;
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Step 2: Recursively calculate the height of each parent based on children
|
|
39
|
+
const calculateHeight = node => {
|
|
40
|
+
if (!node.children || Object.keys(node.children).length === 0) {
|
|
41
|
+
// Base case: If there are no children, return the node's height
|
|
42
|
+
return node.props.height;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Calculate the height by summing the heights of all children
|
|
46
|
+
let totalHeight = 0;
|
|
47
|
+
Object.values(node.children).forEach(child => {
|
|
48
|
+
totalHeight += calculateHeight(child);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// Update the parent's height to be the total height of its children
|
|
52
|
+
node.props.height = totalHeight;
|
|
53
|
+
if (node?.path) {
|
|
54
|
+
heightData[node.path] = totalHeight;
|
|
55
|
+
}
|
|
56
|
+
return totalHeight;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// Start calculation from the root
|
|
60
|
+
Object.values(root).forEach(node => calculateHeight(node));
|
|
61
|
+
return {
|
|
62
|
+
root,
|
|
63
|
+
heightData
|
|
64
|
+
};
|
|
65
|
+
}
|
|
8
66
|
const VirtualElement = props => {
|
|
9
67
|
const classes = useVirtualElementStyles();
|
|
10
68
|
const {
|
|
@@ -19,9 +77,10 @@ const VirtualElement = props => {
|
|
|
19
77
|
if (virtualRef?.current) {
|
|
20
78
|
setTimeout(() => {
|
|
21
79
|
const allData = calculateProps(path, virtualRef?.current, ROOT_ITEM_CLASS, []);
|
|
80
|
+
const groupData = groupByPathAndCalculateHeight(allData);
|
|
22
81
|
// it should trigger by auto alignment or on clicking mobile view change
|
|
23
|
-
updateAutoProps(editor, allData, "xs");
|
|
24
|
-
},
|
|
82
|
+
updateAutoProps(editor, allData, "xs", groupData);
|
|
83
|
+
}, 100);
|
|
25
84
|
}
|
|
26
85
|
}, [updated_at, virtualRef?.current]);
|
|
27
86
|
const calculateProps = (curPath, dom, domClass, allData) => {
|
|
@@ -35,11 +94,12 @@ const VirtualElement = props => {
|
|
|
35
94
|
};
|
|
36
95
|
const itemsData = [];
|
|
37
96
|
const items = dom.querySelectorAll(domClass);
|
|
38
|
-
|
|
97
|
+
const nextItemPathLength = curPath?.split("|").length + 2;
|
|
98
|
+
let sectionHeight = 12;
|
|
39
99
|
for (let i = 0; i < items.length; i++) {
|
|
40
100
|
const itemRect = items[i]?.getBoundingClientRect();
|
|
41
101
|
if (items[i]?.classList.contains("type_box")) {
|
|
42
|
-
allData = calculateProps(items[i]?.dataset.path, items[i],
|
|
102
|
+
allData = calculateProps(items[i]?.dataset.path, items[i], `.freegrid-item.path-${nextItemPathLength}`, allData);
|
|
43
103
|
} else {
|
|
44
104
|
const y = Math.abs(rect.top - itemRect?.top);
|
|
45
105
|
itemsData.push({
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Node, Transforms } from "slate";
|
|
2
|
-
const updateAutoProps = (editor, datas = [], breakpoint = "") => {
|
|
2
|
+
const updateAutoProps = (editor, datas = [], breakpoint = "", groupData) => {
|
|
3
3
|
try {
|
|
4
|
+
// const { heightData } = groupData;
|
|
4
5
|
for (let i = 0; i < datas.length; i++) {
|
|
5
6
|
const {
|
|
6
7
|
path,
|
|
@@ -13,7 +13,7 @@ const getStartEnd = ({
|
|
|
13
13
|
// Get start and end, modify it as we move along.
|
|
14
14
|
let [start, end] = Range.edges(selection);
|
|
15
15
|
|
|
16
|
-
// Move backwards
|
|
16
|
+
// Move backwards to find the start of the word
|
|
17
17
|
while (true) {
|
|
18
18
|
const before = Editor.before(editor, start, {
|
|
19
19
|
unit: "character"
|
|
@@ -22,16 +22,15 @@ const getStartEnd = ({
|
|
|
22
22
|
anchor: before,
|
|
23
23
|
focus: start
|
|
24
24
|
});
|
|
25
|
-
if (before
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
if (before) {
|
|
26
|
+
if (wordBefore.trim() === "") {
|
|
27
|
+
break;
|
|
28
|
+
} else if (SHORTHAND_CMDS.indexOf(wordBefore) < 0) {
|
|
29
|
+
start = before;
|
|
30
|
+
} else {
|
|
31
|
+
start = before;
|
|
29
32
|
break;
|
|
30
33
|
}
|
|
31
|
-
} else if (SHORTHAND_CMDS.indexOf(wordBefore) >= 0) {
|
|
32
|
-
// reached the character end
|
|
33
|
-
start = before;
|
|
34
|
-
break;
|
|
35
34
|
} else {
|
|
36
35
|
break;
|
|
37
36
|
}
|
|
@@ -41,11 +40,38 @@ const getStartEnd = ({
|
|
|
41
40
|
focus: end
|
|
42
41
|
};
|
|
43
42
|
const word = Editor.string(editor, wordRange);
|
|
43
|
+
const firstChar = word[0];
|
|
44
|
+
|
|
45
|
+
// Handle the commands
|
|
46
|
+
if (firstChar === '@') {
|
|
47
|
+
// Only trigger @ if preceded by a space
|
|
48
|
+
const isPrecededBySpace = Editor.string(editor, {
|
|
49
|
+
anchor: {
|
|
50
|
+
path: start.path,
|
|
51
|
+
offset: start.offset - 1
|
|
52
|
+
},
|
|
53
|
+
focus: start
|
|
54
|
+
}).trim() === "";
|
|
55
|
+
if (isPrecededBySpace) {
|
|
56
|
+
return {
|
|
57
|
+
word,
|
|
58
|
+
search: word.substring(1),
|
|
59
|
+
target: wordRange,
|
|
60
|
+
type: TYPES[firstChar]
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
} else if (firstChar === '/') {
|
|
64
|
+
return {
|
|
65
|
+
word,
|
|
66
|
+
search: word.substring(1),
|
|
67
|
+
target: wordRange,
|
|
68
|
+
type: TYPES[firstChar]
|
|
69
|
+
};
|
|
70
|
+
}
|
|
44
71
|
return {
|
|
45
|
-
word,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
type: TYPES[word[0]]
|
|
72
|
+
word: "",
|
|
73
|
+
wordRange: null,
|
|
74
|
+
type: null
|
|
49
75
|
};
|
|
50
76
|
} catch (err) {
|
|
51
77
|
return {
|
|
@@ -9,7 +9,12 @@ import withLayout from "../plugins/withLayout";
|
|
|
9
9
|
import withHtml from "../plugins/withHTML";
|
|
10
10
|
import withErrorHandling from "./withErrorHandling";
|
|
11
11
|
import withCustomDeleteBackward from "../plugins/withCustomDeleteBackward";
|
|
12
|
-
const withCommon = (props,
|
|
13
|
-
|
|
12
|
+
const withCommon = (props, {
|
|
13
|
+
needLayout = false,
|
|
14
|
+
isChatEditor = false
|
|
15
|
+
}) => {
|
|
16
|
+
const editor = needLayout ? withErrorHandling(withHtml(withEquation(withLayout(withHistory(withEmbeds(withTables(withLinks(withMentions(withCustomDeleteBackward(withReact(props))))))))))) : withErrorHandling(withHtml(withEquation(withHistory(withEmbeds(withTables(withLinks(withMentions(withCustomDeleteBackward(withReact(props))))))))));
|
|
17
|
+
editor.isChatEditor = isChatEditor;
|
|
18
|
+
return editor;
|
|
14
19
|
};
|
|
15
20
|
export default withCommon;
|
|
@@ -101,6 +101,9 @@ const withHtml = editor => {
|
|
|
101
101
|
return element.type === "image" ? true : isVoid(element);
|
|
102
102
|
};
|
|
103
103
|
editor.insertData = data => {
|
|
104
|
+
if (editor.isChatEditor) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
104
107
|
const slateHTML = data?.getData("application/x-slate-fragment");
|
|
105
108
|
const html = data?.getData("text/html");
|
|
106
109
|
const currentEl = getCurrentElement(editor);
|