@flozy/editor 1.0.0 → 1.0.6
Sign up to get free protection for your applications and to get access to all the features.
- package/build/asset-manifest.json +14 -0
- package/build/index.html +1 -0
- package/build/static/css/main.71100b24.css +2 -0
- package/build/static/css/main.71100b24.css.map +1 -0
- package/build/static/js/main.dd36b23b.js +3 -0
- package/build/static/js/main.dd36b23b.js.LICENSE.txt +19 -0
- package/build/static/js/main.dd36b23b.js.map +1 -0
- package/package.json +6 -2
- package/.eslintignore +0 -4
- package/.eslintrc.json +0 -6
- package/.github/workflows/npm-publish.yml +0 -33
- package/.husky/pre-commit +0 -1
- package/.storybook/main.js +0 -20
- package/.storybook/preview.js +0 -14
- package/.vscode/extensions.json +0 -7
- package/.vscode/launch.json +0 -15
- package/.vscode/settings.json +0 -22
- package/craco.config.js +0 -16
- package/public/index.html +0 -43
- package/src/components/Editor/CollaborativeEditor.js +0 -119
- package/src/components/Editor/CommonEditor.js +0 -549
- package/src/components/Editor/Editor.css +0 -115
- package/src/components/Editor/Elements/CodeToText/CodeToText.css +0 -57
- package/src/components/Editor/Elements/CodeToText/CodeToText.jsx +0 -115
- package/src/components/Editor/Elements/CodeToText/CodeToTextButton.jsx +0 -16
- package/src/components/Editor/Elements/CodeToText/HtmlCode.jsx +0 -59
- package/src/components/Editor/Elements/CodeToText/HtmlContextMenu.jsx +0 -39
- package/src/components/Editor/Elements/Color Picker/ColorPicker.css +0 -38
- package/src/components/Editor/Elements/Color Picker/ColorPicker.jsx +0 -110
- package/src/components/Editor/Elements/Color Picker/defaultColors.js +0 -34
- package/src/components/Editor/Elements/Embed/Embed.css +0 -14
- package/src/components/Editor/Elements/Embed/Embed.jsx +0 -74
- package/src/components/Editor/Elements/Embed/Image.jsx +0 -82
- package/src/components/Editor/Elements/Embed/Video.jsx +0 -65
- package/src/components/Editor/Elements/Equation/Equation.jsx +0 -19
- package/src/components/Editor/Elements/Equation/EquationButton.jsx +0 -59
- package/src/components/Editor/Elements/Equation/styles.css +0 -4
- package/src/components/Editor/Elements/Grid/Grid.js +0 -48
- package/src/components/Editor/Elements/Grid/GridButton.js +0 -21
- package/src/components/Editor/Elements/Grid/GridItem.js +0 -57
- package/src/components/Editor/Elements/ID/Id.jsx +0 -56
- package/src/components/Editor/Elements/Link/Link.jsx +0 -24
- package/src/components/Editor/Elements/Link/LinkButton.jsx +0 -71
- package/src/components/Editor/Elements/Link/styles.css +0 -20
- package/src/components/Editor/Elements/Mentions/Mentions.jsx +0 -37
- package/src/components/Editor/Elements/NewLine/NewLineButton.js +0 -29
- package/src/components/Editor/Elements/Table/Table.jsx +0 -13
- package/src/components/Editor/Elements/Table/TableSelector.css +0 -18
- package/src/components/Editor/Elements/Table/TableSelector.jsx +0 -76
- package/src/components/Editor/Elements/TableContextMenu/TableContextMenu.jsx +0 -97
- package/src/components/Editor/Elements/TableContextMenu/styles.css +0 -18
- package/src/components/Editor/RemoteCursorOverlay/Overlay.js +0 -78
- package/src/components/Editor/Toolbar/Toolbar.jsx +0 -167
- package/src/components/Editor/Toolbar/styles.css +0 -28
- package/src/components/Editor/Toolbar/toolbarGroups.js +0 -167
- package/src/components/Editor/Toolbar/toolbarIcons/align-center.svg +0 -1
- package/src/components/Editor/Toolbar/toolbarIcons/align-left.svg +0 -1
- package/src/components/Editor/Toolbar/toolbarIcons/align-right.svg +0 -1
- package/src/components/Editor/Toolbar/toolbarIcons/blockquote.svg +0 -1
- package/src/components/Editor/Toolbar/toolbarIcons/bold.png +0 -0
- package/src/components/Editor/Toolbar/toolbarIcons/fontColor.svg +0 -4
- package/src/components/Editor/Toolbar/toolbarIcons/headingOne.svg +0 -3
- package/src/components/Editor/Toolbar/toolbarIcons/headingTwo.svg +0 -3
- package/src/components/Editor/Toolbar/toolbarIcons/italic.png +0 -0
- package/src/components/Editor/Toolbar/toolbarIcons/link.svg +0 -1
- package/src/components/Editor/Toolbar/toolbarIcons/orderedList.svg +0 -1
- package/src/components/Editor/Toolbar/toolbarIcons/strikethrough.png +0 -0
- package/src/components/Editor/Toolbar/toolbarIcons/subscript.svg +0 -1
- package/src/components/Editor/Toolbar/toolbarIcons/superscript.svg +0 -1
- package/src/components/Editor/Toolbar/toolbarIcons/textColor.png +0 -0
- package/src/components/Editor/Toolbar/toolbarIcons/underline.png +0 -0
- package/src/components/Editor/Toolbar/toolbarIcons/unorderedList.svg +0 -1
- package/src/components/Editor/YjsProvider.js +0 -11
- package/src/components/Editor/common/Button.jsx +0 -12
- package/src/components/Editor/common/Icon.jsx +0 -82
- package/src/components/Editor/common/MentionsPopup.jsx +0 -56
- package/src/components/Editor/hooks/useMentions.js +0 -44
- package/src/components/Editor/hooks/withCollaborative.js +0 -15
- package/src/components/Editor/hooks/withCommon.js +0 -17
- package/src/components/Editor/plugins/withEmbeds.js +0 -36
- package/src/components/Editor/plugins/withEquation.js +0 -8
- package/src/components/Editor/plugins/withLinks.js +0 -9
- package/src/components/Editor/plugins/withMentions.js +0 -19
- package/src/components/Editor/plugins/withTable.js +0 -74
- package/src/components/Editor/utils/SlateUtilityFunctions.js +0 -273
- package/src/components/Editor/utils/customHooks/useContextMenu.js +0 -42
- package/src/components/Editor/utils/customHooks/useFormat.js +0 -26
- package/src/components/Editor/utils/customHooks/usePopup.jsx +0 -26
- package/src/components/Editor/utils/customHooks/useResize.js +0 -41
- package/src/components/Editor/utils/draftToSlate.js +0 -104
- package/src/components/Editor/utils/embed.js +0 -18
- package/src/components/Editor/utils/equation.js +0 -22
- package/src/components/Editor/utils/events.js +0 -56
- package/src/components/Editor/utils/grid.js +0 -12
- package/src/components/Editor/utils/gridItem.js +0 -19
- package/src/components/Editor/utils/link.js +0 -53
- package/src/components/Editor/utils/mentions.js +0 -11
- package/src/components/Editor/utils/paragraph.js +0 -4
- package/src/components/Editor/utils/serializer.js +0 -32
- package/src/components/Editor/utils/table.js +0 -151
- package/src/components/index.js +0 -5
- package/src/index.js +0 -1
- package/src/stories/CollaborativeEditor.stories.js +0 -30
- package/src/stories/Editor.stories.js +0 -24
- package/src/stories/EditorSampleProps/ChatSample.js +0 -43
- package/src/stories/EditorSampleProps/LayoutOne.js +0 -551
- /package/{public → build}/favicon.ico +0 -0
- /package/{public → build}/logo192.png +0 -0
- /package/{public → build}/logo512.png +0 -0
- /package/{public → build}/manifest.json +0 -0
- /package/{public → build}/robots.txt +0 -0
- /package/{src/components/Editor/Toolbar/toolbarIcons/unlink.svg → build/static/media/unlink.b8761030d4a17499149d2d61adc064b3.svg} +0 -0
@@ -1,59 +0,0 @@
|
|
1
|
-
import {useRef, useState} from 'react'
|
2
|
-
import Button from '../../common/Button'
|
3
|
-
import Icon from '../../common/Icon'
|
4
|
-
import usePopup from '../../utils/customHooks/usePopup'
|
5
|
-
import {insertEquation} from '../../utils/equation.js'
|
6
|
-
import { Transforms } from 'slate'
|
7
|
-
|
8
|
-
const EquationButton = ({editor}) =>{
|
9
|
-
const equationInputRef = useRef(null);
|
10
|
-
const [showInput,setShowInput] = usePopup(equationInputRef)
|
11
|
-
const [math,setMath] = useState('')
|
12
|
-
const [displayInline,setDisplayInline] = useState(false);
|
13
|
-
const [selection,setSelection] = useState();
|
14
|
-
|
15
|
-
const toggleButton = ()=>{
|
16
|
-
setShowInput(prev => !prev);
|
17
|
-
setDisplayInline(false)
|
18
|
-
setSelection(editor.selection);
|
19
|
-
}
|
20
|
-
|
21
|
-
const handleInputChange = ({target}) =>{
|
22
|
-
if(target.type === 'checkbox'){
|
23
|
-
setDisplayInline(prev => !prev);
|
24
|
-
}
|
25
|
-
else{
|
26
|
-
setMath(target.value)
|
27
|
-
}
|
28
|
-
}
|
29
|
-
|
30
|
-
const handleAddEquation = ()=>{
|
31
|
-
if(!math) return;
|
32
|
-
selection && Transforms.select(editor,selection)
|
33
|
-
insertEquation(editor,math,displayInline);
|
34
|
-
console.log('btn click');
|
35
|
-
setShowInput(false);
|
36
|
-
}
|
37
|
-
return(
|
38
|
-
<div ref={equationInputRef} className='popup-wrapper' >
|
39
|
-
<Button format='equation' onClick={toggleButton}>
|
40
|
-
<Icon icon='equation'/>
|
41
|
-
</Button>
|
42
|
-
{
|
43
|
-
showInput &&
|
44
|
-
<div className='popup' >
|
45
|
-
<div style={{display:'flex',gap:'5px'}}>
|
46
|
-
<input type="text" value={math} onChange={handleInputChange} placeholder='Enter formula' />
|
47
|
-
<div onClick={handleAddEquation}><Icon icon='add'/></div>
|
48
|
-
</div>
|
49
|
-
<label >
|
50
|
-
<input type="checkbox" checked={displayInline} onChange={handleInputChange}/>
|
51
|
-
Inline Equation
|
52
|
-
</label>
|
53
|
-
</div>
|
54
|
-
}
|
55
|
-
</div>
|
56
|
-
)
|
57
|
-
}
|
58
|
-
|
59
|
-
export default EquationButton
|
@@ -1,48 +0,0 @@
|
|
1
|
-
import React from "react";
|
2
|
-
import { Transforms, Path } from "slate";
|
3
|
-
import { useSelected, useSlateStatic } from "slate-react";
|
4
|
-
import { gridItem } from "../../utils/gridItem";
|
5
|
-
|
6
|
-
const Grid = (props) => {
|
7
|
-
const { attributes, children, element } = props;
|
8
|
-
const { grid } = element;
|
9
|
-
const editor = useSlateStatic();
|
10
|
-
const selected = useSelected();
|
11
|
-
|
12
|
-
const onAddGridItem = () => {
|
13
|
-
const currentPath = editor.selection?.anchor?.path;
|
14
|
-
const ancestorsPath = Path.ancestors(currentPath, { reverse: true });
|
15
|
-
const insertPath = ancestorsPath[1];
|
16
|
-
if (insertPath) {
|
17
|
-
insertPath[insertPath.length - 1] = element.children.length;
|
18
|
-
Transforms.insertNodes(editor, [{ ...gridItem() }], {
|
19
|
-
at: insertPath,
|
20
|
-
});
|
21
|
-
// new line
|
22
|
-
Transforms.insertNodes(
|
23
|
-
editor,
|
24
|
-
[{ type: "paragraph", children: [{ text: "" }] }],
|
25
|
-
{
|
26
|
-
at: [editor.children.length],
|
27
|
-
}
|
28
|
-
);
|
29
|
-
}
|
30
|
-
};
|
31
|
-
|
32
|
-
const GridToolBar = () => {
|
33
|
-
return selected ? (
|
34
|
-
<div className="grid-container-toolbar" contentEditable={false}>
|
35
|
-
<button onClick={onAddGridItem}>+ Add Item</button>
|
36
|
-
</div>
|
37
|
-
) : null;
|
38
|
-
};
|
39
|
-
|
40
|
-
return (
|
41
|
-
<div className={`grid-container ${grid}`} {...attributes}>
|
42
|
-
<GridToolBar />
|
43
|
-
{children}
|
44
|
-
</div>
|
45
|
-
);
|
46
|
-
};
|
47
|
-
|
48
|
-
export default Grid;
|
@@ -1,21 +0,0 @@
|
|
1
|
-
import React from "react";
|
2
|
-
import ViewComfyIcon from "@mui/icons-material/ViewComfy";
|
3
|
-
import { insertGrid } from "../../utils/grid";
|
4
|
-
|
5
|
-
const GridButton = (props) => {
|
6
|
-
const { editor } = props;
|
7
|
-
const handleInsertGrid = () => {
|
8
|
-
insertGrid(editor);
|
9
|
-
};
|
10
|
-
return (
|
11
|
-
<button
|
12
|
-
onClick={handleInsertGrid}
|
13
|
-
title="Layout"
|
14
|
-
style={{ marginLeft: "8px" }}
|
15
|
-
>
|
16
|
-
<ViewComfyIcon />
|
17
|
-
</button>
|
18
|
-
);
|
19
|
-
};
|
20
|
-
|
21
|
-
export default GridButton;
|
@@ -1,57 +0,0 @@
|
|
1
|
-
import React from "react";
|
2
|
-
import { Transforms, Element } from "slate";
|
3
|
-
import { useSelected, useSlateStatic } from "slate-react";
|
4
|
-
|
5
|
-
const GridItem = (props) => {
|
6
|
-
const { attributes, children, element } = props;
|
7
|
-
const { grid } = element;
|
8
|
-
const editor = useSlateStatic();
|
9
|
-
const selected = useSelected();
|
10
|
-
const itemWidth = ((grid || 6) / 12) * 100;
|
11
|
-
|
12
|
-
const onItemSizeDecrease = () => {
|
13
|
-
Transforms.setNodes(
|
14
|
-
editor,
|
15
|
-
{ grid: grid <= 1 ? 1 : grid - 1 },
|
16
|
-
{
|
17
|
-
match: (node) => {
|
18
|
-
return Element.matches(node, element);
|
19
|
-
},
|
20
|
-
}
|
21
|
-
);
|
22
|
-
};
|
23
|
-
|
24
|
-
const onItemSizeIncrease = () => {
|
25
|
-
Transforms.setNodes(
|
26
|
-
editor,
|
27
|
-
{ grid: grid >= 12 ? 12 : grid + 1 },
|
28
|
-
{
|
29
|
-
match: (node) => {
|
30
|
-
return Element.matches(node, element);
|
31
|
-
},
|
32
|
-
}
|
33
|
-
);
|
34
|
-
};
|
35
|
-
|
36
|
-
const GridItemToolbar = () => {
|
37
|
-
return selected ? (
|
38
|
-
<div contentEditable={false} className="grid-item-toolbar">
|
39
|
-
<button onClick={onItemSizeDecrease}>-</button>
|
40
|
-
<button onClick={onItemSizeIncrease}>+</button>
|
41
|
-
</div>
|
42
|
-
) : null;
|
43
|
-
};
|
44
|
-
|
45
|
-
return (
|
46
|
-
<div
|
47
|
-
className={`grid-item xs-${grid}`}
|
48
|
-
{...attributes}
|
49
|
-
style={{ width: `${itemWidth}%` }}
|
50
|
-
>
|
51
|
-
{children}
|
52
|
-
<GridItemToolbar />
|
53
|
-
</div>
|
54
|
-
);
|
55
|
-
};
|
56
|
-
|
57
|
-
export default GridItem;
|
@@ -1,56 +0,0 @@
|
|
1
|
-
import { Transforms } from "slate";
|
2
|
-
import React, { useRef, useState } from "react";
|
3
|
-
import Button from "../../common/Button";
|
4
|
-
import Icon from "../../common/Icon";
|
5
|
-
import usePopup from "../../utils/customHooks/usePopup";
|
6
|
-
const Id = ({ editor }) => {
|
7
|
-
const idInputRef = useRef(null);
|
8
|
-
const [showInput, setShowInput] = usePopup(idInputRef);
|
9
|
-
const [selection, setSelection] = useState();
|
10
|
-
const [id, setId] = useState("");
|
11
|
-
const toggleId = () => {
|
12
|
-
setSelection(editor.selection);
|
13
|
-
setShowInput((prev) => !prev);
|
14
|
-
};
|
15
|
-
const handleId = () => {
|
16
|
-
// selection && Transforms.select(editor,selection);
|
17
|
-
if (!selection || !id) return;
|
18
|
-
Transforms.setNodes(
|
19
|
-
editor,
|
20
|
-
{
|
21
|
-
attr: { id },
|
22
|
-
},
|
23
|
-
{
|
24
|
-
at: selection,
|
25
|
-
}
|
26
|
-
);
|
27
|
-
setShowInput(false);
|
28
|
-
setId("");
|
29
|
-
};
|
30
|
-
return (
|
31
|
-
<div className="popup-wrapper" ref={idInputRef}>
|
32
|
-
<Button
|
33
|
-
className={showInput ? "clicked" : ""}
|
34
|
-
format={"add Id"}
|
35
|
-
onClick={toggleId}
|
36
|
-
>
|
37
|
-
<Icon icon="addId" />
|
38
|
-
</Button>
|
39
|
-
{showInput && (
|
40
|
-
<div className="popup" style={{ display: "flex", gap: "4px" }}>
|
41
|
-
<input
|
42
|
-
type="text"
|
43
|
-
placeholder="Enter an unique ID"
|
44
|
-
value={id}
|
45
|
-
onChange={(e) => setId(e.target.value)}
|
46
|
-
/>
|
47
|
-
<div onClick={handleId}>
|
48
|
-
<Icon icon="add" />
|
49
|
-
</div>
|
50
|
-
</div>
|
51
|
-
)}
|
52
|
-
</div>
|
53
|
-
);
|
54
|
-
};
|
55
|
-
|
56
|
-
export default Id;
|
@@ -1,24 +0,0 @@
|
|
1
|
-
import React from 'react';
|
2
|
-
import { useFocused, useSelected, useSlateStatic } from 'slate-react'
|
3
|
-
|
4
|
-
import {removeLink} from '../../utils/link.js'
|
5
|
-
import unlink from '../../Toolbar/toolbarIcons/unlink.svg'
|
6
|
-
import './styles.css'
|
7
|
-
const Link = ({ attributes, element, children}) => {
|
8
|
-
const editor = useSlateStatic();
|
9
|
-
const selected = useSelected();
|
10
|
-
const focused = useFocused();
|
11
|
-
return (
|
12
|
-
<div className='link' >
|
13
|
-
<a href={element.href} {...attributes} {...element.attr} target={element.target}>{children}</a>
|
14
|
-
{selected && focused && (
|
15
|
-
<div className='link-popup' contentEditable={false}>
|
16
|
-
<a href={element.href} target={element.target}>{element.href}</a>
|
17
|
-
<button onClick={()=>removeLink(editor)}><img src={unlink} alt="" /></button>
|
18
|
-
</div>
|
19
|
-
)}
|
20
|
-
</div>
|
21
|
-
)
|
22
|
-
}
|
23
|
-
|
24
|
-
export default Link
|
@@ -1,71 +0,0 @@
|
|
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
|
-
|
9
|
-
const LinkButton = (props) => {
|
10
|
-
const { editor } = props;
|
11
|
-
const linkInputRef = useRef(null);
|
12
|
-
const [showInput, setShowInput] = usePopup(linkInputRef);
|
13
|
-
const [url, setUrl] = useState("");
|
14
|
-
const [showInNewTab, setShowInNewTab] = useState(false);
|
15
|
-
const [selection, setSelection] = useState();
|
16
|
-
const handleInsertLink = () => {
|
17
|
-
Transforms.select(editor, selection);
|
18
|
-
insertLink(editor, { url, showInNewTab });
|
19
|
-
setUrl("");
|
20
|
-
setShowInput((prev) => !prev);
|
21
|
-
setShowInNewTab(false);
|
22
|
-
};
|
23
|
-
const toggleLink = () => {
|
24
|
-
setSelection(editor.selection);
|
25
|
-
setShowInput((prev) => !prev);
|
26
|
-
};
|
27
|
-
const handleInputChange = ({ target }) => {
|
28
|
-
if (target.type === "checkbox") {
|
29
|
-
setShowInNewTab((prev) => !prev);
|
30
|
-
} else {
|
31
|
-
setUrl(target.value);
|
32
|
-
}
|
33
|
-
};
|
34
|
-
return (
|
35
|
-
<div ref={linkInputRef} className="popup-wrapper">
|
36
|
-
<Button
|
37
|
-
className={showInput ? "clicked" : ""}
|
38
|
-
active={isBlockActive(editor, "link")}
|
39
|
-
format={"link"}
|
40
|
-
onClick={toggleLink}
|
41
|
-
>
|
42
|
-
<Icon icon="link" />
|
43
|
-
</Button>
|
44
|
-
{showInput && (
|
45
|
-
<div className="popup">
|
46
|
-
<div style={{ display: "flex", gap: "4px", margin: "5px 2px" }}>
|
47
|
-
<input
|
48
|
-
type="text"
|
49
|
-
placeholder="https://google.com"
|
50
|
-
value={url}
|
51
|
-
onChange={handleInputChange}
|
52
|
-
/>
|
53
|
-
<div onClick={handleInsertLink}>
|
54
|
-
<Icon icon="add" />
|
55
|
-
</div>
|
56
|
-
</div>
|
57
|
-
<label>
|
58
|
-
<input
|
59
|
-
type="checkbox"
|
60
|
-
checked={showInNewTab}
|
61
|
-
onChange={handleInputChange}
|
62
|
-
/>
|
63
|
-
<span style={{ fontSize: "0.8em" }}>Open in new tab</span>
|
64
|
-
</label>
|
65
|
-
</div>
|
66
|
-
)}
|
67
|
-
</div>
|
68
|
-
);
|
69
|
-
};
|
70
|
-
|
71
|
-
export default LinkButton;
|
@@ -1,20 +0,0 @@
|
|
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
|
-
}
|
@@ -1,37 +0,0 @@
|
|
1
|
-
import React from "react";
|
2
|
-
import { useSelected, useFocused } from "slate-react";
|
3
|
-
|
4
|
-
const Mentions = ({ attributes, children, element }) => {
|
5
|
-
const selected = useSelected();
|
6
|
-
const focused = useFocused();
|
7
|
-
const style = {
|
8
|
-
padding: "3px 3px 2px",
|
9
|
-
margin: "0 1px",
|
10
|
-
verticalAlign: "baseline",
|
11
|
-
display: "inline-block",
|
12
|
-
borderRadius: "4px",
|
13
|
-
backgroundColor: "#eee",
|
14
|
-
fontSize: "0.9em",
|
15
|
-
boxShadow: selected && focused ? "0 0 0 2px #B4D5FF" : "none",
|
16
|
-
};
|
17
|
-
// See if our empty text child has any styling marks applied and apply those
|
18
|
-
if (element.children[0].bold) {
|
19
|
-
style.fontWeight = "bold";
|
20
|
-
}
|
21
|
-
if (element.children[0].italic) {
|
22
|
-
style.fontStyle = "italic";
|
23
|
-
}
|
24
|
-
return (
|
25
|
-
<span
|
26
|
-
{...attributes}
|
27
|
-
contentEditable={false}
|
28
|
-
data-cy={`mention-${element.character.replace(" ", "-")}`}
|
29
|
-
style={style}
|
30
|
-
>
|
31
|
-
@{element.character}
|
32
|
-
{children}
|
33
|
-
</span>
|
34
|
-
);
|
35
|
-
};
|
36
|
-
|
37
|
-
export default Mentions;
|
@@ -1,29 +0,0 @@
|
|
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
|
-
|
6
|
-
const NewLineButton = (props) => {
|
7
|
-
const editor = useSlateStatic();
|
8
|
-
|
9
|
-
const onAddNewLine = () => {
|
10
|
-
Transforms.insertNodes(
|
11
|
-
editor,
|
12
|
-
[
|
13
|
-
{
|
14
|
-
type: "paragraph",
|
15
|
-
children: [{ text: "" }],
|
16
|
-
},
|
17
|
-
],
|
18
|
-
{ at: [editor.children.length] }
|
19
|
-
);
|
20
|
-
};
|
21
|
-
|
22
|
-
return (
|
23
|
-
<button title="New Line" onClick={onAddNewLine}>
|
24
|
-
<KeyboardReturnIcon />
|
25
|
-
</button>
|
26
|
-
);
|
27
|
-
};
|
28
|
-
|
29
|
-
export default NewLineButton;
|
@@ -1,13 +0,0 @@
|
|
1
|
-
import React from "react";
|
2
|
-
|
3
|
-
const Table = ({ attributes, children, element }) => {
|
4
|
-
return (
|
5
|
-
<div style={{ minWidth: "100%", maxWidth: "100%", overflow: "auto" }}>
|
6
|
-
<table>
|
7
|
-
<tbody {...attributes}>{children}</tbody>
|
8
|
-
</table>
|
9
|
-
</div>
|
10
|
-
);
|
11
|
-
};
|
12
|
-
|
13
|
-
export default Table;
|
@@ -1,18 +0,0 @@
|
|
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
|
-
}
|
@@ -1,76 +0,0 @@
|
|
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
|
-
|
7
|
-
import './TableSelector.css'
|
8
|
-
|
9
|
-
const TableSelector = ({editor})=>{
|
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({length:6},()=> Array.from ({length:6},(v,i)=>({
|
18
|
-
bg:'lightGray',
|
19
|
-
column:i,
|
20
|
-
}))))
|
21
|
-
|
22
|
-
useEffect(()=>{
|
23
|
-
const newTable = Array.from({length:6},(obj,row)=> Array.from({length:6},(v,col)=>({
|
24
|
-
bg:row+1<=tableData.row && col+1<=tableData.column ? 'orange':'lightgray',
|
25
|
-
column:col,
|
26
|
-
})))
|
27
|
-
setTableInput(newTable)
|
28
|
-
},[tableData])
|
29
|
-
useEffect(()=>{
|
30
|
-
if(!showOptions){
|
31
|
-
setTableData({
|
32
|
-
row:0,
|
33
|
-
column:0,
|
34
|
-
});
|
35
|
-
}
|
36
|
-
},[showOptions])
|
37
|
-
const table = new TableUtil(editor);
|
38
|
-
|
39
|
-
const handleButtonClick = ()=>{
|
40
|
-
setSelection(editor.selection);
|
41
|
-
setShowOptions(prev => !prev)
|
42
|
-
}
|
43
|
-
const handleInsert = () =>{
|
44
|
-
selection && Transforms.select(editor,selection)
|
45
|
-
setTableData({row:-1,column:-1})
|
46
|
-
table.insertTable(tableData.row,tableData.column)
|
47
|
-
setShowOptions(false)
|
48
|
-
}
|
49
|
-
return (
|
50
|
-
<div ref={tableOptionsRef} className='popup-wrapper' >
|
51
|
-
<button style={{border: showOptions?'1px solid lightgray':'none'}} title='table' onClick={handleButtonClick}>
|
52
|
-
<Icon icon='table'/>
|
53
|
-
</button>
|
54
|
-
{
|
55
|
-
showOptions &&
|
56
|
-
<div className='popup' >
|
57
|
-
{
|
58
|
-
|
59
|
-
<span style={{fontSize:'0.85em'}}><i>{`Insert a ${tableData.row>=1 ?`${tableData.row} x ${tableData.column}`:''} table`}</i></span>
|
60
|
-
}
|
61
|
-
<div className='table-input'>
|
62
|
-
{
|
63
|
-
tableInput.map((grp,row)=>
|
64
|
-
grp.map(({column,bg},col)=>
|
65
|
-
<div key={row+col} onClick={()=>handleInsert()} onMouseOver={()=>setTableData({row:row+1,column:column+1})} className='table-unit' style={{border:`1px solid ${bg}`}}></div>
|
66
|
-
)
|
67
|
-
)
|
68
|
-
}
|
69
|
-
</div>
|
70
|
-
</div>
|
71
|
-
}
|
72
|
-
</div>
|
73
|
-
)
|
74
|
-
}
|
75
|
-
|
76
|
-
export default TableSelector;
|
@@ -1,97 +0,0 @@
|
|
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
|
-
|
9
|
-
const TableContextMenu = (props) => {
|
10
|
-
const { editor } = props;
|
11
|
-
const [selection, setSelection] = useState();
|
12
|
-
const [showMenu, { top, left }] = useContextMenu(
|
13
|
-
editor,
|
14
|
-
"table",
|
15
|
-
setSelection
|
16
|
-
);
|
17
|
-
const table = new TableUtil(editor);
|
18
|
-
|
19
|
-
const menu = [
|
20
|
-
{
|
21
|
-
icon: "insertColumnRight",
|
22
|
-
text: "Insert Columns to the Right",
|
23
|
-
action: {
|
24
|
-
type: "insertColumn",
|
25
|
-
position: "after",
|
26
|
-
},
|
27
|
-
},
|
28
|
-
{
|
29
|
-
icon: "insertColumnLeft",
|
30
|
-
text: "Insert Columns to the Left",
|
31
|
-
action: {
|
32
|
-
type: "insertColumn",
|
33
|
-
position: "at",
|
34
|
-
},
|
35
|
-
},
|
36
|
-
{
|
37
|
-
icon: "insertRowAbove",
|
38
|
-
text: "Insert Row Above",
|
39
|
-
action: {
|
40
|
-
type: "insertRow",
|
41
|
-
positon: "at",
|
42
|
-
},
|
43
|
-
},
|
44
|
-
{
|
45
|
-
icon: "insertRowBelow",
|
46
|
-
text: "Insert Row Below",
|
47
|
-
action: {
|
48
|
-
type: "insertRow",
|
49
|
-
position: "after",
|
50
|
-
},
|
51
|
-
},
|
52
|
-
{
|
53
|
-
icon: "trashCan",
|
54
|
-
text: "Remove Table",
|
55
|
-
action: {
|
56
|
-
type: "remove",
|
57
|
-
},
|
58
|
-
},
|
59
|
-
];
|
60
|
-
|
61
|
-
const handleInsert = ({ type, position }) => {
|
62
|
-
Transforms.select(editor, selection);
|
63
|
-
switch (type) {
|
64
|
-
case "insertRow":
|
65
|
-
table.insertRow(position);
|
66
|
-
break;
|
67
|
-
case "insertColumn":
|
68
|
-
table.insertColumn(position);
|
69
|
-
break;
|
70
|
-
case "remove":
|
71
|
-
table.removeTable();
|
72
|
-
break;
|
73
|
-
default:
|
74
|
-
return;
|
75
|
-
}
|
76
|
-
ReactEditor.focus(editor);
|
77
|
-
};
|
78
|
-
|
79
|
-
return (
|
80
|
-
showMenu && (
|
81
|
-
<div className="contextMenu" style={{ top, left }}>
|
82
|
-
{menu.map(({ icon, text, action }, index) => (
|
83
|
-
<div
|
84
|
-
className="menuOption"
|
85
|
-
key={index}
|
86
|
-
onClick={() => handleInsert(action)}
|
87
|
-
>
|
88
|
-
<Icon icon={icon} />
|
89
|
-
<span>{text}</span>
|
90
|
-
</div>
|
91
|
-
))}
|
92
|
-
</div>
|
93
|
-
)
|
94
|
-
);
|
95
|
-
};
|
96
|
-
|
97
|
-
export default TableContextMenu;
|
@@ -1,18 +0,0 @@
|
|
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
|
-
}
|