@seafile/sdoc-editor 0.1.125-beta → 0.1.126
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/basic-sdk/constants/index.js +2 -1
- package/dist/basic-sdk/editor.js +173 -25
- package/dist/basic-sdk/extension/constants/index.js +71 -0
- package/dist/basic-sdk/extension/index.js +2 -2
- package/dist/basic-sdk/extension/plugins/blockquote/helpers.js +1 -2
- package/dist/basic-sdk/extension/plugins/blockquote/menu/index.js +5 -7
- package/dist/basic-sdk/extension/plugins/blockquote/render-elem.js +2 -1
- package/dist/basic-sdk/extension/plugins/check-list/helpers.js +1 -2
- package/dist/basic-sdk/extension/plugins/check-list/menu/index.js +5 -7
- package/dist/basic-sdk/extension/plugins/check-list/render-elem.js +2 -1
- package/dist/basic-sdk/extension/plugins/clear-format/helpers.js +0 -2
- package/dist/basic-sdk/extension/plugins/clear-format/menu/index.js +2 -3
- package/dist/basic-sdk/extension/plugins/code-block/helpers.js +1 -2
- package/dist/basic-sdk/extension/plugins/code-block/menu/index.js +4 -7
- package/dist/basic-sdk/extension/plugins/code-block/render-elem.js +1 -0
- package/dist/basic-sdk/extension/plugins/font/helpers.js +1 -2
- package/dist/basic-sdk/extension/plugins/font/menu/font-family/index.js +2 -3
- package/dist/basic-sdk/extension/plugins/font/menu/font-size/index.js +2 -3
- package/dist/basic-sdk/extension/plugins/font/menu/index.js +3 -6
- package/dist/basic-sdk/extension/plugins/header/helpers.js +0 -2
- package/dist/basic-sdk/extension/plugins/header/menu/index.js +2 -4
- package/dist/basic-sdk/extension/plugins/header/render-elem.js +2 -2
- package/dist/basic-sdk/extension/plugins/image/helpers.js +1 -2
- package/dist/basic-sdk/extension/plugins/image/menu/index.js +6 -8
- package/dist/basic-sdk/extension/plugins/link/helpers.js +1 -2
- package/dist/basic-sdk/extension/plugins/link/menu/add-link-dialog.js +7 -2
- package/dist/basic-sdk/extension/plugins/link/menu/index.js +6 -8
- package/dist/basic-sdk/extension/plugins/list/helpers.js +1 -2
- package/dist/basic-sdk/extension/plugins/list/menu/index.js +9 -11
- package/dist/basic-sdk/extension/plugins/list/render-elem.js +3 -1
- package/dist/basic-sdk/extension/plugins/paragraph/render-elem.js +2 -1
- package/dist/basic-sdk/extension/plugins/sdoc-link/helpers.js +1 -2
- package/dist/basic-sdk/extension/plugins/sdoc-link/menu/index.js +3 -4
- package/dist/basic-sdk/extension/plugins/sdoc-link/render-elem.js +0 -1
- package/dist/basic-sdk/extension/plugins/table/helpers.js +1 -2
- package/dist/basic-sdk/extension/plugins/table/menu/active-table-menu/cell-text-align-menu.js +3 -6
- package/dist/basic-sdk/extension/plugins/table/menu/active-table-menu/common-menu.js +2 -3
- package/dist/basic-sdk/extension/plugins/table/menu/active-table-menu/index.js +6 -12
- package/dist/basic-sdk/extension/plugins/table/menu/active-table-menu/remove-table-menu.js +3 -5
- package/dist/basic-sdk/extension/plugins/table/menu/active-table-menu/table-column-menu.js +4 -8
- package/dist/basic-sdk/extension/plugins/table/menu/active-table-menu/table-row-menu.js +4 -8
- package/dist/basic-sdk/extension/plugins/table/menu/table-menu/index.js +5 -7
- package/dist/basic-sdk/extension/plugins/table/popover/table-size-popover/index.js +11 -4
- package/dist/basic-sdk/extension/plugins/table/render/table-root.js +1 -0
- package/dist/basic-sdk/extension/plugins/text-align/helpers.js +1 -2
- package/dist/basic-sdk/extension/plugins/text-align/menu/index.js +2 -3
- package/dist/basic-sdk/extension/plugins/text-style/helpers.js +1 -2
- package/dist/basic-sdk/extension/plugins/text-style/menu/index.js +4 -5
- package/dist/basic-sdk/extension/render/render-element.js +17 -2
- package/dist/basic-sdk/extension/toolbar/header-toolbar/index.js +17 -37
- package/dist/basic-sdk/extension/toolbar/header-toolbar/redo-undo.js +4 -7
- package/dist/basic-sdk/extension/toolbar/index.js +2 -1
- package/dist/basic-sdk/extension/toolbar/side-toolbar/helpers.js +121 -0
- package/dist/basic-sdk/extension/toolbar/side-toolbar/index.css +24 -0
- package/dist/basic-sdk/extension/toolbar/side-toolbar/index.js +123 -0
- package/dist/basic-sdk/extension/toolbar/side-toolbar/insert-below-menu.js +23 -0
- package/dist/basic-sdk/extension/toolbar/side-toolbar/insert-block-menu.js +95 -0
- package/dist/basic-sdk/extension/toolbar/side-toolbar/side-menu-item.js +35 -0
- package/dist/basic-sdk/extension/toolbar/side-toolbar/side-menu.css +64 -0
- package/dist/basic-sdk/extension/toolbar/side-toolbar/side-menu.js +76 -0
- package/dist/basic-sdk/extension/toolbar/side-toolbar/transform-menus.js +41 -0
- package/dist/basic-sdk/layout/article-container.js +3 -2
- package/dist/basic-sdk/outline/index.js +1 -0
- package/dist/basic-sdk/outline/style.css +1 -5
- package/dist/basic-sdk/socket/socket-client.js +1 -1
- package/dist/basic-sdk/socket/socket-manager.js +0 -4
- package/dist/basic-sdk/socket/with-socket-io.js +0 -1
- package/dist/basic-sdk/utils/diff.js +0 -12
- package/dist/basic-sdk/views/diff-viewer.js +5 -10
- package/dist/basic-sdk/views/viewer.js +20 -20
- package/dist/components/doc-operations/index.js +0 -2
- package/dist/components/doc-operations/revision-operations/index.js +1 -5
- package/dist/pages/diff-viewer/history-version-viewer.js +15 -0
- package/dist/pages/diff-viewer/index.js +35 -0
- package/dist/pages/simple-editor.js +3 -16
- package/package.json +1 -1
- package/public/locales/en/sdoc-editor.json +7 -1
- package/public/locales/zh-CN/sdoc-editor.json +8 -1
- package/public/media/sdoc-editor-font/iconfont.eot +0 -0
- package/public/media/sdoc-editor-font/iconfont.svg +0 -4
- package/public/media/sdoc-editor-font/iconfont.ttf +0 -0
- package/public/media/sdoc-editor-font/iconfont.woff +0 -0
- package/public/media/sdoc-editor-font/iconfont.woff2 +0 -0
- package/public/media/sdoc-editor-font.css +6 -14
- package/dist/basic-sdk/layout/editor-container.js +0 -26
- package/dist/basic-sdk/layout/editor-content.js +0 -56
- package/dist/basic-sdk/layout/index.js +0 -4
- package/dist/basic-sdk/slate-editor.js +0 -149
- package/dist/components/doc-operations/revision-operations/changes-count/index.css +0 -34
- package/dist/components/doc-operations/revision-operations/changes-count/index.js +0 -85
- package/dist/pages/diff-viewer.js +0 -2
|
@@ -17,64 +17,44 @@ import HistoryMenu from './redo-undo';
|
|
|
17
17
|
import Font from '../../plugins/font/menu';
|
|
18
18
|
import SdocLinkMenu from '../../plugins/sdoc-link/menu';
|
|
19
19
|
var Toolbar = function Toolbar(_ref) {
|
|
20
|
-
var editor = _ref.editor
|
|
21
|
-
readonly = _ref.readonly;
|
|
20
|
+
var editor = _ref.editor;
|
|
22
21
|
useSelectionUpdate();
|
|
23
22
|
return /*#__PURE__*/React.createElement("div", {
|
|
24
23
|
className: "sdoc-editor-toolbar"
|
|
25
24
|
}, /*#__PURE__*/React.createElement(MenuGroup, null, /*#__PURE__*/React.createElement(HistoryMenu, {
|
|
26
|
-
editor: editor
|
|
27
|
-
readonly: readonly
|
|
25
|
+
editor: editor
|
|
28
26
|
}), /*#__PURE__*/React.createElement(ClearFormatMenu, {
|
|
29
|
-
editor: editor
|
|
30
|
-
readonly: readonly
|
|
27
|
+
editor: editor
|
|
31
28
|
})), /*#__PURE__*/React.createElement(HeaderMenu, {
|
|
32
|
-
editor: editor
|
|
33
|
-
readonly: readonly
|
|
29
|
+
editor: editor
|
|
34
30
|
}), /*#__PURE__*/React.createElement(MenuGroup, null, /*#__PURE__*/React.createElement(Font, {
|
|
35
|
-
editor: editor
|
|
36
|
-
readonly: readonly
|
|
31
|
+
editor: editor
|
|
37
32
|
}), /*#__PURE__*/React.createElement(TextStyleMenuList, {
|
|
38
|
-
editor: editor
|
|
39
|
-
readonly: readonly
|
|
33
|
+
editor: editor
|
|
40
34
|
})), /*#__PURE__*/React.createElement(MenuGroup, null, /*#__PURE__*/React.createElement(QuoteMenu, {
|
|
41
|
-
editor: editor
|
|
42
|
-
readonly: readonly
|
|
35
|
+
editor: editor
|
|
43
36
|
}), /*#__PURE__*/React.createElement(ListMenu, {
|
|
44
37
|
editor: editor,
|
|
45
|
-
type: UNORDERED_LIST
|
|
46
|
-
readonly: readonly
|
|
38
|
+
type: UNORDERED_LIST
|
|
47
39
|
}), /*#__PURE__*/React.createElement(ListMenu, {
|
|
48
40
|
editor: editor,
|
|
49
|
-
type: ORDERED_LIST
|
|
50
|
-
readonly: readonly
|
|
41
|
+
type: ORDERED_LIST
|
|
51
42
|
}), /*#__PURE__*/React.createElement(CheckListMenu, {
|
|
52
|
-
editor: editor
|
|
53
|
-
readonly: readonly
|
|
43
|
+
editor: editor
|
|
54
44
|
}), /*#__PURE__*/React.createElement(TextAlignMenu, {
|
|
55
|
-
editor: editor
|
|
56
|
-
readonly: readonly
|
|
45
|
+
editor: editor
|
|
57
46
|
})), /*#__PURE__*/React.createElement(MenuGroup, null, /*#__PURE__*/React.createElement(CodeBlockMenu, {
|
|
58
|
-
editor: editor
|
|
59
|
-
readonly: readonly
|
|
47
|
+
editor: editor
|
|
60
48
|
}), /*#__PURE__*/React.createElement(TableMenu, {
|
|
61
|
-
editor: editor
|
|
62
|
-
readonly: readonly
|
|
49
|
+
editor: editor
|
|
63
50
|
})), /*#__PURE__*/React.createElement(ActiveTableMenu, {
|
|
64
|
-
editor: editor
|
|
65
|
-
readonly: readonly
|
|
51
|
+
editor: editor
|
|
66
52
|
}), /*#__PURE__*/React.createElement(MenuGroup, null, /*#__PURE__*/React.createElement(ImageMenu, {
|
|
67
|
-
editor: editor
|
|
68
|
-
readonly: readonly
|
|
53
|
+
editor: editor
|
|
69
54
|
}), /*#__PURE__*/React.createElement(LinkMenu, {
|
|
70
|
-
editor: editor
|
|
71
|
-
readonly: readonly
|
|
55
|
+
editor: editor
|
|
72
56
|
})), /*#__PURE__*/React.createElement(MenuGroup, null, /*#__PURE__*/React.createElement(SdocLinkMenu, {
|
|
73
|
-
editor: editor
|
|
74
|
-
readonly: readonly
|
|
57
|
+
editor: editor
|
|
75
58
|
})));
|
|
76
59
|
};
|
|
77
|
-
Toolbar.defaultProps = {
|
|
78
|
-
readonly: false
|
|
79
|
-
};
|
|
80
60
|
export default Toolbar;
|
|
@@ -17,10 +17,7 @@ var HistoryMenu = /*#__PURE__*/function (_React$Component) {
|
|
|
17
17
|
}
|
|
18
18
|
_this = _super.call.apply(_super, [this].concat(args));
|
|
19
19
|
_this.isDisabled = function (type) {
|
|
20
|
-
var
|
|
21
|
-
editor = _this$props.editor,
|
|
22
|
-
readonly = _this$props.readonly;
|
|
23
|
-
if (readonly) return true;
|
|
20
|
+
var editor = _this.props.editor;
|
|
24
21
|
var history = editor.history;
|
|
25
22
|
if (type === UNDO) {
|
|
26
23
|
return history.undos.length === 0;
|
|
@@ -40,9 +37,9 @@ var HistoryMenu = /*#__PURE__*/function (_React$Component) {
|
|
|
40
37
|
_createClass(HistoryMenu, [{
|
|
41
38
|
key: "render",
|
|
42
39
|
value: function render() {
|
|
43
|
-
var _this$
|
|
44
|
-
isRichEditor = _this$
|
|
45
|
-
className = _this$
|
|
40
|
+
var _this$props = this.props,
|
|
41
|
+
isRichEditor = _this$props.isRichEditor,
|
|
42
|
+
className = _this$props.className;
|
|
46
43
|
var undoConfig = MENUS_CONFIG_MAP[UNDO];
|
|
47
44
|
var redoConfig = MENUS_CONFIG_MAP[REDO];
|
|
48
45
|
var undoProps = _objectSpread(_objectSpread({
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { Transforms, Editor } from '@seafile/slate';
|
|
2
|
+
import { ReactEditor } from '@seafile/slate-react';
|
|
3
|
+
import copy from 'copy-to-clipboard';
|
|
4
|
+
import slugid from 'slugid';
|
|
5
|
+
import { toggleList } from '../../plugins/list/transforms';
|
|
6
|
+
import { generateImageNode } from '../../plugins/image/helpers';
|
|
7
|
+
import { generateEmptyTable } from '../../plugins/table/helpers';
|
|
8
|
+
import { genLinkNode } from '../../plugins/link/helpers';
|
|
9
|
+
import { generateEmptyElement } from '../../core';
|
|
10
|
+
import { ORDERED_LIST, UNORDERED_LIST, PARAGRAPH, CHECK_LIST_ITEM, CODE_BLOCK, CODE_LINE } from '../../constants';
|
|
11
|
+
export var onSetNodeType = function onSetNodeType(editor, element, type) {
|
|
12
|
+
if (!type) return;
|
|
13
|
+
if ([ORDERED_LIST, UNORDERED_LIST].includes(type)) {
|
|
14
|
+
toggleList(editor, type);
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if (type === CHECK_LIST_ITEM) {
|
|
18
|
+
var newType = element.type === CHECK_LIST_ITEM ? PARAGRAPH : CHECK_LIST_ITEM;
|
|
19
|
+
Transforms.setNodes(editor, {
|
|
20
|
+
type: newType
|
|
21
|
+
});
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (['left', 'center', 'right'].includes(type)) {
|
|
25
|
+
Transforms.setNodes(editor, {
|
|
26
|
+
'align': type
|
|
27
|
+
});
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
Transforms.setNodes(editor, {
|
|
31
|
+
type: type
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
export var setSelection = function setSelection(editor, element) {
|
|
35
|
+
if (element) {
|
|
36
|
+
var path = ReactEditor.findPath(editor, element);
|
|
37
|
+
Transforms.select(editor, path);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
export var onCopyNode = function onCopyNode(editor) {
|
|
41
|
+
var newData = editor.setFragmentData(new DataTransfer());
|
|
42
|
+
copy('copy', {
|
|
43
|
+
onCopy: function onCopy(clipboardData) {
|
|
44
|
+
newData.types.forEach(function (type) {
|
|
45
|
+
var data = newData.getData(type);
|
|
46
|
+
clipboardData.setData(type, data);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
export var onDeleteNode = function onDeleteNode(editor, element) {
|
|
52
|
+
var path = ReactEditor.findPath(editor, element);
|
|
53
|
+
Transforms.removeNodes(editor, {
|
|
54
|
+
at: path
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
export var insertBelowImage = function insertBelowImage(editor, src, selection) {
|
|
58
|
+
if (!src) return;
|
|
59
|
+
var p = generateEmptyElement(PARAGRAPH);
|
|
60
|
+
var imageNode = generateImageNode(src);
|
|
61
|
+
p.children[0] = imageNode;
|
|
62
|
+
var path = Editor.path(editor, selection);
|
|
63
|
+
Transforms.insertNodes(editor, p, {
|
|
64
|
+
at: [path[0] + 1]
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
export var insertBelowCodeBlock = function insertBelowCodeBlock(editor, language) {
|
|
68
|
+
var newCodeBlockNode = {
|
|
69
|
+
id: slugid.nice(),
|
|
70
|
+
type: CODE_BLOCK,
|
|
71
|
+
language: language,
|
|
72
|
+
style: {
|
|
73
|
+
white_space: 'nowrap' // default nowrap
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
children: [{
|
|
77
|
+
id: slugid.nice(),
|
|
78
|
+
type: CODE_LINE,
|
|
79
|
+
children: [{
|
|
80
|
+
text: '',
|
|
81
|
+
id: slugid.nice()
|
|
82
|
+
}]
|
|
83
|
+
}]
|
|
84
|
+
};
|
|
85
|
+
var path = Editor.path(editor, editor.selection);
|
|
86
|
+
Transforms.insertNodes(editor, newCodeBlockNode, {
|
|
87
|
+
mode: 'highest',
|
|
88
|
+
at: [path[0] + 1]
|
|
89
|
+
});
|
|
90
|
+
};
|
|
91
|
+
export var insertBelowTable = function insertBelowTable(editor, size, selection) {
|
|
92
|
+
if (!size) return;
|
|
93
|
+
var tableNode = generateEmptyTable(editor, size);
|
|
94
|
+
var path = Editor.path(editor, selection);
|
|
95
|
+
Transforms.insertNodes(editor, tableNode, {
|
|
96
|
+
at: [path[0] + 1]
|
|
97
|
+
});
|
|
98
|
+
};
|
|
99
|
+
export var insertBelowLink = function insertBelowLink(editor, title, url) {
|
|
100
|
+
if (!title || !url) return;
|
|
101
|
+
var p = generateEmptyElement(PARAGRAPH);
|
|
102
|
+
var linkNode = genLinkNode(url, title);
|
|
103
|
+
p.children[0] = {
|
|
104
|
+
id: slugid.nice(),
|
|
105
|
+
text: ' '
|
|
106
|
+
};
|
|
107
|
+
p.children[1] = linkNode;
|
|
108
|
+
p.children[2] = {
|
|
109
|
+
id: slugid.nice(),
|
|
110
|
+
text: ' '
|
|
111
|
+
};
|
|
112
|
+
var path = Editor.path(editor, editor.selection);
|
|
113
|
+
Transforms.insertNodes(editor, p, {
|
|
114
|
+
at: [path[0] + 1]
|
|
115
|
+
});
|
|
116
|
+
};
|
|
117
|
+
export var getDomTopHeight = function getDomTopHeight(dom) {
|
|
118
|
+
var HEADER_HEIGHT = 56 + 44;
|
|
119
|
+
var rect = dom.getBoundingClientRect();
|
|
120
|
+
return rect.y - HEADER_HEIGHT;
|
|
121
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
.sdoc-side-toolbar-container {
|
|
2
|
+
position: absolute;
|
|
3
|
+
left: 0px;
|
|
4
|
+
top: 0px;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.sdoc-side-toolbar-container .sdoc-side-op-icon {
|
|
8
|
+
border-radius: 3px;
|
|
9
|
+
padding: 0px 3px;
|
|
10
|
+
height: 24px;
|
|
11
|
+
color: #BDBDBD;
|
|
12
|
+
margin-right: 1px;
|
|
13
|
+
transform: rotate(180deg);
|
|
14
|
+
cursor: pointer;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.sdoc-side-toolbar-container .sdoc-side-op-icon :first-child {
|
|
18
|
+
font-size: 14px;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.sdoc-side-toolbar-container .side-op-icon-active {
|
|
22
|
+
background-color: #F2F2F2;
|
|
23
|
+
border-radius: 2px;
|
|
24
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
|
2
|
+
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
3
|
+
import classnames from 'classnames';
|
|
4
|
+
import { Node } from '@seafile/slate';
|
|
5
|
+
import { ReactEditor, useSlateStatic } from '@seafile/slate-react';
|
|
6
|
+
import EventBus from '../../../utils/event-bus';
|
|
7
|
+
import { useScrollContext } from '../../../hooks/use-scroll-context';
|
|
8
|
+
import { INTERNAL_EVENT } from '../../../constants';
|
|
9
|
+
import { getDomTopHeight, setSelection } from './helpers';
|
|
10
|
+
import SideMenu from './side-menu';
|
|
11
|
+
import './index.css';
|
|
12
|
+
var SideToolbar = function SideToolbar() {
|
|
13
|
+
var editor = useSlateStatic();
|
|
14
|
+
var scrollRef = useScrollContext();
|
|
15
|
+
var menuRef = useRef(null);
|
|
16
|
+
var _useState = useState(null),
|
|
17
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
18
|
+
slateNode = _useState2[0],
|
|
19
|
+
setSlateNode = _useState2[1];
|
|
20
|
+
var _useState3 = useState({}),
|
|
21
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
22
|
+
sidePosition = _useState4[0],
|
|
23
|
+
setSidePosition = _useState4[1];
|
|
24
|
+
var _useState5 = useState(false),
|
|
25
|
+
_useState6 = _slicedToArray(_useState5, 2),
|
|
26
|
+
isActive = _useState6[0],
|
|
27
|
+
setActive = _useState6[1];
|
|
28
|
+
var _useState7 = useState(false),
|
|
29
|
+
_useState8 = _slicedToArray(_useState7, 2),
|
|
30
|
+
isNodeEmpty = _useState8[0],
|
|
31
|
+
setNodeEmpty = _useState8[1];
|
|
32
|
+
var _useState9 = useState(false),
|
|
33
|
+
_useState10 = _slicedToArray(_useState9, 2),
|
|
34
|
+
isShowSideMenu = _useState10[0],
|
|
35
|
+
setShowSideMenu = _useState10[1];
|
|
36
|
+
var _useState11 = useState({}),
|
|
37
|
+
_useState12 = _slicedToArray(_useState11, 2),
|
|
38
|
+
menuPosition = _useState12[0],
|
|
39
|
+
setMenuPosition = _useState12[1];
|
|
40
|
+
var onReset = useCallback(function () {
|
|
41
|
+
setShowSideMenu(false);
|
|
42
|
+
setMenuPosition({});
|
|
43
|
+
setSlateNode(null);
|
|
44
|
+
setActive(false);
|
|
45
|
+
}, []);
|
|
46
|
+
useEffect(function () {
|
|
47
|
+
var observerRefValue;
|
|
48
|
+
if (isShowSideMenu) {
|
|
49
|
+
scrollRef.current.addEventListener('scroll', onReset);
|
|
50
|
+
observerRefValue = scrollRef.current;
|
|
51
|
+
} else {
|
|
52
|
+
scrollRef.current.removeEventListener('scroll', onReset);
|
|
53
|
+
observerRefValue = null;
|
|
54
|
+
}
|
|
55
|
+
return function () {
|
|
56
|
+
if (observerRefValue) {
|
|
57
|
+
observerRefValue.removeEventListener('scroll', onReset);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
61
|
+
}, [isShowSideMenu]);
|
|
62
|
+
useEffect(function () {
|
|
63
|
+
var handleMouseEnter = function handleMouseEnter(e) {
|
|
64
|
+
if (isShowSideMenu) return;
|
|
65
|
+
var dom = e.target;
|
|
66
|
+
while (((_dom = dom) === null || _dom === void 0 ? void 0 : (_dom$dataset = _dom.dataset) === null || _dom$dataset === void 0 ? void 0 : _dom$dataset.root) !== 'true') {
|
|
67
|
+
var _dom, _dom$dataset;
|
|
68
|
+
if (!dom.parentNode) return;
|
|
69
|
+
dom = dom.parentNode;
|
|
70
|
+
}
|
|
71
|
+
var top = getDomTopHeight(dom);
|
|
72
|
+
var node = ReactEditor.toSlateNode(editor, dom);
|
|
73
|
+
var isEmpty = Node.string(node) === '';
|
|
74
|
+
setSidePosition({
|
|
75
|
+
top: top + scrollRef.current.scrollTop,
|
|
76
|
+
left: 20
|
|
77
|
+
});
|
|
78
|
+
setSlateNode(node);
|
|
79
|
+
setNodeEmpty(isEmpty);
|
|
80
|
+
};
|
|
81
|
+
var eventBus = EventBus.getInstance();
|
|
82
|
+
var unSubscribeMouseEnter = eventBus.subscribe(INTERNAL_EVENT.ON_MOUSE_ENTER_BLOCK, handleMouseEnter);
|
|
83
|
+
return unSubscribeMouseEnter;
|
|
84
|
+
}, [editor, isShowSideMenu, scrollRef]);
|
|
85
|
+
var onActiveToggle = useCallback(function () {
|
|
86
|
+
if (isShowSideMenu) return;
|
|
87
|
+
setActive(!isActive);
|
|
88
|
+
}, [isActive, isShowSideMenu]);
|
|
89
|
+
var onShowSideMenuToggle = useCallback(function () {
|
|
90
|
+
setSelection(editor, slateNode);
|
|
91
|
+
var _menuRef$current$getB = menuRef.current.getBoundingClientRect(),
|
|
92
|
+
top = _menuRef$current$getB.top,
|
|
93
|
+
left = _menuRef$current$getB.left;
|
|
94
|
+
setShowSideMenu(!isShowSideMenu);
|
|
95
|
+
setMenuPosition({
|
|
96
|
+
top: top,
|
|
97
|
+
left: left
|
|
98
|
+
});
|
|
99
|
+
}, [editor, isShowSideMenu, slateNode]);
|
|
100
|
+
var iconClass = classnames('sdocfont', {
|
|
101
|
+
'sdoc-more-vertical': !isActive,
|
|
102
|
+
'sdoc-more-vertical-right': isActive && !isNodeEmpty,
|
|
103
|
+
'sdoc-append': isActive && isNodeEmpty
|
|
104
|
+
});
|
|
105
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
106
|
+
className: "sdoc-side-toolbar-container",
|
|
107
|
+
style: sidePosition
|
|
108
|
+
}, slateNode && /*#__PURE__*/React.createElement("div", {
|
|
109
|
+
ref: menuRef,
|
|
110
|
+
className: "sdoc-side-op-icon",
|
|
111
|
+
onMouseEnter: onActiveToggle,
|
|
112
|
+
onMouseLeave: onActiveToggle,
|
|
113
|
+
onClick: onShowSideMenuToggle
|
|
114
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
115
|
+
className: iconClass
|
|
116
|
+
})), isShowSideMenu && /*#__PURE__*/React.createElement(SideMenu, {
|
|
117
|
+
slateNode: slateNode,
|
|
118
|
+
isNodeEmpty: isNodeEmpty,
|
|
119
|
+
menuPosition: menuPosition,
|
|
120
|
+
onReset: onReset
|
|
121
|
+
}));
|
|
122
|
+
};
|
|
123
|
+
export default SideToolbar;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { UncontrolledPopover } from 'reactstrap';
|
|
3
|
+
import { insertBelowImage, insertBelowTable, insertBelowLink, insertBelowCodeBlock } from './helpers';
|
|
4
|
+
import InsertBlockMenu from './insert-block-menu';
|
|
5
|
+
var InsertBelowMenu = function InsertBelowMenu(_ref) {
|
|
6
|
+
var target = _ref.target;
|
|
7
|
+
return /*#__PURE__*/React.createElement(UncontrolledPopover, {
|
|
8
|
+
target: target,
|
|
9
|
+
className: "sdoc-side-menu-insert-below-popover",
|
|
10
|
+
trigger: "hover",
|
|
11
|
+
placement: "right-start",
|
|
12
|
+
hideArrow: true,
|
|
13
|
+
fade: false
|
|
14
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
15
|
+
className: "sdoc-side-inner-menu"
|
|
16
|
+
}, /*#__PURE__*/React.createElement(InsertBlockMenu, {
|
|
17
|
+
insertImage: insertBelowImage,
|
|
18
|
+
insertTable: insertBelowTable,
|
|
19
|
+
insertLink: insertBelowLink,
|
|
20
|
+
insertCodeBlock: insertBelowCodeBlock
|
|
21
|
+
})));
|
|
22
|
+
};
|
|
23
|
+
export default InsertBelowMenu;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
|
2
|
+
import React, { useRef, useCallback, useState } from 'react';
|
|
3
|
+
import { withTranslation } from 'react-i18next';
|
|
4
|
+
import { Transforms } from '@seafile/slate';
|
|
5
|
+
import { useSlateStatic } from '@seafile/slate-react';
|
|
6
|
+
import context from '../../../../context';
|
|
7
|
+
import AddLinkDialog from '../../plugins/link/menu/add-link-dialog';
|
|
8
|
+
import { insertImage } from '../../plugins/image/helpers';
|
|
9
|
+
import { insertTable } from '../../plugins/table/helpers';
|
|
10
|
+
import SideMenuItem from './side-menu-item';
|
|
11
|
+
import TableSizePopover from '../../plugins/table/popover/table-size-popover';
|
|
12
|
+
import { changeToCodeBlock } from '../../plugins/code-block/helpers';
|
|
13
|
+
var InsertBlockMenu = function InsertBlockMenu(_ref) {
|
|
14
|
+
var propsInsertImage = _ref.insertImage,
|
|
15
|
+
propsInsertLink = _ref.insertLink,
|
|
16
|
+
propsInsertTable = _ref.insertTable,
|
|
17
|
+
propsInsertCodeBlock = _ref.insertCodeBlock,
|
|
18
|
+
t = _ref.t;
|
|
19
|
+
var inputRef = useRef(null);
|
|
20
|
+
var editor = useSlateStatic();
|
|
21
|
+
var _useState = useState(false),
|
|
22
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
23
|
+
isShowLinkDialog = _useState2[0],
|
|
24
|
+
setShowLinkDialog = _useState2[1];
|
|
25
|
+
var onInsertImageToggle = useCallback(function () {
|
|
26
|
+
if (propsInsertImage) {
|
|
27
|
+
inputRef.current.click();
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
Transforms.select(editor, editor.selection.focus);
|
|
31
|
+
inputRef.current.click();
|
|
32
|
+
}, [editor, propsInsertImage]);
|
|
33
|
+
var onFileChanged = useCallback(function (event) {
|
|
34
|
+
var file = event.target.files[0];
|
|
35
|
+
context.uploadLocalImage(file).then(function (fileUrl) {
|
|
36
|
+
if (propsInsertImage) {
|
|
37
|
+
propsInsertImage(editor, fileUrl, editor.selection);
|
|
38
|
+
} else {
|
|
39
|
+
insertImage(editor, fileUrl, editor.selection);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}, [editor, propsInsertImage]);
|
|
43
|
+
var createTable = useCallback(function (size) {
|
|
44
|
+
if (propsInsertTable) {
|
|
45
|
+
propsInsertTable(editor, size, editor.selection);
|
|
46
|
+
} else {
|
|
47
|
+
insertTable(editor, size, editor.selection);
|
|
48
|
+
}
|
|
49
|
+
}, [editor, propsInsertTable]);
|
|
50
|
+
var onLinkDialogToggle = useCallback(function () {
|
|
51
|
+
setShowLinkDialog(!isShowLinkDialog);
|
|
52
|
+
}, [isShowLinkDialog]);
|
|
53
|
+
var onInsertCodeBlock = useCallback(function () {
|
|
54
|
+
if (propsInsertCodeBlock) {
|
|
55
|
+
propsInsertCodeBlock(editor, 'plaintext');
|
|
56
|
+
} else {
|
|
57
|
+
changeToCodeBlock(editor, 'plaintext');
|
|
58
|
+
}
|
|
59
|
+
}, [editor, propsInsertCodeBlock]);
|
|
60
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(SideMenuItem, {
|
|
61
|
+
iconClass: "sdocfont sdoc-image",
|
|
62
|
+
iconName: t('Image'),
|
|
63
|
+
onClick: onInsertImageToggle
|
|
64
|
+
}, /*#__PURE__*/React.createElement("input", {
|
|
65
|
+
ref: inputRef,
|
|
66
|
+
type: "file",
|
|
67
|
+
accept: "image/*",
|
|
68
|
+
className: "sdoc-upload-locale-image",
|
|
69
|
+
onChange: onFileChanged
|
|
70
|
+
})), /*#__PURE__*/React.createElement(SideMenuItem, {
|
|
71
|
+
menuId: "sdoc-side-menu-item-table",
|
|
72
|
+
iconClass: "sdocfont sdoc-table",
|
|
73
|
+
iconName: t('Table'),
|
|
74
|
+
hasRight: true
|
|
75
|
+
}, /*#__PURE__*/React.createElement(TableSizePopover, {
|
|
76
|
+
target: "sdoc-side-menu-item-table",
|
|
77
|
+
trigger: "hover",
|
|
78
|
+
placement: "right-start",
|
|
79
|
+
popperClassName: "sdoc-side-menu-table-size",
|
|
80
|
+
createTable: createTable
|
|
81
|
+
})), /*#__PURE__*/React.createElement(SideMenuItem, {
|
|
82
|
+
iconClass: "sdocfont sdoc-link",
|
|
83
|
+
iconName: t('Link'),
|
|
84
|
+
onClick: onLinkDialogToggle
|
|
85
|
+
}, isShowLinkDialog && /*#__PURE__*/React.createElement(AddLinkDialog, {
|
|
86
|
+
editor: editor,
|
|
87
|
+
insertLink: propsInsertLink,
|
|
88
|
+
onLinkDialogToggle: onLinkDialogToggle
|
|
89
|
+
})), /*#__PURE__*/React.createElement(SideMenuItem, {
|
|
90
|
+
iconClass: "sdocfont sdoc-code-block",
|
|
91
|
+
iconName: t('Code_block'),
|
|
92
|
+
onClick: onInsertCodeBlock
|
|
93
|
+
}));
|
|
94
|
+
};
|
|
95
|
+
export default withTranslation('sdoc-editor')(InsertBlockMenu);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
|
2
|
+
import React, { useEffect, useState } from 'react';
|
|
3
|
+
var SideMenuItem = function SideMenuItem(_ref) {
|
|
4
|
+
var menuId = _ref.menuId,
|
|
5
|
+
iconClass = _ref.iconClass,
|
|
6
|
+
iconName = _ref.iconName,
|
|
7
|
+
_ref$hasRight = _ref.hasRight,
|
|
8
|
+
hasRight = _ref$hasRight === void 0 ? false : _ref$hasRight,
|
|
9
|
+
_ref$children = _ref.children,
|
|
10
|
+
children = _ref$children === void 0 ? null : _ref$children,
|
|
11
|
+
onClick = _ref.onClick;
|
|
12
|
+
// onMount
|
|
13
|
+
var _useState = useState(false),
|
|
14
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
15
|
+
isShowChildren = _useState2[0],
|
|
16
|
+
setShowChildren = _useState2[1];
|
|
17
|
+
useEffect(function () {
|
|
18
|
+
setShowChildren(!isShowChildren);
|
|
19
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
20
|
+
}, []);
|
|
21
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
22
|
+
id: menuId,
|
|
23
|
+
className: "sdoc-side-menu-item",
|
|
24
|
+
onClick: onClick
|
|
25
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
26
|
+
className: "sdoc-side-menu-item__left"
|
|
27
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
28
|
+
className: iconClass
|
|
29
|
+
}), /*#__PURE__*/React.createElement("span", null, iconName)), hasRight && /*#__PURE__*/React.createElement("span", {
|
|
30
|
+
className: "sdoc-side-menu-item__right"
|
|
31
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
32
|
+
className: "sdocfont sdoc-right-slide"
|
|
33
|
+
})), isShowChildren && children);
|
|
34
|
+
};
|
|
35
|
+
export default React.memo(SideMenuItem);
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
.sdoc-side-menu-popover {
|
|
2
|
+
position: absolute;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.sdoc-side-menu {
|
|
6
|
+
position: absolute;
|
|
7
|
+
width: 200px;
|
|
8
|
+
background-color: #fff;
|
|
9
|
+
border: 1px solid rgba(0, 0, 0, .12);
|
|
10
|
+
border-radius: 4px;
|
|
11
|
+
transform: translateX(-200px);
|
|
12
|
+
padding: 8px 0px;
|
|
13
|
+
box-shadow: 0 2px 12px 2px rgba(68, 73, 77, .16);
|
|
14
|
+
z-index: 999;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.sdoc-side-menu .sdoc-side-menu-item:nth-child(2),
|
|
18
|
+
.sdoc-side-inner-menu .sdoc-side-menu-item:nth-child(2) {
|
|
19
|
+
border-bottom: 1px solid var(--border-weak,rgba(0,0,0,.04));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.sdoc-side-menu .sdoc-side-menu-item,
|
|
23
|
+
.sdoc-side-inner-menu .sdoc-side-menu-item {
|
|
24
|
+
padding: 6px 16px;
|
|
25
|
+
display: flex;
|
|
26
|
+
justify-content: space-between;
|
|
27
|
+
font-size: 12px;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.sdoc-side-menu .sdoc-upload-locale-image,
|
|
31
|
+
.sdoc-side-inner-menu .sdoc-upload-locale-image {
|
|
32
|
+
display: none;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.sdoc-side-menu .sdoc-side-menu-item:hover,
|
|
36
|
+
.sdoc-side-inner-menu .sdoc-side-menu-item:hover {
|
|
37
|
+
background-color: #F2F2F2;
|
|
38
|
+
border-radius: 2px;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.sdoc-side-menu .sdoc-side-menu-item :nth-child(2),
|
|
42
|
+
.sdoc-side-inner-menu .sdoc-side-menu-item :nth-child(2) {
|
|
43
|
+
transform: scale(0.6);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.sdoc-side-menu .sdoc-side-menu-item :first-child,
|
|
47
|
+
.sdoc-side-inner-menu .sdoc-side-menu-item :first-child {
|
|
48
|
+
padding-right: 5px;
|
|
49
|
+
font-size: 12px;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.sdoc-side-menu-insert-below-popover .popover {
|
|
53
|
+
background-color: #fff;
|
|
54
|
+
min-width: 150px;
|
|
55
|
+
min-height: 120px;
|
|
56
|
+
border-radius: 2px;
|
|
57
|
+
left: -6px !important;
|
|
58
|
+
cursor: pointer;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.sdoc-side-operation-translate-popover .popover,
|
|
62
|
+
.sdoc-selected-table-size-popover .sdoc-side-menu-table-size {
|
|
63
|
+
left: -6px !important;
|
|
64
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import React, { useCallback, useEffect, useMemo } from 'react';
|
|
2
|
+
import { withTranslation } from 'react-i18next';
|
|
3
|
+
import { useSlateStatic } from '@seafile/slate-react';
|
|
4
|
+
import EventBus from '../../../utils/event-bus';
|
|
5
|
+
import { ElementPopover } from '../../commons';
|
|
6
|
+
import InsertBelowMenu from './insert-below-menu';
|
|
7
|
+
import InsertBlockMenu from './insert-block-menu';
|
|
8
|
+
import SideMenuItem from './side-menu-item';
|
|
9
|
+
import { onCopyNode, onDeleteNode } from './helpers';
|
|
10
|
+
import './side-menu.css';
|
|
11
|
+
import TransformMenus from './transform-menus';
|
|
12
|
+
var SideMenu = function SideMenu(_ref) {
|
|
13
|
+
var slateNode = _ref.slateNode,
|
|
14
|
+
isNodeEmpty = _ref.isNodeEmpty,
|
|
15
|
+
menuPosition = _ref.menuPosition,
|
|
16
|
+
onReset = _ref.onReset,
|
|
17
|
+
t = _ref.t;
|
|
18
|
+
var editor = useSlateStatic();
|
|
19
|
+
useEffect(function () {
|
|
20
|
+
var eventBus = EventBus.getInstance();
|
|
21
|
+
var unsubscribeChange = eventBus.subscribe('change', onReset);
|
|
22
|
+
return unsubscribeChange;
|
|
23
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
24
|
+
}, []);
|
|
25
|
+
var onCopy = useCallback(function () {
|
|
26
|
+
onCopyNode(editor);
|
|
27
|
+
onReset();
|
|
28
|
+
}, [editor, onReset]);
|
|
29
|
+
var onCut = useCallback(function () {
|
|
30
|
+
onCopyNode(editor);
|
|
31
|
+
onDeleteNode(editor, slateNode);
|
|
32
|
+
onReset();
|
|
33
|
+
}, [editor, onReset, slateNode]);
|
|
34
|
+
var onDelete = useCallback(function () {
|
|
35
|
+
onDeleteNode(editor, slateNode);
|
|
36
|
+
onReset();
|
|
37
|
+
}, [editor, onReset, slateNode]);
|
|
38
|
+
var menuStyle = useMemo(function () {
|
|
39
|
+
return "top: ".concat(menuPosition.top, "px; left: ").concat(menuPosition.left, "px");
|
|
40
|
+
}, [menuPosition]);
|
|
41
|
+
return /*#__PURE__*/React.createElement(ElementPopover, {
|
|
42
|
+
className: "sdoc-side-menu-popover",
|
|
43
|
+
style: menuStyle
|
|
44
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
45
|
+
className: "sdoc-side-menu"
|
|
46
|
+
}, /*#__PURE__*/React.createElement(SideMenuItem, {
|
|
47
|
+
menuId: "sdoc-side-menu-item__transform",
|
|
48
|
+
iconClass: "sdocfont sdoc-table-of-content",
|
|
49
|
+
iconName: t('Transform_to'),
|
|
50
|
+
hasRight: true
|
|
51
|
+
}, /*#__PURE__*/React.createElement(TransformMenus, {
|
|
52
|
+
target: "sdoc-side-menu-item__transform",
|
|
53
|
+
slateNode: slateNode,
|
|
54
|
+
onReset: onReset
|
|
55
|
+
})), isNodeEmpty && /*#__PURE__*/React.createElement(InsertBlockMenu, null), !isNodeEmpty && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(SideMenuItem, {
|
|
56
|
+
menuId: "sdoc-side-menu-item__below",
|
|
57
|
+
iconClass: "sdocfont sdoc-insert",
|
|
58
|
+
iconName: t('Insert_below'),
|
|
59
|
+
hasRight: true
|
|
60
|
+
}, /*#__PURE__*/React.createElement(InsertBelowMenu, {
|
|
61
|
+
target: "sdoc-side-menu-item__below"
|
|
62
|
+
})), /*#__PURE__*/React.createElement(SideMenuItem, {
|
|
63
|
+
iconClass: "sdocfont sdoc-copy",
|
|
64
|
+
iconName: t('Copy'),
|
|
65
|
+
onClick: onCopy
|
|
66
|
+
}), /*#__PURE__*/React.createElement(SideMenuItem, {
|
|
67
|
+
iconClass: "sdocfont sdoc-cut",
|
|
68
|
+
iconName: t('Cut'),
|
|
69
|
+
onClick: onCut
|
|
70
|
+
}), /*#__PURE__*/React.createElement(SideMenuItem, {
|
|
71
|
+
iconClass: "sdocfont sdoc-delete",
|
|
72
|
+
iconName: t('Delete'),
|
|
73
|
+
onClick: onDelete
|
|
74
|
+
}))));
|
|
75
|
+
};
|
|
76
|
+
export default withTranslation('sdoc-editor')(SideMenu);
|