@seafile/sdoc-editor 0.1.48 → 0.1.50

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 (40) hide show
  1. package/dist/basic-sdk/assets/css/layout.css +4 -0
  2. package/dist/basic-sdk/assets/css/sdoc-editor-plugins.css +9 -0
  3. package/dist/basic-sdk/cursor/helper.js +42 -0
  4. package/dist/basic-sdk/cursor/use-cursors.js +24 -0
  5. package/dist/basic-sdk/editor.js +113 -108
  6. package/dist/basic-sdk/extension/constants/index.js +1 -1
  7. package/dist/basic-sdk/extension/index.js +4 -3
  8. package/dist/basic-sdk/extension/menu/context-menu/index.css +1 -0
  9. package/dist/basic-sdk/extension/menu/context-menu/index.js +37 -0
  10. package/dist/basic-sdk/extension/menu/index.js +2 -1
  11. package/dist/basic-sdk/extension/plugins/table/index.js +3 -2
  12. package/dist/basic-sdk/extension/plugins/table/menu/context-menu/index.css +27 -0
  13. package/dist/basic-sdk/extension/plugins/table/menu/context-menu/index.js +124 -0
  14. package/dist/basic-sdk/extension/plugins/table/menu/context-menu/insert-table-element.js +93 -0
  15. package/dist/basic-sdk/extension/plugins/table/menu/index.js +2 -1
  16. package/dist/basic-sdk/extension/plugins/table/plugin.js +19 -12
  17. package/dist/basic-sdk/extension/plugins/table/render/render-table/index.css +8 -0
  18. package/dist/basic-sdk/extension/plugins/text-style/caret.js +49 -0
  19. package/dist/basic-sdk/extension/plugins/text-style/render-elem.js +11 -1
  20. package/dist/basic-sdk/extension/render/render-element.js +6 -1
  21. package/dist/basic-sdk/extension/render/render-leaf.js +7 -1
  22. package/dist/basic-sdk/socket/helpers.js +15 -4
  23. package/dist/basic-sdk/socket/socket-client.js +7 -4
  24. package/dist/basic-sdk/socket/socket-manager.js +12 -3
  25. package/dist/basic-sdk/socket/with-socket-io.js +5 -3
  26. package/dist/basic-sdk/utils/diff.js +1 -0
  27. package/dist/components/doc-operations/style.css +1 -0
  28. package/dist/components/modal-portal.js +41 -0
  29. package/dist/pages/simple-editor.js +2 -5
  30. package/package.json +4 -2
  31. package/public/locales/cs/sdoc-editor.json +1 -1
  32. package/public/locales/de/sdoc-editor.json +1 -1
  33. package/public/locales/en/sdoc-editor.json +8 -2
  34. package/public/locales/es/sdoc-editor.json +1 -1
  35. package/public/locales/es-AR/sdoc-editor.json +1 -1
  36. package/public/locales/es-MX/sdoc-editor.json +1 -1
  37. package/public/locales/fr/sdoc-editor.json +1 -1
  38. package/public/locales/it/sdoc-editor.json +1 -1
  39. package/public/locales/ru/sdoc-editor.json +1 -1
  40. package/public/locales/zh-CN/sdoc-editor.json +8 -2
@@ -32,3 +32,7 @@
32
32
  border: 1px solid #e5e6e8;
33
33
  box-shadow: 0 0 15px rgba(0, 0, 0, 0.06);
34
34
  }
35
+
36
+ .sdoc-editor-container .sdoc-editor-content .article > div {
37
+ caret-color: blue;
38
+ }
@@ -69,3 +69,12 @@
69
69
  font-size: 12px;
70
70
  }
71
71
 
72
+ /* caret */
73
+ .sdoc-editor-container .article .caret-item .caret-name {
74
+ display: none;
75
+ }
76
+
77
+ .sdoc-editor-container .article .caret-item:hover .caret-name {
78
+ display: block;
79
+ }
80
+
@@ -0,0 +1,42 @@
1
+ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
2
+ import randomColor from 'randomcolor';
3
+
4
+ // selection: { anchor, focus }
5
+ // cursor: { anchor, focus }
6
+
7
+ export var setCursor = function setCursor(editor, operations, user, selection, cursorData) {
8
+ var clientId = user.username;
9
+ var cursorOps = operations.filter(function (operation) {
10
+ return operation.type === 'set_selection';
11
+ });
12
+ if (!editor.cursors) editor.cursors = {};
13
+ var oldCursor = editor.cursors[clientId] ? editor.cursors[clientId] : {};
14
+ var lastCursorOp = cursorOps[cursorOps.length - 1];
15
+ if (selection) {
16
+ var newCursor = lastCursorOp && lastCursorOp.newProperties || {};
17
+ var newCursorData = _objectSpread(_objectSpread(_objectSpread(_objectSpread({}, oldCursor), newCursor), selection), cursorData);
18
+ editor.cursors[clientId] = newCursorData;
19
+ } else {
20
+ delete editor.cursors[clientId];
21
+ }
22
+ editor.cursors = _objectSpread({}, editor.cursors);
23
+ return editor;
24
+ };
25
+ export var deleteCursor = function deleteCursor(editor, username) {
26
+ delete editor.cursors[username];
27
+ editor.cursors = _objectSpread({}, editor.cursors);
28
+ return editor;
29
+ };
30
+ export var generateCursorData = function generateCursorData(config) {
31
+ var user = config.user;
32
+ var options = {
33
+ luminosity: 'dark',
34
+ format: 'rgba',
35
+ alpha: 1
36
+ };
37
+ var color = randomColor(options);
38
+ return {
39
+ name: user.name,
40
+ color: color
41
+ };
42
+ };
@@ -0,0 +1,24 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
2
+ import { useEffect, useState } from 'react';
3
+ export var useCursors = function useCursors(editor) {
4
+ var _useState = useState([]),
5
+ _useState2 = _slicedToArray(_useState, 2),
6
+ cursors = _useState2[0],
7
+ setCursors = _useState2[1];
8
+ useEffect(function () {
9
+ var cursors = Object.values(editor.cursors) || [];
10
+ setCursors(cursors);
11
+ // eslint-disable-next-line react-hooks/exhaustive-deps
12
+ }, []);
13
+ useEffect(function () {
14
+ editor.onCursor = function (editorCursors) {
15
+ var cursors = Object.values(editorCursors) || [];
16
+ setCursors(cursors);
17
+ };
18
+ // eslint-disable-next-line react-hooks/exhaustive-deps
19
+ }, []);
20
+ return {
21
+ cursors: cursors,
22
+ setCursors: setCursors
23
+ };
24
+ };
@@ -1,122 +1,127 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
1
2
  import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
2
- import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
3
- import _createClass from "@babel/runtime/helpers/esm/createClass";
4
- import _inherits from "@babel/runtime/helpers/esm/inherits";
5
- import _createSuper from "@babel/runtime/helpers/esm/createSuper";
6
- import React from 'react';
7
- import { Node } from '@seafile/slate';
3
+ import React, { useCallback, useEffect, useMemo, useState } from 'react';
4
+ import { Node, Editor } from '@seafile/slate';
8
5
  import { Editable, Slate, ReactEditor } from '@seafile/slate-react';
9
- import { Editor } from '@seafile/slate';
10
- import editor, { renderLeaf, renderElement, Toolbar } from './extension';
6
+ import defaultEditor, { renderLeaf, renderElement, Toolbar, ContextMenu } from './extension';
7
+ import { focusEditor } from './extension/core';
11
8
  import { withSocketIO } from './socket';
12
9
  import withNodeId from './node-id';
13
10
  import SDocOutline from './outline';
14
11
  import EventProxy from './utils/event-handler';
15
- import { focusEditor } from './extension/core';
12
+ import { useCursors } from './cursor/use-cursors';
16
13
  import './assets/css/layout.css';
17
14
  import './assets/css/sdoc-editor-plugins.css';
18
- var SDocEditor = /*#__PURE__*/function (_React$Component) {
19
- _inherits(SDocEditor, _React$Component);
20
- var _super = _createSuper(SDocEditor);
21
- function SDocEditor(props) {
22
- var _this;
23
- _classCallCheck(this, SDocEditor);
24
- _this = _super.call(this, props);
25
- _this.onChange = function (slateValue) {
26
- var onValueChanged = _this.props.onValueChanged;
27
- _this.setState({
28
- slateValue: slateValue
29
- });
30
- onValueChanged && onValueChanged(slateValue);
31
- };
32
- _this.onDOMBeforeInput = function (e) {
33
- var slateValue = _this.state.slateValue;
34
- if (e.data && e.data !== '') {
35
- var _node$;
36
- var node = Editor.parent(_this.editor, editor.selection);
37
- _this.editor.onDOMBeforeInputId = (_node$ = node[0]) === null || _node$ === void 0 ? void 0 : _node$.id;
38
- _this.setState({
39
- slateValue: _toConsumableArray(slateValue)
40
- });
41
- } else {
42
- _this.editor.onDOMBeforeInputId = null;
43
- _this.setState({
44
- slateValue: _toConsumableArray(slateValue)
45
- });
46
- }
47
- };
48
- var children = props.document.children;
49
- _this.state = {
50
- slateValue: children,
51
- isLoading: true
52
- };
53
- _this.socketManager = null;
54
- _this.editor = withNodeId(editor);
55
- if (props.isOpenSocket) {
56
- var document = props.document,
57
- config = props.config;
58
- _this.editor = withSocketIO(_this.editor, {
59
- document: document,
60
- config: config
61
- });
62
- }
63
- _this.eventProxy = new EventProxy(_this.editor);
64
- _this.renderElement = function (props) {
65
- return renderElement(props, _this.editor);
66
- };
67
- _this.renderLeaf = function (props) {
68
- return renderLeaf(props, _this.editor);
15
+ var SDocEditor = function SDocEditor(_ref) {
16
+ var document = _ref.document,
17
+ config = _ref.config;
18
+ // init editor
19
+ var editor = useMemo(function () {
20
+ var newEditor = withNodeId(withSocketIO(defaultEditor, {
21
+ document: document,
22
+ config: config
23
+ }));
24
+ var cursors = document.cursors;
25
+ newEditor.cursors = cursors || {};
26
+ return newEditor;
27
+ // eslint-disable-next-line react-hooks/exhaustive-deps
28
+ }, []);
29
+
30
+ // init eventHandler
31
+ // eslint-disable-next-line react-hooks/exhaustive-deps
32
+ var eventProxy = useMemo(function () {
33
+ return new EventProxy(editor);
34
+ }, []);
35
+
36
+ // useMount: init socket connection
37
+ useEffect(function () {
38
+ editor.openConnection();
39
+ return function () {
40
+ editor.closeConnection();
69
41
  };
70
- return _this;
71
- }
72
- _createClass(SDocEditor, [{
73
- key: "componentDidMount",
74
- value: function componentDidMount() {
75
- this.editor.openConnection();
76
- if (Node.string(editor) === '') {
77
- var firstNodePath = ReactEditor.findPath(editor, this.editor.children[0]);
78
- focusEditor(this.editor, firstNodePath);
79
- }
42
+ // eslint-disable-next-line react-hooks/exhaustive-deps
43
+ }, []);
44
+
45
+ // useMount: focus editor
46
+ useEffect(function () {
47
+ if (Node.string(editor) === '') {
48
+ var firstNodePath = ReactEditor.findPath(editor, editor.children[0]);
49
+ focusEditor(editor, firstNodePath);
80
50
  }
81
- }, {
82
- key: "componentWillUnmount",
83
- value: function componentWillUnmount() {
84
- this.editor.closeConnection();
51
+ // eslint-disable-next-line react-hooks/exhaustive-deps
52
+ }, []);
53
+
54
+ // handle placeholder
55
+ var onDOMBeforeInput = useCallback(function (e) {
56
+ if (e.data && e.data !== '') {
57
+ var _node$;
58
+ var node = Editor.parent(editor, editor.selection);
59
+ editor.onDOMBeforeInputId = (_node$ = node[0]) === null || _node$ === void 0 ? void 0 : _node$.id;
60
+ setSlateValue(_toConsumableArray(slateValue));
61
+ } else {
62
+ editor.onDOMBeforeInputId = null;
63
+ setSlateValue(_toConsumableArray(slateValue));
85
64
  }
86
- }, {
87
- key: "render",
88
- value: function render() {
89
- var slateValue = this.state.slateValue;
90
- var config = this.props.config;
91
- var docUuid = config.docUuid;
92
- return /*#__PURE__*/React.createElement("div", {
93
- className: "sdoc-editor-container"
94
- }, /*#__PURE__*/React.createElement(Toolbar, {
95
- editor: this.editor
96
- }), /*#__PURE__*/React.createElement("div", {
97
- className: "sdoc-editor-content"
98
- }, /*#__PURE__*/React.createElement(SDocOutline, {
99
- doc: slateValue,
100
- docUuid: docUuid
101
- }), /*#__PURE__*/React.createElement("div", {
102
- className: "flex-fill o-auto"
103
- }, /*#__PURE__*/React.createElement(Slate, {
104
- editor: this.editor,
105
- value: slateValue,
106
- onChange: this.onChange
107
- }, /*#__PURE__*/React.createElement("div", {
108
- className: "article"
109
- }, /*#__PURE__*/React.createElement(Editable, {
110
- renderElement: this.renderElement,
111
- renderLeaf: this.renderLeaf,
112
- onKeyDown: this.eventProxy.onKeyDown,
113
- onDOMBeforeInput: this.onDOMBeforeInput
114
- }))))));
65
+ // eslint-disable-next-line react-hooks/exhaustive-deps
66
+ }, []);
67
+ var _useState = useState(false),
68
+ _useState2 = _slicedToArray(_useState, 2),
69
+ isShowContextMenu = _useState2[0],
70
+ setContextMenu = _useState2[1];
71
+ var _useState3 = useState({}),
72
+ _useState4 = _slicedToArray(_useState3, 2),
73
+ menuPosition = _useState4[0],
74
+ setMenuPosition = _useState4[1];
75
+ var onContextMenu = useCallback(function (event) {
76
+ if (editor.isAllInTable()) {
77
+ event.preventDefault();
78
+ var contextMenuPosition = {
79
+ left: event.clientX,
80
+ top: event.clientY
81
+ };
82
+ setContextMenu(true);
83
+ setMenuPosition(contextMenuPosition);
115
84
  }
116
- }]);
117
- return SDocEditor;
118
- }(React.Component);
119
- SDocEditor.defaultProps = {
120
- isOpenSocket: false
85
+ // eslint-disable-next-line react-hooks/exhaustive-deps
86
+ }, []);
87
+ var _useState5 = useState(document.children),
88
+ _useState6 = _slicedToArray(_useState5, 2),
89
+ slateValue = _useState6[0],
90
+ setSlateValue = _useState6[1];
91
+ var onChange = useCallback(function (slateValue) {
92
+ setSlateValue(slateValue);
93
+ setContextMenu(false);
94
+ // eslint-disable-next-line react-hooks/exhaustive-deps
95
+ }, []);
96
+ var _useCursors = useCursors(editor),
97
+ cursors = _useCursors.cursors;
98
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
99
+ className: "sdoc-editor-container"
100
+ }, /*#__PURE__*/React.createElement(Toolbar, {
101
+ editor: editor
102
+ }), /*#__PURE__*/React.createElement("div", {
103
+ className: "sdoc-editor-content"
104
+ }, /*#__PURE__*/React.createElement(SDocOutline, {
105
+ doc: slateValue,
106
+ docUuid: config.docUuid
107
+ }), /*#__PURE__*/React.createElement("div", {
108
+ className: "flex-fill o-auto"
109
+ }, /*#__PURE__*/React.createElement(Slate, {
110
+ editor: editor,
111
+ value: slateValue,
112
+ onChange: onChange
113
+ }, /*#__PURE__*/React.createElement("div", {
114
+ className: "article"
115
+ }, /*#__PURE__*/React.createElement(Editable, {
116
+ renderElement: renderElement,
117
+ renderLeaf: renderLeaf,
118
+ onKeyDown: eventProxy.onKeyDown,
119
+ onDOMBeforeInput: onDOMBeforeInput,
120
+ cursors: cursors,
121
+ onContextMenu: onContextMenu
122
+ })))))), isShowContextMenu && /*#__PURE__*/React.createElement(ContextMenu, {
123
+ editor: editor,
124
+ contextMenuPosition: menuPosition
125
+ }));
121
126
  };
122
127
  export default SDocEditor;
@@ -48,7 +48,7 @@ export var MENUS_CONFIG_MAP = (_MENUS_CONFIG_MAP = {}, _defineProperty(_MENUS_CO
48
48
  }), _defineProperty(_MENUS_CONFIG_MAP, REMOVE_TABLE, {
49
49
  id: "sdoc_".concat(REMOVE_TABLE),
50
50
  iconClass: 'sdocfont sdoc-delete-table',
51
- text: 'remove_table'
51
+ text: 'Remove_table'
52
52
  }), _defineProperty(_MENUS_CONFIG_MAP, TEXT_STYLE, [{
53
53
  id: ITALIC,
54
54
  iconClass: 'sdocfont sdoc-italic',
@@ -5,13 +5,14 @@ import Plugins from './plugins';
5
5
  import renderElement from './render/render-element';
6
6
  import renderLeaf from './render/render-leaf';
7
7
  import Toolbar from './toolbar';
8
+ import { ContextMenu } from './menu';
8
9
  var baseEditor = withHistory(withReact(createEditor()));
9
- var editor = Plugins.reduce(function (editor, pluginItem) {
10
+ var defaultEditor = Plugins.reduce(function (editor, pluginItem) {
10
11
  var withPlugin = pluginItem.editorPlugin;
11
12
  if (withPlugin) {
12
13
  return withPlugin(editor);
13
14
  }
14
15
  return editor;
15
16
  }, baseEditor);
16
- export default editor;
17
- export { renderLeaf, renderElement, Toolbar };
17
+ export default defaultEditor;
18
+ export { renderLeaf, renderElement, Toolbar, ContextMenu };
@@ -0,0 +1,37 @@
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';
6
+ import ModalPortal from '../../../../components/modal-portal';
7
+ import { TablePlugin } from '../../plugins';
8
+ var ContextMenu = /*#__PURE__*/function (_Component) {
9
+ _inherits(ContextMenu, _Component);
10
+ var _super = _createSuper(ContextMenu);
11
+ function ContextMenu() {
12
+ var _this;
13
+ _classCallCheck(this, ContextMenu);
14
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
15
+ args[_key] = arguments[_key];
16
+ }
17
+ _this = _super.call.apply(_super, [this].concat(args));
18
+ _this.renderContextMenu = function () {
19
+ var editor = _this.props.editor;
20
+ if (editor.isAllInTable()) {
21
+ var ContextMenuComponent = TablePlugin.contextMenu;
22
+ return /*#__PURE__*/React.createElement(ContextMenuComponent, _this.props);
23
+ }
24
+ };
25
+ return _this;
26
+ }
27
+ _createClass(ContextMenu, [{
28
+ key: "render",
29
+ value: function render() {
30
+ return /*#__PURE__*/React.createElement(ModalPortal, {
31
+ className: "sdoc-context-menu"
32
+ }, this.renderContextMenu());
33
+ }
34
+ }]);
35
+ return ContextMenu;
36
+ }(Component);
37
+ export default ContextMenu;
@@ -1,4 +1,5 @@
1
1
  import MenuGroup from './menu-group';
2
2
  import MenuItem from './menu-item';
3
+ import ContextMenu from './context-menu';
3
4
  import './menu.css';
4
- export { MenuGroup, MenuItem };
5
+ export { MenuGroup, MenuItem, ContextMenu };
@@ -1,5 +1,5 @@
1
1
  import { TABLE } from '../../constants';
2
- import { TableMenu } from './menu';
2
+ import { TableMenu, ContextMenu } from './menu';
3
3
  import Table from './model';
4
4
  import withTable from './plugin';
5
5
  import { renderTable, renderTableRow, renderTableCell } from './render-elem';
@@ -9,6 +9,7 @@ var TablePlugin = {
9
9
  model: Table,
10
10
  editorMenus: [TableMenu],
11
11
  editorPlugin: withTable,
12
- renderElements: [renderTable, renderTableRow, renderTableCell]
12
+ renderElements: [renderTable, renderTableRow, renderTableCell],
13
+ contextMenu: ContextMenu
13
14
  };
14
15
  export default TablePlugin;
@@ -0,0 +1,27 @@
1
+ .sdoc-context-menu .sdoc-table-context-menu {
2
+ display: block;
3
+ }
4
+
5
+ .sdoc-table-context-menu .insert-number {
6
+ margin-left: 50px;
7
+ }
8
+
9
+ .sdoc-table-context-menu .insert-number-input {
10
+ width: 36px;
11
+ height: 20px;
12
+ margin-right: .25rem;
13
+ padding-left: 4px;
14
+ padding-right: 4px;
15
+ text-align: center;
16
+ transition: none;
17
+ }
18
+
19
+ .sdoc-table-context-menu .dropdown-item:hover .insert-number-input {
20
+ background-color: transparent;
21
+ border: 1px solid #fff;
22
+ color: #fff;
23
+ }
24
+
25
+ .sdoc-table-context-menu .dropdown-item:disabled .insert-number-input {
26
+ color: #adb5bd;
27
+ }
@@ -0,0 +1,124 @@
1
+ import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
2
+ import _createClass from "@babel/runtime/helpers/esm/createClass";
3
+ import _assertThisInitialized from "@babel/runtime/helpers/esm/assertThisInitialized";
4
+ import _inherits from "@babel/runtime/helpers/esm/inherits";
5
+ import _createSuper from "@babel/runtime/helpers/esm/createSuper";
6
+ import React from 'react';
7
+ import { withTranslation } from 'react-i18next';
8
+ import ObjectUtils from '../../../../../utils/object-utils';
9
+ import { TABLE_ELEMENT, TABLE_ELEMENT_POSITION, ELEMENT_TYPE } from '../../../../constants';
10
+ import InsertTableElement from './insert-table-element';
11
+ import { getSelectedNodeByType } from '../../../../core';
12
+ import './index.css';
13
+ var ContextMenu = /*#__PURE__*/function (_React$Component) {
14
+ _inherits(ContextMenu, _React$Component);
15
+ var _super = _createSuper(ContextMenu);
16
+ function ContextMenu(props) {
17
+ var _this;
18
+ _classCallCheck(this, ContextMenu);
19
+ _this = _super.call(this, props);
20
+ _this.updateMenuPosition = function () {
21
+ var menuHeight = _this.menu.offsetHeight;
22
+
23
+ // get height of context menu when the menu is drawing completed in this page
24
+ // if (menuHeight === 0) {
25
+ // requestAnimationFrame(this.updateMenuPosition);
26
+ // }
27
+ var top = 0;
28
+ if (_this.position.top + menuHeight > document.body.clientHeight) {
29
+ top = document.body.clientHeight - menuHeight - 5;
30
+ } else {
31
+ top = _this.position.top;
32
+ }
33
+ var left = _this.position.left + 3;
34
+ _this.setState({
35
+ contextStyle: {
36
+ top: top,
37
+ left: left
38
+ }
39
+ });
40
+ };
41
+ _this.insertTableElement = function (type, position, count) {
42
+ var editor = _this.props.editor;
43
+ editor.insertTableElement(type, position, count);
44
+ };
45
+ _this.removeTableElement = function (type) {
46
+ var editor = _this.props.editor;
47
+ editor.removeTableElement(type);
48
+ };
49
+ _this.renderRemoveBtn = function (type, title) {
50
+ return /*#__PURE__*/React.createElement("button", {
51
+ onMouseDown: _this.removeTableElement.bind(_assertThisInitialized(_this), type),
52
+ className: "dropdown-item"
53
+ }, _this.props.t(title));
54
+ };
55
+ _this.state = {
56
+ contextStyle: {}
57
+ };
58
+ _this.position = null;
59
+ return _this;
60
+ }
61
+ _createClass(ContextMenu, [{
62
+ key: "componentDidMount",
63
+ value: function componentDidMount() {
64
+ this.position = this.props.contextMenuPosition;
65
+ this.updateMenuPosition();
66
+ }
67
+ }, {
68
+ key: "UNSAFE_componentWillReceiveProps",
69
+ value: function UNSAFE_componentWillReceiveProps(nextProps) {
70
+ var nextContextMenuPosition = nextProps.contextMenuPosition;
71
+ if (!ObjectUtils.isSameObject(nextContextMenuPosition, this.props.contextMenuPosition)) {
72
+ this.position = nextContextMenuPosition;
73
+ this.updateMenuPosition();
74
+ }
75
+ }
76
+ }, {
77
+ key: "componentWillUnmount",
78
+ value: function componentWillUnmount() {
79
+ this.menu = null;
80
+ }
81
+ }, {
82
+ key: "render",
83
+ value: function render() {
84
+ var _this2 = this;
85
+ var contextStyle = this.state.contextStyle;
86
+ var editor = this.props.editor;
87
+ var currentTable = getSelectedNodeByType(editor, ELEMENT_TYPE.TABLE);
88
+ var currentRow = getSelectedNodeByType(editor, ELEMENT_TYPE.TABLE_ROW);
89
+ var currentRowsCount = currentTable.children.length;
90
+ var currentColumnsCount = currentRow.children.length;
91
+ return /*#__PURE__*/React.createElement("div", {
92
+ style: contextStyle,
93
+ ref: function ref(_ref) {
94
+ return _this2.menu = _ref;
95
+ },
96
+ className: "sdoc-table-context-menu dropdown-menu"
97
+ }, /*#__PURE__*/React.createElement(InsertTableElement, {
98
+ type: TABLE_ELEMENT.ROW,
99
+ currentCount: currentRowsCount,
100
+ position: TABLE_ELEMENT_POSITION.BEFORE,
101
+ insertTableElement: this.insertTableElement
102
+ }), /*#__PURE__*/React.createElement(InsertTableElement, {
103
+ type: TABLE_ELEMENT.ROW,
104
+ currentCount: currentRowsCount,
105
+ position: TABLE_ELEMENT_POSITION.AFTER,
106
+ insertTableElement: this.insertTableElement
107
+ }), /*#__PURE__*/React.createElement(InsertTableElement, {
108
+ type: TABLE_ELEMENT.COLUMN,
109
+ currentCount: currentColumnsCount,
110
+ position: TABLE_ELEMENT_POSITION.BEFORE,
111
+ insertTableElement: this.insertTableElement
112
+ }), /*#__PURE__*/React.createElement(InsertTableElement, {
113
+ type: TABLE_ELEMENT.COLUMN,
114
+ currentCount: currentColumnsCount,
115
+ position: TABLE_ELEMENT_POSITION.AFTER,
116
+ insertTableElement: this.insertTableElement
117
+ }), /*#__PURE__*/React.createElement("div", {
118
+ 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'));
120
+ }
121
+ }]);
122
+ return ContextMenu;
123
+ }(React.Component);
124
+ export default withTranslation('sdoc-editor')(ContextMenu);
@@ -0,0 +1,93 @@
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';
6
+ import { withTranslation } from 'react-i18next';
7
+ import { Input } from 'reactstrap';
8
+ import isHotkey from 'is-hotkey';
9
+ import { TABLE_ELEMENT, TABLE_ELEMENT_POSITION } from '../../../../constants';
10
+ import { TABLE_MAX_COLUMNS, TABLE_MAX_ROWS } from '../../constants';
11
+ var InsertTableElement = /*#__PURE__*/function (_Component) {
12
+ _inherits(InsertTableElement, _Component);
13
+ var _super = _createSuper(InsertTableElement);
14
+ function InsertTableElement(props) {
15
+ var _this;
16
+ _classCallCheck(this, InsertTableElement);
17
+ _this = _super.call(this, props);
18
+ _this.insertTableElement = function () {
19
+ var _this$props = _this.props,
20
+ type = _this$props.type,
21
+ position = _this$props.position;
22
+ var count = _this.state.count;
23
+ _this.props.insertTableElement(type, position, count);
24
+ };
25
+ _this.getTip = function () {
26
+ var _this$props2 = _this.props,
27
+ type = _this$props2.type,
28
+ position = _this$props2.position,
29
+ t = _this$props2.t;
30
+ if (type === TABLE_ELEMENT.ROW) {
31
+ return position === TABLE_ELEMENT_POSITION.AFTER ? t('Insert_below') : t('Insert_above');
32
+ }
33
+ return position === TABLE_ELEMENT_POSITION.AFTER ? t('Insert_on_the_right') : t('Insert_on_the_left');
34
+ };
35
+ _this.onKeyDown = function (event) {
36
+ if (isHotkey('enter', event)) {
37
+ event.preventDefault();
38
+ _this.insertTableElement();
39
+ return;
40
+ }
41
+ };
42
+ _this.onChange = function (event) {
43
+ var value = event.target.value || '0';
44
+ var newValue = value ? value.replace(/[^\d,]/g, '') : value;
45
+ if (newValue === _this.state.count) return;
46
+ var currentCount = _this.props.currentCount;
47
+ var numberValue = parseInt(newValue);
48
+ if (currentCount + numberValue > _this.maxCount) {
49
+ _this.setState({
50
+ count: _this.maxCount - currentCount
51
+ });
52
+ return;
53
+ }
54
+ _this.setState({
55
+ count: numberValue
56
+ });
57
+ };
58
+ _this.state = {
59
+ count: 1
60
+ };
61
+ _this.maxCount = props.type === TABLE_ELEMENT.ROW ? TABLE_MAX_ROWS : TABLE_MAX_COLUMNS;
62
+ return _this;
63
+ }
64
+ _createClass(InsertTableElement, [{
65
+ key: "render",
66
+ value: function render() {
67
+ var count = this.state.count;
68
+ var _this$props3 = this.props,
69
+ t = _this$props3.t,
70
+ type = _this$props3.type,
71
+ currentCount = _this$props3.currentCount;
72
+ var isDisabled = currentCount >= this.maxCount;
73
+ return /*#__PURE__*/React.createElement("button", {
74
+ onMouseDown: this.insertTableElement,
75
+ className: "dropdown-item d-flex align-items-center justify-content-between",
76
+ disabled: isDisabled
77
+ }, this.getTip(), /*#__PURE__*/React.createElement("div", {
78
+ className: "insert-number d-flex align-items-center"
79
+ }, /*#__PURE__*/React.createElement(Input, {
80
+ disabled: isDisabled,
81
+ className: "insert-number-input",
82
+ onMouseDown: function onMouseDown(e) {
83
+ e.stopPropagation();
84
+ },
85
+ onKeyDown: this.onKeyDown,
86
+ value: count,
87
+ onChange: this.onChange
88
+ }), /*#__PURE__*/React.createElement("span", null, type === TABLE_ELEMENT.ROW ? t('row(s)') : t('column(s)'))));
89
+ }
90
+ }]);
91
+ return InsertTableElement;
92
+ }(Component);
93
+ export default withTranslation('sdoc-editor')(InsertTableElement);
@@ -1,3 +1,4 @@
1
1
  import TableMenu from './table-menu';
2
2
  import ActiveTableMenu from './active-table-menu';
3
- export { TableMenu, ActiveTableMenu };
3
+ import ContextMenu from './context-menu';
4
+ export { TableMenu, ActiveTableMenu, ContextMenu };
@@ -489,31 +489,38 @@ var withTable = function withTable(editor) {
489
489
  };
490
490
  newEditor.insertTableElement = function (type) {
491
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;
492
493
  var _getSelectedInfo7 = getSelectedInfo(newEditor),
493
494
  tablePath = _getSelectedInfo7.tablePath,
494
495
  tableSize = _getSelectedInfo7.tableSize,
495
496
  rowIndex = _getSelectedInfo7.rowIndex,
496
497
  cellIndex = _getSelectedInfo7.cellIndex;
497
498
  if (type === TABLE_ELEMENT.ROW) {
498
- if (tableSize[0] === TABLE_MAX_ROWS) return;
499
+ if (tableSize[0] >= TABLE_MAX_ROWS) return;
499
500
  var targetPath = position === TABLE_ELEMENT_POSITION.AFTER ? [].concat(_toConsumableArray(tablePath), [rowIndex + 1]) : [].concat(_toConsumableArray(tablePath), [rowIndex]);
500
- var row = generateTableRow(tableSize[1]);
501
- Transforms.insertNodes(editor, row, {
502
- at: targetPath
503
- });
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
+ }
504
508
  var focusPath = [].concat(_toConsumableArray(targetPath), [cellIndex]);
505
509
  focusEditor(newEditor, focusPath);
506
510
  return;
507
511
  }
508
512
  if (type === TABLE_ELEMENT.COLUMN) {
509
- if (tableSize[1] === TABLE_MAX_COLUMNS) return;
513
+ if (tableSize[1] >= TABLE_MAX_COLUMNS) return;
510
514
  var newCellIndex = position === TABLE_ELEMENT_POSITION.AFTER ? cellIndex + 1 : cellIndex;
511
- for (var i = 0; i < tableSize[0]; i++) {
512
- var newCellPath = [].concat(_toConsumableArray(tablePath), [i, newCellIndex]);
513
- var newCell = generateTableCell();
514
- Transforms.insertNodes(editor, newCell, {
515
- at: newCellPath
516
- });
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
+ }
517
524
  }
518
525
  var _focusPath = [].concat(_toConsumableArray(tablePath), [rowIndex, cellIndex + 1, 0]);
519
526
  focusEditor(newEditor, _focusPath);
@@ -21,6 +21,10 @@
21
21
  border-bottom: none;
22
22
  }
23
23
 
24
+ .sdoc-table-wrapper {
25
+ overflow: scroll;
26
+ }
27
+
24
28
  .sdoc-table-wrapper tr:first-child {
25
29
  font-weight: unset;
26
30
  }
@@ -28,3 +32,7 @@
28
32
  .sdoc-table-wrapper tr:nth-child(2n+1) {
29
33
  background-color: unset;
30
34
  }
35
+
36
+ .article .sdoc-table-wrapper td {
37
+ min-width: 35px;
38
+ }
@@ -0,0 +1,49 @@
1
+ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
2
+ import React from 'react';
3
+ var cursorStyleBase = {
4
+ position: 'absolute',
5
+ top: -2,
6
+ pointerEvents: 'none',
7
+ userSelect: 'none',
8
+ transform: 'translateY(-100%)',
9
+ fontSize: 10,
10
+ color: 'white',
11
+ background: 'palevioletred',
12
+ whiteSpace: 'nowrap'
13
+ };
14
+ var caretStyleBase = {
15
+ position: 'absolute',
16
+ // pointerEvents: 'none',
17
+ userSelect: 'none',
18
+ height: '1.2em',
19
+ width: 2,
20
+ background: 'palevioletred'
21
+ };
22
+ var Caret = function Caret(_ref) {
23
+ var color = _ref.color,
24
+ name = _ref.name;
25
+ var cursorStyles = _objectSpread(_objectSpread({}, cursorStyleBase), {}, {
26
+ background: color,
27
+ left: '0%',
28
+ cursor: 'default'
29
+ });
30
+ var caretStyles = _objectSpread(_objectSpread({}, caretStyleBase), {}, {
31
+ background: color,
32
+ left: '0%'
33
+ });
34
+ caretStyles['top'] = 1;
35
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("span", {
36
+ className: "caret-item",
37
+ contentEditable: false,
38
+ style: caretStyles
39
+ }, /*#__PURE__*/React.createElement("span", {
40
+ style: {
41
+ position: 'relative'
42
+ }
43
+ }, /*#__PURE__*/React.createElement("span", {
44
+ className: "caret-name",
45
+ contentEditable: false,
46
+ style: cursorStyles
47
+ }, name))));
48
+ };
49
+ export default Caret;
@@ -1,4 +1,5 @@
1
1
  import React from 'react';
2
+ import Caret from './caret';
2
3
  var renderText = function renderText(props, editor) {
3
4
  var attributes = props.attributes,
4
5
  children = props.children,
@@ -38,8 +39,17 @@ var renderText = function renderText(props, editor) {
38
39
  className: "token ".concat(leaf.type)
39
40
  }, markedChildren);
40
41
  }
42
+ var style = {
43
+ position: 'relative'
44
+ };
45
+ if (leaf.isCaret) {
46
+ style['display'] = 'inline-block';
47
+ style['minWidth'] = '2px';
48
+ }
41
49
  return /*#__PURE__*/React.createElement("span", Object.assign({
42
50
  "data-id": leaf.id
43
- }, attributes), markedChildren);
51
+ }, attributes, {
52
+ style: style
53
+ }), leaf.isCaret ? /*#__PURE__*/React.createElement(Caret, leaf) : null, markedChildren);
44
54
  };
45
55
  export default renderText;
@@ -1,10 +1,12 @@
1
1
  import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
2
2
  import React from 'react';
3
3
  import { Node, Editor } from '@seafile/slate';
4
+ import { useSlateStatic } from '@seafile/slate-react';
4
5
  import { BLOCKQUOTE, LINK, CHECK_LIST_ITEM, HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6, LIST_ITEM, LIST_LIC, ORDERED_LIST, PARAGRAPH, UNORDERED_LIST, CODE_BLOCK, IMAGE, ELEMENT_TYPE } from '../constants';
5
6
  import { BlockquotePlugin, LinkPlugin, CheckListPlugin, HeaderPlugin, ListPlugin, CodeBlockPlugin, ImagePlugin, TablePlugin } from '../plugins';
6
7
  import { Placeholder, findNode } from '../core';
7
- var renderElement = function renderElement(props, editor) {
8
+ var CustomElement = function CustomElement(props) {
9
+ var editor = useSlateStatic();
8
10
  var attributes = props.attributes,
9
11
  children = props.children,
10
12
  element = props.element;
@@ -127,4 +129,7 @@ var renderElement = function renderElement(props, editor) {
127
129
  }
128
130
  }
129
131
  };
132
+ var renderElement = function renderElement(props) {
133
+ return /*#__PURE__*/React.createElement(CustomElement, props);
134
+ };
130
135
  export default renderElement;
@@ -1,8 +1,14 @@
1
1
  import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
2
+ import React from 'react';
3
+ import { useSlateStatic } from '@seafile/slate-react';
2
4
  import { TextPlugin } from '../plugins';
3
- var renderLeaf = function renderLeaf(props, editor) {
5
+ var CustomLeaf = function CustomLeaf(props) {
6
+ var editor = useSlateStatic();
4
7
  var _TextPlugin$renderEle = _slicedToArray(TextPlugin.renderElements, 1),
5
8
  renderText = _TextPlugin$renderEle[0];
6
9
  return renderText(props, editor);
7
10
  };
11
+ var renderLeaf = function renderLeaf(props) {
12
+ return /*#__PURE__*/React.createElement(CustomLeaf, props);
13
+ };
8
14
  export default renderLeaf;
@@ -3,6 +3,7 @@ import deepCopy from 'deep-copy';
3
3
  import { Editor, Operation } from '@seafile/slate';
4
4
  import { getNode } from '../extension/core';
5
5
  import * as OPERATION from '../node-id/constants';
6
+ import { setCursor } from '../cursor/helper';
6
7
  export var getNodePathById = function getNodePathById(rootNode, nodeId) {
7
8
  var path = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
8
9
  if (rootNode.id === nodeId) return path;
@@ -250,11 +251,21 @@ export var reExecRevertOperationList = function reExecRevertOperationList(editor
250
251
  _loop2();
251
252
  }
252
253
  };
253
- export var syncRemoteOperations = function syncRemoteOperations(editor, remoteOperations) {
254
+ export var syncRemoteOperations = function syncRemoteOperations(editor, remoteOperations, user, selection, cursorData) {
254
255
  if (remoteOperations.length === 0) return;
255
256
  Editor.withoutNormalizing(editor, function () {
256
- remoteOperations.forEach(function (item) {
257
- editor.apply(item);
258
- });
257
+ for (var i = 0; i < remoteOperations.length; i++) {
258
+ var op = remoteOperations[i];
259
+ if (op.type === 'set_selection') {
260
+ continue;
261
+ }
262
+ editor.apply(op);
263
+ }
264
+ var currentUser = editor.user;
265
+ if (user && user.username !== currentUser.username) {
266
+ setCursor(editor, remoteOperations, user, selection, cursorData);
267
+ // sync cursor position
268
+ editor.onCursor && editor.onCursor(editor.cursors);
269
+ }
259
270
  });
260
271
  };
@@ -11,10 +11,12 @@ var SocketClient = /*#__PURE__*/_createClass(function SocketClient(config) {
11
11
  var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
12
12
  var _this$config = _this.config,
13
13
  docUuid = _this$config.docUuid,
14
- user = _this$config.user;
14
+ user = _this$config.user,
15
+ cursorData = _this$config.cursorData;
15
16
  return _objectSpread({
16
17
  doc_uuid: docUuid,
17
- user: user
18
+ user: user,
19
+ cursor_data: cursorData
18
20
  }, params);
19
21
  };
20
22
  this.onConnected = function () {
@@ -76,13 +78,14 @@ var SocketClient = /*#__PURE__*/_createClass(function SocketClient(config) {
76
78
  var socketManager = SocketManager.getInstance();
77
79
  socketManager.dispatchConnectState('leave-room', username);
78
80
  };
79
- this.sendOperations = function (operations, version, callback) {
81
+ this.sendOperations = function (operations, version, selection, callback) {
80
82
  debug('=========== send operations ==========');
81
83
  debug('%O', operations);
82
84
  debug('======================================');
83
85
  _this.socket.emit('update-document', _this.getParams({
84
86
  operations: operations,
85
- version: version
87
+ version: version,
88
+ selection: selection
86
89
  }), function (result) {
87
90
  callback && callback(result);
88
91
  });
@@ -4,6 +4,7 @@ import EventBus from '../utils/event-bus';
4
4
  import { syncRemoteOperations, reExecRevertOperationList, revertOperationList } from './helpers';
5
5
  import SocketClient from './socket-client';
6
6
  import debug from '../utils/debug';
7
+ import { deleteCursor } from '../cursor/helper';
7
8
  var SocketManager = /*#__PURE__*/_createClass(function SocketManager(editor, document, config) {
8
9
  var _this = this;
9
10
  _classCallCheck(this, SocketManager);
@@ -28,7 +29,8 @@ var SocketManager = /*#__PURE__*/_createClass(function SocketManager(editor, doc
28
29
  _this.dispatchConnectState('is-saving');
29
30
  var version = _this.document.version;
30
31
  var operations = _this.pendingOperationList.shift();
31
- _this.socketClient.sendOperations(operations, version, _this.sendOperationsCallback);
32
+ var selection = _this.editor.selection;
33
+ _this.socketClient.sendOperations(operations, version, selection, _this.sendOperationsCallback);
32
34
  };
33
35
  this.sendOperationsCallback = function (result) {
34
36
  if (result && result.success) {
@@ -83,10 +85,13 @@ var SocketManager = /*#__PURE__*/_createClass(function SocketManager(editor, doc
83
85
  }
84
86
 
85
87
  // 2. execute operations
86
- var operations = params.operations;
88
+ var operations = params.operations,
89
+ user = params.user,
90
+ selection = params.selection,
91
+ cursorData = params.cursor_data;
87
92
  // 2.1 Update content & version
88
93
  debug('execute remote operations: %O', operations);
89
- syncRemoteOperations(_this.editor, operations);
94
+ syncRemoteOperations(_this.editor, operations, user, selection, cursorData);
90
95
 
91
96
  // 2.2 Update document
92
97
  _this.document.version = serverVersion;
@@ -157,6 +162,10 @@ var SocketManager = /*#__PURE__*/_createClass(function SocketManager(editor, doc
157
162
  });
158
163
  };
159
164
  this.dispatchConnectState = function (type, message) {
165
+ if (type === 'leave-room') {
166
+ deleteCursor(_this.editor, message);
167
+ _this.editor.onCursor && _this.editor.onCursor(_this.editor.cursors);
168
+ }
160
169
  _this.eventBus.dispatch(type, message);
161
170
  };
162
171
  this.closeSocketConnect = function () {
@@ -1,12 +1,17 @@
1
1
  var _this = this;
2
+ import { generateCursorData } from '../cursor/helper';
2
3
  import SocketManager from './socket-manager';
3
4
  var withSocketIO = function withSocketIO(editor, options) {
4
5
  var onChange = editor.onChange;
5
6
  var newEditor = editor;
6
7
  var socketManager = null;
8
+ var user = options.config.user;
9
+ newEditor.user = user;
7
10
  newEditor.openConnection = function () {
8
11
  var document = options.document,
9
12
  config = options.config;
13
+ var cursorData = generateCursorData(options.config);
14
+ config['cursorData'] = cursorData;
10
15
  socketManager = SocketManager.getInstance(newEditor, document, config);
11
16
  };
12
17
  newEditor.closeConnection = function () {
@@ -14,9 +19,6 @@ var withSocketIO = function withSocketIO(editor, options) {
14
19
  };
15
20
  newEditor.onChange = function () {
16
21
  var operations = newEditor.operations;
17
- operations = operations.filter(function (item) {
18
- return item.type !== 'set_selection';
19
- });
20
22
  if (!newEditor.isRemote && operations.length > 0) {
21
23
  var _socketManager = SocketManager.getInstance();
22
24
  _socketManager.addOperations && _socketManager.addOperations(operations);
@@ -3,6 +3,7 @@ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
3
3
  import { DIFF_TYPE, ELEMENT_TYPE } from '../../basic-sdk/extension/constants';
4
4
  import ObjectUtils from './object-utils';
5
5
  var getElementIndexInDiffDocument = function getElementIndexInDiffDocument(diffValue, element) {
6
+ if (!diffValue || !element) return -1;
6
7
  return diffValue.findIndex(function (item) {
7
8
  return item.id === element.id;
8
9
  });
@@ -8,6 +8,7 @@
8
8
  display: flex;
9
9
  align-items: center;
10
10
  position: relative;
11
+ cursor: pointer;
11
12
  }
12
13
 
13
14
  .doc-ops .op-item .sdocfont {
@@ -0,0 +1,41 @@
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 from 'react';
6
+ import ReactDOM from 'react-dom';
7
+ var ModalPortal = /*#__PURE__*/function (_React$Component) {
8
+ _inherits(ModalPortal, _React$Component);
9
+ var _super = _createSuper(ModalPortal);
10
+ function ModalPortal(props) {
11
+ var _this;
12
+ _classCallCheck(this, ModalPortal);
13
+ _this = _super.call(this, props);
14
+ _this.state = {
15
+ isMounted: false
16
+ };
17
+ _this.el = document.createElement('div');
18
+ if (props.className) {
19
+ _this.el.className = props.className;
20
+ }
21
+ return _this;
22
+ }
23
+ _createClass(ModalPortal, [{
24
+ key: "componentDidMount",
25
+ value: function componentDidMount() {
26
+ document.body.appendChild(this.el);
27
+ }
28
+ }, {
29
+ key: "componentWillUnmount",
30
+ value: function componentWillUnmount() {
31
+ document.body.removeChild(this.el);
32
+ }
33
+ }, {
34
+ key: "render",
35
+ value: function render() {
36
+ return ReactDOM.createPortal(this.props.children, this.el);
37
+ }
38
+ }]);
39
+ return ModalPortal;
40
+ }(React.Component);
41
+ export default ModalPortal;
@@ -37,9 +37,6 @@ var SimpleEditor = /*#__PURE__*/function (_React$Component) {
37
37
  });
38
38
  }
39
39
  };
40
- _this.setEditorRef = function (ref) {
41
- _this.editorRef = ref;
42
- };
43
40
  _this.state = {
44
41
  isContextInit: false,
45
42
  errorMessage: null,
@@ -68,7 +65,8 @@ var SimpleEditor = /*#__PURE__*/function (_React$Component) {
68
65
  if (result && !result.children) {
69
66
  result = {
70
67
  version: 0,
71
- children: result.content
68
+ children: result.content,
69
+ cursors: result.cursors || {}
72
70
  };
73
71
  }
74
72
  this.setState({
@@ -115,7 +113,6 @@ var SimpleEditor = /*#__PURE__*/function (_React$Component) {
115
113
  }
116
114
  var isOpenSocket = context.getSetting('isOpenSocket');
117
115
  return /*#__PURE__*/React.createElement(Layout, null, /*#__PURE__*/React.createElement(Header, null, /*#__PURE__*/React.createElement(DocInfo, null), /*#__PURE__*/React.createElement(DocOperations, null)), /*#__PURE__*/React.createElement(Content, null, /*#__PURE__*/React.createElement(SDocEditor, {
118
- ref: this.setEditorRef,
119
116
  config: context.getEditorConfig(),
120
117
  document: document,
121
118
  isOpenSocket: isOpenSocket,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seafile/sdoc-editor",
3
- "version": "0.1.48",
3
+ "version": "0.1.50",
4
4
  "private": false,
5
5
  "description": "This is a sdoc editor",
6
6
  "main": "dist/index.js",
@@ -9,11 +9,13 @@
9
9
  "@seafile/slate": "0.91.8",
10
10
  "@seafile/slate-history": "0.86.2",
11
11
  "@seafile/slate-hyperscript": "0.81.7",
12
- "@seafile/slate-react": "0.92.2",
12
+ "@seafile/slate-react": "0.92.5",
13
+ "ahooks": "3.7.7",
13
14
  "classnames": "2.3.2",
14
15
  "deep-copy": "1.4.2",
15
16
  "is-hotkey": "0.2.0",
16
17
  "is-url": "^1.2.4",
18
+ "randomcolor": "0.6.2",
17
19
  "react-cookies": "0.1.1",
18
20
  "reactstrap": "8.9.0",
19
21
  "slugid": "3.2.0",
@@ -29,7 +29,7 @@
29
29
  "switch_to_rich_text_editor": "Přepnout do rozšířeného textového editoru",
30
30
  "switch_to_viewer": "Přepnout do značkovacího prohlížeče",
31
31
  "help": "Pomoc",
32
- "remove_table": "Odebrat tabulku",
32
+ "Remove_table": "Odebrat tabulku",
33
33
  "column": "Sloupec",
34
34
  "row": "Řádek",
35
35
  "set_align": "Nastavit zarovnání",
@@ -29,7 +29,7 @@
29
29
  "switch_to_rich_text_editor": "Zum Editor mit Formatierungen wechseln",
30
30
  "switch_to_viewer": "Zur Markdown-Vorschau wechseln",
31
31
  "help": "Hilfe",
32
- "remove_table": "Tabelle entfernen",
32
+ "Remove_table": "Tabelle entfernen",
33
33
  "column": "Spalte",
34
34
  "row": "Zeile",
35
35
  "set_align": "Ausrichtung festlegen",
@@ -34,7 +34,7 @@
34
34
  "switch_to_rich_text_editor": "Switch to Rich Text Editor",
35
35
  "switch_to_viewer": "Switch to Markdown Viewer",
36
36
  "help": "Help",
37
- "remove_table": "Remove Table",
37
+ "Remove_table": "Remove table",
38
38
  "column": "Column",
39
39
  "row": "Row",
40
40
  "Insert_Row_Before": "Insert Row Before",
@@ -246,5 +246,11 @@
246
246
  "Rows": "Rows",
247
247
  "Columns": "Columns",
248
248
  "Please_enter_title": "Please enter title",
249
- "Please_enter_text": "Please enter text"
249
+ "Please_enter_text": "Please enter text",
250
+ "row(s)": "row(s)",
251
+ "column(s)": "column(s)",
252
+ "Insert_below": "Insert below",
253
+ "Insert_above": "Insert above",
254
+ "Insert_on_the_right": "Insert on the right",
255
+ "Insert_on_the_left": "Insert on the left"
250
256
  }
@@ -29,7 +29,7 @@
29
29
  "switch_to_rich_text_editor": "Cambiar a editor de texto enriquecido",
30
30
  "switch_to_viewer": "Cambiar a visualizador Markdown",
31
31
  "help": "Ayuda",
32
- "remove_table": "Eliminar tabla",
32
+ "Remove_table": "Eliminar tabla",
33
33
  "column": "Columna",
34
34
  "row": "Fila",
35
35
  "set_align": "Establecer alineación",
@@ -29,7 +29,7 @@
29
29
  "switch_to_rich_text_editor": "Cambiar a editor de texto enriquecido",
30
30
  "switch_to_viewer": "Cambiar a visualizador Markdown",
31
31
  "help": "Ayuda",
32
- "remove_table": "Eliminar tabla",
32
+ "Remove_table": "Eliminar tabla",
33
33
  "column": "Columna",
34
34
  "row": "Fila",
35
35
  "set_align": "Establecer alineación",
@@ -29,7 +29,7 @@
29
29
  "switch_to_rich_text_editor": "Cambiar a editor de texto enriquecido",
30
30
  "switch_to_viewer": "Cambiar a visualizador Markdown",
31
31
  "help": "Ayuda",
32
- "remove_table": "Eliminar tabla",
32
+ "Remove_table": "Eliminar tabla",
33
33
  "column": "Columna",
34
34
  "row": "Fila",
35
35
  "set_align": "Establecer alineación",
@@ -29,7 +29,7 @@
29
29
  "switch_to_rich_text_editor": "Basculer en éditeur de texte riche",
30
30
  "switch_to_viewer": "Basculer en visualiseur Markdown",
31
31
  "help": "Aide",
32
- "remove_table": "Supprimer la table",
32
+ "Remove_table": "Supprimer la table",
33
33
  "column": "Colonne",
34
34
  "row": "Ligne",
35
35
  "set_align": "Ajuster l'alignement",
@@ -29,7 +29,7 @@
29
29
  "switch_to_rich_text_editor": "Passa all'Editor di testo formattato",
30
30
  "switch_to_viewer": "Passa alla vista di tipo Markdown",
31
31
  "help": "Aiuto",
32
- "remove_table": "Rimuovere Tabella",
32
+ "Remove_table": "Rimuovere Tabella",
33
33
  "column": "Colonna",
34
34
  "row": "Riga",
35
35
  "set_align": "Imposta allineamento",
@@ -29,7 +29,7 @@
29
29
  "switch_to_rich_text_editor": "Переключиться на визуальный редактор",
30
30
  "switch_to_viewer": "Переключиться на просмотр Markdown",
31
31
  "help": "Помощь",
32
- "remove_table": "Удалить таблицу",
32
+ "Remove_table": "Удалить таблицу",
33
33
  "column": "Столбец",
34
34
  "row": "Строка",
35
35
  "set_align": "Установить выравнивание",
@@ -32,7 +32,7 @@
32
32
  "switch_to_rich_text_editor": "切换至富文本编辑器",
33
33
  "switch_to_viewer": "切换到只读模式",
34
34
  "help": "帮助",
35
- "remove_table": "删除表格",
35
+ "Remove_table": "删除表格",
36
36
  "column": "列",
37
37
  "row": "行",
38
38
  "Insert_Row_Before": "上方插入行",
@@ -238,5 +238,11 @@
238
238
  "Rows": "行数",
239
239
  "Columns": "列数",
240
240
  "Please_enter_title": "请输入标题",
241
- "Please_enter_text": "请输入正文"
241
+ "Please_enter_text": "请输入正文",
242
+ "row(s)": "行",
243
+ "column(s)": "列",
244
+ "Insert_above": "在上方插入",
245
+ "Insert_below": "在下方插入",
246
+ "Insert_on_the_right": "在右侧插入",
247
+ "Insert_on_the_left": "在左侧插入"
242
248
  }