@flozy/editor 1.0.5 → 1.0.7
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/Editor/CollaborativeEditor.js +116 -0
- package/dist/Editor/CommonEditor.js +132 -0
- package/dist/Editor/Editor.css +115 -0
- package/dist/Editor/Elements/CodeToText/CodeToText.css +57 -0
- package/dist/Editor/Elements/CodeToText/CodeToText.js +112 -0
- package/dist/Editor/Elements/CodeToText/CodeToTextButton.js +18 -0
- package/dist/Editor/Elements/CodeToText/HtmlCode.js +54 -0
- package/dist/Editor/Elements/CodeToText/HtmlContextMenu.js +39 -0
- package/dist/Editor/Elements/Color Picker/ColorPicker.css +38 -0
- package/dist/Editor/Elements/Color Picker/ColorPicker.js +116 -0
- package/dist/Editor/Elements/Color Picker/defaultColors.js +1 -0
- package/dist/Editor/Elements/Embed/Embed.css +14 -0
- package/dist/Editor/Elements/Embed/Embed.js +94 -0
- package/dist/Editor/Elements/Embed/Image.js +70 -0
- package/dist/Editor/Elements/Embed/Video.js +62 -0
- package/dist/Editor/Elements/Equation/Equation.js +24 -0
- package/dist/Editor/Elements/Equation/EquationButton.js +66 -0
- package/dist/Editor/Elements/Equation/styles.css +4 -0
- package/dist/Editor/Elements/Grid/Grid.js +53 -0
- package/dist/Editor/Elements/Grid/GridButton.js +19 -0
- package/dist/Editor/Elements/Grid/GridItem.js +53 -0
- package/dist/Editor/Elements/ID/Id.js +56 -0
- package/dist/Editor/Elements/Link/Link.js +34 -0
- package/dist/Editor/Elements/Link/LinkButton.js +77 -0
- package/dist/Editor/Elements/Link/styles.css +20 -0
- package/dist/Editor/Elements/Mentions/Mentions.js +34 -0
- package/dist/Editor/Elements/NewLine/NewLineButton.js +22 -0
- package/dist/Editor/Elements/Table/Table.js +15 -0
- package/dist/Editor/Elements/Table/TableSelector.css +18 -0
- package/dist/Editor/Elements/Table/TableSelector.js +93 -0
- package/dist/Editor/Elements/TableContextMenu/TableContextMenu.js +91 -0
- package/dist/Editor/Elements/TableContextMenu/styles.css +18 -0
- package/dist/Editor/RemoteCursorOverlay/Overlay.js +75 -0
- package/dist/Editor/Toolbar/Toolbar.js +166 -0
- package/dist/Editor/Toolbar/styles.css +28 -0
- package/dist/Editor/Toolbar/toolbarGroups.js +131 -0
- package/dist/Editor/Toolbar/toolbarIcons/align-center.svg +1 -0
- package/dist/Editor/Toolbar/toolbarIcons/align-left.svg +1 -0
- package/dist/Editor/Toolbar/toolbarIcons/align-right.svg +1 -0
- package/dist/Editor/Toolbar/toolbarIcons/blockquote.svg +1 -0
- package/dist/Editor/Toolbar/toolbarIcons/bold.png +0 -0
- package/dist/Editor/Toolbar/toolbarIcons/fontColor.svg +4 -0
- package/dist/Editor/Toolbar/toolbarIcons/headingOne.svg +3 -0
- package/dist/Editor/Toolbar/toolbarIcons/headingTwo.svg +3 -0
- package/dist/Editor/Toolbar/toolbarIcons/italic.png +0 -0
- package/dist/Editor/Toolbar/toolbarIcons/link.svg +1 -0
- package/dist/Editor/Toolbar/toolbarIcons/orderedList.svg +1 -0
- package/dist/Editor/Toolbar/toolbarIcons/strikethrough.png +0 -0
- package/dist/Editor/Toolbar/toolbarIcons/subscript.svg +1 -0
- package/dist/Editor/Toolbar/toolbarIcons/superscript.svg +1 -0
- package/dist/Editor/Toolbar/toolbarIcons/textColor.png +0 -0
- package/dist/Editor/Toolbar/toolbarIcons/underline.png +0 -0
- package/dist/Editor/Toolbar/toolbarIcons/unlink.svg +1 -0
- package/dist/Editor/Toolbar/toolbarIcons/unorderedList.svg +1 -0
- package/dist/Editor/YjsProvider.js +9 -0
- package/dist/Editor/common/Button.js +21 -0
- package/dist/Editor/common/Icon.js +114 -0
- package/dist/Editor/common/MentionsPopup.js +54 -0
- package/dist/Editor/hooks/useMentions.js +44 -0
- package/dist/Editor/hooks/withCollaborative.js +15 -0
- package/dist/Editor/hooks/withCommon.js +11 -0
- package/dist/Editor/plugins/withEmbeds.js +29 -0
- package/dist/Editor/plugins/withEquation.js +8 -0
- package/dist/Editor/plugins/withLinks.js +8 -0
- package/dist/Editor/plugins/withMentions.js +18 -0
- package/dist/Editor/plugins/withTable.js +61 -0
- package/dist/Editor/utils/SlateUtilityFunctions.js +224 -0
- package/dist/Editor/utils/customHooks/useContextMenu.js +37 -0
- package/dist/Editor/utils/customHooks/useFormat.js +21 -0
- package/dist/Editor/utils/customHooks/usePopup.js +21 -0
- package/dist/Editor/utils/customHooks/useResize.js +47 -0
- package/dist/Editor/utils/draftToSlate.js +111 -0
- package/dist/Editor/utils/embed.js +24 -0
- package/dist/Editor/utils/equation.js +23 -0
- package/dist/Editor/utils/events.js +76 -0
- package/dist/Editor/utils/grid.js +13 -0
- package/dist/Editor/utils/gridItem.js +19 -0
- package/dist/Editor/utils/link.js +52 -0
- package/dist/Editor/utils/mentions.js +12 -0
- package/dist/Editor/utils/paragraph.js +6 -0
- package/dist/Editor/utils/serializer.js +28 -0
- package/dist/Editor/utils/table.js +129 -0
- package/dist/index.js +4 -0
- package/package.json +18 -8
@@ -0,0 +1,77 @@
|
|
1
|
+
import { useRef, useState } from "react";
|
2
|
+
import { insertLink } from "../../utils/link.js";
|
3
|
+
import Button from "../../common/Button.jsx";
|
4
|
+
import Icon from "../../common/Icon.jsx";
|
5
|
+
import { isBlockActive } from "../../utils/SlateUtilityFunctions.js";
|
6
|
+
import usePopup from "../../utils/customHooks/usePopup.jsx";
|
7
|
+
import { Transforms } from "slate";
|
8
|
+
const LinkButton = props => {
|
9
|
+
const {
|
10
|
+
editor
|
11
|
+
} = props;
|
12
|
+
const linkInputRef = useRef(null);
|
13
|
+
const [showInput, setShowInput] = usePopup(linkInputRef);
|
14
|
+
const [url, setUrl] = useState("");
|
15
|
+
const [showInNewTab, setShowInNewTab] = useState(false);
|
16
|
+
const [selection, setSelection] = useState();
|
17
|
+
const handleInsertLink = () => {
|
18
|
+
Transforms.select(editor, selection);
|
19
|
+
insertLink(editor, {
|
20
|
+
url,
|
21
|
+
showInNewTab
|
22
|
+
});
|
23
|
+
setUrl("");
|
24
|
+
setShowInput(prev => !prev);
|
25
|
+
setShowInNewTab(false);
|
26
|
+
};
|
27
|
+
const toggleLink = () => {
|
28
|
+
setSelection(editor.selection);
|
29
|
+
setShowInput(prev => !prev);
|
30
|
+
};
|
31
|
+
const handleInputChange = ({
|
32
|
+
target
|
33
|
+
}) => {
|
34
|
+
if (target.type === "checkbox") {
|
35
|
+
setShowInNewTab(prev => !prev);
|
36
|
+
} else {
|
37
|
+
setUrl(target.value);
|
38
|
+
}
|
39
|
+
};
|
40
|
+
return /*#__PURE__*/React.createElement("div", {
|
41
|
+
ref: linkInputRef,
|
42
|
+
className: "popup-wrapper"
|
43
|
+
}, /*#__PURE__*/React.createElement(Button, {
|
44
|
+
className: showInput ? "clicked" : "",
|
45
|
+
active: isBlockActive(editor, "link"),
|
46
|
+
format: "link",
|
47
|
+
onClick: toggleLink
|
48
|
+
}, /*#__PURE__*/React.createElement(Icon, {
|
49
|
+
icon: "link"
|
50
|
+
})), showInput && /*#__PURE__*/React.createElement("div", {
|
51
|
+
className: "popup"
|
52
|
+
}, /*#__PURE__*/React.createElement("div", {
|
53
|
+
style: {
|
54
|
+
display: "flex",
|
55
|
+
gap: "4px",
|
56
|
+
margin: "5px 2px"
|
57
|
+
}
|
58
|
+
}, /*#__PURE__*/React.createElement("input", {
|
59
|
+
type: "text",
|
60
|
+
placeholder: "https://google.com",
|
61
|
+
value: url,
|
62
|
+
onChange: handleInputChange
|
63
|
+
}), /*#__PURE__*/React.createElement("div", {
|
64
|
+
onClick: handleInsertLink
|
65
|
+
}, /*#__PURE__*/React.createElement(Icon, {
|
66
|
+
icon: "add"
|
67
|
+
}))), /*#__PURE__*/React.createElement("label", null, /*#__PURE__*/React.createElement("input", {
|
68
|
+
type: "checkbox",
|
69
|
+
checked: showInNewTab,
|
70
|
+
onChange: handleInputChange
|
71
|
+
}), /*#__PURE__*/React.createElement("span", {
|
72
|
+
style: {
|
73
|
+
fontSize: "0.8em"
|
74
|
+
}
|
75
|
+
}, "Open in new tab"))));
|
76
|
+
};
|
77
|
+
export default LinkButton;
|
@@ -0,0 +1,20 @@
|
|
1
|
+
.link{
|
2
|
+
display: inline;
|
3
|
+
position: relative;
|
4
|
+
}
|
5
|
+
.link-popup{
|
6
|
+
position: absolute;
|
7
|
+
left: 0;
|
8
|
+
display: flex;
|
9
|
+
align-items: center;
|
10
|
+
background-color: white;
|
11
|
+
padding: 6px 10px;
|
12
|
+
gap: 10px;
|
13
|
+
border-radius: 6px;
|
14
|
+
border: 1px solid lightgray;
|
15
|
+
width: fit-content;
|
16
|
+
z-index: 1;
|
17
|
+
}
|
18
|
+
img{
|
19
|
+
height: 15px;
|
20
|
+
}
|
@@ -0,0 +1,34 @@
|
|
1
|
+
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
2
|
+
import React from "react";
|
3
|
+
import { useSelected, useFocused } from "slate-react";
|
4
|
+
const Mentions = ({
|
5
|
+
attributes,
|
6
|
+
children,
|
7
|
+
element
|
8
|
+
}) => {
|
9
|
+
const selected = useSelected();
|
10
|
+
const focused = useFocused();
|
11
|
+
const style = {
|
12
|
+
padding: "3px 3px 2px",
|
13
|
+
margin: "0 1px",
|
14
|
+
verticalAlign: "baseline",
|
15
|
+
display: "inline-block",
|
16
|
+
borderRadius: "4px",
|
17
|
+
backgroundColor: "#eee",
|
18
|
+
fontSize: "0.9em",
|
19
|
+
boxShadow: selected && focused ? "0 0 0 2px #B4D5FF" : "none"
|
20
|
+
};
|
21
|
+
// See if our empty text child has any styling marks applied and apply those
|
22
|
+
if (element.children[0].bold) {
|
23
|
+
style.fontWeight = "bold";
|
24
|
+
}
|
25
|
+
if (element.children[0].italic) {
|
26
|
+
style.fontStyle = "italic";
|
27
|
+
}
|
28
|
+
return /*#__PURE__*/React.createElement("span", _extends({}, attributes, {
|
29
|
+
contentEditable: false,
|
30
|
+
"data-cy": `mention-${element.character.replace(" ", "-")}`,
|
31
|
+
style: style
|
32
|
+
}), "@", element.character, children);
|
33
|
+
};
|
34
|
+
export default Mentions;
|
@@ -0,0 +1,22 @@
|
|
1
|
+
import React from "react";
|
2
|
+
import KeyboardReturnIcon from "@mui/icons-material/KeyboardReturn";
|
3
|
+
import { Transforms } from "slate";
|
4
|
+
import { useSlateStatic } from "slate-react";
|
5
|
+
const NewLineButton = props => {
|
6
|
+
const editor = useSlateStatic();
|
7
|
+
const onAddNewLine = () => {
|
8
|
+
Transforms.insertNodes(editor, [{
|
9
|
+
type: "paragraph",
|
10
|
+
children: [{
|
11
|
+
text: ""
|
12
|
+
}]
|
13
|
+
}], {
|
14
|
+
at: [editor.children.length]
|
15
|
+
});
|
16
|
+
};
|
17
|
+
return /*#__PURE__*/React.createElement("button", {
|
18
|
+
title: "New Line",
|
19
|
+
onClick: onAddNewLine
|
20
|
+
}, /*#__PURE__*/React.createElement(KeyboardReturnIcon, null));
|
21
|
+
};
|
22
|
+
export default NewLineButton;
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import React from "react";
|
2
|
+
const Table = ({
|
3
|
+
attributes,
|
4
|
+
children,
|
5
|
+
element
|
6
|
+
}) => {
|
7
|
+
return /*#__PURE__*/React.createElement("div", {
|
8
|
+
style: {
|
9
|
+
minWidth: "100%",
|
10
|
+
maxWidth: "100%",
|
11
|
+
overflow: "auto"
|
12
|
+
}
|
13
|
+
}, /*#__PURE__*/React.createElement("table", null, /*#__PURE__*/React.createElement("tbody", attributes, children)));
|
14
|
+
};
|
15
|
+
export default Table;
|
@@ -0,0 +1,18 @@
|
|
1
|
+
.table-option{
|
2
|
+
display: flex;
|
3
|
+
margin: 5px 2px;
|
4
|
+
gap: 5px;
|
5
|
+
}
|
6
|
+
.table-option{
|
7
|
+
white-space: nowrap;
|
8
|
+
}
|
9
|
+
.table-input{
|
10
|
+
display: grid;
|
11
|
+
grid-template-columns: auto auto auto auto auto auto;
|
12
|
+
gap: 3px;
|
13
|
+
}
|
14
|
+
.table-unit{
|
15
|
+
width:15px;
|
16
|
+
height:15px;
|
17
|
+
border: 1px solid lightgray;
|
18
|
+
}
|
@@ -0,0 +1,93 @@
|
|
1
|
+
import React, { useEffect, useRef, useState } from 'react';
|
2
|
+
import Icon from '../../common/Icon';
|
3
|
+
import usePopup from '../../utils/customHooks/usePopup';
|
4
|
+
import { Transforms } from 'slate';
|
5
|
+
import { TableUtil } from '../../utils/table.js';
|
6
|
+
import './TableSelector.css';
|
7
|
+
const TableSelector = ({
|
8
|
+
editor
|
9
|
+
}) => {
|
10
|
+
const tableOptionsRef = useRef();
|
11
|
+
const [selection, setSelection] = useState();
|
12
|
+
const [showOptions, setShowOptions] = usePopup(tableOptionsRef);
|
13
|
+
const [tableData, setTableData] = useState({
|
14
|
+
row: 0,
|
15
|
+
column: 0
|
16
|
+
});
|
17
|
+
const [tableInput, setTableInput] = useState(Array.from({
|
18
|
+
length: 6
|
19
|
+
}, () => Array.from({
|
20
|
+
length: 6
|
21
|
+
}, (v, i) => ({
|
22
|
+
bg: 'lightGray',
|
23
|
+
column: i
|
24
|
+
}))));
|
25
|
+
useEffect(() => {
|
26
|
+
const newTable = Array.from({
|
27
|
+
length: 6
|
28
|
+
}, (obj, row) => Array.from({
|
29
|
+
length: 6
|
30
|
+
}, (v, col) => ({
|
31
|
+
bg: row + 1 <= tableData.row && col + 1 <= tableData.column ? 'orange' : 'lightgray',
|
32
|
+
column: col
|
33
|
+
})));
|
34
|
+
setTableInput(newTable);
|
35
|
+
}, [tableData]);
|
36
|
+
useEffect(() => {
|
37
|
+
if (!showOptions) {
|
38
|
+
setTableData({
|
39
|
+
row: 0,
|
40
|
+
column: 0
|
41
|
+
});
|
42
|
+
}
|
43
|
+
}, [showOptions]);
|
44
|
+
const table = new TableUtil(editor);
|
45
|
+
const handleButtonClick = () => {
|
46
|
+
setSelection(editor.selection);
|
47
|
+
setShowOptions(prev => !prev);
|
48
|
+
};
|
49
|
+
const handleInsert = () => {
|
50
|
+
selection && Transforms.select(editor, selection);
|
51
|
+
setTableData({
|
52
|
+
row: -1,
|
53
|
+
column: -1
|
54
|
+
});
|
55
|
+
table.insertTable(tableData.row, tableData.column);
|
56
|
+
setShowOptions(false);
|
57
|
+
};
|
58
|
+
return /*#__PURE__*/React.createElement("div", {
|
59
|
+
ref: tableOptionsRef,
|
60
|
+
className: "popup-wrapper"
|
61
|
+
}, /*#__PURE__*/React.createElement("button", {
|
62
|
+
style: {
|
63
|
+
border: showOptions ? '1px solid lightgray' : 'none'
|
64
|
+
},
|
65
|
+
title: "table",
|
66
|
+
onClick: handleButtonClick
|
67
|
+
}, /*#__PURE__*/React.createElement(Icon, {
|
68
|
+
icon: "table"
|
69
|
+
})), showOptions && /*#__PURE__*/React.createElement("div", {
|
70
|
+
className: "popup"
|
71
|
+
}, /*#__PURE__*/React.createElement("span", {
|
72
|
+
style: {
|
73
|
+
fontSize: '0.85em'
|
74
|
+
}
|
75
|
+
}, /*#__PURE__*/React.createElement("i", null, `Insert a ${tableData.row >= 1 ? `${tableData.row} x ${tableData.column}` : ''} table`)), /*#__PURE__*/React.createElement("div", {
|
76
|
+
className: "table-input"
|
77
|
+
}, tableInput.map((grp, row) => grp.map(({
|
78
|
+
column,
|
79
|
+
bg
|
80
|
+
}, col) => /*#__PURE__*/React.createElement("div", {
|
81
|
+
key: row + col,
|
82
|
+
onClick: () => handleInsert(),
|
83
|
+
onMouseOver: () => setTableData({
|
84
|
+
row: row + 1,
|
85
|
+
column: column + 1
|
86
|
+
}),
|
87
|
+
className: "table-unit",
|
88
|
+
style: {
|
89
|
+
border: `1px solid ${bg}`
|
90
|
+
}
|
91
|
+
}))))));
|
92
|
+
};
|
93
|
+
export default TableSelector;
|
@@ -0,0 +1,91 @@
|
|
1
|
+
import React, { useState } from "react";
|
2
|
+
import useContextMenu from "../../utils/customHooks/useContextMenu.js";
|
3
|
+
import Icon from "../../common/Icon.jsx";
|
4
|
+
import "./styles.css";
|
5
|
+
import { TableUtil } from "../../utils/table.js";
|
6
|
+
import { Transforms } from "slate";
|
7
|
+
import { ReactEditor } from "slate-react";
|
8
|
+
const TableContextMenu = props => {
|
9
|
+
const {
|
10
|
+
editor
|
11
|
+
} = props;
|
12
|
+
const [selection, setSelection] = useState();
|
13
|
+
const [showMenu, {
|
14
|
+
top,
|
15
|
+
left
|
16
|
+
}] = useContextMenu(editor, "table", setSelection);
|
17
|
+
const table = new TableUtil(editor);
|
18
|
+
const menu = [{
|
19
|
+
icon: "insertColumnRight",
|
20
|
+
text: "Insert Columns to the Right",
|
21
|
+
action: {
|
22
|
+
type: "insertColumn",
|
23
|
+
position: "after"
|
24
|
+
}
|
25
|
+
}, {
|
26
|
+
icon: "insertColumnLeft",
|
27
|
+
text: "Insert Columns to the Left",
|
28
|
+
action: {
|
29
|
+
type: "insertColumn",
|
30
|
+
position: "at"
|
31
|
+
}
|
32
|
+
}, {
|
33
|
+
icon: "insertRowAbove",
|
34
|
+
text: "Insert Row Above",
|
35
|
+
action: {
|
36
|
+
type: "insertRow",
|
37
|
+
positon: "at"
|
38
|
+
}
|
39
|
+
}, {
|
40
|
+
icon: "insertRowBelow",
|
41
|
+
text: "Insert Row Below",
|
42
|
+
action: {
|
43
|
+
type: "insertRow",
|
44
|
+
position: "after"
|
45
|
+
}
|
46
|
+
}, {
|
47
|
+
icon: "trashCan",
|
48
|
+
text: "Remove Table",
|
49
|
+
action: {
|
50
|
+
type: "remove"
|
51
|
+
}
|
52
|
+
}];
|
53
|
+
const handleInsert = ({
|
54
|
+
type,
|
55
|
+
position
|
56
|
+
}) => {
|
57
|
+
Transforms.select(editor, selection);
|
58
|
+
switch (type) {
|
59
|
+
case "insertRow":
|
60
|
+
table.insertRow(position);
|
61
|
+
break;
|
62
|
+
case "insertColumn":
|
63
|
+
table.insertColumn(position);
|
64
|
+
break;
|
65
|
+
case "remove":
|
66
|
+
table.removeTable();
|
67
|
+
break;
|
68
|
+
default:
|
69
|
+
return;
|
70
|
+
}
|
71
|
+
ReactEditor.focus(editor);
|
72
|
+
};
|
73
|
+
return showMenu && /*#__PURE__*/React.createElement("div", {
|
74
|
+
className: "contextMenu",
|
75
|
+
style: {
|
76
|
+
top,
|
77
|
+
left
|
78
|
+
}
|
79
|
+
}, menu.map(({
|
80
|
+
icon,
|
81
|
+
text,
|
82
|
+
action
|
83
|
+
}, index) => /*#__PURE__*/React.createElement("div", {
|
84
|
+
className: "menuOption",
|
85
|
+
key: index,
|
86
|
+
onClick: () => handleInsert(action)
|
87
|
+
}, /*#__PURE__*/React.createElement(Icon, {
|
88
|
+
icon: icon
|
89
|
+
}), /*#__PURE__*/React.createElement("span", null, text))));
|
90
|
+
};
|
91
|
+
export default TableContextMenu;
|
@@ -0,0 +1,18 @@
|
|
1
|
+
.contextMenu{
|
2
|
+
width: fit-content;
|
3
|
+
height: fit-content;
|
4
|
+
position: fixed;
|
5
|
+
background: white;
|
6
|
+
border: 1px solid lightgray;
|
7
|
+
border-radius: 10px;
|
8
|
+
padding: 0.5%;
|
9
|
+
display: flex;
|
10
|
+
gap: 15px;
|
11
|
+
flex-direction: column;
|
12
|
+
cursor: pointer;
|
13
|
+
}
|
14
|
+
|
15
|
+
.menuOption {
|
16
|
+
display: flex;
|
17
|
+
gap:15px;
|
18
|
+
}
|
@@ -0,0 +1,75 @@
|
|
1
|
+
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
2
|
+
import React, { useRef } from "react";
|
3
|
+
import { useRemoteCursorOverlayPositions } from "@slate-yjs/react";
|
4
|
+
function Caret({
|
5
|
+
caretPosition,
|
6
|
+
data
|
7
|
+
}) {
|
8
|
+
const caretStyle = {
|
9
|
+
...caretPosition,
|
10
|
+
background: data?.color || "#d33d3db5"
|
11
|
+
};
|
12
|
+
const labelStyle = {
|
13
|
+
transform: "translateY(-100%)",
|
14
|
+
background: data?.color || "#d33d3db5"
|
15
|
+
};
|
16
|
+
return /*#__PURE__*/React.createElement("div", {
|
17
|
+
style: {
|
18
|
+
...caretStyle,
|
19
|
+
position: "absolute",
|
20
|
+
width: "0.5px"
|
21
|
+
}
|
22
|
+
}, /*#__PURE__*/React.createElement("div", {
|
23
|
+
style: {
|
24
|
+
position: "absolute",
|
25
|
+
color: "#FFF",
|
26
|
+
whiteSpace: "nowrap",
|
27
|
+
top: 0,
|
28
|
+
...labelStyle
|
29
|
+
}
|
30
|
+
}, data?.name));
|
31
|
+
}
|
32
|
+
function RemoteSelection({
|
33
|
+
data,
|
34
|
+
selectionRects,
|
35
|
+
caretPosition
|
36
|
+
}) {
|
37
|
+
if (!data) {
|
38
|
+
return null;
|
39
|
+
}
|
40
|
+
const selectionStyle = {
|
41
|
+
backgroundColor: data.color
|
42
|
+
};
|
43
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, selectionRects.map((position, i) => /*#__PURE__*/React.createElement("div", {
|
44
|
+
style: {
|
45
|
+
...selectionStyle,
|
46
|
+
...position,
|
47
|
+
position: "absolute",
|
48
|
+
pointerEvents: "none"
|
49
|
+
}
|
50
|
+
// eslint-disable-next-line react/no-array-index-key
|
51
|
+
,
|
52
|
+
key: i
|
53
|
+
})), caretPosition && /*#__PURE__*/React.createElement(Caret, {
|
54
|
+
caretPosition: caretPosition,
|
55
|
+
data: data
|
56
|
+
}));
|
57
|
+
}
|
58
|
+
export function RemoteCursorOverlay({
|
59
|
+
className,
|
60
|
+
children
|
61
|
+
}) {
|
62
|
+
const containerRef = useRef(null);
|
63
|
+
const [cursors] = useRemoteCursorOverlayPositions({
|
64
|
+
containerRef
|
65
|
+
});
|
66
|
+
return /*#__PURE__*/React.createElement("div", {
|
67
|
+
className: `${className}`,
|
68
|
+
style: {
|
69
|
+
position: "relative"
|
70
|
+
},
|
71
|
+
ref: containerRef
|
72
|
+
}, children, cursors.map(cursor => /*#__PURE__*/React.createElement(RemoteSelection, _extends({
|
73
|
+
key: cursor.clientId
|
74
|
+
}, cursor))));
|
75
|
+
}
|
@@ -0,0 +1,166 @@
|
|
1
|
+
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
2
|
+
import React, { useEffect, useState } from "react";
|
3
|
+
import { useSlate } from "slate-react";
|
4
|
+
import Button from "../common/Button";
|
5
|
+
import Icon from "../common/Icon";
|
6
|
+
import { toggleBlock, toggleMark, isMarkActive, addMarkData, isBlockActive, activeMark } from "../utils/SlateUtilityFunctions.js";
|
7
|
+
import useFormat from "../utils/customHooks/useFormat.js";
|
8
|
+
import defaultToolbarGroups from "./toolbarGroups.js";
|
9
|
+
import "./styles.css";
|
10
|
+
import ColorPicker from "../Elements/Color Picker/ColorPicker";
|
11
|
+
import LinkButton from "../Elements/Link/LinkButton";
|
12
|
+
import Embed from "../Elements/Embed/Embed";
|
13
|
+
import TableSelector from "../Elements/Table/TableSelector";
|
14
|
+
import EquationButton from "../Elements/Equation/EquationButton";
|
15
|
+
import Id from "../Elements/ID/Id";
|
16
|
+
import TableContextMenu from "../Elements/TableContextMenu/TableContextMenu";
|
17
|
+
import CodeToTextButton from "../Elements/CodeToText/CodeToTextButton";
|
18
|
+
import HtmlContextMenu from "../Elements/CodeToText/HtmlContextMenu";
|
19
|
+
import GridButton from "../Elements/Grid/GridButton";
|
20
|
+
import NewLineButton from "../Elements/NewLine/NewLineButton";
|
21
|
+
const Toolbar = props => {
|
22
|
+
const {
|
23
|
+
handleCodeToText
|
24
|
+
} = props;
|
25
|
+
const editor = useSlate();
|
26
|
+
const isTable = useFormat(editor, "table");
|
27
|
+
const [toolbarGroups, setToolbarGroups] = useState(defaultToolbarGroups);
|
28
|
+
useEffect(() => {
|
29
|
+
// Filter out the groups which are not allowed to be inserted when a table is in focus.
|
30
|
+
let filteredGroups = [...defaultToolbarGroups];
|
31
|
+
if (isTable) {
|
32
|
+
filteredGroups = toolbarGroups.map(grp => grp.filter(element =>
|
33
|
+
//groups that are not supported inside the table
|
34
|
+
!["codeToText"].includes(element.type)));
|
35
|
+
filteredGroups = filteredGroups.filter(elem => elem.length);
|
36
|
+
}
|
37
|
+
setToolbarGroups(filteredGroups);
|
38
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
39
|
+
}, [isTable]);
|
40
|
+
const BlockButton = ({
|
41
|
+
format
|
42
|
+
}) => {
|
43
|
+
return /*#__PURE__*/React.createElement(Button, {
|
44
|
+
active: isBlockActive(editor, format),
|
45
|
+
format: format,
|
46
|
+
onMouseDown: e => {
|
47
|
+
e.preventDefault();
|
48
|
+
toggleBlock(editor, format);
|
49
|
+
}
|
50
|
+
}, /*#__PURE__*/React.createElement(Icon, {
|
51
|
+
icon: format
|
52
|
+
}));
|
53
|
+
};
|
54
|
+
const MarkButton = ({
|
55
|
+
format
|
56
|
+
}) => {
|
57
|
+
return /*#__PURE__*/React.createElement(Button, {
|
58
|
+
active: isMarkActive(editor, format),
|
59
|
+
format: format,
|
60
|
+
onMouseDown: e => {
|
61
|
+
e.preventDefault();
|
62
|
+
toggleMark(editor, format);
|
63
|
+
}
|
64
|
+
}, /*#__PURE__*/React.createElement(Icon, {
|
65
|
+
icon: format
|
66
|
+
}));
|
67
|
+
};
|
68
|
+
const Dropdown = ({
|
69
|
+
format,
|
70
|
+
options
|
71
|
+
}) => {
|
72
|
+
return /*#__PURE__*/React.createElement("select", {
|
73
|
+
value: activeMark(editor, format),
|
74
|
+
onChange: e => changeMarkData(e, format)
|
75
|
+
}, options.map((item, index) => /*#__PURE__*/React.createElement("option", {
|
76
|
+
key: index,
|
77
|
+
value: item.value
|
78
|
+
}, item.text)));
|
79
|
+
};
|
80
|
+
const changeMarkData = (event, format) => {
|
81
|
+
event.preventDefault();
|
82
|
+
const value = event.target.value;
|
83
|
+
addMarkData(editor, {
|
84
|
+
format,
|
85
|
+
value
|
86
|
+
});
|
87
|
+
};
|
88
|
+
return /*#__PURE__*/React.createElement("div", {
|
89
|
+
className: "toolbar"
|
90
|
+
}, toolbarGroups.map((group, index) => /*#__PURE__*/React.createElement("span", {
|
91
|
+
key: index,
|
92
|
+
className: "toolbar-grp"
|
93
|
+
}, group.map((element, gi) => {
|
94
|
+
switch (element.type) {
|
95
|
+
case "block":
|
96
|
+
return /*#__PURE__*/React.createElement(BlockButton, _extends({
|
97
|
+
key: element.id
|
98
|
+
}, element));
|
99
|
+
case "mark":
|
100
|
+
return /*#__PURE__*/React.createElement(MarkButton, _extends({
|
101
|
+
key: element.id
|
102
|
+
}, element));
|
103
|
+
case "dropdown":
|
104
|
+
return /*#__PURE__*/React.createElement(Dropdown, _extends({
|
105
|
+
key: element.id
|
106
|
+
}, element));
|
107
|
+
case "link":
|
108
|
+
return /*#__PURE__*/React.createElement(LinkButton, {
|
109
|
+
key: element.id,
|
110
|
+
active: isBlockActive(editor, "link"),
|
111
|
+
editor: editor
|
112
|
+
});
|
113
|
+
case "embed":
|
114
|
+
return /*#__PURE__*/React.createElement(Embed, {
|
115
|
+
key: element.id,
|
116
|
+
format: element.format,
|
117
|
+
editor: editor
|
118
|
+
});
|
119
|
+
case "color-picker":
|
120
|
+
return /*#__PURE__*/React.createElement(ColorPicker, {
|
121
|
+
key: element.id,
|
122
|
+
activeMark: activeMark,
|
123
|
+
format: element.format,
|
124
|
+
editor: editor
|
125
|
+
});
|
126
|
+
case "table":
|
127
|
+
return /*#__PURE__*/React.createElement(TableSelector, {
|
128
|
+
key: element.id,
|
129
|
+
editor: editor
|
130
|
+
});
|
131
|
+
case "id":
|
132
|
+
return /*#__PURE__*/React.createElement(Id, {
|
133
|
+
key: `gi_id_${gi}`,
|
134
|
+
editor: editor
|
135
|
+
});
|
136
|
+
case "equation":
|
137
|
+
return /*#__PURE__*/React.createElement(EquationButton, {
|
138
|
+
key: `gi_equation_${gi}`,
|
139
|
+
editor: editor
|
140
|
+
});
|
141
|
+
case "codeToText":
|
142
|
+
return /*#__PURE__*/React.createElement(CodeToTextButton, {
|
143
|
+
key: `gi_codeToText_${gi}`,
|
144
|
+
handleButtonClick: handleCodeToText
|
145
|
+
});
|
146
|
+
case "grid":
|
147
|
+
return /*#__PURE__*/React.createElement(GridButton, {
|
148
|
+
key: element.id,
|
149
|
+
editor: editor
|
150
|
+
});
|
151
|
+
case "newLine":
|
152
|
+
return /*#__PURE__*/React.createElement(NewLineButton, {
|
153
|
+
key: element.id,
|
154
|
+
editor: editor
|
155
|
+
});
|
156
|
+
default:
|
157
|
+
return null;
|
158
|
+
}
|
159
|
+
}))), /*#__PURE__*/React.createElement(TableContextMenu, {
|
160
|
+
editor: editor
|
161
|
+
}), /*#__PURE__*/React.createElement(HtmlContextMenu, {
|
162
|
+
editor: editor,
|
163
|
+
handleCodeToText: handleCodeToText
|
164
|
+
}));
|
165
|
+
};
|
166
|
+
export default Toolbar;
|
@@ -0,0 +1,28 @@
|
|
1
|
+
.toolbar{
|
2
|
+
border-radius: 10px;
|
3
|
+
background: #ffffff;
|
4
|
+
box-shadow: -8px 8px 13px #ededed,
|
5
|
+
8px -8px 13px #ffffff;
|
6
|
+
margin:4px 0;
|
7
|
+
display:flex;
|
8
|
+
flex-wrap:wrap;
|
9
|
+
align-items:center;
|
10
|
+
padding: 15px 10px;
|
11
|
+
row-gap: 15px;
|
12
|
+
position: -webkit-sticky;
|
13
|
+
position: sticky;
|
14
|
+
top: 0;
|
15
|
+
z-index: 2;
|
16
|
+
}
|
17
|
+
.toolbar-grp>*{
|
18
|
+
margin-right: 10px;
|
19
|
+
cursor: pointer;
|
20
|
+
}
|
21
|
+
.toolbar-grp{
|
22
|
+
margin:0 10px;
|
23
|
+
}
|
24
|
+
select{
|
25
|
+
height: 30px;
|
26
|
+
border: none;
|
27
|
+
width: 6.9rem;
|
28
|
+
}
|