@seafile/sdoc-editor 0.1.53 → 0.1.54

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.
Files changed (25) hide show
  1. package/dist/basic-sdk/editor.js +13 -2
  2. package/dist/basic-sdk/extension/constants/index.js +2 -1
  3. package/dist/basic-sdk/extension/menu/context-menu/index.js +2 -1
  4. package/dist/basic-sdk/extension/plugins/link/menu/hover-link-dialog.js +4 -4
  5. package/dist/basic-sdk/extension/plugins/table/constants/index.js +7 -1
  6. package/dist/basic-sdk/extension/plugins/table/helpers.js +216 -2
  7. package/dist/basic-sdk/extension/plugins/table/menu/active-table-menu/index.js +10 -10
  8. package/dist/basic-sdk/extension/plugins/table/menu/context-menu/index.js +18 -6
  9. package/dist/basic-sdk/extension/plugins/table/menu/context-menu/insert-table-element.js +1 -1
  10. package/dist/basic-sdk/extension/plugins/table/plugin.js +64 -256
  11. package/dist/basic-sdk/extension/plugins/table/render/context.js +5 -0
  12. package/dist/basic-sdk/extension/plugins/table/render/render-cell.js +35 -16
  13. package/dist/basic-sdk/extension/plugins/table/render/render-row.js +7 -16
  14. package/dist/basic-sdk/extension/plugins/table/render/render-table/index.css +34 -0
  15. package/dist/basic-sdk/extension/plugins/table/render/render-table/index.js +81 -28
  16. package/dist/constants/index.js +2 -1
  17. package/package.json +2 -1
  18. package/public/locales/en/sdoc-editor.json +3 -8
  19. package/public/locales/zh-CN/sdoc-editor.json +5 -5
  20. package/public/media/sdoc-editor-font/iconfont.eot +0 -0
  21. package/public/media/sdoc-editor-font/iconfont.svg +6 -0
  22. package/public/media/sdoc-editor-font/iconfont.ttf +0 -0
  23. package/public/media/sdoc-editor-font/iconfont.woff +0 -0
  24. package/public/media/sdoc-editor-font/iconfont.woff2 +0 -0
  25. package/public/media/sdoc-editor-font.css +4 -0
@@ -9,6 +9,9 @@ import withNodeId from './node-id';
9
9
  import SDocOutline from './outline';
10
10
  import EventProxy from './utils/event-handler';
11
11
  import { useCursors } from './cursor/use-cursors';
12
+ import EventBus from './utils/event-bus';
13
+ import { EXTERNAL_EVENT } from '../constants';
14
+ import { isAllInTable } from './extension/plugins/table/helpers';
12
15
  import './assets/css/layout.css';
13
16
  import './assets/css/sdoc-editor-plugins.css';
14
17
  var SDocEditor = function SDocEditor(_ref) {
@@ -45,6 +48,7 @@ var SDocEditor = function SDocEditor(_ref) {
45
48
  var eventProxy = useMemo(function () {
46
49
  return new EventProxy(editor);
47
50
  }, []);
51
+ var eventBus = EventBus.getInstance();
48
52
 
49
53
  // useMount: init socket connection
50
54
  useEffect(function () {
@@ -64,7 +68,7 @@ var SDocEditor = function SDocEditor(_ref) {
64
68
  // eslint-disable-next-line react-hooks/exhaustive-deps
65
69
  }, []);
66
70
  var onContextMenu = useCallback(function (event) {
67
- if (editor.isAllInTable()) {
71
+ if (isAllInTable(editor)) {
68
72
  event.preventDefault();
69
73
  var contextMenuPosition = {
70
74
  left: event.clientX,
@@ -80,6 +84,12 @@ var SDocEditor = function SDocEditor(_ref) {
80
84
  setContextMenu(false);
81
85
  // eslint-disable-next-line react-hooks/exhaustive-deps
82
86
  }, []);
87
+ var onMouseDown = useCallback(function (event) {
88
+ if (event.button === 0) {
89
+ eventBus.dispatch(EXTERNAL_EVENT.CANCEL_TABLE_SELECT_RANGE);
90
+ }
91
+ // eslint-disable-next-line react-hooks/exhaustive-deps
92
+ }, []);
83
93
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
84
94
  className: "sdoc-editor-container"
85
95
  }, /*#__PURE__*/React.createElement(Toolbar, {
@@ -102,7 +112,8 @@ var SDocEditor = function SDocEditor(_ref) {
102
112
  renderLeaf: renderLeaf,
103
113
  onKeyDown: eventProxy.onKeyDown,
104
114
  cursors: cursors,
105
- onContextMenu: onContextMenu
115
+ onContextMenu: onContextMenu,
116
+ onMouseDown: onMouseDown
106
117
  })))))), isShowContextMenu && /*#__PURE__*/React.createElement(ContextMenu, {
107
118
  editor: editor,
108
119
  contextMenuPosition: menuPosition
@@ -1,5 +1,5 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
2
- var _MENUS_CONFIG_MAP, _HEADER_TITLE_MAP;
2
+ var _MENUS_CONFIG_MAP, _HEADER_TITLE_MAP, _TABLE_ELEMENT_SPAN;
3
3
  // extension plugin
4
4
  import * as ELEMENT_TYPE from './element-type';
5
5
  import { BLOCKQUOTE, HEADER, HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6, PARAGRAPH, BOLD, ITALIC, UNDERLINE, STRIKETHROUGH, 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, BOLD_ITALIC } from './element-type';
@@ -96,6 +96,7 @@ export var TABLE_ELEMENT = {
96
96
  COLUMN: 'column',
97
97
  CELL: 'cell'
98
98
  };
99
+ export var TABLE_ELEMENT_SPAN = (_TABLE_ELEMENT_SPAN = {}, _defineProperty(_TABLE_ELEMENT_SPAN, TABLE_ELEMENT.TABLE, 'table'), _defineProperty(_TABLE_ELEMENT_SPAN, TABLE_ELEMENT.ROW, 'tr'), _defineProperty(_TABLE_ELEMENT_SPAN, TABLE_ELEMENT.CELL, 'td'), _TABLE_ELEMENT_SPAN);
99
100
  export var TABLE_ELEMENT_POSITION = {
100
101
  AFTER: 'after',
101
102
  BEFORE: 'before'
@@ -5,6 +5,7 @@ import _createSuper from "@babel/runtime/helpers/esm/createSuper";
5
5
  import React, { Component } from 'react';
6
6
  import ModalPortal from '../../../../components/modal-portal';
7
7
  import { TablePlugin } from '../../plugins';
8
+ import { isAllInTable } from '../../plugins/table/helpers';
8
9
  var ContextMenu = /*#__PURE__*/function (_Component) {
9
10
  _inherits(ContextMenu, _Component);
10
11
  var _super = _createSuper(ContextMenu);
@@ -17,7 +18,7 @@ var ContextMenu = /*#__PURE__*/function (_Component) {
17
18
  _this = _super.call.apply(_super, [this].concat(args));
18
19
  _this.renderContextMenu = function () {
19
20
  var editor = _this.props.editor;
20
- if (editor.isAllInTable()) {
21
+ if (isAllInTable(editor)) {
21
22
  var ContextMenuComponent = TablePlugin.contextMenu;
22
23
  return /*#__PURE__*/React.createElement(ContextMenuComponent, _this.props);
23
24
  }
@@ -34,15 +34,15 @@ var LinkHoverComponent = /*#__PURE__*/function (_React$Component) {
34
34
  }, /*#__PURE__*/React.createElement("span", {
35
35
  role: "button",
36
36
  className: "link-op-icon",
37
- onClick: this.props.onDeleteLink
37
+ onClick: this.props.onEditLink
38
38
  }, /*#__PURE__*/React.createElement("i", {
39
- className: "sdocfont sdoc-delete"
39
+ className: "sdocfont sdoc-rename"
40
40
  })), /*#__PURE__*/React.createElement("span", {
41
41
  role: "button",
42
42
  className: "link-op-icon",
43
- onClick: this.props.onEditLink
43
+ onClick: this.props.onDeleteLink
44
44
  }, /*#__PURE__*/React.createElement("i", {
45
- className: "sdocfont sdoc-rename"
45
+ className: "sdocfont sdoc-unlink"
46
46
  }))), /*#__PURE__*/React.createElement("span", {
47
47
  className: "link-op-menu-triangle"
48
48
  })), document.body));
@@ -1,2 +1,8 @@
1
1
  export var TABLE_MAX_ROWS = 50;
2
- export var TABLE_MAX_COLUMNS = 50;
2
+ export var TABLE_MAX_COLUMNS = 50;
3
+ export var EMPTY_SELECTED_RANGE = {
4
+ minRowIndex: -1,
5
+ maxRowIndex: -1,
6
+ minColIndex: -1,
7
+ maxColIndex: -1
8
+ };
@@ -1,8 +1,15 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
2
+ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
1
3
  import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
2
4
  import slugid from 'slugid';
3
5
  import { Editor, Range, Transforms } from '@seafile/slate';
4
- import { ELEMENT_TYPE } from '../../constants';
5
- import { getNodeType, getParentNode, isTextNode } from '../../core';
6
+ import { getNodeType, getParentNode, getSelectedNodeByType, isTextNode, getSelectedElems, replaceNodeChildren, focusEditor } from '../../core';
7
+ import { getNodePathById } from '../../../socket/helpers';
8
+ import { ELEMENT_TYPE, TABLE_ELEMENT, TABLE_ELEMENT_POSITION } from '../../constants';
9
+ import { TABLE_MAX_ROWS, TABLE_MAX_COLUMNS, EMPTY_SELECTED_RANGE } from './constants';
10
+ import EventBus from '../../../utils/event-bus';
11
+ import { EXTERNAL_EVENT } from '../../../../constants';
12
+ import ObjectUtils from '../../../utils/object-utils';
6
13
  export var isTableMenuDisabled = function isTableMenuDisabled(editor) {
7
14
  var selection = editor.selection;
8
15
  if (selection === null) return true;
@@ -78,4 +85,211 @@ export var insertTable = function insertTable(editor, size, selection) {
78
85
  Transforms.insertNodes(editor, tableNode, {
79
86
  at: selection
80
87
  });
88
+ };
89
+ export var getSelectedInfo = function getSelectedInfo(editor) {
90
+ var currentTable = getSelectedNodeByType(editor, ELEMENT_TYPE.TABLE);
91
+ var currentRow = getSelectedNodeByType(editor, ELEMENT_TYPE.TABLE_ROW);
92
+ var currentCell = getSelectedNodeByType(editor, ELEMENT_TYPE.TABLE_CELL);
93
+ var currentCellPath = getNodePathById(editor, currentCell.id);
94
+ return {
95
+ table: currentTable,
96
+ tablePath: getNodePathById(editor, currentTable.id),
97
+ tableSize: [currentTable.children.length, currentRow.children.length],
98
+ row: currentRow,
99
+ rowPath: getNodePathById(editor, currentRow.id),
100
+ rowIndex: currentCellPath[currentCellPath.length - 2],
101
+ cell: currentCell,
102
+ cellPath: getNodePathById(editor, currentCell.id),
103
+ cellIndex: currentCellPath[currentCellPath.length - 1]
104
+ };
105
+ };
106
+ export var isInTable = function isInTable(editor) {
107
+ var selectedNodes = getSelectedElems(editor);
108
+ if (!selectedNodes.some(function (node) {
109
+ return node.type === ELEMENT_TYPE.TABLE;
110
+ })) return false;
111
+ var firstSelectedNode = selectedNodes[0];
112
+ return firstSelectedNode.type === ELEMENT_TYPE.TABLE;
113
+ };
114
+ export var isAllInTable = function isAllInTable(editor) {
115
+ var selectedNodes = getSelectedElems(editor);
116
+ if (!selectedNodes.some(function (node) {
117
+ return node.type === ELEMENT_TYPE.TABLE;
118
+ })) return false;
119
+ var firstSelectedNode = selectedNodes[0];
120
+ if (firstSelectedNode.type !== ELEMENT_TYPE.TABLE) return false;
121
+ return selectedNodes.slice(1).every(function (node) {
122
+ return [ELEMENT_TYPE.TABLE_ROW, ELEMENT_TYPE.TABLE_CELL].includes(node.type);
123
+ }); // same table element
124
+ };
125
+
126
+ export var setTextStyle = function setTextStyle(editor, style) {
127
+ var selectedNodes = getSelectedElems(editor);
128
+ var firstTableCellNodePath;
129
+ selectedNodes.forEach(function (node) {
130
+ if (node.type === ELEMENT_TYPE.TABLE_CELL) {
131
+ var targetNode = node.children[0];
132
+ var path = getNodePathById(editor, node.id);
133
+ firstTableCellNodePath = firstTableCellNodePath ? firstTableCellNodePath : path;
134
+ replaceNodeChildren(editor, {
135
+ at: path,
136
+ nodes: _objectSpread(_objectSpread({}, targetNode), style)
137
+ });
138
+ }
139
+ });
140
+ if (firstTableCellNodePath) {
141
+ var start = Editor.start(editor, firstTableCellNodePath);
142
+ var end = Editor.end(editor, firstTableCellNodePath);
143
+ var newSelection = {
144
+ anchor: start,
145
+ focus: end
146
+ };
147
+ Transforms.select(editor, newSelection);
148
+ }
149
+ };
150
+ export var insertTableElement = function insertTableElement(editor, type) {
151
+ var position = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : TABLE_ELEMENT_POSITION.AFTER;
152
+ var count = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1;
153
+ var _getSelectedInfo = getSelectedInfo(editor),
154
+ tablePath = _getSelectedInfo.tablePath,
155
+ tableSize = _getSelectedInfo.tableSize,
156
+ rowIndex = _getSelectedInfo.rowIndex,
157
+ cellIndex = _getSelectedInfo.cellIndex;
158
+ var eventBus = EventBus.getInstance();
159
+ eventBus.dispatch(EXTERNAL_EVENT.CANCEL_TABLE_SELECT_RANGE);
160
+ if (type === TABLE_ELEMENT.ROW) {
161
+ if (tableSize[0] >= TABLE_MAX_ROWS) return;
162
+ var targetPath = position === TABLE_ELEMENT_POSITION.AFTER ? [].concat(_toConsumableArray(tablePath), [rowIndex + 1]) : [].concat(_toConsumableArray(tablePath), [rowIndex]);
163
+ var validCount = Math.min(TABLE_MAX_ROWS - tableSize[0], count);
164
+ for (var i = 0; i < validCount; i++) {
165
+ var row = generateTableRow(tableSize[1]);
166
+ Transforms.insertNodes(editor, row, {
167
+ at: targetPath
168
+ });
169
+ }
170
+ var focusPath = [].concat(_toConsumableArray(targetPath), [cellIndex]);
171
+ focusEditor(editor, focusPath);
172
+ return;
173
+ }
174
+ if (type === TABLE_ELEMENT.COLUMN) {
175
+ if (tableSize[1] >= TABLE_MAX_COLUMNS) return;
176
+ var newCellIndex = position === TABLE_ELEMENT_POSITION.AFTER ? cellIndex + 1 : cellIndex;
177
+ var _validCount = Math.min(TABLE_MAX_COLUMNS - tableSize[1], count);
178
+ for (var j = 0; j < _validCount; j++) {
179
+ for (var _i = 0; _i < tableSize[0]; _i++) {
180
+ var newCellPath = [].concat(_toConsumableArray(tablePath), [_i, newCellIndex]);
181
+ var newCell = generateTableCell();
182
+ Transforms.insertNodes(editor, newCell, {
183
+ at: newCellPath
184
+ });
185
+ }
186
+ }
187
+ var _focusPath = [].concat(_toConsumableArray(tablePath), [rowIndex, cellIndex + 1, 0]);
188
+ focusEditor(editor, _focusPath);
189
+ return;
190
+ }
191
+ };
192
+ var removeTable = function removeTable(editor, path) {
193
+ var validPath = path;
194
+ if (!validPath) {
195
+ var _getSelectedInfo2 = getSelectedInfo(editor),
196
+ tablePath = _getSelectedInfo2.tablePath;
197
+ validPath = tablePath;
198
+ }
199
+ var tableIndex = validPath[validPath.length - 1];
200
+ var tableParentPath = validPath.slice(0, validPath.length - 1);
201
+ var targetNodeIndex = tableIndex >= 1 ? tableIndex - 1 : 1;
202
+ var targetNodePath = [].concat(_toConsumableArray(tableParentPath), [targetNodeIndex]);
203
+ Transforms.removeNodes(editor, {
204
+ at: path
205
+ });
206
+ focusEditor(editor, targetNodePath);
207
+ };
208
+ export var removeTableElement = function removeTableElement(editor, type) {
209
+ var _getSelectedInfo3 = getSelectedInfo(editor),
210
+ tablePath = _getSelectedInfo3.tablePath,
211
+ tableSize = _getSelectedInfo3.tableSize,
212
+ rowPath = _getSelectedInfo3.rowPath,
213
+ rowIndex = _getSelectedInfo3.rowIndex,
214
+ cellIndex = _getSelectedInfo3.cellIndex;
215
+ var eventBus = EventBus.getInstance();
216
+ eventBus.dispatch(EXTERNAL_EVENT.CANCEL_TABLE_SELECT_RANGE);
217
+ if (type === TABLE_ELEMENT.TABLE) {
218
+ removeTable(editor, tablePath);
219
+ return;
220
+ }
221
+ if (type === TABLE_ELEMENT.ROW) {
222
+ if (tableSize[0] === 1) {
223
+ removeTable(editor, tablePath);
224
+ return;
225
+ }
226
+ if (!ObjectUtils.isSameObject(editor.tableSelectedRange, EMPTY_SELECTED_RANGE)) {
227
+ var _editor$tableSelected = editor.tableSelectedRange,
228
+ minRowIndex = _editor$tableSelected.minRowIndex,
229
+ maxRowIndex = _editor$tableSelected.maxRowIndex;
230
+ if (minRowIndex === 0 && maxRowIndex === tableSize[0] - 1) {
231
+ removeTable(editor, tablePath);
232
+ return;
233
+ }
234
+ for (var i = minRowIndex; i <= maxRowIndex; i++) {
235
+ Transforms.removeNodes(editor, {
236
+ at: [].concat(_toConsumableArray(tablePath), [minRowIndex])
237
+ });
238
+ }
239
+ var _focusPath2 = [].concat(_toConsumableArray(tablePath), [minRowIndex === 0 ? 0 : minRowIndex - 1, cellIndex]);
240
+ focusEditor(editor, _focusPath2);
241
+ return;
242
+ }
243
+ Transforms.removeNodes(editor, {
244
+ at: rowPath
245
+ });
246
+ var focusRowIndex = rowIndex === tableSize[0] - 1 ? rowIndex - 1 : rowIndex;
247
+ var focusPath = [].concat(_toConsumableArray(tablePath), [focusRowIndex, cellIndex]);
248
+ focusEditor(editor, focusPath);
249
+ return;
250
+ }
251
+ if (type === TABLE_ELEMENT.COLUMN) {
252
+ if (tableSize[1] === 1) {
253
+ removeTable(editor, tablePath);
254
+ return;
255
+ }
256
+ if (!ObjectUtils.isSameObject(editor.tableSelectedRange, EMPTY_SELECTED_RANGE)) {
257
+ var _editor$tableSelected2 = editor.tableSelectedRange,
258
+ minColIndex = _editor$tableSelected2.minColIndex,
259
+ maxColIndex = _editor$tableSelected2.maxColIndex;
260
+ if (minColIndex === 0 && maxColIndex === tableSize[1] - 1) {
261
+ removeTable(editor, tablePath);
262
+ return;
263
+ }
264
+ for (var _i2 = 0; _i2 < tableSize[0]; _i2++) {
265
+ for (var j = minColIndex; j <= maxColIndex; j++) {
266
+ // count
267
+ var cellPath = [].concat(_toConsumableArray(tablePath), [_i2, minColIndex]);
268
+ Transforms.removeNodes(editor, {
269
+ at: cellPath
270
+ });
271
+ }
272
+ }
273
+ var _focusPath3 = [].concat(_toConsumableArray(tablePath), [rowIndex, minColIndex === 0 ? 0 : minColIndex - 1]);
274
+ focusEditor(editor, _focusPath3);
275
+ return;
276
+ }
277
+ for (var _i3 = 0; _i3 < tableSize[0]; _i3++) {
278
+ var _cellPath = [].concat(_toConsumableArray(tablePath), [_i3, cellIndex]);
279
+ Transforms.removeNodes(editor, {
280
+ at: _cellPath
281
+ });
282
+ }
283
+ var focusCellIndex = cellIndex === tableSize[1] - 1 ? cellIndex - 1 : cellIndex;
284
+ var _focusPath4 = [].concat(_toConsumableArray(tablePath), [rowIndex, focusCellIndex]);
285
+ focusEditor(editor, _focusPath4);
286
+ return;
287
+ }
288
+ };
289
+ export var setTableSelectedRange = function setTableSelectedRange(editor, range) {
290
+ if (range) {
291
+ editor.tableSelectedRange = range;
292
+ return;
293
+ }
294
+ editor.tableSelectedRange = EMPTY_SELECTED_RANGE;
81
295
  };
@@ -9,6 +9,7 @@ import { withTranslation } from 'react-i18next';
9
9
  import { MenuGroup, MenuItem } from '../../../../menu';
10
10
  import CommonMenu from './common-menu';
11
11
  import { TABLE_ELEMENT, MENUS_CONFIG_MAP, REMOVE_TABLE } from '../../../../constants';
12
+ import { setTextStyle, insertTableElement, removeTableElement, isAllInTable } from '../../helpers';
12
13
  import './index.css';
13
14
  var ActiveTableMenu = /*#__PURE__*/function (_Component) {
14
15
  _inherits(ActiveTableMenu, _Component);
@@ -22,14 +23,14 @@ var ActiveTableMenu = /*#__PURE__*/function (_Component) {
22
23
  _this = _super.call.apply(_super, [this].concat(args));
23
24
  _this.setTextAlignStyle = function (textAlign) {
24
25
  var editor = _this.props.editor;
25
- editor.setTextStyle({
26
+ setTextStyle(editor, {
26
27
  textAlign: textAlign
27
28
  });
28
29
  _this.textAlignRef.hidePopover();
29
30
  };
30
31
  _this.insertTableElement = function (type) {
31
32
  var editor = _this.props.editor;
32
- editor.insertTableElement(type);
33
+ insertTableElement(editor, type);
33
34
  if (type === TABLE_ELEMENT.ROW) {
34
35
  _this.tableRowRef.hidePopover();
35
36
  return;
@@ -38,7 +39,7 @@ var ActiveTableMenu = /*#__PURE__*/function (_Component) {
38
39
  };
39
40
  _this.removeTableElement = function (type) {
40
41
  var editor = _this.props.editor;
41
- editor.removeTableElement(type);
42
+ removeTableElement(editor, type);
42
43
  if (type === TABLE_ELEMENT.ROW) {
43
44
  _this.tableRowRef.hidePopover();
44
45
  return;
@@ -47,7 +48,7 @@ var ActiveTableMenu = /*#__PURE__*/function (_Component) {
47
48
  };
48
49
  _this.removeTable = function () {
49
50
  var editor = _this.props.editor;
50
- editor.removeTableElement(TABLE_ELEMENT.TABLE);
51
+ removeTableElement(editor, TABLE_ELEMENT.TABLE);
51
52
  };
52
53
  _this.renderTextAlign = function () {
53
54
  var t = _this.props.t;
@@ -85,10 +86,10 @@ var ActiveTableMenu = /*#__PURE__*/function (_Component) {
85
86
  }, /*#__PURE__*/React.createElement("button", {
86
87
  className: "dropdown-item",
87
88
  onClick: _this.insertTableElement.bind(_assertThisInitialized(_this), TABLE_ELEMENT.COLUMN)
88
- }, t('Insert_Column')), /*#__PURE__*/React.createElement("button", {
89
+ }, t('Insert_column')), /*#__PURE__*/React.createElement("button", {
89
90
  className: "dropdown-item",
90
91
  onClick: _this.removeTableElement.bind(_assertThisInitialized(_this), TABLE_ELEMENT.COLUMN)
91
- }, t('Remove_Column')));
92
+ }, t('Remove_column')));
92
93
  };
93
94
  _this.renderTableRow = function () {
94
95
  var t = _this.props.t;
@@ -101,10 +102,10 @@ var ActiveTableMenu = /*#__PURE__*/function (_Component) {
101
102
  }, /*#__PURE__*/React.createElement("button", {
102
103
  className: "dropdown-item",
103
104
  onClick: _this.insertTableElement.bind(_assertThisInitialized(_this), TABLE_ELEMENT.ROW)
104
- }, t('Insert_Row')), /*#__PURE__*/React.createElement("button", {
105
+ }, t('Insert_row')), /*#__PURE__*/React.createElement("button", {
105
106
  className: "dropdown-item",
106
107
  onClick: _this.removeTableElement.bind(_assertThisInitialized(_this), TABLE_ELEMENT.ROW)
107
- }, t('Remove_Row')));
108
+ }, t('Remove_row')));
108
109
  };
109
110
  return _this;
110
111
  }
@@ -115,8 +116,7 @@ var ActiveTableMenu = /*#__PURE__*/function (_Component) {
115
116
  editor = _this$props.editor,
116
117
  isRichEditor = _this$props.isRichEditor,
117
118
  className = _this$props.className;
118
- var isAllInTable = editor.isAllInTable && editor.isAllInTable();
119
- if (!isAllInTable) return null;
119
+ if (!isAllInTable(editor)) return null;
120
120
  var menuConfig = MENUS_CONFIG_MAP[REMOVE_TABLE];
121
121
  var props = _objectSpread(_objectSpread({
122
122
  isRichEditor: isRichEditor,
@@ -9,6 +9,8 @@ import ObjectUtils from '../../../../../utils/object-utils';
9
9
  import { TABLE_ELEMENT, TABLE_ELEMENT_POSITION, ELEMENT_TYPE } from '../../../../constants';
10
10
  import InsertTableElement from './insert-table-element';
11
11
  import { getSelectedNodeByType } from '../../../../core';
12
+ import { TABLE_MAX_COLUMNS, TABLE_MAX_ROWS } from '../../constants';
13
+ import { insertTableElement, removeTableElement } from '../../helpers';
12
14
  import './index.css';
13
15
  var ContextMenu = /*#__PURE__*/function (_React$Component) {
14
16
  _inherits(ContextMenu, _React$Component);
@@ -21,9 +23,10 @@ var ContextMenu = /*#__PURE__*/function (_React$Component) {
21
23
  var menuHeight = _this.menu.offsetHeight;
22
24
 
23
25
  // get height of context menu when the menu is drawing completed in this page
24
- // if (menuHeight === 0) {
25
- // requestAnimationFrame(this.updateMenuPosition);
26
- // }
26
+ if (menuHeight === 0) {
27
+ requestAnimationFrame(_this.updateMenuPosition);
28
+ return;
29
+ }
27
30
  var top = 0;
28
31
  if (_this.position.top + menuHeight > document.body.clientHeight) {
29
32
  top = document.body.clientHeight - menuHeight - 5;
@@ -40,11 +43,11 @@ var ContextMenu = /*#__PURE__*/function (_React$Component) {
40
43
  };
41
44
  _this.insertTableElement = function (type, position, count) {
42
45
  var editor = _this.props.editor;
43
- editor.insertTableElement(type, position, count);
46
+ insertTableElement(editor, type, position, count);
44
47
  };
45
48
  _this.removeTableElement = function (type) {
46
49
  var editor = _this.props.editor;
47
- editor.removeTableElement(type);
50
+ removeTableElement(editor, type);
48
51
  };
49
52
  _this.renderRemoveBtn = function (type, title) {
50
53
  return /*#__PURE__*/React.createElement("button", {
@@ -88,6 +91,11 @@ var ContextMenu = /*#__PURE__*/function (_React$Component) {
88
91
  var currentRow = getSelectedNodeByType(editor, ELEMENT_TYPE.TABLE_ROW);
89
92
  var currentRowsCount = currentTable.children.length;
90
93
  var currentColumnsCount = currentRow.children.length;
94
+ var tableSelectedRange = editor.tableSelectedRange;
95
+ var selectedRows = tableSelectedRange.maxRowIndex - tableSelectedRange.minRowIndex + 1;
96
+ var selectedCols = tableSelectedRange.maxColIndex - tableSelectedRange.minColIndex + 1;
97
+ var canAddRowsCount = currentRowsCount + selectedRows > TABLE_MAX_ROWS ? TABLE_MAX_ROWS - currentRowsCount : selectedRows;
98
+ var canAddColsCount = currentColumnsCount + selectedCols > TABLE_MAX_COLUMNS ? TABLE_MAX_COLUMNS - currentColumnsCount : selectedCols;
91
99
  return /*#__PURE__*/React.createElement("div", {
92
100
  style: contextStyle,
93
101
  ref: function ref(_ref) {
@@ -96,27 +104,31 @@ var ContextMenu = /*#__PURE__*/function (_React$Component) {
96
104
  className: "sdoc-table-context-menu dropdown-menu"
97
105
  }, /*#__PURE__*/React.createElement(InsertTableElement, {
98
106
  type: TABLE_ELEMENT.ROW,
107
+ count: canAddRowsCount,
99
108
  currentCount: currentRowsCount,
100
109
  position: TABLE_ELEMENT_POSITION.BEFORE,
101
110
  insertTableElement: this.insertTableElement
102
111
  }), /*#__PURE__*/React.createElement(InsertTableElement, {
103
112
  type: TABLE_ELEMENT.ROW,
113
+ count: canAddRowsCount,
104
114
  currentCount: currentRowsCount,
105
115
  position: TABLE_ELEMENT_POSITION.AFTER,
106
116
  insertTableElement: this.insertTableElement
107
117
  }), /*#__PURE__*/React.createElement(InsertTableElement, {
108
118
  type: TABLE_ELEMENT.COLUMN,
119
+ count: canAddColsCount,
109
120
  currentCount: currentColumnsCount,
110
121
  position: TABLE_ELEMENT_POSITION.BEFORE,
111
122
  insertTableElement: this.insertTableElement
112
123
  }), /*#__PURE__*/React.createElement(InsertTableElement, {
113
124
  type: TABLE_ELEMENT.COLUMN,
125
+ count: canAddColsCount,
114
126
  currentCount: currentColumnsCount,
115
127
  position: TABLE_ELEMENT_POSITION.AFTER,
116
128
  insertTableElement: this.insertTableElement
117
129
  }), /*#__PURE__*/React.createElement("div", {
118
130
  className: 'seafile-divider dropdown-divider'
119
- }), this.renderRemoveBtn(TABLE_ELEMENT.ROW, 'Remove_Row'), this.renderRemoveBtn(TABLE_ELEMENT.COLUMN, 'Remove_Column'), this.renderRemoveBtn(TABLE_ELEMENT.TABLE, 'Remove_table'));
131
+ }), this.renderRemoveBtn(TABLE_ELEMENT.ROW, 'Remove_row'), this.renderRemoveBtn(TABLE_ELEMENT.COLUMN, 'Remove_column'), this.renderRemoveBtn(TABLE_ELEMENT.TABLE, 'Remove_table'));
120
132
  }
121
133
  }]);
122
134
  return ContextMenu;
@@ -56,7 +56,7 @@ var InsertTableElement = /*#__PURE__*/function (_Component) {
56
56
  });
57
57
  };
58
58
  _this.state = {
59
- count: 1
59
+ count: props.count || 1
60
60
  };
61
61
  _this.maxCount = props.type === TABLE_ELEMENT.ROW ? TABLE_MAX_ROWS : TABLE_MAX_COLUMNS;
62
62
  return _this;
@@ -5,14 +5,18 @@ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
5
5
  import isHotkey from 'is-hotkey';
6
6
  import { Editor, Transforms, Point, Path, Node } from '@seafile/slate';
7
7
  import { ReactEditor } from '@seafile/slate-react';
8
- import { getNodeType, getParentNode, getSelectedNodeByType, isTextNode, isLastNode, genEmptyParagraph, getSelectedElems, replaceNodeChildren, focusEditor } from '../../core';
9
- import { getNodePathById } from '../../../socket/helpers';
8
+ import { getNodeType, getParentNode, getSelectedNodeByType, isTextNode, isLastNode, genEmptyParagraph, replaceNodeChildren, focusEditor, getNode } from '../../core';
10
9
  import { ELEMENT_TYPE, TABLE_ELEMENT, TABLE_ELEMENT_POSITION, KEYBOARD } from '../../constants';
11
- import { generateTableRow, generateTableCell } from './helpers';
12
- import { TABLE_MAX_ROWS, TABLE_MAX_COLUMNS } from './constants';
10
+ import { TABLE_MAX_ROWS, EMPTY_SELECTED_RANGE } from './constants';
11
+ import ObjectUtils from '../../../utils/object-utils';
12
+ import { getSelectedInfo } from './helpers';
13
13
  var deleteHandler = function deleteHandler(editor) {
14
- var selection = editor.selection;
15
- if (selection == null) return false;
14
+ var selection = editor.selection,
15
+ tableSelectedRange = editor.tableSelectedRange;
16
+ if (selection == null) return '';
17
+ if (!ObjectUtils.isSameObject(tableSelectedRange, EMPTY_SELECTED_RANGE)) {
18
+ return 'range';
19
+ }
16
20
  var _Editor$nodes = Editor.nodes(editor, {
17
21
  match: function match(n) {
18
22
  var type = getNodeType(n);
@@ -30,10 +34,10 @@ var deleteHandler = function deleteHandler(editor) {
30
34
  cellPath = _cellNodeEntry[1];
31
35
  var start = Editor.start(editor, cellPath);
32
36
  if (Point.equals(selection.anchor, start)) {
33
- return true;
37
+ return 'default';
34
38
  }
35
39
  }
36
- return false;
40
+ return '';
37
41
  };
38
42
  var isTableLocation = function isTableLocation(editor, location) {
39
43
  var tables = Editor.nodes(editor, {
@@ -63,43 +67,12 @@ var isTableLocation = function isTableLocation(editor, location) {
63
67
  }
64
68
  return hasTable;
65
69
  };
66
- var getSelectedInfo = function getSelectedInfo(editor) {
67
- var currentTable = getSelectedNodeByType(editor, ELEMENT_TYPE.TABLE);
68
- var currentRow = getSelectedNodeByType(editor, ELEMENT_TYPE.TABLE_ROW);
69
- var currentCell = getSelectedNodeByType(editor, ELEMENT_TYPE.TABLE_CELL);
70
- var currentCellPath = getNodePathById(editor, currentCell.id);
71
- return {
72
- table: currentTable,
73
- tablePath: getNodePathById(editor, currentTable.id),
74
- tableSize: [currentTable.children.length, currentRow.children.length],
75
- row: currentRow,
76
- rowPath: getNodePathById(editor, currentRow.id),
77
- rowIndex: currentCellPath[currentCellPath.length - 2],
78
- cell: currentCell,
79
- cellPath: getNodePathById(editor, currentCell.id),
80
- cellIndex: currentCellPath[currentCellPath.length - 1]
81
- };
82
- };
83
- var removeTable = function removeTable(editor, path) {
84
- var validPath = path;
85
- if (!validPath) {
86
- var _getSelectedInfo = getSelectedInfo(editor),
87
- tablePath = _getSelectedInfo.tablePath;
88
- validPath = tablePath;
89
- }
90
- var tableIndex = validPath[validPath.length - 1];
91
- var tableParentPath = validPath.slice(0, validPath.length - 1);
92
- var targetNodeIndex = tableIndex >= 1 ? tableIndex - 1 : 1;
93
- var targetNodePath = [].concat(_toConsumableArray(tableParentPath), [targetNodeIndex]);
94
- Transforms.removeNodes(editor, {
95
- at: path
96
- });
97
- focusEditor(editor, targetNodePath);
98
- };
99
70
  var isCursorAtCellEnd = function isCursorAtCellEnd(cell) {
100
71
  var cursor = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
101
72
  if (!cell) return false;
102
- var textCount = cell.children[0].text.length;
73
+ var childrenCount = cell.children.length;
74
+ var lastChildren = cell.children[childrenCount - 1];
75
+ var textCount = lastChildren.text.length;
103
76
  return cursor === textCount;
104
77
  };
105
78
  var isCursorAtCellStart = function isCursorAtCellStart() {
@@ -108,12 +81,12 @@ var isCursorAtCellStart = function isCursorAtCellStart() {
108
81
  };
109
82
  var focusCell = function focusCell(editor, event) {
110
83
  var keyboardName = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
111
- var _getSelectedInfo2 = getSelectedInfo(editor),
112
- tableSize = _getSelectedInfo2.tableSize,
113
- tablePath = _getSelectedInfo2.tablePath,
114
- rowIndex = _getSelectedInfo2.rowIndex,
115
- cellIndex = _getSelectedInfo2.cellIndex,
116
- cell = _getSelectedInfo2.cell;
84
+ var _getSelectedInfo = getSelectedInfo(editor),
85
+ tableSize = _getSelectedInfo.tableSize,
86
+ tablePath = _getSelectedInfo.tablePath,
87
+ rowIndex = _getSelectedInfo.rowIndex,
88
+ cellIndex = _getSelectedInfo.cellIndex,
89
+ cell = _getSelectedInfo.cell;
117
90
  var tableIndex = tablePath[0];
118
91
  var selection = editor.selection;
119
92
  var focus = selection.focus;
@@ -188,8 +161,8 @@ var focusCell = function focusCell(editor, event) {
188
161
  };
189
162
  var isLastTableCell = function isLastTableCell(editor, cellNode) {
190
163
  if (cellNode[0].type !== ELEMENT_TYPE.TABLE_CELL) return false;
191
- var _getSelectedInfo3 = getSelectedInfo(editor),
192
- tableSize = _getSelectedInfo3.tableSize;
164
+ var _getSelectedInfo2 = getSelectedInfo(editor),
165
+ tableSize = _getSelectedInfo2.tableSize;
193
166
  var lastRowIndex = tableSize[0] - 1;
194
167
  var lastColumnIndex = tableSize[1] - 1;
195
168
  var cellNodePath = cellNode[1];
@@ -203,9 +176,9 @@ var withTable = function withTable(editor) {
203
176
  insertData = editor.insertData,
204
177
  selectAll = editor.selectAll,
205
178
  normalizeNode = editor.normalizeNode,
206
- deleteFragment = editor.deleteFragment,
207
179
  handleTab = editor.handleTab;
208
180
  var newEditor = editor;
181
+ newEditor.tableSelectedRange = EMPTY_SELECTED_RANGE;
209
182
  newEditor.tableOnKeyDown = function (event) {
210
183
  // Handle special keyboard events
211
184
 
@@ -239,8 +212,38 @@ var withTable = function withTable(editor) {
239
212
  insertBreak();
240
213
  };
241
214
  newEditor.deleteBackward = function (unit) {
242
- var res = deleteHandler(newEditor);
243
- if (res) return;
215
+ var deleteType = deleteHandler(newEditor);
216
+
217
+ // range selection delete
218
+ if (deleteType === 'range') {
219
+ var tableSelectedRange = newEditor.tableSelectedRange;
220
+ var minRowIndex = tableSelectedRange.minRowIndex,
221
+ maxRowIndex = tableSelectedRange.maxRowIndex,
222
+ minColIndex = tableSelectedRange.minColIndex,
223
+ maxColIndex = tableSelectedRange.maxColIndex;
224
+ var _getSelectedInfo3 = getSelectedInfo(newEditor),
225
+ tablePath = _getSelectedInfo3.tablePath;
226
+ for (var i = minRowIndex; i <= maxRowIndex; i++) {
227
+ for (var j = minColIndex; j <= maxColIndex; j++) {
228
+ var path = [].concat(_toConsumableArray(tablePath), [i, j]);
229
+ var node = getNode(newEditor, path);
230
+ var firstNode = node.children[0];
231
+ for (var m = 1; m < node.children.length; m++) {
232
+ Transforms.removeNodes(editor, {
233
+ at: [].concat(_toConsumableArray(path), [m])
234
+ });
235
+ }
236
+ replaceNodeChildren(newEditor, {
237
+ at: path,
238
+ nodes: _objectSpread(_objectSpread({}, firstNode), {}, {
239
+ text: ''
240
+ })
241
+ });
242
+ }
243
+ }
244
+ return;
245
+ }
246
+ if (deleteType === 'default') return;
244
247
  var selection = newEditor.selection;
245
248
  if (selection) {
246
249
  var before = Editor.before(newEditor, selection);
@@ -325,74 +328,6 @@ var withTable = function withTable(editor) {
325
328
  }
326
329
  };
327
330
 
328
- // range selection delete
329
- newEditor.deleteFragment = function (fragment) {
330
- if (newEditor.isAllInTable()) {
331
- var selectedNodes = getSelectedElems(newEditor);
332
- var selectedNodesCount = selectedNodes.length;
333
-
334
- // Some text is selected in a cell
335
- if (selectedNodesCount === 3) {
336
- var _getSelectedInfo4 = getSelectedInfo(newEditor),
337
- cell = _getSelectedInfo4.cell,
338
- cellPath = _getSelectedInfo4.cellPath;
339
- var selection = newEditor.selection;
340
- var focus = selection.focus,
341
- anchor = selection.anchor;
342
- var oldText = cell.children[0].text;
343
- replaceNodeChildren(newEditor, {
344
- at: cellPath,
345
- nodes: _objectSpread(_objectSpread({}, cell.children[0]), {}, {
346
- text: oldText.slice(0, focus.offset) + oldText.slice(anchor.offset)
347
- })
348
- });
349
- Transforms.select(newEditor, {
350
- focus: focus,
351
- anchor: focus
352
- });
353
- return;
354
- }
355
- var firstSelectedNode = selectedNodes[0];
356
-
357
- // select all table elements
358
- if (selectedNodesCount === 1 + firstSelectedNode.children.length * (1 + firstSelectedNode.children[0].children.length)) {
359
- Transforms.removeNodes(newEditor, {
360
- match: function match(n) {
361
- return n.id === firstSelectedNode.id;
362
- }
363
- });
364
- return;
365
- }
366
-
367
- // clear cell value
368
- var firstTableCellNodePath;
369
- selectedNodes.forEach(function (node) {
370
- if (node.type === ELEMENT_TYPE.TABLE_CELL) {
371
- var targetNode = node.children[0];
372
- var path = getNodePathById(editor, node.id);
373
- firstTableCellNodePath = firstTableCellNodePath ? firstTableCellNodePath : path;
374
- replaceNodeChildren(newEditor, {
375
- at: path,
376
- nodes: _objectSpread(_objectSpread({}, targetNode), {}, {
377
- text: ''
378
- })
379
- });
380
- }
381
- });
382
- if (firstTableCellNodePath) {
383
- var start = Editor.start(newEditor, firstTableCellNodePath);
384
- var end = Editor.end(newEditor, firstTableCellNodePath);
385
- var newSelection = {
386
- anchor: start,
387
- focus: end
388
- };
389
- Transforms.select(newEditor, newSelection);
390
- }
391
- return;
392
- }
393
- deleteFragment(fragment);
394
- };
395
-
396
331
  // Jump to the next cell when pressing tab in the table
397
332
  newEditor.handleTab = function (event) {
398
333
  var selectedNode = getSelectedNodeByType(newEditor, ELEMENT_TYPE.TABLE);
@@ -412,9 +347,9 @@ var withTable = function withTable(editor) {
412
347
 
413
348
  // Add row to the last cell
414
349
  if (isLastTableCell(newEditor, above)) {
415
- var _getSelectedInfo5 = getSelectedInfo(newEditor),
416
- tablePath = _getSelectedInfo5.tablePath,
417
- tableSize = _getSelectedInfo5.tableSize;
350
+ var _getSelectedInfo4 = getSelectedInfo(newEditor),
351
+ tablePath = _getSelectedInfo4.tablePath,
352
+ tableSize = _getSelectedInfo4.tableSize;
418
353
  if (tableSize[0] === TABLE_MAX_ROWS) return;
419
354
  newEditor.insertTableElement(TABLE_ELEMENT.ROW, TABLE_ELEMENT_POSITION.AFTER);
420
355
  Transforms.select(newEditor, [].concat(_toConsumableArray(tablePath), [tableSize[0], 0]));
@@ -425,11 +360,11 @@ var withTable = function withTable(editor) {
425
360
  // The default behavior, the cursor is in the middle of the text, and the current text content is selected
426
361
  // Change to jump to next cell
427
362
  if (selection.anchor.offset === selection.focus.offset) {
428
- var _getSelectedInfo6 = getSelectedInfo(newEditor),
429
- _tableSize = _getSelectedInfo6.tableSize,
430
- _tablePath = _getSelectedInfo6.tablePath,
431
- rowIndex = _getSelectedInfo6.rowIndex,
432
- cellIndex = _getSelectedInfo6.cellIndex;
363
+ var _getSelectedInfo5 = getSelectedInfo(newEditor),
364
+ _tableSize = _getSelectedInfo5.tableSize,
365
+ _tablePath = _getSelectedInfo5.tablePath,
366
+ rowIndex = _getSelectedInfo5.rowIndex,
367
+ cellIndex = _getSelectedInfo5.cellIndex;
433
368
  var lastColumnIndex = _tableSize[1] - 1;
434
369
  var nextCell = [rowIndex, cellIndex + 1];
435
370
  if (lastColumnIndex < nextCell[1]) {
@@ -441,133 +376,6 @@ var withTable = function withTable(editor) {
441
376
  var next = Editor.next(newEditor);
442
377
  Transforms.select(newEditor, next[1]);
443
378
  };
444
-
445
- // specific business logic
446
- newEditor.isInTable = function () {
447
- var selectedNodes = getSelectedElems(newEditor);
448
- if (!selectedNodes.some(function (node) {
449
- return node.type === ELEMENT_TYPE.TABLE;
450
- })) return false;
451
- var firstSelectedNode = selectedNodes[0];
452
- return firstSelectedNode.type === ELEMENT_TYPE.TABLE;
453
- };
454
- newEditor.isAllInTable = function () {
455
- var selectedNodes = getSelectedElems(newEditor);
456
- if (!selectedNodes.some(function (node) {
457
- return node.type === ELEMENT_TYPE.TABLE;
458
- })) return false;
459
- var firstSelectedNode = selectedNodes[0];
460
- if (firstSelectedNode.type !== ELEMENT_TYPE.TABLE) return false;
461
- return selectedNodes.slice(1).every(function (node) {
462
- return [ELEMENT_TYPE.TABLE_ROW, ELEMENT_TYPE.TABLE_CELL].includes(node.type);
463
- }); // same table element
464
- };
465
-
466
- newEditor.setTextStyle = function (style) {
467
- var selectedNodes = getSelectedElems(newEditor);
468
- var firstTableCellNodePath;
469
- selectedNodes.forEach(function (node) {
470
- if (node.type === ELEMENT_TYPE.TABLE_CELL) {
471
- var targetNode = node.children[0];
472
- var path = getNodePathById(editor, node.id);
473
- firstTableCellNodePath = firstTableCellNodePath ? firstTableCellNodePath : path;
474
- replaceNodeChildren(newEditor, {
475
- at: path,
476
- nodes: _objectSpread(_objectSpread({}, targetNode), style)
477
- });
478
- }
479
- });
480
- if (firstTableCellNodePath) {
481
- var start = Editor.start(newEditor, firstTableCellNodePath);
482
- var end = Editor.end(newEditor, firstTableCellNodePath);
483
- var newSelection = {
484
- anchor: start,
485
- focus: end
486
- };
487
- Transforms.select(newEditor, newSelection);
488
- }
489
- };
490
- newEditor.insertTableElement = function (type) {
491
- var position = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : TABLE_ELEMENT_POSITION.AFTER;
492
- var count = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
493
- var _getSelectedInfo7 = getSelectedInfo(newEditor),
494
- tablePath = _getSelectedInfo7.tablePath,
495
- tableSize = _getSelectedInfo7.tableSize,
496
- rowIndex = _getSelectedInfo7.rowIndex,
497
- cellIndex = _getSelectedInfo7.cellIndex;
498
- if (type === TABLE_ELEMENT.ROW) {
499
- if (tableSize[0] >= TABLE_MAX_ROWS) return;
500
- var targetPath = position === TABLE_ELEMENT_POSITION.AFTER ? [].concat(_toConsumableArray(tablePath), [rowIndex + 1]) : [].concat(_toConsumableArray(tablePath), [rowIndex]);
501
- var validCount = Math.min(TABLE_MAX_ROWS - tableSize[0], count);
502
- for (var i = 0; i < validCount; i++) {
503
- var row = generateTableRow(tableSize[1]);
504
- Transforms.insertNodes(editor, row, {
505
- at: targetPath
506
- });
507
- }
508
- var focusPath = [].concat(_toConsumableArray(targetPath), [cellIndex]);
509
- focusEditor(newEditor, focusPath);
510
- return;
511
- }
512
- if (type === TABLE_ELEMENT.COLUMN) {
513
- if (tableSize[1] >= TABLE_MAX_COLUMNS) return;
514
- var newCellIndex = position === TABLE_ELEMENT_POSITION.AFTER ? cellIndex + 1 : cellIndex;
515
- var _validCount = Math.min(TABLE_MAX_COLUMNS - tableSize[1], count);
516
- for (var j = 0; j < _validCount; j++) {
517
- for (var _i = 0; _i < tableSize[0]; _i++) {
518
- var newCellPath = [].concat(_toConsumableArray(tablePath), [_i, newCellIndex]);
519
- var newCell = generateTableCell();
520
- Transforms.insertNodes(editor, newCell, {
521
- at: newCellPath
522
- });
523
- }
524
- }
525
- var _focusPath = [].concat(_toConsumableArray(tablePath), [rowIndex, cellIndex + 1, 0]);
526
- focusEditor(newEditor, _focusPath);
527
- return;
528
- }
529
- };
530
- newEditor.removeTableElement = function (type) {
531
- var _getSelectedInfo8 = getSelectedInfo(newEditor),
532
- tablePath = _getSelectedInfo8.tablePath,
533
- tableSize = _getSelectedInfo8.tableSize,
534
- rowPath = _getSelectedInfo8.rowPath,
535
- rowIndex = _getSelectedInfo8.rowIndex,
536
- cellIndex = _getSelectedInfo8.cellIndex;
537
- if (type === TABLE_ELEMENT.TABLE) {
538
- removeTable(newEditor, tablePath);
539
- return;
540
- }
541
- if (type === TABLE_ELEMENT.ROW) {
542
- if (tableSize[0] === 1) {
543
- removeTable(newEditor, tablePath);
544
- return;
545
- }
546
- Transforms.removeNodes(newEditor, {
547
- at: rowPath
548
- });
549
- var focusRowIndex = rowIndex === tableSize[0] - 1 ? rowIndex - 1 : rowIndex;
550
- var focusPath = [].concat(_toConsumableArray(tablePath), [focusRowIndex, cellIndex, 0]);
551
- focusEditor(newEditor, focusPath);
552
- return;
553
- }
554
- if (type === TABLE_ELEMENT.COLUMN) {
555
- if (tableSize[1] === 1) {
556
- removeTable(newEditor, tablePath);
557
- return;
558
- }
559
- for (var i = 0; i < tableSize[0]; i++) {
560
- var cellPath = [].concat(_toConsumableArray(tablePath), [i, cellIndex]);
561
- Transforms.removeNodes(newEditor, {
562
- at: cellPath
563
- });
564
- }
565
- var focusCellIndex = cellIndex === tableSize[1] - 1 ? cellIndex - 1 : cellIndex;
566
- var _focusPath2 = [].concat(_toConsumableArray(tablePath), [rowIndex, focusCellIndex, 0]);
567
- focusEditor(newEditor, _focusPath2);
568
- return;
569
- }
570
- };
571
379
  return newEditor;
572
380
  };
573
381
  export default withTable;
@@ -0,0 +1,5 @@
1
+ import { createContext, useContext } from 'react';
2
+ export var TableContext = createContext();
3
+ export var useTableContext = function useTableContext() {
4
+ return useContext(TableContext);
5
+ };
@@ -1,32 +1,51 @@
1
1
  import React from 'react';
2
2
  import classnames from 'classnames';
3
- import { useSelected } from '@seafile/slate-react';
3
+ import { useSlateStatic } from '@seafile/slate-react';
4
4
  import ObjectUtils from '../../../../utils/object-utils';
5
5
  import { STYLE_KEY } from '../../../constants';
6
- function TableCell(props) {
7
- var attributes = props.attributes,
8
- element = props.element,
9
- children = props.children,
10
- isSelected = props.isSelected;
6
+ import { getNodePathById } from '../../../../socket/helpers';
7
+ import { useTableContext } from './context';
8
+ var TableCell = function TableCell(_ref) {
9
+ var attributes = _ref.attributes,
10
+ element = _ref.element,
11
+ children = _ref.children;
12
+ var editor = useSlateStatic();
13
+ var selectedRange = useTableContext();
14
+ var cellPath = getNodePathById(editor, element.id);
15
+ if (!cellPath) return null;
11
16
  var cellValue = element.children[0];
12
17
  var style = attributes.style || {};
13
18
  if (ObjectUtils.hasProperty(cellValue, STYLE_KEY.TEXT_ALIGN)) {
14
19
  style[STYLE_KEY.TEXT_ALIGN] = cellValue[STYLE_KEY.TEXT_ALIGN];
15
20
  }
21
+ var pathLength = cellPath.length;
22
+ var rowIndex = cellPath[pathLength - 2];
23
+ var cellIndex = cellPath[pathLength - 1];
24
+ var minColIndex = selectedRange.minColIndex,
25
+ maxColIndex = selectedRange.maxColIndex,
26
+ minRowIndex = selectedRange.minRowIndex,
27
+ maxRowIndex = selectedRange.maxRowIndex;
28
+ var isRowSelected = rowIndex >= minRowIndex && rowIndex <= maxRowIndex;
29
+ var isSelected = isRowSelected && cellIndex >= minColIndex && cellIndex <= maxColIndex;
30
+ var isSelectedFirstCell = isSelected && cellIndex === minColIndex;
31
+ var isSelectedLastCell = isSelected && cellIndex === maxColIndex;
32
+ var isSelectedFirstRow = isSelected && rowIndex === minRowIndex;
33
+ var isSelectedLastRow = isSelected && rowIndex === maxRowIndex;
16
34
  return /*#__PURE__*/React.createElement("td", Object.assign({}, attributes, {
17
35
  style: style,
18
36
  className: classnames('', attributes.className, {
19
- 'cell-selected': isSelected
37
+ 'cell-selected': isSelected,
38
+ 'cell-light-height-left-border': isSelectedFirstCell,
39
+ 'cell-light-height-right-border': isSelectedLastCell,
40
+ 'cell-light-height-top-border': isSelectedFirstRow,
41
+ 'cell-light-height-bottom-border': isSelectedLastRow
20
42
  }),
21
- "data-id": element.id
43
+ "data-id": element.id,
44
+ "row-index": rowIndex,
45
+ "cell-index": cellIndex
22
46
  }), children);
23
- }
24
- function renderTableCell(props, editor) {
25
- // eslint-disable-next-line react-hooks/rules-of-hooks
26
- var isSelected = useSelected();
27
- return /*#__PURE__*/React.createElement(TableCell, Object.assign({}, props, {
28
- editor: editor,
29
- isSelected: isSelected
30
- }));
47
+ };
48
+ function renderTableCell(props) {
49
+ return /*#__PURE__*/React.createElement(TableCell, props);
31
50
  }
32
51
  export default renderTableCell;
@@ -1,24 +1,15 @@
1
1
  import React from 'react';
2
2
  import classnames from 'classnames';
3
- import { useSelected } from '@seafile/slate-react';
4
- function TableRow(props) {
5
- var attributes = props.attributes,
6
- element = props.element,
7
- children = props.children,
8
- isSelected = props.isSelected;
3
+ var TableRow = function TableRow(_ref) {
4
+ var attributes = _ref.attributes,
5
+ element = _ref.element,
6
+ children = _ref.children;
9
7
  return /*#__PURE__*/React.createElement("tr", Object.assign({}, attributes, {
10
- className: classnames('', attributes.className, {
11
- 'row-selected': isSelected
12
- }),
8
+ className: classnames('', attributes.className),
13
9
  "data-id": element.id
14
10
  }), children);
15
- }
11
+ };
16
12
  function renderTableRow(props, editor) {
17
- // eslint-disable-next-line react-hooks/rules-of-hooks
18
- var isSelected = useSelected();
19
- return /*#__PURE__*/React.createElement(TableRow, Object.assign({}, props, {
20
- editor: editor,
21
- isSelected: isSelected
22
- }));
13
+ return /*#__PURE__*/React.createElement(TableRow, props);
23
14
  }
24
15
  export default renderTableRow;
@@ -36,3 +36,37 @@
36
36
  .article .sdoc-table-wrapper td {
37
37
  min-width: 35px;
38
38
  }
39
+
40
+ .sdoc-table-wrapper .cell-selected {
41
+ caret-color: transparent;
42
+ background-color: #fff4e6;
43
+ position: relative;
44
+ }
45
+
46
+ .sdoc-table-wrapper .cell-light-height-top-border::before {
47
+ content: '';
48
+ position: absolute;
49
+ top: -1px;
50
+ left: 0;
51
+ width: 100%;
52
+ height: 2px;
53
+ border-top: 1px double #ffa94d;
54
+ }
55
+
56
+ .sdoc-table-wrapper .cell-light-height-bottom-border {
57
+ border-bottom: 1px double #ffa94d;
58
+ }
59
+
60
+ .sdoc-table-wrapper .cell-light-height-left-border::after {
61
+ content: '';
62
+ position: absolute;
63
+ top: 0px;
64
+ left: -1px;
65
+ width: 2px;
66
+ height: 100%;
67
+ border-left: 1px double #ffa94d;
68
+ }
69
+
70
+ .sdoc-table-wrapper .cell-light-height-right-border {
71
+ border-right: 1px double #ffa94d;
72
+ }
@@ -1,35 +1,88 @@
1
- import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
2
- import _createClass from "@babel/runtime/helpers/esm/createClass";
3
- import _inherits from "@babel/runtime/helpers/esm/inherits";
4
- import _createSuper from "@babel/runtime/helpers/esm/createSuper";
5
- import React, { Component } from 'react';
1
+ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
2
+ import React, { useRef, useState, useEffect } from 'react';
6
3
  import classnames from 'classnames';
4
+ import throttle from 'lodash.throttle';
7
5
  import { useSelected } from '@seafile/slate-react';
6
+ import { EMPTY_SELECTED_RANGE } from '../../constants';
7
+ import { TableContext } from '../context';
8
+ import EventBus from '../../../../../utils/event-bus';
9
+ import { EXTERNAL_EVENT } from '../../../../../../constants';
10
+ import { setTableSelectedRange } from '../../helpers';
11
+ import ObjectUtils from '../../../../../utils/object-utils';
8
12
  import './index.css';
9
- var Table = /*#__PURE__*/function (_Component) {
10
- _inherits(Table, _Component);
11
- var _super = _createSuper(Table);
12
- function Table() {
13
- _classCallCheck(this, Table);
14
- return _super.apply(this, arguments);
15
- }
16
- _createClass(Table, [{
17
- key: "render",
18
- value: function render() {
19
- var _this$props = this.props,
20
- className = _this$props.className,
21
- attributes = _this$props.attributes,
22
- children = _this$props.children,
23
- isSelected = _this$props.isSelected;
24
- return /*#__PURE__*/React.createElement("div", Object.assign({}, attributes, {
25
- className: classnames('sdoc-table-wrapper', attributes.className, className, {
26
- 'sdoc-table-selected': isSelected
27
- })
28
- }), /*#__PURE__*/React.createElement("table", null, /*#__PURE__*/React.createElement("tbody", null, children)));
13
+ var Table = function Table(_ref) {
14
+ var className = _ref.className,
15
+ attributes = _ref.attributes,
16
+ children = _ref.children,
17
+ isSelected = _ref.isSelected,
18
+ editor = _ref.editor;
19
+ var table = useRef(null);
20
+ var startRowIndex = 0;
21
+ var startColIndex = 0;
22
+ var _selectedRange = EMPTY_SELECTED_RANGE;
23
+ var _useState = useState(EMPTY_SELECTED_RANGE),
24
+ _useState2 = _slicedToArray(_useState, 2),
25
+ selectedRange = _useState2[0],
26
+ setSelectedRange = _useState2[1];
27
+ var eventBus = EventBus.getInstance();
28
+ useEffect(function () {
29
+ var cancelTableSelectRangeSubscribe = eventBus.subscribe(EXTERNAL_EVENT.CANCEL_TABLE_SELECT_RANGE, clearRange);
30
+ return function () {
31
+ cancelTableSelectRangeSubscribe();
32
+ };
33
+ // eslint-disable-next-line react-hooks/exhaustive-deps
34
+ }, []);
35
+ var clearRange = function clearRange() {
36
+ _selectedRange = EMPTY_SELECTED_RANGE;
37
+ setSelectedRange(EMPTY_SELECTED_RANGE);
38
+ };
39
+ var onMouseMove = throttle(function (event) {
40
+ // if event.target not in the table, clear the mouseMove event
41
+ if (event.target.nodeName === 'TBODY' || !table.current.contains(event.target)) {
42
+ return;
29
43
  }
30
- }]);
31
- return Table;
32
- }(Component);
44
+ var endRowIndex = Number(event.target.getAttribute('row-index'));
45
+ var endColIndex = Number(event.target.getAttribute('cell-index'));
46
+ var newSelectedRange = {
47
+ minRowIndex: Math.min(startRowIndex, endRowIndex),
48
+ maxRowIndex: Math.max(startRowIndex, endRowIndex),
49
+ minColIndex: Math.min(startColIndex, endColIndex),
50
+ maxColIndex: Math.max(startColIndex, endColIndex)
51
+ };
52
+
53
+ // same cell
54
+ if (newSelectedRange.minRowIndex === newSelectedRange.maxRowIndex && newSelectedRange.minColIndex === newSelectedRange.maxColIndex) return;
55
+ _selectedRange = newSelectedRange;
56
+ setSelectedRange(newSelectedRange);
57
+ setTableSelectedRange(editor, newSelectedRange);
58
+ }, 200);
59
+ var onMouseUp = function onMouseUp(event) {
60
+ if (!ObjectUtils.isSameObject(_selectedRange, EMPTY_SELECTED_RANGE)) {
61
+ window.getSelection().collapseToEnd();
62
+ }
63
+ window.document.removeEventListener('mousemove', onMouseMove);
64
+ window.document.removeEventListener('mouseup', onMouseUp);
65
+ };
66
+ var onMouseDown = function onMouseDown(event) {
67
+ if (event.button !== 0) return; // right click not deal
68
+ startRowIndex = Number(event.target.getAttribute('row-index'));
69
+ startColIndex = Number(event.target.getAttribute('cell-index'));
70
+ setSelectedRange(EMPTY_SELECTED_RANGE);
71
+ setTableSelectedRange(editor, EMPTY_SELECTED_RANGE);
72
+ window.document.addEventListener('mousemove', onMouseMove);
73
+ window.document.addEventListener('mouseup', onMouseUp);
74
+ };
75
+ return /*#__PURE__*/React.createElement(TableContext.Provider, {
76
+ value: selectedRange
77
+ }, /*#__PURE__*/React.createElement("div", Object.assign({}, attributes, {
78
+ className: classnames('sdoc-table-wrapper', attributes.className, className, {
79
+ 'sdoc-table-selected': isSelected
80
+ })
81
+ }), /*#__PURE__*/React.createElement("table", {
82
+ onMouseDown: onMouseDown,
83
+ ref: table
84
+ }, /*#__PURE__*/React.createElement("tbody", null, children))));
85
+ };
33
86
  function renderTable(props, editor) {
34
87
  // eslint-disable-next-line react-hooks/rules-of-hooks
35
88
  var isSelected = useSelected();
@@ -1,3 +1,4 @@
1
1
  export var EXTERNAL_EVENT = {
2
- INTERNAL_LINK_CLICK: 'internal_link_click'
2
+ INTERNAL_LINK_CLICK: 'internal_link_click',
3
+ CANCEL_TABLE_SELECT_RANGE: 'cancel_table_select_range'
3
4
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seafile/sdoc-editor",
3
- "version": "0.1.53",
3
+ "version": "0.1.54",
4
4
  "private": false,
5
5
  "description": "This is a sdoc editor",
6
6
  "main": "dist/index.js",
@@ -13,6 +13,7 @@
13
13
  "ahooks": "3.7.7",
14
14
  "classnames": "2.3.2",
15
15
  "deep-copy": "1.4.2",
16
+ "lodash.throttle": "4.1.1",
16
17
  "is-hotkey": "0.2.0",
17
18
  "is-url": "^1.2.4",
18
19
  "randomcolor": "0.6.2",
@@ -37,14 +37,9 @@
37
37
  "Remove_table": "Remove table",
38
38
  "column": "Column",
39
39
  "row": "Row",
40
- "Insert_Row_Before": "Insert Row Before",
41
- "Insert_Row_After": "Insert Row After",
42
- "Insert_Column_Before": "Insert Column Before",
43
- "Insert_Column_After": "Insert Column After",
44
- "Remove_Row": "Remove Row",
45
- "Remove_Column": "Remove Column",
46
- "Insert_Row": "Insert Row",
47
- "Insert_Column": "Insert Column",
40
+ "Remove_row": "Remove row",
41
+ "Remove_column": "Remove column",
42
+ "Insert_row": "Insert row",
48
43
  "set_align": "Set align",
49
44
  "left": "Left",
50
45
  "center": "Center",
@@ -35,14 +35,14 @@
35
35
  "Remove_table": "删除表格",
36
36
  "column": "列",
37
37
  "row": "行",
38
- "Insert_Row_Before": "上方插入行",
38
+ "Insert_row_before": "上方插入行",
39
39
  "Insert_Row_After": "下方插入行",
40
40
  "Insert_Column_Before": "左边插入列",
41
41
  "Insert_Column_After": "右边插入列",
42
- "Remove_Row": "删除当前行",
43
- "Remove_Column": "删除当前列",
44
- "Insert_Row": "插入行",
45
- "Insert_Column": "插入列",
42
+ "Remove_row": "删除当前行",
43
+ "Remove_column": "删除当前列",
44
+ "Insert_row": "插入行",
45
+ "Insert_column": "插入列",
46
46
  "set_align": "对齐方式",
47
47
  "left": "左对齐",
48
48
  "center": "居中",
@@ -14,6 +14,12 @@
14
14
  />
15
15
  <missing-glyph />
16
16
 
17
+ <glyph glyph-name="unlink" unicode="&#58938;" d="M252.8 435.2c0-32 6.4-60.8 16-92.8 3.2-9.6 0-19.2-6.4-28.8l-25.6-25.6c-48-48-51.2-128-3.2-179.2 48-48 131.2-51.2 179.2 0l96 96 99.2-99.2-89.6-89.6c-102.4-102.4-272-102.4-377.6 0s-102.4 272 0 377.6l60.8 60.8c19.2 16 51.2 6.4 51.2-19.2z m60.8-35.2l156.8-156.8-12.8-12.8c-6.4-9.6-22.4-9.6-32-6.4l-3.2 3.2c-9.6 9.6-25.6 19.2-35.2 32-38.4 41.6-64 89.6-73.6 140.8z m192 355.2c102.4 102.4 272 102.4 377.6 0s102.4-272 0-374.4l-67.2-67.2c-16-16-48-6.4-48 19.2 0 32-6.4 60.8-16 92.8-3.2 9.6 0 19.2 6.4 28.8l19.2 19.2c51.2 51.2 51.2 131.2 3.2 179.2s-131.2 48-179.2 0L512 563.2l-99.2 99.2 92.8 92.8z m89.6-217.6c16-6.4 28.8-16 41.6-28.8 41.6-41.6 64-89.6 73.6-140.8l-156.8 156.8 9.6 9.6c6.4 9.6 22.4 9.6 32 3.2zM195.2 700.8c25.6 25.6 64 25.6 89.6 0l544-544c25.6-25.6 25.6-64 0-89.6-25.6-25.6-64-25.6-89.6 0l-544 544c-25.6 25.6-25.6 64 0 89.6z" horiz-adv-x="1024" />
18
+
19
+ <glyph glyph-name="more-level" unicode="&#58936;" d="M777.6 384c0 64 54.4 118.4 118.4 118.4S1014.4 448 1014.4 384 960 265.6 896 265.6 777.6 320 777.6 384zM384 384c0 64 54.4 118.4 118.4 118.4S620.8 448 620.8 384s-54.4-118.4-118.4-118.4S384 320 384 384zM0 384c0 64 41.6 118.4 108.8 118.4s128-54.4 128-118.4-60.8-118.4-128-118.4S0 320 0 384z" horiz-adv-x="1024" />
20
+
21
+ <glyph glyph-name="plus-square" unicode="&#58937;" d="M809.6 345.6v76.8c0 9.6-3.2 19.2-9.6 25.6s-16 9.6-25.6 9.6H588.8V646.4c0 9.6-3.2 19.2-9.6 25.6-6.4 6.4-16 9.6-25.6 9.6h-76.8c-9.6 0-19.2-3.2-25.6-9.6-6.4-6.4-12.8-16-12.8-25.6v-185.6H249.6c-9.6 0-19.2-3.2-25.6-9.6s-9.6-16-9.6-25.6v-76.8c0-9.6 3.2-19.2 9.6-25.6s16-9.6 25.6-9.6h185.6v-188.8c0-9.6 3.2-19.2 9.6-25.6 6.4-6.4 16-9.6 25.6-9.6h76.8c9.6 0 19.2 3.2 25.6 9.6 6.4 6.4 9.6 16 9.6 25.6V310.4h188.8c9.6 0 19.2 3.2 25.6 9.6 9.6 6.4 12.8 12.8 12.8 25.6z m150.4 320v-560c0-44.8-16-86.4-48-118.4S838.4-64 793.6-64H230.4c-44.8 0-86.4 16-118.4 48s-48 70.4-48 115.2V665.6c0 44.8 16 86.4 48 118.4s73.6 48 118.4 48h560c44.8 0 86.4-16 118.4-48S960 710.4 960 665.6z" horiz-adv-x="1024" />
22
+
17
23
  <glyph glyph-name="sdoc-delete-table" unicode="&#58935;" d="M800 352c124.8 0 224-102.4 224-220.8S921.6-96 800-96s-224 102.4-224 220.8 99.2 227.2 224 227.2z m128 448c35.2 0 60.8-25.6 64-60.8v-396.8c-35.2 32-80 54.4-128 67.2V544h-288v-160h92.8C576 336 512 240 512 128c0-60.8 19.2-115.2 48-160H96c-35.2 0-60.8 25.6-64 60.8V736c0 35.2 25.6 60.8 60.8 64H928z m-38.4-640h-176c-25.6 0-38.4-12.8-38.4-32 0-12.8 19.2-32 38.4-32h176c25.6 0 38.4 12.8 38.4 32 0 12.8-16 32-38.4 32zM448 256H160v-160h288v160z m0 288H160v-160h288v160z" horiz-adv-x="1024" />
18
24
 
19
25
  <glyph glyph-name="sdoc-caret-up" unicode="&#58934;" d="M870.4 137.6H153.6c-51.2 0-73.6 60.8-38.4 96L473.6 592c22.4 22.4 57.6 22.4 80 0L912 233.6c35.2-38.4 9.6-96-41.6-96z" horiz-adv-x="1024" />
@@ -16,6 +16,10 @@
16
16
  -moz-osx-font-smoothing: grayscale;
17
17
  }
18
18
 
19
+ .sdoc-unlink:before {
20
+ content: "\e63a";
21
+ }
22
+
19
23
  .sdoc-delete-table:before {
20
24
  content: "\e637";
21
25
  }