@seafile/sdoc-editor 0.4.12 → 0.4.14

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 (37) hide show
  1. package/dist/basic-sdk/assets/css/layout.css +1 -1
  2. package/dist/basic-sdk/comment/components/global-comment/index.js +2 -2
  3. package/dist/basic-sdk/extension/constants/font.js +0 -1
  4. package/dist/basic-sdk/extension/plugins/blockquote/plugin.js +17 -6
  5. package/dist/basic-sdk/extension/plugins/blockquote/render-elem.js +1 -2
  6. package/dist/basic-sdk/extension/plugins/callout/plugin.js +21 -1
  7. package/dist/basic-sdk/extension/plugins/callout/render-elem/index.js +0 -3
  8. package/dist/basic-sdk/extension/plugins/check-list/render-elem.js +1 -2
  9. package/dist/basic-sdk/extension/plugins/code-block/helpers.js +0 -2
  10. package/dist/basic-sdk/extension/plugins/code-block/render-elem.js +1 -4
  11. package/dist/basic-sdk/extension/plugins/file-link/helpers.js +0 -1
  12. package/dist/basic-sdk/extension/plugins/header/render-elem.js +2 -6
  13. package/dist/basic-sdk/extension/plugins/html/helper.js +0 -1
  14. package/dist/basic-sdk/extension/plugins/image/hover-menu/index.js +4 -1
  15. package/dist/basic-sdk/extension/plugins/image/plugin.js +2 -1
  16. package/dist/basic-sdk/extension/plugins/link/helpers.js +0 -1
  17. package/dist/basic-sdk/extension/plugins/list/render-elem.js +2 -5
  18. package/dist/basic-sdk/extension/plugins/paragraph/render-elem.js +1 -4
  19. package/dist/basic-sdk/extension/plugins/sdoc-link/helpers.js +0 -1
  20. package/dist/basic-sdk/extension/plugins/search-replace/popover/index.js +1 -1
  21. package/dist/basic-sdk/extension/plugins/table/helpers.js +0 -1
  22. package/dist/basic-sdk/extension/plugins/table/plugin.js +33 -3
  23. package/dist/basic-sdk/extension/plugins/table/render/index.js +25 -28
  24. package/dist/basic-sdk/extension/plugins/table/render/table-root.js +0 -1
  25. package/dist/basic-sdk/extension/render/helper.js +1 -0
  26. package/dist/basic-sdk/extension/toolbar/side-toolbar/helpers.js +0 -1
  27. package/dist/basic-sdk/extension/toolbar/side-toolbar/transform-menus.js +10 -2
  28. package/dist/basic-sdk/utils/event-handler.js +1 -0
  29. package/package.json +1 -1
  30. package/public/locales/cs/sdoc-editor.json +1 -1
  31. package/public/locales/de/sdoc-editor.json +1 -1
  32. package/public/locales/en/sdoc-editor.json +1 -1
  33. package/public/locales/es/sdoc-editor.json +1 -1
  34. package/public/locales/fr/sdoc-editor.json +1 -1
  35. package/public/locales/it/sdoc-editor.json +1 -1
  36. package/public/locales/ru/sdoc-editor.json +1 -1
  37. package/public/locales/zh_CN/sdoc-editor.json +2 -2
@@ -24,7 +24,7 @@
24
24
  display: flex;
25
25
  flex-direction: row-reverse;
26
26
  position: absolute;
27
- right: 20px;
27
+ right: 8px;
28
28
  border-right: none;
29
29
  }
30
30
 
@@ -78,6 +78,7 @@ const GlobalComment = _ref => {
78
78
  setActiveComment(comment);
79
79
  deleteUnseenNotifications && deleteUnseenNotifications(comment);
80
80
  if (comment.detail.element_id === DOC_COMMENT_ELEMENT_ID) return;
81
+ if (!element) return;
81
82
  const elementDom = ReactEditor.toDOMNode(editor, element, scrollRef);
82
83
  scrollRef.current.scrollTop = elementDom.offsetTop - scrollRef.current.clientHeight / 3;
83
84
  focusToCommentElement(editor, element);
@@ -150,8 +151,7 @@ const GlobalComment = _ref => {
150
151
  className: "sdoc-comment-list-container"
151
152
  }, Array.isArray(commentList) && commentList.map(comment => {
152
153
  const elementId = comment.detail.element_id;
153
- const element = getNodeById(editor.children, elementId);
154
- if (!element && elementId !== DOC_COMMENT_ELEMENT_ID) return null;
154
+ const element = elementId !== DOC_COMMENT_ELEMENT_ID ? getNodeById(editor.children, elementId) : null;
155
155
  const isActive = activeComment && activeComment.id === comment.id;
156
156
  return /*#__PURE__*/React.createElement(CommentItemWrapper, {
157
157
  key: comment.id,
@@ -517,7 +517,6 @@ export const FONT = [
517
517
  }
518
518
  } // 楷体
519
519
  ];
520
-
521
520
  export const SDOC_FONT_SIZE = {
522
521
  DEFAULT: 11,
523
522
  [ELEMENT_TYPE.TITLE]: 26,
@@ -1,7 +1,7 @@
1
1
  import { Editor, Element, Transforms, Node, Path } from '@seafile/slate';
2
- import { focusEditor, generateDefaultText, getSelectedNodeByType, isSelectionAtBlockStart } from '../../core';
2
+ import { focusEditor, generateDefaultText, generateEmptyElement, getSelectedNodeByType, getSelectedNodeEntryByType, isBlockAboveEmpty, isSelectionAtBlockStart } from '../../core';
3
3
  import { BLOCKQUOTE, PARAGRAPH, CODE_BLOCK, TABLE } from '../../constants';
4
- import { setBlockQuoteType, getFormattedElements, getFormattedRestElements } from './helpers';
4
+ import { getFormattedElements, getFormattedRestElements } from './helpers';
5
5
  const withBlockquote = editor => {
6
6
  const {
7
7
  insertBreak,
@@ -54,23 +54,34 @@ const withBlockquote = editor => {
54
54
  deleteBackward(unit);
55
55
  return;
56
56
  }
57
- const node = getSelectedNodeByType(editor, BLOCKQUOTE);
58
- if (node) {
57
+ const blockQuoteEntry = getSelectedNodeEntryByType(editor, BLOCKQUOTE);
58
+ if (blockQuoteEntry) {
59
59
  const [currentLineEntry] = Editor.nodes(newEditor, {
60
60
  match: n => Element.isElement(n) && n.type === PARAGRAPH,
61
61
  mode: 'lowest'
62
62
  });
63
63
  if (!currentLineEntry) return deleteBackward(unit);
64
64
  const currentLineIndex = currentLineEntry[1].slice(-1)[0];
65
- if (currentLineIndex === 0) {
66
- setBlockQuoteType(editor, PARAGRAPH);
65
+ // Transforms to paragraph when Select at the beginning of the first line
66
+ if (currentLineIndex === 0 && isBlockAboveEmpty(newEditor)) {
67
+ const emptyParagraph = generateEmptyElement(PARAGRAPH);
68
+ Transforms.removeNodes(editor, {
69
+ at: currentLineEntry[1]
70
+ });
71
+ Transforms.insertNodes(newEditor, emptyParagraph, {
72
+ at: blockQuoteEntry[1]
73
+ });
74
+ const previous = Path.previous(blockQuoteEntry[1]);
75
+ focusEditor(newEditor, Path.next(previous).concat(0));
67
76
  return;
68
77
  }
78
+ // Merge with previous line when Select at the beginning of the line
69
79
  if (isSelectionAtBlockStart(editor)) {
70
80
  const lineText = Node.string(currentLineEntry[0]);
71
81
  const previousNodeEntry = Editor.previous(editor, {
72
82
  at: currentLineEntry[1]
73
83
  });
84
+ if (!previousNodeEntry) return;
74
85
  const focusPoint = Editor.end(newEditor, previousNodeEntry[1]);
75
86
  Transforms.insertText(newEditor, lineText, {
76
87
  at: Editor.end(newEditor, previousNodeEntry[1])
@@ -9,8 +9,7 @@ const renderBlockquote = (props, editor) => {
9
9
  textAlign: element.align
10
10
  };
11
11
  return /*#__PURE__*/React.createElement("blockquote", Object.assign({
12
- "data-id": element.id,
13
- "data-root": "true"
12
+ "data-id": element.id
14
13
  }, attributes, {
15
14
  style: style
16
15
  }), children);
@@ -1,4 +1,5 @@
1
1
  import isHotkey from 'is-hotkey';
2
+ import { Editor, Transforms } from '@seafile/slate';
2
3
  import { PARAGRAPH, INSERT_POSITION, CODE_BLOCK } from '../../constants';
3
4
  import { isSelectionAtBlockStart } from '../../core';
4
5
  import { getCalloutEntry, isCalloutContentEmpty, unwrapCallout } from './helper';
@@ -52,7 +53,9 @@ const withCallout = editor => {
52
53
  return insertFragment(data);
53
54
  };
54
55
  newEditor.onHotKeyDown = event => {
55
- if (getCalloutEntry(editor)) {
56
+ const calloutEntry = getCalloutEntry(editor);
57
+ if (calloutEntry) {
58
+ const [, calloutPath] = calloutEntry;
56
59
  // Close color picker
57
60
  const eventBus = EventBus.getInstance();
58
61
  eventBus.dispatch(INTERNAL_EVENT.CLOSE_CALLOUT_COLOR_PICKER);
@@ -60,9 +63,26 @@ const withCallout = editor => {
60
63
  insertElement(newEditor, PARAGRAPH, INSERT_POSITION.AFTER);
61
64
  return true;
62
65
  }
66
+ if (isHotkey('mod+a', event)) {
67
+ event.preventDefault();
68
+ try {
69
+ const startPoint = Editor.start(newEditor, calloutPath);
70
+ const endPoint = Editor.end(newEditor, calloutPath);
71
+ const selectRange = Editor.range(newEditor, startPoint, endPoint);
72
+ Transforms.select(newEditor, selectRange);
73
+ return true;
74
+ } catch (error) {
75
+ return true;
76
+ }
77
+ }
63
78
  }
64
79
  return onHotKeyDown && onHotKeyDown(event);
65
80
  };
81
+ newEditor.onCopy = event => {
82
+ if (getCalloutEntry(editor)) {
83
+ event.stopPropagation();
84
+ }
85
+ };
66
86
  return newEditor;
67
87
  };
68
88
  export default withCallout;
@@ -51,7 +51,6 @@ const renderCallout = (_ref, editor) => {
51
51
  top: menuTop,
52
52
  left: left // left = code-block left distance
53
53
  };
54
-
55
54
  setPopoverPosition(newMenuPosition);
56
55
  }
57
56
  }, [isShowColorSelector, readOnly]);
@@ -82,7 +81,6 @@ const renderCallout = (_ref, editor) => {
82
81
  top: menuTop,
83
82
  left: left // left = callout left distance
84
83
  };
85
-
86
84
  setPopoverPosition(newMenuPosition);
87
85
  setIsShowColorSelector(true);
88
86
  }, [readOnly]);
@@ -100,7 +98,6 @@ const renderCallout = (_ref, editor) => {
100
98
  }, [editor, element, isFocusOnCallout]);
101
99
  return /*#__PURE__*/React.createElement("div", Object.assign({}, attributes, {
102
100
  "data-id": element.id,
103
- "data-root": "true",
104
101
  className: "sdoc-callout-white-wrapper",
105
102
  onMouseLeave: handleCloseColorSelector
106
103
  }), /*#__PURE__*/React.createElement("div", {
@@ -33,8 +33,7 @@ class CheckListItem extends React.PureComponent {
33
33
  textAlign: align
34
34
  };
35
35
  return /*#__PURE__*/React.createElement("div", Object.assign({
36
- "data-id": id,
37
- "data-root": "true"
36
+ "data-id": id
38
37
  }, attributes, {
39
38
  className: "sdoc-checkbox-container ".concat(attributes.className),
40
39
  style: style
@@ -23,7 +23,6 @@ export const isMenuDisabled = (editor, readonly) => {
23
23
  if (isMatch) return false; // enable
24
24
  return true; // disable
25
25
  };
26
-
27
26
  export const getSelectCodeElem = editor => {
28
27
  const codeNode = getSelectedNodeByType(editor, CODE_BLOCK);
29
28
  if (codeNode == null) return null;
@@ -63,7 +62,6 @@ export const changeToCodeBlock = function (editor) {
63
62
  style: {
64
63
  white_space: 'nowrap' // default nowrap
65
64
  },
66
-
67
65
  children: [{
68
66
  id: slugid.nice(),
69
67
  type: CODE_LINE,
@@ -81,7 +81,6 @@ const CodeBlock = _ref => {
81
81
  top: menuTop,
82
82
  left: left // left = code-block left distance
83
83
  };
84
-
85
84
  setMenuPosition(newMenuPosition);
86
85
  }
87
86
  setShowHoverMenu(true);
@@ -105,7 +104,6 @@ const CodeBlock = _ref => {
105
104
  top: menuTop,
106
105
  left: left // left = code-block left distance
107
106
  };
108
-
109
107
  setMenuPosition(newMenuPosition);
110
108
  }
111
109
  }, [readOnly, showHoverMenu]);
@@ -134,8 +132,7 @@ const CodeBlock = _ref => {
134
132
  EventBus.getInstance().dispatch(INTERNAL_EVENT.UPDATE_SEARCH_REPLACE_HIGHLIGHT);
135
133
  };
136
134
  return /*#__PURE__*/React.createElement("div", Object.assign({
137
- "data-id": element.id,
138
- "data-root": "true"
135
+ "data-id": element.id
139
136
  }, attributes, {
140
137
  className: "sdoc-code-block-container ".concat(attributes.className),
141
138
  onClick: onFocusCodeBlock,
@@ -20,7 +20,6 @@ export const isMenuDisabled = (editor, readonly) => {
20
20
  if (notMatch) return true; // disabled
21
21
  return false; // enable
22
22
  };
23
-
24
23
  export const generateFileNode = (uuid, text) => {
25
24
  const fileNode = {
26
25
  id: slugid.nice(),
@@ -14,8 +14,7 @@ export const renderTitle = (props, editor) => {
14
14
  textAlign: element.align
15
15
  };
16
16
  return /*#__PURE__*/React.createElement("div", Object.assign({
17
- "data-id": element.id,
18
- "data-root": "true"
17
+ "data-id": element.id
19
18
  }, attributes, {
20
19
  className: "sdoc-header-title ".concat(attributes.className),
21
20
  style: _objectSpread({}, style)
@@ -33,8 +32,7 @@ export const renderSubtitle = (props, editor) => {
33
32
  textAlign: element.align
34
33
  };
35
34
  return /*#__PURE__*/React.createElement("div", Object.assign({
36
- "data-id": element.id,
37
- "data-root": "true"
35
+ "data-id": element.id
38
36
  }, attributes, {
39
37
  className: "sdoc-header-subtitle ".concat(attributes.className),
40
38
  style: _objectSpread({}, style)
@@ -65,8 +63,6 @@ export const renderHeader = (props, editor) => {
65
63
  return /*#__PURE__*/React.createElement("div", Object.assign({
66
64
  "data-id": element.id,
67
65
  id: element.id // used for click left outline item, page scroll this element
68
- ,
69
- "data-root": "true"
70
66
  }, attributes, {
71
67
  className: "sdoc-header-".concat(level, " ").concat(attributes.className),
72
68
  style: _objectSpread({
@@ -68,7 +68,6 @@ const deserializeElements = function () {
68
68
  // nothing todo
69
69
  }
70
70
  });
71
-
72
71
  return nodes;
73
72
  };
74
73
  const formatElementNodes = nodes => {
@@ -89,7 +89,10 @@ const ImageHoverMenu = _ref => {
89
89
  at: [p]
90
90
  });
91
91
  p = p + 1;
92
- if (!afterLeaf.every(item => item.text.length === 0)) {
92
+ if (!afterLeaf.every(item => {
93
+ var _item$text;
94
+ return (item === null || item === void 0 ? void 0 : (_item$text = item.text) === null || _item$text === void 0 ? void 0 : _item$text.length) === 0;
95
+ })) {
93
96
  afterNode = generateEmptyElement(PARAGRAPH);
94
97
  afterNode.children = afterLeaf;
95
98
  Transforms.insertNodes(editor, afterNode, {
@@ -115,7 +115,8 @@ const withImage = editor => {
115
115
  distance: 2
116
116
  });
117
117
  const [node, path] = Editor.node(editor, [point.path[0], point.path[1]]);
118
- if (Range.isCollapsed(selection) && isBlockAboveEmpty(editor) && !Path.isCommon(path, selection.anchor.path)) {
118
+ const isPerviousNodeImage = node.type === IMAGE;
119
+ if (isPerviousNodeImage && Range.isCollapsed(selection) && isBlockAboveEmpty(editor) && !Path.isCommon(path, selection.anchor.path)) {
119
120
  deleteBackward(unit);
120
121
  focusEditor(newEditor, Editor.end(newEditor, focusPoint));
121
122
  return;
@@ -19,7 +19,6 @@ export const isMenuDisabled = (editor, readonly) => {
19
19
  if (notMatch) return true; // disabled
20
20
  return false; // enable
21
21
  };
22
-
23
22
  export const checkLink = url => {
24
23
  if (url.indexOf('http') !== 0) {
25
24
  return true;
@@ -10,7 +10,6 @@ const renderList = (props, editor) => {
10
10
  const Tag = node.type === ORDERED_LIST ? 'ol' : 'ul';
11
11
  return /*#__PURE__*/React.createElement(Tag, Object.assign({
12
12
  "data-id": node.id,
13
- "data-root": "true",
14
13
  className: "list-container d-flex flex-column"
15
14
  }, attributes), children);
16
15
  };
@@ -36,8 +35,7 @@ const renderListItem = (props, editor) => {
36
35
  }
37
36
  const isBlod = element.children[0].children.every(item => item.bold === true);
38
37
  return /*#__PURE__*/React.createElement("li", Object.assign({
39
- "data-id": element.id,
40
- "data-root": "true"
38
+ "data-id": element.id
41
39
  }, attributes, {
42
40
  className: classnames(className, {
43
41
  'sdoc-li-blod': isBlod
@@ -51,8 +49,7 @@ const renderListLic = (props, editor) => {
51
49
  element
52
50
  } = props;
53
51
  return /*#__PURE__*/React.createElement("div", Object.assign({
54
- "data-id": element.id,
55
- "data-root": "true"
52
+ "data-id": element.id
56
53
  }, attributes), children);
57
54
  };
58
55
  export { renderList, renderListItem, renderListLic };
@@ -26,12 +26,9 @@ const Paragraph = _ref => {
26
26
  textAlign: element.align,
27
27
  paddingLeft: indent ? '28px' : ''
28
28
  };
29
- const newAttributes = _objectSpread(_objectSpread({}, attributes), typeof attributes.onMouseEnter === 'function' && {
30
- 'data-root': 'true'
31
- });
32
29
  return /*#__PURE__*/React.createElement("p", Object.assign({
33
30
  "data-id": element.id
34
- }, newAttributes, {
31
+ }, attributes, {
35
32
  style: _objectSpread({
36
33
  position: isShowPlaceHolder ? 'relative' : ''
37
34
  }, style)
@@ -21,7 +21,6 @@ export const isMenuDisabled = (editor, readonly) => {
21
21
  if (notMatch) return true; // disabled
22
22
  return false; // enable
23
23
  };
24
-
25
24
  export const generateSdocFileNode = (uuid, text) => {
26
25
  const sdocFileNode = {
27
26
  id: slugid.nice(),
@@ -188,7 +188,7 @@ const SearchReplacePopover = _ref => {
188
188
  disabled: !highlightInfos.length,
189
189
  onClick: handleLast,
190
190
  className: "btn btn-secondary"
191
- }, t('Previous')), /*#__PURE__*/React.createElement("button", {
191
+ }, t('Prevs')), /*#__PURE__*/React.createElement("button", {
192
192
  disabled: !highlightInfos.length,
193
193
  onClick: handleNext,
194
194
  className: "btn btn-secondary"
@@ -175,7 +175,6 @@ export const isAllInTable = editor => {
175
175
  if (firstSelectedNode.type !== ELEMENT_TYPE.TABLE) return false;
176
176
  return selectedNodes.slice(1).every(node => [ELEMENT_TYPE.TABLE_ROW, ELEMENT_TYPE.TABLE_CELL].includes(node.type)); // same table element
177
177
  };
178
-
179
178
  export const setCellStyle = (editor, style) => {
180
179
  // Select single cell
181
180
  if (ObjectUtils.isSameObject(editor.tableSelectedRange, EMPTY_SELECTED_RANGE)) {
@@ -88,17 +88,47 @@ const withTable = editor => {
88
88
  if (selection) {
89
89
  const before = Editor.before(newEditor, selection);
90
90
  if (before) {
91
- // If the current is not a table and the previous one is a table, no deletion will be performed. Otherwise, the last cell of the table will be deleted
92
- // If deleting node is empty check-list, order-list, unordered-list, change to paragraph
93
91
  const isTableOnBeforeLocation = isTableLocation(newEditor, before);
94
92
  const isTableOnCurSelection = isTableLocation(newEditor, selection);
93
+ // If the current is not a table and the previous one is a table.
95
94
  if (isTableOnBeforeLocation && !isTableOnCurSelection) {
96
- const transformTypes = [CHECK_LIST_ITEM, ORDERED_LIST, UNORDERED_LIST];
97
95
  const [currentNodeEntry] = Editor.nodes(editor, {
98
96
  match: n => Element.isElement(n) && !Editor.parent(n, ReactEditor.findPath(editor, n))[1].length
99
97
  });
100
98
  if (!currentNodeEntry) return;
101
99
  const [currentNode, currentPath] = Array.from(currentNodeEntry);
100
+
101
+ // If the current is paragraph.
102
+ if (currentNode.type === PARAGRAPH) {
103
+ const {
104
+ path
105
+ } = before;
106
+ Transforms.select(editor, {
107
+ anchor: {
108
+ offset: 0,
109
+ path: [path[0], 0, 0, 0]
110
+ },
111
+ focus: {
112
+ offset: 0,
113
+ path: [path[0], 0, 0, 0]
114
+ }
115
+ });
116
+ const beforeTable = Editor.node(editor, [path[0]]);
117
+ const beforeRow = Editor.node(editor, [path[0], path[1]]);
118
+ const tableSize = [beforeTable[0].children.length, beforeRow[0].children.length];
119
+ const allTableRange = {
120
+ minRowIndex: 0,
121
+ maxRowIndex: tableSize[0] - 1,
122
+ minColIndex: 0,
123
+ maxColIndex: tableSize[1] - 1
124
+ };
125
+ newEditor.tableSelectedRange = allTableRange;
126
+ eventBus.dispatch(INTERNAL_EVENT.SET_TABLE_SELECT_RANGE, beforeTable[0], allTableRange);
127
+ return;
128
+ }
129
+
130
+ // If deleting node is empty check-list, order-list, unordered-list, change to paragraph
131
+ const transformTypes = [CHECK_LIST_ITEM, ORDERED_LIST, UNORDERED_LIST];
102
132
  if (transformTypes.includes(currentNode.type)) {
103
133
  Transforms.delete(newEditor, {
104
134
  at: currentPath
@@ -59,19 +59,33 @@ const Table = _ref => {
59
59
 
60
60
  // eslint-disable-next-line react-hooks/exhaustive-deps
61
61
  }, []);
62
+ const setSelectedRangeByClick = useCallback(range => {
63
+ setSelectedRange(range);
64
+ setTableSelectedRange(editor, range);
65
+ const {
66
+ maxRowIndex,
67
+ maxColIndex
68
+ } = range;
69
+ const selection = {
70
+ offset: 0,
71
+ path: [...path, maxRowIndex, maxColIndex, 0]
72
+ };
73
+ Transforms.setSelection(editor, {
74
+ anchor: selection,
75
+ focus: selection
76
+ });
77
+ // eslint-disable-next-line react-hooks/exhaustive-deps
78
+ }, [editor, path]);
62
79
  useEffect(() => {
63
- if (isSelected) {
64
- const eventBus = EventBus.getInstance();
65
- const cancelTableSelectRangeSubscribe = eventBus.subscribe(INTERNAL_EVENT.CANCEL_TABLE_SELECT_RANGE, clearRange);
66
- const setTableSelectRangeSubscribe = eventBus.subscribe(INTERNAL_EVENT.SET_TABLE_SELECT_RANGE, setRange);
67
- return () => {
68
- cancelTableSelectRangeSubscribe();
69
- setTableSelectRangeSubscribe();
70
- };
71
- }
72
-
80
+ const eventBus = EventBus.getInstance();
81
+ const cancelTableSelectRangeSubscribe = eventBus.subscribe(INTERNAL_EVENT.CANCEL_TABLE_SELECT_RANGE, clearRange);
82
+ const setTableSelectRangeSubscribe = eventBus.subscribe(INTERNAL_EVENT.SET_TABLE_SELECT_RANGE, setRange);
83
+ return () => {
84
+ cancelTableSelectRangeSubscribe();
85
+ setTableSelectRangeSubscribe();
86
+ };
73
87
  // eslint-disable-next-line react-hooks/exhaustive-deps
74
- }, [isSelected]);
88
+ }, []);
75
89
  useEffect(() => {
76
90
  setColumns(getTableColumns(editor, element));
77
91
  if (isSettingSelectRange) {
@@ -150,23 +164,6 @@ const Table = _ref => {
150
164
 
151
165
  // eslint-disable-next-line react-hooks/exhaustive-deps
152
166
  }, []);
153
- const setSelectedRangeByClick = useCallback(range => {
154
- setSelectedRange(range);
155
- setTableSelectedRange(editor, range);
156
- const {
157
- maxRowIndex,
158
- maxColIndex
159
- } = range;
160
- const selection = {
161
- offset: 0,
162
- path: [...path, maxRowIndex, maxColIndex, 0]
163
- };
164
- Transforms.setSelection(editor, {
165
- anchor: selection,
166
- focus: selection
167
- });
168
- // eslint-disable-next-line react-hooks/exhaustive-deps
169
- }, [editor, path]);
170
167
  const tableContainerClassName = classnames('sdoc-table-container position-relative', attributes.className, className, {
171
168
  'sdoc-table-selected': isSelected,
172
169
  'sdoc-table-selected-range': !ObjectUtils.isSameObject(selectedRange, EMPTY_SELECTED_RANGE)
@@ -30,7 +30,6 @@ const TableRoot = _ref => {
30
30
  className: classnames('sdoc-table-wrapper position-relative', attributes.className, {
31
31
  'scroll': allWidth > editor.width
32
32
  }),
33
- "data-root": "true",
34
33
  style: _objectSpread(_objectSpread({}, attributes.style), {}, {
35
34
  maxWidth: editor.width ? editor.width : '100%'
36
35
  })
@@ -18,4 +18,5 @@ const isNeedAddMouseEnterEvent = (editor, element) => {
18
18
  export const setMouseEnter = (editor, element, attributes) => {
19
19
  if (!isNeedAddMouseEnterEvent(editor, element)) return;
20
20
  attributes['onMouseEnter'] = e => onMouseEnter(e, element);
21
+ attributes['data-root'] = 'true';
21
22
  };
@@ -92,7 +92,6 @@ export const getDomTopHeight = (dom, slateNode) => {
92
92
  if (ADD_POSITION_OFFSET_TYPE.includes(slateNode.type)) {
93
93
  offsetY = lightHight / 2 + paddingTop - 12; // side toolbar icon is 12 px
94
94
  }
95
-
96
95
  const HEADER_HEIGHT = 56 + 44;
97
96
  return rect.y - HEADER_HEIGHT + offsetY;
98
97
  };
@@ -1,9 +1,9 @@
1
1
  import React, { useCallback } from 'react';
2
2
  import { UncontrolledPopover } from 'reactstrap';
3
3
  import { withTranslation } from 'react-i18next';
4
- import { useSlateStatic } from '@seafile/slate-react';
4
+ import { ReactEditor, useSlateStatic } from '@seafile/slate-react';
5
5
  import { onSetNodeType } from './helpers';
6
- import { SIDE_TRANSFORM_MENUS_CONFIG, LIST_ITEM_SUPPORTED_TRANSFORMATION, LIST_ITEM_CORRELATION_TYPE } from '../../constants';
6
+ import { SIDE_TRANSFORM_MENUS_CONFIG, LIST_ITEM_SUPPORTED_TRANSFORMATION, LIST_ITEM_CORRELATION_TYPE, BLOCKQUOTE, CALL_OUT } from '../../constants';
7
7
  import DropdownMenuItem from '../../commons/dropdown-menu-item';
8
8
  const TransformMenus = _ref => {
9
9
  let {
@@ -23,6 +23,14 @@ const TransformMenus = _ref => {
23
23
  if (LIST_ITEM_CORRELATION_TYPE.includes(slateNode.type)) {
24
24
  newSideMenusConfig = SIDE_TRANSFORM_MENUS_CONFIG.filter(item => LIST_ITEM_SUPPORTED_TRANSFORMATION.includes(item.type));
25
25
  }
26
+ const path = ReactEditor.findPath(editor, slateNode);
27
+ if (path && path.length > 1) {
28
+ const nodeIndex = path[0];
29
+ const highestNode = editor.children[nodeIndex];
30
+ if (highestNode.type === BLOCKQUOTE) {
31
+ newSideMenusConfig = SIDE_TRANSFORM_MENUS_CONFIG.filter(item => item.type !== CALL_OUT);
32
+ }
33
+ }
26
34
  return newSideMenusConfig;
27
35
  // eslint-disable-next-line react-hooks/exhaustive-deps
28
36
  }, [slateNode]);
@@ -81,6 +81,7 @@ class EventProxy {
81
81
  }
82
82
  };
83
83
  this.onCopy = event => {
84
+ if (this.editor.onCopy) this.editor.onCopy(event);
84
85
  setOriginSdocKey(event);
85
86
  };
86
87
  this.onCut = event => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seafile/sdoc-editor",
3
- "version": "0.4.12",
3
+ "version": "0.4.14",
4
4
  "private": false,
5
5
  "description": "This is a sdoc editor",
6
6
  "main": "dist/index.js",
@@ -434,7 +434,7 @@
434
434
  "Type_search_content": "Type search content",
435
435
  "Replace_as": "Replace as",
436
436
  "Type_replace_content": "Type replace content",
437
- "Previous": "Předchozí",
437
+ "Prevs": "Prevs",
438
438
  "Next": "Další",
439
439
  "Replace": "Nahradit",
440
440
  "Replace_all": "Replace all",
@@ -434,7 +434,7 @@
434
434
  "Type_search_content": "Type search content",
435
435
  "Replace_as": "Replace as",
436
436
  "Type_replace_content": "Type replace content",
437
- "Previous": "Vorherige",
437
+ "Prevs": "Prevs",
438
438
  "Next": "Nächste Seite",
439
439
  "Replace": "Ersetzen",
440
440
  "Replace_all": "Replace all",
@@ -434,7 +434,7 @@
434
434
  "Type_search_content": "Type search content",
435
435
  "Replace_as": "Replace as",
436
436
  "Type_replace_content": "Type replace content",
437
- "Previous": "Previous",
437
+ "Prevs": "Prevs",
438
438
  "Next": "Next",
439
439
  "Replace": "Replace",
440
440
  "Replace_all": "Replace all",
@@ -434,7 +434,7 @@
434
434
  "Type_search_content": "Type search content",
435
435
  "Replace_as": "Replace as",
436
436
  "Type_replace_content": "Type replace content",
437
- "Previous": "Anterior",
437
+ "Prevs": "Prevs",
438
438
  "Next": "Siguiente",
439
439
  "Replace": "Reemplazar",
440
440
  "Replace_all": "Replace all",
@@ -434,7 +434,7 @@
434
434
  "Type_search_content": "Type search content",
435
435
  "Replace_as": "Replace as",
436
436
  "Type_replace_content": "Type replace content",
437
- "Previous": "Précédent",
437
+ "Prevs": "Prevs",
438
438
  "Next": "Suivant",
439
439
  "Replace": "Remplacer",
440
440
  "Replace_all": "Replace all",
@@ -434,7 +434,7 @@
434
434
  "Type_search_content": "Type search content",
435
435
  "Replace_as": "Replace as",
436
436
  "Type_replace_content": "Type replace content",
437
- "Previous": "Precedente",
437
+ "Prevs": "Prevs",
438
438
  "Next": "Successivo",
439
439
  "Replace": "Sostituire",
440
440
  "Replace_all": "Replace all",
@@ -434,7 +434,7 @@
434
434
  "Type_search_content": "Введите содержимое для поиска",
435
435
  "Replace_as": "Заменить как",
436
436
  "Type_replace_content": "Введите содержимое для замены",
437
- "Previous": "Предыдущий",
437
+ "Prevs": "Prevs",
438
438
  "Next": "Следующий",
439
439
  "Replace": "Заменить",
440
440
  "Replace_all": "Заменить все",
@@ -434,10 +434,10 @@
434
434
  "Type_search_content": "输入查找内容",
435
435
  "Replace_as": "替换为",
436
436
  "Type_replace_content": "输入替换内容",
437
- "Previous": "上一个",
437
+ "Prevs": "上一个",
438
438
  "Next": "下一页",
439
439
  "Replace": "替换",
440
- "Replace_all": "下一个",
440
+ "Replace_all": "替换全部",
441
441
  "Are_you_sure_to_replace_all_number_xxx_in_this_document_with_yyy": "确定要将此文档内的 {{number}} 处 \"{{originalWord}} \" 替换为 \"{{replacedWord}} \" 吗?",
442
442
  "Are_you_sure_to_clear_all_number_xxx_in_this_document": "确定将此文档内的 {{number}} 处 \"{{originalWord}}\" 全部清除吗?",
443
443
  "Search_not_found": "未找到"