@seafile/sdoc-editor 0.1.81 → 0.1.82
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/assets/css/sdoc-editor-plugins.css +2 -0
- package/dist/basic-sdk/extension/constants/index.js +2 -0
- package/dist/basic-sdk/extension/core/queries/index.js +15 -3
- package/dist/basic-sdk/extension/plugins/check-list/plugin.js +18 -8
- package/dist/basic-sdk/extension/plugins/header/menu/index.js +15 -3
- package/dist/basic-sdk/extension/plugins/header/plugin.js +20 -4
- package/dist/basic-sdk/extension/plugins/image/render-elem.js +1 -1
- package/dist/basic-sdk/extension/plugins/table/helpers.js +11 -0
- package/dist/basic-sdk/extension/plugins/table/render/table-header/rows-header/row-header.js +13 -0
- package/dist/basic-sdk/extension/plugins/text-align/menu/index.js +15 -3
- package/package.json +1 -1
|
@@ -57,10 +57,12 @@
|
|
|
57
57
|
.sdoc-editor-container .article .image-size {
|
|
58
58
|
display: inline-block;
|
|
59
59
|
padding: 5px;
|
|
60
|
+
white-space: nowrap;
|
|
60
61
|
height: 22px;
|
|
61
62
|
position: absolute;
|
|
62
63
|
bottom: -25px;
|
|
63
64
|
left: 100%;
|
|
65
|
+
z-index: 1;
|
|
64
66
|
transform: translateX(5px);
|
|
65
67
|
border-radius: 3px;
|
|
66
68
|
line-height: 12px;
|
|
@@ -120,4 +120,6 @@ export var ADDED_STYLE = {
|
|
|
120
120
|
computed_bg_color: '#e6ffed',
|
|
121
121
|
color: 'rgb(137, 181, 66)'
|
|
122
122
|
};
|
|
123
|
+
export var HEADER_TYPE_ARRAY = ['header1', 'header2', 'header3', 'header4', 'header5', 'header6'];
|
|
124
|
+
export var LIST_TYPE_ARRAY = ['unordered_list', 'ordered_list'];
|
|
123
125
|
export { BLOCKQUOTE, HEADER, HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6, PARAGRAPH, BOLD, ITALIC, UNDERLINE, STRIKETHROUGH, SUPERSCRIPT, SUBSCRIPT, ORDERED_LIST, UNORDERED_LIST, LIST_ITEM, LIST_LIC, CHECK_LIST, CHECK_LIST_ITEM, LINK, HTML, CODE_BLOCK, CODE_LINE, IMAGE, TABLE, TABLE_CELL, TABLE_ROW, FORMULA, COLUMN, TEXT_STYLE, TEXT_STYLE_MORE, BOLD_ITALIC, TEXT_ALIGN, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTER, ELEMENT_TYPE, KEYBOARD };
|
|
@@ -84,16 +84,28 @@ export var getSelectedNodeByType = function getSelectedNodeByType(editor, type)
|
|
|
84
84
|
nodeEntry = _Editor$nodes2[0];
|
|
85
85
|
return nodeEntry ? nodeEntry[0] : null;
|
|
86
86
|
};
|
|
87
|
-
export var
|
|
87
|
+
export var getSelectedNodeByTypes = function getSelectedNodeByTypes(editor, types) {
|
|
88
88
|
var match = function match(n) {
|
|
89
|
-
return getNodeType(n)
|
|
89
|
+
return types.includes(getNodeType(n));
|
|
90
90
|
};
|
|
91
91
|
var _Editor$nodes3 = Editor.nodes(editor, {
|
|
92
92
|
match: match,
|
|
93
|
-
universal:
|
|
93
|
+
universal: true
|
|
94
94
|
}),
|
|
95
95
|
_Editor$nodes4 = _slicedToArray(_Editor$nodes3, 1),
|
|
96
96
|
nodeEntry = _Editor$nodes4[0];
|
|
97
|
+
return nodeEntry ? nodeEntry[0] : null;
|
|
98
|
+
};
|
|
99
|
+
export var getSelectedNodeEntryByType = function getSelectedNodeEntryByType(editor, type) {
|
|
100
|
+
var match = function match(n) {
|
|
101
|
+
return getNodeType(n) === type;
|
|
102
|
+
};
|
|
103
|
+
var _Editor$nodes5 = Editor.nodes(editor, {
|
|
104
|
+
match: match,
|
|
105
|
+
universal: false
|
|
106
|
+
}),
|
|
107
|
+
_Editor$nodes6 = _slicedToArray(_Editor$nodes5, 1),
|
|
108
|
+
nodeEntry = _Editor$nodes6[0];
|
|
97
109
|
return nodeEntry ? nodeEntry : null;
|
|
98
110
|
};
|
|
99
111
|
export var getNodeEntries = function getNodeEntries(editor, options) {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Node, Range, Transforms } from '@seafile/slate';
|
|
2
2
|
import { CHECK_LIST_ITEM, PARAGRAPH } from '../../constants';
|
|
3
|
-
import { getSelectedNodeByType } from '../../core';
|
|
3
|
+
import { generateDefaultText, getSelectedNodeByType } from '../../core';
|
|
4
4
|
var withCheckList = function withCheckList(editor) {
|
|
5
5
|
var insertBreak = editor.insertBreak,
|
|
6
|
-
|
|
6
|
+
deleteBackward = editor.deleteBackward;
|
|
7
7
|
var newEditor = editor;
|
|
8
8
|
newEditor.insertBreak = function () {
|
|
9
9
|
var selection = newEditor.selection;
|
|
@@ -18,16 +18,25 @@ var withCheckList = function withCheckList(editor) {
|
|
|
18
18
|
}
|
|
19
19
|
if (Node.string(node).length === 0) {
|
|
20
20
|
Transforms.setNodes(editor, {
|
|
21
|
-
type: PARAGRAPH
|
|
21
|
+
type: PARAGRAPH,
|
|
22
|
+
children: [generateDefaultText()]
|
|
22
23
|
}, {
|
|
23
|
-
|
|
24
|
+
at: node[1]
|
|
25
|
+
});
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// If it is check-list-item, handle your own business logic
|
|
30
|
+
if (Node.string(node).length > 0) {
|
|
31
|
+
Transforms.splitNodes(editor, {
|
|
32
|
+
always: true
|
|
24
33
|
});
|
|
25
34
|
return;
|
|
26
35
|
}
|
|
27
36
|
insertBreak();
|
|
28
37
|
return;
|
|
29
38
|
};
|
|
30
|
-
newEditor.
|
|
39
|
+
newEditor.deleteBackward = function (unit) {
|
|
31
40
|
var selection = newEditor.selection;
|
|
32
41
|
if (selection && Range.isCollapsed(selection)) {
|
|
33
42
|
var selectedTodo = getSelectedNodeByType(editor, CHECK_LIST_ITEM);
|
|
@@ -35,15 +44,16 @@ var withCheckList = function withCheckList(editor) {
|
|
|
35
44
|
// If the current todo has no text, it will be converted to a paragraph
|
|
36
45
|
if (Node.string(selectedTodo).length === 0) {
|
|
37
46
|
Transforms.setNodes(editor, {
|
|
38
|
-
type: PARAGRAPH
|
|
47
|
+
type: PARAGRAPH,
|
|
48
|
+
children: [generateDefaultText()]
|
|
39
49
|
}, {
|
|
40
|
-
|
|
50
|
+
at: selectedTodo[1]
|
|
41
51
|
});
|
|
42
52
|
return;
|
|
43
53
|
}
|
|
44
54
|
}
|
|
45
55
|
}
|
|
46
|
-
|
|
56
|
+
deleteBackward(unit);
|
|
47
57
|
};
|
|
48
58
|
return newEditor;
|
|
49
59
|
};
|
|
@@ -16,12 +16,15 @@ var HeaderMenu = /*#__PURE__*/function (_React$Component) {
|
|
|
16
16
|
_classCallCheck(this, HeaderMenu);
|
|
17
17
|
_this = _super.call(this, props);
|
|
18
18
|
_this.registerEventHandler = function () {
|
|
19
|
-
document.addEventListener('click', _this.onHideHeaderMenu);
|
|
19
|
+
document.addEventListener('click', _this.onHideHeaderMenu, true);
|
|
20
20
|
};
|
|
21
21
|
_this.unregisterEventHandler = function () {
|
|
22
|
-
document.removeEventListener('click', _this.onHideHeaderMenu);
|
|
22
|
+
document.removeEventListener('click', _this.onHideHeaderMenu, true);
|
|
23
23
|
};
|
|
24
|
-
_this.onHideHeaderMenu = function () {
|
|
24
|
+
_this.onHideHeaderMenu = function (e) {
|
|
25
|
+
var menu = _this.menu;
|
|
26
|
+
var clickIsInMenu = menu && menu.contains(e.target) && menu !== e.target;
|
|
27
|
+
if (clickIsInMenu) return;
|
|
25
28
|
_this.setState({
|
|
26
29
|
isShowHeaderPopover: false
|
|
27
30
|
}, function () {
|
|
@@ -65,8 +68,16 @@ var HeaderMenu = /*#__PURE__*/function (_React$Component) {
|
|
|
65
68
|
|
|
66
69
|
// 执行命令
|
|
67
70
|
setHeaderType(editor, newType);
|
|
71
|
+
_this.setState({
|
|
72
|
+
isShowHeaderPopover: false
|
|
73
|
+
}, function () {
|
|
74
|
+
_this.unregisterEventHandler();
|
|
75
|
+
});
|
|
68
76
|
};
|
|
69
77
|
};
|
|
78
|
+
_this.setMenuRef = function (ref) {
|
|
79
|
+
_this.menu = ref;
|
|
80
|
+
};
|
|
70
81
|
_this.state = {
|
|
71
82
|
isShowHeaderPopover: false
|
|
72
83
|
};
|
|
@@ -92,6 +103,7 @@ var HeaderMenu = /*#__PURE__*/function (_React$Component) {
|
|
|
92
103
|
}, t(HEADER_TITLE_MAP[headerType])), !disabled && /*#__PURE__*/React.createElement("span", {
|
|
93
104
|
className: headerIconClass
|
|
94
105
|
})), isShowHeaderPopover && /*#__PURE__*/React.createElement("div", {
|
|
106
|
+
ref: this.setMenuRef,
|
|
95
107
|
className: "header-popover sdoc-dropdown-menu"
|
|
96
108
|
}, /*#__PURE__*/React.createElement("div", {
|
|
97
109
|
className: "sdoc-dropdown-menu-item",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
|
2
|
-
import { Editor, Element, Transforms } from '@seafile/slate';
|
|
3
|
-
import { PARAGRAPH } from '../../constants';
|
|
4
|
-
import { generateEmptyElement } from '../../core';
|
|
2
|
+
import { Editor, Element, Transforms, Node } from '@seafile/slate';
|
|
3
|
+
import { PARAGRAPH, HEADER_TYPE_ARRAY, LIST_TYPE_ARRAY } from '../../constants';
|
|
4
|
+
import { generateEmptyElement, getSelectedNodeByTypes } from '../../core';
|
|
5
5
|
var isSelectionAtLineEnd = function isSelectionAtLineEnd(editor, path) {
|
|
6
6
|
var selection = editor.selection;
|
|
7
7
|
if (!selection) return false;
|
|
@@ -9,7 +9,9 @@ var isSelectionAtLineEnd = function isSelectionAtLineEnd(editor, path) {
|
|
|
9
9
|
return isAtLineEnd;
|
|
10
10
|
};
|
|
11
11
|
var withHeader = function withHeader(editor) {
|
|
12
|
-
var insertBreak = editor.insertBreak
|
|
12
|
+
var insertBreak = editor.insertBreak,
|
|
13
|
+
insertFragment = editor.insertFragment,
|
|
14
|
+
insertText = editor.insertText;
|
|
13
15
|
var newEditor = editor;
|
|
14
16
|
|
|
15
17
|
// Rewrite insertBreak - insert paragraph when carriage return at the end of header
|
|
@@ -51,6 +53,20 @@ var withHeader = function withHeader(editor) {
|
|
|
51
53
|
insertBreak();
|
|
52
54
|
}
|
|
53
55
|
};
|
|
56
|
+
newEditor.insertFragment = function (data) {
|
|
57
|
+
var headerNode = getSelectedNodeByTypes(editor, HEADER_TYPE_ARRAY);
|
|
58
|
+
var headerText = Node.string(headerNode || {
|
|
59
|
+
children: []
|
|
60
|
+
});
|
|
61
|
+
var isSingleListItem = data.length === 1 && data[0].children.length === 1 && LIST_TYPE_ARRAY.includes(data[0].type);
|
|
62
|
+
// Insert a list item when the header is empty, insert only the text
|
|
63
|
+
if (headerNode && headerText.length === 0 && isSingleListItem) {
|
|
64
|
+
var text = Node.string(data[0]);
|
|
65
|
+
insertText(text);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
return insertFragment(data);
|
|
69
|
+
};
|
|
54
70
|
return newEditor;
|
|
55
71
|
};
|
|
56
72
|
export default withHeader;
|
|
@@ -464,4 +464,15 @@ export var getFirstTableCell = function getFirstTableCell(element) {
|
|
|
464
464
|
tableCellElement = tableCellElement.parentNode;
|
|
465
465
|
}
|
|
466
466
|
return tableCellElement;
|
|
467
|
+
};
|
|
468
|
+
export var rowElementHasImage = function rowElementHasImage(element) {
|
|
469
|
+
if (!element) return false;
|
|
470
|
+
if (!Array.isArray(element.children) || element.children.length === 0) return false;
|
|
471
|
+
return element.children.some(function (child) {
|
|
472
|
+
if (child.type === ELEMENT_TYPE.IMAGE) return true;
|
|
473
|
+
if (ObjectUtils.hasProperty(child, 'children')) {
|
|
474
|
+
return rowElementHasImage(child);
|
|
475
|
+
}
|
|
476
|
+
return false;
|
|
477
|
+
});
|
|
467
478
|
};
|
package/dist/basic-sdk/extension/plugins/table/render/table-header/rows-header/row-header.js
CHANGED
|
@@ -8,6 +8,7 @@ import { useResizeHandlersContext, useTableSelectedRangeContext } from '../../ho
|
|
|
8
8
|
import { useScrollContext } from '../../../../../../hooks/use-scroll-context';
|
|
9
9
|
import { ELEMENT_TYPE } from '../../../../../constants';
|
|
10
10
|
import { findPath, getSelectedNodeByType } from '../../../../../core';
|
|
11
|
+
import { rowElementHasImage } from '../../../helpers';
|
|
11
12
|
var RowHeader = function RowHeader(_ref) {
|
|
12
13
|
var _row$style;
|
|
13
14
|
var row = _ref.row,
|
|
@@ -30,6 +31,18 @@ var RowHeader = function RowHeader(_ref) {
|
|
|
30
31
|
var currentCellPath = currentCell ? findPath(editor, currentCell, [-1, -1]) : [-1, -1];
|
|
31
32
|
var pathLength = currentCellPath.length;
|
|
32
33
|
useEffect(function () {
|
|
34
|
+
if (rowElementHasImage(row)) {
|
|
35
|
+
var time = setTimeout(function () {
|
|
36
|
+
// There is a delay in image loading
|
|
37
|
+
var rowDom = ReactEditor.toDOMNode(editor, row);
|
|
38
|
+
if (!rowDom) return;
|
|
39
|
+
if (rowHeight === rowDom.clientHeight) return;
|
|
40
|
+
setRowHeight(rowDom.clientHeight);
|
|
41
|
+
}, 300);
|
|
42
|
+
return function () {
|
|
43
|
+
clearTimeout(time);
|
|
44
|
+
};
|
|
45
|
+
}
|
|
33
46
|
var rowDom = ReactEditor.toDOMNode(editor, row);
|
|
34
47
|
if (!rowDom) return;
|
|
35
48
|
if (rowHeight === rowDom.clientHeight) return;
|
|
@@ -16,12 +16,15 @@ var TextAlignMenu = /*#__PURE__*/function (_React$Component) {
|
|
|
16
16
|
_classCallCheck(this, TextAlignMenu);
|
|
17
17
|
_this = _super.call(this, props);
|
|
18
18
|
_this.registerEventHandler = function () {
|
|
19
|
-
document.addEventListener('click', _this.onHideTextAlignMenu);
|
|
19
|
+
document.addEventListener('click', _this.onHideTextAlignMenu, true);
|
|
20
20
|
};
|
|
21
21
|
_this.unregisterEventHandler = function () {
|
|
22
|
-
document.removeEventListener('click', _this.onHideTextAlignMenu);
|
|
22
|
+
document.removeEventListener('click', _this.onHideTextAlignMenu, true);
|
|
23
23
|
};
|
|
24
|
-
_this.onHideTextAlignMenu = function () {
|
|
24
|
+
_this.onHideTextAlignMenu = function (e) {
|
|
25
|
+
var menu = _this.menu;
|
|
26
|
+
var clickIsInMenu = menu && menu.contains(e.target) && menu !== e.target;
|
|
27
|
+
if (clickIsInMenu) return;
|
|
25
28
|
_this.setState({
|
|
26
29
|
isDropdownMenuOpen: false
|
|
27
30
|
}, function () {
|
|
@@ -60,6 +63,14 @@ var TextAlignMenu = /*#__PURE__*/function (_React$Component) {
|
|
|
60
63
|
_this.setType = function (type) {
|
|
61
64
|
var editor = _this.props.editor;
|
|
62
65
|
setAlignType(editor, type);
|
|
66
|
+
_this.setState({
|
|
67
|
+
isDropdownMenuOpen: false
|
|
68
|
+
}, function () {
|
|
69
|
+
_this.unregisterEventHandler();
|
|
70
|
+
});
|
|
71
|
+
};
|
|
72
|
+
_this.setMenuRef = function (ref) {
|
|
73
|
+
_this.menu = ref;
|
|
63
74
|
};
|
|
64
75
|
_this.state = {
|
|
65
76
|
isDropdownMenuOpen: false
|
|
@@ -89,6 +100,7 @@ var TextAlignMenu = /*#__PURE__*/function (_React$Component) {
|
|
|
89
100
|
}), !disabled && /*#__PURE__*/React.createElement("span", {
|
|
90
101
|
className: caretIconClass
|
|
91
102
|
})), isDropdownMenuOpen && /*#__PURE__*/React.createElement("div", {
|
|
103
|
+
ref: this.setMenuRef,
|
|
92
104
|
className: "align-popover sdoc-dropdown-menu"
|
|
93
105
|
}, MENUS_CONFIG_MAP[TEXT_ALIGN].map(function (item, index) {
|
|
94
106
|
return /*#__PURE__*/React.createElement("span", {
|