@seafile/sdoc-editor 0.3.11 → 0.3.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/basic-sdk/comment/components/comment-item-wrapper.js +13 -5
- package/dist/basic-sdk/comment/components/comment-list.css +15 -0
- package/dist/basic-sdk/comment/components/elements-comment-count/element-comment-count.js +3 -11
- package/dist/basic-sdk/comment/components/global-comment/index.css +12 -0
- package/dist/basic-sdk/comment/components/global-comment/index.js +12 -3
- package/dist/basic-sdk/comment/utils/index.js +13 -0
- package/dist/basic-sdk/constants/index.js +2 -1
- package/dist/basic-sdk/extension/constants/element-type.js +1 -0
- package/dist/basic-sdk/extension/constants/index.js +21 -3
- package/dist/basic-sdk/extension/constants/menus-config.js +16 -1
- package/dist/basic-sdk/extension/core/utils/index.js +7 -4
- package/dist/basic-sdk/extension/plugins/blockquote/helpers.js +11 -3
- package/dist/basic-sdk/extension/plugins/blockquote/plugin.js +9 -0
- package/dist/basic-sdk/extension/plugins/callout/constant.js +47 -0
- package/dist/basic-sdk/extension/plugins/callout/helper.js +117 -0
- package/dist/basic-sdk/extension/plugins/callout/index.js +12 -0
- package/dist/basic-sdk/extension/plugins/callout/menu/index.css +16 -0
- package/dist/basic-sdk/extension/plugins/callout/menu/index.js +40 -0
- package/dist/basic-sdk/extension/plugins/callout/plugin.js +57 -0
- package/dist/basic-sdk/extension/plugins/callout/render-elem/color-selector.js +51 -0
- package/dist/basic-sdk/extension/plugins/callout/render-elem/index.css +59 -0
- package/dist/basic-sdk/extension/plugins/callout/render-elem/index.js +82 -0
- package/dist/basic-sdk/extension/plugins/code-block/helpers.js +2 -0
- package/dist/basic-sdk/extension/plugins/index.js +3 -2
- package/dist/basic-sdk/extension/plugins/paragraph/render-elem.js +5 -3
- package/dist/basic-sdk/extension/plugins/table/helpers.js +1 -0
- package/dist/basic-sdk/extension/plugins/table/popover/table-size-popover/index.css +2 -1
- package/dist/basic-sdk/extension/plugins/table/popover/table-size-popover/index.js +27 -9
- package/dist/basic-sdk/extension/plugins/table/popover/table-template/index.css +8 -4
- package/dist/basic-sdk/extension/render/custom-element.js +15 -4
- package/dist/basic-sdk/extension/render/helper.js +37 -0
- package/dist/basic-sdk/extension/toolbar/header-toolbar/index.js +4 -0
- package/dist/basic-sdk/extension/toolbar/side-toolbar/event.js +5 -1
- package/dist/basic-sdk/extension/toolbar/side-toolbar/helpers.js +13 -3
- package/dist/basic-sdk/extension/toolbar/side-toolbar/index.js +7 -1
- package/dist/basic-sdk/extension/toolbar/side-toolbar/insert-block-menu.js +13 -1
- package/package.json +1 -1
- package/public/locales/en/sdoc-editor.json +4 -1
- package/public/locales/zh_CN/sdoc-editor.json +4 -1
- package/public/media/sdoc-editor-font/iconfont.eot +0 -0
- package/public/media/sdoc-editor-font/iconfont.svg +10 -0
- package/public/media/sdoc-editor-font/iconfont.ttf +0 -0
- package/public/media/sdoc-editor-font/iconfont.woff +0 -0
- package/public/media/sdoc-editor-font/iconfont.woff2 +0 -0
- package/public/media/sdoc-editor-font.css +14 -7
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import isHotkey from 'is-hotkey';
|
|
2
|
+
import { PARAGRAPH, INSERT_POSITION } from '../../constants';
|
|
3
|
+
import { isSelectionAtBlockStart } from '../../core';
|
|
4
|
+
import { getCalloutEntry, isCalloutContentEmpty, unwrapCallout } from './helper';
|
|
5
|
+
import { insertElement } from '../../toolbar/side-toolbar/helpers';
|
|
6
|
+
import EventBus from '../../../utils/event-bus';
|
|
7
|
+
import { INTERNAL_EVENT } from '../../../constants';
|
|
8
|
+
import { CALLOUT_ALLOWED_INSIDE_TYPES } from './constant';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {Editor} editor
|
|
12
|
+
* @returns
|
|
13
|
+
*/
|
|
14
|
+
const withCallout = editor => {
|
|
15
|
+
const {
|
|
16
|
+
insertFragment,
|
|
17
|
+
deleteBackward,
|
|
18
|
+
onHotKeyDown
|
|
19
|
+
} = editor;
|
|
20
|
+
const newEditor = editor;
|
|
21
|
+
newEditor.deleteBackward = unit => {
|
|
22
|
+
const calloutEntry = getCalloutEntry(editor);
|
|
23
|
+
if (calloutEntry) {
|
|
24
|
+
if (isSelectionAtBlockStart(editor) && isCalloutContentEmpty(editor, calloutEntry)) return;
|
|
25
|
+
}
|
|
26
|
+
return deleteBackward(unit);
|
|
27
|
+
};
|
|
28
|
+
newEditor.insertFragment = data => {
|
|
29
|
+
var _data$find;
|
|
30
|
+
const eventBus = EventBus.getInstance();
|
|
31
|
+
const unsupportType = (_data$find = data.find(node => !CALLOUT_ALLOWED_INSIDE_TYPES.includes(node.type))) === null || _data$find === void 0 ? void 0 : _data$find.type;
|
|
32
|
+
if (unsupportType) {
|
|
33
|
+
eventBus.dispatch(INTERNAL_EVENT.DISPLAY_CALLOUT_UNSUPPORT_ALERT, unsupportType);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
return insertFragment(data);
|
|
37
|
+
};
|
|
38
|
+
newEditor.onHotKeyDown = event => {
|
|
39
|
+
if (isHotkey('mod+enter', event)) {
|
|
40
|
+
insertElement(newEditor, PARAGRAPH, INSERT_POSITION.AFTER);
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
if (isHotkey('enter', event)) {
|
|
44
|
+
const calloutEntry = getCalloutEntry(editor);
|
|
45
|
+
if (calloutEntry) {
|
|
46
|
+
if (isCalloutContentEmpty(editor, calloutEntry)) {
|
|
47
|
+
unwrapCallout(editor);
|
|
48
|
+
event.preventDefault();
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return onHotKeyDown && onHotKeyDown(event);
|
|
54
|
+
};
|
|
55
|
+
return newEditor;
|
|
56
|
+
};
|
|
57
|
+
export default withCallout;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import React, { forwardRef, useCallback, useImperativeHandle, useRef } from 'react';
|
|
2
|
+
import { Transforms } from '@seafile/slate';
|
|
3
|
+
import { CALLOUT_COLOR_MAP } from '../constant';
|
|
4
|
+
import { findPath } from '../../../core';
|
|
5
|
+
import { changeFillBackgroundColor } from '../helper';
|
|
6
|
+
import './index.css';
|
|
7
|
+
const ColorSelector = (_ref, ref) => {
|
|
8
|
+
let {
|
|
9
|
+
editor,
|
|
10
|
+
element
|
|
11
|
+
} = _ref;
|
|
12
|
+
const selectorRef = useRef(null);
|
|
13
|
+
const handleClickColor = useCallback((editor, element, background_color) => {
|
|
14
|
+
const currentPath = findPath(editor, element);
|
|
15
|
+
Transforms.select(editor, currentPath);
|
|
16
|
+
changeFillBackgroundColor(editor, background_color);
|
|
17
|
+
}, []);
|
|
18
|
+
useImperativeHandle(ref, () => ({
|
|
19
|
+
colorSelectorContainer: selectorRef.current
|
|
20
|
+
}));
|
|
21
|
+
const isShowCheckedIcon = useCallback((element, currentBackgroundColor) => {
|
|
22
|
+
const {
|
|
23
|
+
background_color
|
|
24
|
+
} = element.style;
|
|
25
|
+
return background_color && background_color === currentBackgroundColor;
|
|
26
|
+
}, []);
|
|
27
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
28
|
+
ref: selectorRef,
|
|
29
|
+
className: "sdoc-callout-color-selector-container",
|
|
30
|
+
contentEditable: false
|
|
31
|
+
}, /*#__PURE__*/React.createElement("ul", {
|
|
32
|
+
className: "sdoc-color-selector-list"
|
|
33
|
+
}, Object.values(CALLOUT_COLOR_MAP).map((_ref2, index) => {
|
|
34
|
+
let {
|
|
35
|
+
border_color,
|
|
36
|
+
background_color
|
|
37
|
+
} = _ref2;
|
|
38
|
+
return /*#__PURE__*/React.createElement("li", {
|
|
39
|
+
key: "sdoc-callout-color-selector-".concat(index),
|
|
40
|
+
className: "sdoc-callout-color-item",
|
|
41
|
+
onClick: () => handleClickColor(editor, element, Object.keys(CALLOUT_COLOR_MAP)[index]),
|
|
42
|
+
style: {
|
|
43
|
+
borderColor: border_color,
|
|
44
|
+
backgroundColor: background_color
|
|
45
|
+
}
|
|
46
|
+
}, isShowCheckedIcon(element, background_color) && /*#__PURE__*/React.createElement("i", {
|
|
47
|
+
className: "sdoc-callout-color-checked-icon sdocfont sdoc-check-mark"
|
|
48
|
+
}));
|
|
49
|
+
})));
|
|
50
|
+
};
|
|
51
|
+
export default forwardRef(ColorSelector);
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
.sdoc-callout-white-wrapper {
|
|
2
|
+
padding: 5px 0;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.sdoc-callout-container {
|
|
6
|
+
position: relative;
|
|
7
|
+
padding: 10px;
|
|
8
|
+
border-width: 1px;
|
|
9
|
+
border-style: solid;
|
|
10
|
+
border-radius: 5px;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.sdoc-callout-container .sdoc-callout-placeholder {
|
|
14
|
+
position: absolute;
|
|
15
|
+
top: 15px;
|
|
16
|
+
left: 10px;
|
|
17
|
+
color: #b8b6b6;
|
|
18
|
+
pointer-events: none;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.sdoc-callout-color-selector-container {
|
|
22
|
+
position: absolute;
|
|
23
|
+
padding: 10px;
|
|
24
|
+
top: -39px;
|
|
25
|
+
left: 5px;
|
|
26
|
+
background-color: #fff;
|
|
27
|
+
box-shadow: -2px 0px 8px 2px #d0cfcf;
|
|
28
|
+
border: 1px solid #eee;
|
|
29
|
+
border-radius: 3px;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.sdoc-callout-color-selector-container .sdoc-color-selector-list {
|
|
33
|
+
display: flex;
|
|
34
|
+
margin: 0;
|
|
35
|
+
padding: 0;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.sdoc-callout-color-selector-container .sdoc-color-selector-list .sdoc-callout-color-item {
|
|
39
|
+
position: relative;
|
|
40
|
+
margin-right: 10px;
|
|
41
|
+
width: 16px;
|
|
42
|
+
height: 16px;
|
|
43
|
+
list-style: none;
|
|
44
|
+
border-width: 1px;
|
|
45
|
+
border-style: solid;
|
|
46
|
+
border-radius: 3px;
|
|
47
|
+
cursor: pointer;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.sdoc-callout-color-selector-container .sdoc-color-selector-list .sdoc-callout-color-item:last-child {
|
|
51
|
+
margin-right: 0px;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.sdoc-callout-color-selector-container .sdoc-color-selector-list .sdoc-callout-color-item .sdoc-callout-color-checked-icon {
|
|
55
|
+
position: absolute;
|
|
56
|
+
top: -2px;
|
|
57
|
+
font-size: 12px;
|
|
58
|
+
left: 1px;
|
|
59
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/* eslint-disable react-hooks/rules-of-hooks */
|
|
2
|
+
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import ColorSelector from './color-selector';
|
|
5
|
+
import { CALLOUT_COLOR_MAP } from '../constant';
|
|
6
|
+
import { isFocusOnElement } from '../helper';
|
|
7
|
+
import { Editor } from '@seafile/slate';
|
|
8
|
+
import { findPath } from '../../../core';
|
|
9
|
+
import { INTERNAL_EVENT } from '../../../../constants';
|
|
10
|
+
import EventBus from '../../../../utils/event-bus';
|
|
11
|
+
import './index.css';
|
|
12
|
+
const renderCallout = (_ref, editor) => {
|
|
13
|
+
let {
|
|
14
|
+
attributes,
|
|
15
|
+
children,
|
|
16
|
+
element
|
|
17
|
+
} = _ref;
|
|
18
|
+
const [isShowColorSelector, setIsShowColorSelector] = useState(false);
|
|
19
|
+
const [isSelecting, setIsSelecting] = useState(false);
|
|
20
|
+
const calloutRef = useRef(null);
|
|
21
|
+
const colorSelectorRef = useRef({
|
|
22
|
+
colorSelectorContainer: null
|
|
23
|
+
});
|
|
24
|
+
const {
|
|
25
|
+
t
|
|
26
|
+
} = useTranslation();
|
|
27
|
+
const {
|
|
28
|
+
background_color
|
|
29
|
+
} = element.style;
|
|
30
|
+
const isFocusOnCallout = isFocusOnElement(editor, element);
|
|
31
|
+
const handleMouseEnter = useCallback(id => {
|
|
32
|
+
const isMoveInCurrentCallout = id === element.id;
|
|
33
|
+
isMoveInCurrentCallout && !isSelecting && setIsShowColorSelector(true);
|
|
34
|
+
}, [element.id, isSelecting]);
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
const eventBus = EventBus.getInstance();
|
|
37
|
+
const unsubscribe = eventBus.subscribe(INTERNAL_EVENT.DISPLAY_CALLOUT_COLOR_PICKER, handleMouseEnter);
|
|
38
|
+
return unsubscribe;
|
|
39
|
+
}, [handleMouseEnter]);
|
|
40
|
+
const handleMouseLeave = useCallback(e => {
|
|
41
|
+
setIsShowColorSelector(false);
|
|
42
|
+
setIsSelecting(false);
|
|
43
|
+
}, []);
|
|
44
|
+
const handleClick = useCallback(e => {
|
|
45
|
+
var _colorSelectorRef$cur, _colorSelectorRef$cur2;
|
|
46
|
+
setIsSelecting(true);
|
|
47
|
+
const isClickInColorSelector = (_colorSelectorRef$cur = colorSelectorRef.current) === null || _colorSelectorRef$cur === void 0 ? void 0 : (_colorSelectorRef$cur2 = _colorSelectorRef$cur.colorSelectorContainer) === null || _colorSelectorRef$cur2 === void 0 ? void 0 : _colorSelectorRef$cur2.contains(e.target);
|
|
48
|
+
!isClickInColorSelector && setIsShowColorSelector(false);
|
|
49
|
+
}, []);
|
|
50
|
+
const isShowPlaceholder = useCallback(() => {
|
|
51
|
+
if (isFocusOnCallout) return false;
|
|
52
|
+
// If element contains more than one element or element is not paragraph, show placeholder
|
|
53
|
+
const isContainUnitElement = element.children.length !== 1 || element.children.some(childElement => childElement.type !== 'paragraph');
|
|
54
|
+
if (isContainUnitElement) return false;
|
|
55
|
+
const elementPath = findPath(editor, element);
|
|
56
|
+
const elementContent = Editor.string(editor, elementPath);
|
|
57
|
+
return !elementContent.length;
|
|
58
|
+
}, [editor, element, isFocusOnCallout]);
|
|
59
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
60
|
+
className: "sdoc-callout-white-wrapper"
|
|
61
|
+
}, /*#__PURE__*/React.createElement("div", Object.assign({
|
|
62
|
+
"data-id": element.id,
|
|
63
|
+
"data-root": "true",
|
|
64
|
+
onMouseLeave: handleMouseLeave,
|
|
65
|
+
onClick: handleClick,
|
|
66
|
+
ref: calloutRef,
|
|
67
|
+
style: {
|
|
68
|
+
backgroundColor: background_color ? CALLOUT_COLOR_MAP[background_color].background_color : 'transparent',
|
|
69
|
+
borderColor: isFocusOnCallout ? CALLOUT_COLOR_MAP[background_color].border_color : 'transparent'
|
|
70
|
+
}
|
|
71
|
+
}, attributes, {
|
|
72
|
+
className: "".concat(attributes.className, " sdoc-callout-container")
|
|
73
|
+
}), children, isShowPlaceholder() && /*#__PURE__*/React.createElement("div", {
|
|
74
|
+
contentEditable: false,
|
|
75
|
+
className: "sdoc-callout-placeholder"
|
|
76
|
+
}, t('Please_enter...')), isShowColorSelector && /*#__PURE__*/React.createElement(ColorSelector, {
|
|
77
|
+
ref: colorSelectorRef,
|
|
78
|
+
editor: editor,
|
|
79
|
+
element: element
|
|
80
|
+
})));
|
|
81
|
+
};
|
|
82
|
+
export default renderCallout;
|
|
@@ -4,12 +4,14 @@ import slugid from 'slugid';
|
|
|
4
4
|
import { CODE_BLOCK, CODE_LINE, INSERT_POSITION, PARAGRAPH } from '../../constants';
|
|
5
5
|
import { getNodeType, getSelectedNodeByType, getSelectedElems } from '../../core';
|
|
6
6
|
import { genCodeLangs } from './prismjs';
|
|
7
|
+
import { getCalloutEntry } from '../callout/helper';
|
|
7
8
|
export const isMenuDisabled = (editor, readonly) => {
|
|
8
9
|
if (readonly) return true;
|
|
9
10
|
const {
|
|
10
11
|
selection
|
|
11
12
|
} = editor;
|
|
12
13
|
if (selection == null) return true;
|
|
14
|
+
if (getCalloutEntry(editor)) return true;
|
|
13
15
|
const selectedElems = getSelectedElems(editor);
|
|
14
16
|
const hasVoid = selectedElems.some(elem => editor.isVoid(elem));
|
|
15
17
|
if (hasVoid) return true;
|
|
@@ -14,6 +14,7 @@ import FontPlugin from './font';
|
|
|
14
14
|
import SdocLinkPlugin from './sdoc-link';
|
|
15
15
|
import FileLinkPlugin from './file-link';
|
|
16
16
|
import ParagraphPlugin from './paragraph';
|
|
17
|
-
|
|
17
|
+
import CalloutPlugin from './callout';
|
|
18
|
+
const Plugins = [MarkDownPlugin, HtmlPlugin, HeaderPlugin, LinkPlugin, BlockquotePlugin, ListPlugin, CheckListPlugin, CodeBlockPlugin, ImagePlugin, TablePlugin, TextPlugin, TextAlignPlugin, FontPlugin, SdocLinkPlugin, FileLinkPlugin, CalloutPlugin];
|
|
18
19
|
export default Plugins;
|
|
19
|
-
export { MarkDownPlugin, HeaderPlugin, LinkPlugin, BlockquotePlugin, ListPlugin, CheckListPlugin, CodeBlockPlugin, ImagePlugin, TablePlugin, TextPlugin, HtmlPlugin, TextAlignPlugin, FontPlugin, SdocLinkPlugin, ParagraphPlugin, FileLinkPlugin };
|
|
20
|
+
export { MarkDownPlugin, HeaderPlugin, LinkPlugin, BlockquotePlugin, ListPlugin, CheckListPlugin, CodeBlockPlugin, ImagePlugin, TablePlugin, TextPlugin, HtmlPlugin, TextAlignPlugin, FontPlugin, SdocLinkPlugin, ParagraphPlugin, FileLinkPlugin, CalloutPlugin };
|
|
@@ -22,10 +22,12 @@ const Paragraph = _ref => {
|
|
|
22
22
|
const style = {
|
|
23
23
|
textAlign: element.align
|
|
24
24
|
};
|
|
25
|
+
const newAttributes = _objectSpread(_objectSpread({}, attributes), typeof attributes.onMouseEnter === 'function' && {
|
|
26
|
+
'data-root': 'true'
|
|
27
|
+
});
|
|
25
28
|
return /*#__PURE__*/React.createElement("p", Object.assign({
|
|
26
|
-
"data-id": element.id
|
|
27
|
-
|
|
28
|
-
}, attributes, {
|
|
29
|
+
"data-id": element.id
|
|
30
|
+
}, newAttributes, {
|
|
29
31
|
style: _objectSpread({
|
|
30
32
|
position: isShowPlaceHolder ? 'relative' : ''
|
|
31
33
|
}, style)
|
|
@@ -32,6 +32,7 @@ export const isTableMenuDisabled = (editor, readonly) => {
|
|
|
32
32
|
if (type === ELEMENT_TYPE.TABLE) return true;
|
|
33
33
|
if (type === ELEMENT_TYPE.TABLE_CELL) return true;
|
|
34
34
|
if (type === ELEMENT_TYPE.TABLE_ROW) return true;
|
|
35
|
+
if (type === ELEMENT_TYPE.CALL_OUT) return true;
|
|
35
36
|
if (Editor.isVoid(editor, n)) return true;
|
|
36
37
|
return false;
|
|
37
38
|
},
|
|
@@ -15,12 +15,12 @@ const TableSizePopover = _ref => {
|
|
|
15
15
|
} = _ref;
|
|
16
16
|
const minSize = [5, 10];
|
|
17
17
|
const maxSize = [10, 10];
|
|
18
|
-
const {
|
|
19
|
-
t
|
|
20
|
-
} = useTranslation();
|
|
21
18
|
const [displaySize, setDisplaySize] = useState([5, 10]);
|
|
22
19
|
const [selectedSize, setSelectedSize] = useState([1, 1]);
|
|
23
20
|
const ref = useRef(null);
|
|
21
|
+
const {
|
|
22
|
+
t
|
|
23
|
+
} = useTranslation();
|
|
24
24
|
const onMouseEnter = useCallback(function (event) {
|
|
25
25
|
let cellPosition = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [1, 1];
|
|
26
26
|
let newDisplaySize = displaySize.slice(0);
|
|
@@ -83,12 +83,11 @@ const TableSizePopover = _ref => {
|
|
|
83
83
|
className: "sdoc-selected-table-size-container w-100 h-100 d-flex flex-column"
|
|
84
84
|
}, /*#__PURE__*/React.createElement("div", {
|
|
85
85
|
className: "sdoc-selected-table-tools-container"
|
|
86
|
-
}, /*#__PURE__*/React.createElement(
|
|
86
|
+
}, /*#__PURE__*/React.createElement(MenuItem, {
|
|
87
87
|
id: "sdoc-table-template-review-btn",
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}))), /*#__PURE__*/React.createElement("div", {
|
|
88
|
+
text: "Table_template",
|
|
89
|
+
iconClassname: "sdocfont sdoc-right-slide sdoc-dropdown-item-right-icon"
|
|
90
|
+
})), /*#__PURE__*/React.createElement("div", {
|
|
92
91
|
className: "sdoc-table-size-select"
|
|
93
92
|
}, renderTableSize()), /*#__PURE__*/React.createElement("div", {
|
|
94
93
|
className: "sdoc-selected-table-size-tip w-100 "
|
|
@@ -97,4 +96,23 @@ const TableSizePopover = _ref => {
|
|
|
97
96
|
targetId: "sdoc-table-template-review-btn"
|
|
98
97
|
})));
|
|
99
98
|
};
|
|
100
|
-
export default TableSizePopover;
|
|
99
|
+
export default TableSizePopover;
|
|
100
|
+
const MenuItem = _ref2 => {
|
|
101
|
+
let {
|
|
102
|
+
id,
|
|
103
|
+
className,
|
|
104
|
+
text,
|
|
105
|
+
iconClassname
|
|
106
|
+
} = _ref2;
|
|
107
|
+
const {
|
|
108
|
+
t
|
|
109
|
+
} = useTranslation();
|
|
110
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
111
|
+
id: id,
|
|
112
|
+
className: classnames('sdoc-selected-table-size-custom', {
|
|
113
|
+
className
|
|
114
|
+
})
|
|
115
|
+
}, /*#__PURE__*/React.createElement("span", null, t(text)), /*#__PURE__*/React.createElement("i", {
|
|
116
|
+
className: iconClassname
|
|
117
|
+
}));
|
|
118
|
+
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
.sdoc-table-template-inner-popover {
|
|
2
2
|
display: flex;
|
|
3
3
|
flex-wrap: wrap;
|
|
4
|
-
padding:
|
|
5
|
-
width:
|
|
4
|
+
padding: 10px;
|
|
5
|
+
width: 310px;
|
|
6
6
|
height: 100%;
|
|
7
7
|
background-color: #fff;
|
|
8
8
|
}
|
|
@@ -14,9 +14,13 @@
|
|
|
14
14
|
cursor: pointer;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
.sdoc-table-template-view-table:hover {
|
|
18
|
+
box-shadow: 0 0 3px 2px #e2e3e6;
|
|
19
|
+
}
|
|
20
|
+
|
|
17
21
|
.sdoc-table-template-view-table .sdoc-table-template-row .sdoc-table-template-cell {
|
|
18
|
-
width:
|
|
19
|
-
height:
|
|
22
|
+
width: 28px;
|
|
23
|
+
height: 15px;
|
|
20
24
|
border-left: 1px solid #e2e3e6;
|
|
21
25
|
border-right: 1px solid #e2e3e6;
|
|
22
26
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
|
|
2
2
|
import { useSlateStatic } from '@seafile/slate-react';
|
|
3
|
-
import { BLOCKQUOTE, LINK, CHECK_LIST_ITEM, HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6, LIST_ITEM, ORDERED_LIST, PARAGRAPH, UNORDERED_LIST, CODE_BLOCK, CODE_LINE, IMAGE, ELEMENT_TYPE, SDOC_LINK, FILE_LINK, TITLE, SUBTITLE, SUPPORTED_SIDE_OPERATION_TYPE } from '../constants';
|
|
4
|
-
import { BlockquotePlugin, LinkPlugin, CheckListPlugin, HeaderPlugin, ListPlugin, CodeBlockPlugin, ImagePlugin, TablePlugin, SdocLinkPlugin, ParagraphPlugin, FileLinkPlugin } from '../plugins';
|
|
5
|
-
import {
|
|
3
|
+
import { BLOCKQUOTE, LINK, CHECK_LIST_ITEM, HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6, LIST_ITEM, ORDERED_LIST, PARAGRAPH, UNORDERED_LIST, CODE_BLOCK, CODE_LINE, IMAGE, ELEMENT_TYPE, SDOC_LINK, FILE_LINK, TITLE, SUBTITLE, CALL_OUT, SUPPORTED_SIDE_OPERATION_TYPE } from '../constants';
|
|
4
|
+
import { BlockquotePlugin, LinkPlugin, CheckListPlugin, HeaderPlugin, ListPlugin, CodeBlockPlugin, ImagePlugin, TablePlugin, SdocLinkPlugin, ParagraphPlugin, FileLinkPlugin, CalloutPlugin } from '../plugins';
|
|
5
|
+
import { onDragOver, onDragLeave, onDrop } from '../toolbar/side-toolbar/event';
|
|
6
6
|
import { getParentNode } from '../core';
|
|
7
|
+
import { setMouseEnter } from './helper';
|
|
7
8
|
const CustomRenderElement = props => {
|
|
8
9
|
const editor = useSlateStatic();
|
|
9
10
|
const {
|
|
@@ -11,7 +12,7 @@ const CustomRenderElement = props => {
|
|
|
11
12
|
attributes
|
|
12
13
|
} = props;
|
|
13
14
|
if (SUPPORTED_SIDE_OPERATION_TYPE.includes(element.type)) {
|
|
14
|
-
|
|
15
|
+
setMouseEnter(editor, element, attributes);
|
|
15
16
|
attributes['onDragOver'] = onDragOver;
|
|
16
17
|
attributes['onDragLeave'] = onDragLeave;
|
|
17
18
|
attributes['onDrop'] = onDrop;
|
|
@@ -20,6 +21,11 @@ const CustomRenderElement = props => {
|
|
|
20
21
|
switch (element.type) {
|
|
21
22
|
case PARAGRAPH:
|
|
22
23
|
{
|
|
24
|
+
const parentNode = getParentNode(editor.children, element.id);
|
|
25
|
+
if (parentNode && parentNode.type === LIST_ITEM) {
|
|
26
|
+
const [renderParagraph] = ParagraphPlugin.renderElements;
|
|
27
|
+
return renderParagraph(props);
|
|
28
|
+
}
|
|
23
29
|
const [renderParagraph] = ParagraphPlugin.renderElements;
|
|
24
30
|
return renderParagraph(props);
|
|
25
31
|
}
|
|
@@ -119,6 +125,11 @@ const CustomRenderElement = props => {
|
|
|
119
125
|
const [renderFileLink] = FileLinkPlugin.renderElements;
|
|
120
126
|
return renderFileLink(props, editor);
|
|
121
127
|
}
|
|
128
|
+
case CALL_OUT:
|
|
129
|
+
{
|
|
130
|
+
const [renderCallout] = CalloutPlugin.renderElements;
|
|
131
|
+
return renderCallout(props, editor);
|
|
132
|
+
}
|
|
122
133
|
default:
|
|
123
134
|
{
|
|
124
135
|
const [renderParagraph] = ParagraphPlugin.renderElements;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Editor } from '@seafile/slate';
|
|
2
|
+
import { findPath } from '../core';
|
|
3
|
+
import { CALL_OUT, MOUSE_ENTER_EVENT_DISABLED_MAP } from '../constants';
|
|
4
|
+
import { INTERNAL_EVENT } from '../../constants';
|
|
5
|
+
import EventBus from '../../utils/event-bus';
|
|
6
|
+
import { onMouseEnter } from '../toolbar/side-toolbar/event';
|
|
7
|
+
const isNeedAddMouseEnterEvent = (editor, element) => {
|
|
8
|
+
const elementPath = findPath(editor, element);
|
|
9
|
+
// If the element is the root element, return true
|
|
10
|
+
if (elementPath.length <= 1) return true;
|
|
11
|
+
// If the element type is not in filter list, return true
|
|
12
|
+
if (!Reflect.ownKeys(MOUSE_ENTER_EVENT_DISABLED_MAP).includes(element.type)) return true;
|
|
13
|
+
const disableEventEntry = Editor.above(editor, {
|
|
14
|
+
match: n => MOUSE_ENTER_EVENT_DISABLED_MAP[element.type].includes(n.type),
|
|
15
|
+
mode: 'highest',
|
|
16
|
+
at: elementPath
|
|
17
|
+
});
|
|
18
|
+
return !disableEventEntry;
|
|
19
|
+
};
|
|
20
|
+
export const setMouseEnter = (editor, element, attributes) => {
|
|
21
|
+
if (!isNeedAddMouseEnterEvent(editor, element)) return;
|
|
22
|
+
attributes['onMouseEnter'] = e => onMouseEnter(e, element);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// Element extra event
|
|
26
|
+
export const handleElementMouseEnterEvent = element => {
|
|
27
|
+
const {
|
|
28
|
+
id,
|
|
29
|
+
type
|
|
30
|
+
} = element;
|
|
31
|
+
const eventBus = EventBus.getInstance();
|
|
32
|
+
const elementEventMap = {
|
|
33
|
+
[CALL_OUT]: eventBus.dispatch(INTERNAL_EVENT.DISPLAY_CALLOUT_COLOR_PICKER, id)
|
|
34
|
+
};
|
|
35
|
+
const event = elementEventMap[type];
|
|
36
|
+
event && event();
|
|
37
|
+
};
|
|
@@ -13,6 +13,7 @@ import HistoryMenu from './redo-undo';
|
|
|
13
13
|
import Font from '../../plugins/font/menu';
|
|
14
14
|
import InsertToolbar from './insert-toolbar';
|
|
15
15
|
import ActiveTableMenu from '../../plugins/table/menu/active-table-menu';
|
|
16
|
+
import CalloutMenu from '../../plugins/callout/menu';
|
|
16
17
|
const HeaderToolbar = _ref => {
|
|
17
18
|
let {
|
|
18
19
|
editor,
|
|
@@ -56,6 +57,9 @@ const HeaderToolbar = _ref => {
|
|
|
56
57
|
}), /*#__PURE__*/React.createElement(TextAlignMenu, {
|
|
57
58
|
editor: editor,
|
|
58
59
|
readonly: readonly
|
|
60
|
+
}), /*#__PURE__*/React.createElement(CalloutMenu, {
|
|
61
|
+
editor: editor,
|
|
62
|
+
readonly: readonly
|
|
59
63
|
})), /*#__PURE__*/React.createElement(ActiveTableMenu, {
|
|
60
64
|
editor: editor,
|
|
61
65
|
readonly: readonly
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import EventBus from '../../../utils/event-bus';
|
|
2
2
|
import { INTERNAL_EVENT } from '../../../constants';
|
|
3
|
-
|
|
3
|
+
import { CALL_OUT } from '../../constants';
|
|
4
|
+
import { handleElementMouseEnterEvent } from '../../render/helper';
|
|
5
|
+
export const onMouseEnter = (event, element) => {
|
|
4
6
|
event.stopPropagation();
|
|
5
7
|
const eventBus = EventBus.getInstance();
|
|
6
8
|
eventBus.dispatch(INTERNAL_EVENT.ON_MOUSE_ENTER_BLOCK, event);
|
|
9
|
+
element.type === CALL_OUT && eventBus.dispatch(INTERNAL_EVENT.DISPLAY_CALLOUT_COLOR_PICKER);
|
|
10
|
+
handleElementMouseEnterEvent(element);
|
|
7
11
|
};
|
|
8
12
|
export const onDragOver = event => {
|
|
9
13
|
event.stopPropagation();
|
|
@@ -6,10 +6,15 @@ import { toggleList } from '../../plugins/list/transforms';
|
|
|
6
6
|
import { generateEmptyElement } from '../../core';
|
|
7
7
|
import { generateEmptyList } from '../../plugins/list/model';
|
|
8
8
|
import { setClipboardCodeBlockData } from '../../plugins/code-block/helpers';
|
|
9
|
-
import { ORDERED_LIST, UNORDERED_LIST, PARAGRAPH, CHECK_LIST_ITEM, IMAGE, TABLE, CODE_BLOCK, BLOCKQUOTE, LIST_ITEM_CORRELATION_TYPE, ADD_POSITION_OFFSET_TYPE, INSERT_POSITION, ELEMENT_TYPE } from '../../constants';
|
|
9
|
+
import { ORDERED_LIST, UNORDERED_LIST, PARAGRAPH, CHECK_LIST_ITEM, IMAGE, TABLE, CODE_BLOCK, BLOCKQUOTE, LIST_ITEM_CORRELATION_TYPE, ADD_POSITION_OFFSET_TYPE, INSERT_POSITION, ELEMENT_TYPE, CALL_OUT } from '../../constants';
|
|
10
10
|
import { EMPTY_SELECTED_RANGE } from '../../plugins/table/constants';
|
|
11
|
+
import { unwrapCallout, wrapCallout } from '../../plugins/callout/helper';
|
|
11
12
|
export const onSetNodeType = (editor, element, type) => {
|
|
12
13
|
if (!type) return;
|
|
14
|
+
if (type === CALL_OUT) {
|
|
15
|
+
wrapCallout(editor);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
13
18
|
if ([ORDERED_LIST, UNORDERED_LIST].includes(type)) {
|
|
14
19
|
toggleList(editor, type);
|
|
15
20
|
return;
|
|
@@ -70,6 +75,10 @@ export const onCopyNode = (editor, element) => {
|
|
|
70
75
|
}
|
|
71
76
|
};
|
|
72
77
|
export const onDeleteNode = (editor, element) => {
|
|
78
|
+
if (element.type === CALL_OUT) {
|
|
79
|
+
unwrapCallout(editor);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
73
82
|
const path = ReactEditor.findPath(editor, element);
|
|
74
83
|
Transforms.removeNodes(editor, {
|
|
75
84
|
at: path
|
|
@@ -92,10 +101,11 @@ export const isVoidNode = node => {
|
|
|
92
101
|
const hasImage = node.children.find(n => n.type === IMAGE);
|
|
93
102
|
const isTable = node.type === TABLE;
|
|
94
103
|
const isCodeBlock = node.type === CODE_BLOCK;
|
|
95
|
-
|
|
104
|
+
const isCallout = node.type === CALL_OUT;
|
|
105
|
+
return Node.string(node) === '' && !hasImage && !isTable && !isCodeBlock && !isCallout;
|
|
96
106
|
};
|
|
97
107
|
export const isNotSupportTransform = node => {
|
|
98
|
-
if (node.type && [CODE_BLOCK, TABLE].includes(node.type)) {
|
|
108
|
+
if (node.type && [CODE_BLOCK, TABLE, CALL_OUT].includes(node.type)) {
|
|
99
109
|
return true;
|
|
100
110
|
}
|
|
101
111
|
return false;
|
|
@@ -8,7 +8,8 @@ import { useScrollContext } from '../../../hooks/use-scroll-context';
|
|
|
8
8
|
import { focusEditor } from '../../core';
|
|
9
9
|
import { getDomTopHeight, setSelection, isVoidNode, getNodeEntry, isBlockquote, isList, onWrapListItem } from './helpers';
|
|
10
10
|
import { INTERNAL_EVENT } from '../../../constants';
|
|
11
|
-
import { CODE_BLOCK, TABLE, BLOCKQUOTE, CHECK_LIST_ITEM } from '../../constants';
|
|
11
|
+
import { CODE_BLOCK, TABLE, BLOCKQUOTE, CHECK_LIST_ITEM, CALL_OUT } from '../../constants';
|
|
12
|
+
import { getCalloutEntry } from '../../plugins/callout/helper';
|
|
12
13
|
import './index.css';
|
|
13
14
|
let sourceElement = null;
|
|
14
15
|
let targetElement = null;
|
|
@@ -118,6 +119,11 @@ const SideToolbar = () => {
|
|
|
118
119
|
return;
|
|
119
120
|
}
|
|
120
121
|
|
|
122
|
+
// Drag into callout is not supported
|
|
123
|
+
if ([CALL_OUT, CODE_BLOCK, TABLE].includes(sourceNode.type) && getCalloutEntry(editor, targetPath)) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
121
127
|
// Drag list
|
|
122
128
|
if (isList(editor, sourcePath)) {
|
|
123
129
|
// ordinary list items
|
|
@@ -8,10 +8,11 @@ import TableSizePopover from '../../plugins/table/popover/table-size-popover';
|
|
|
8
8
|
import { changeToCodeBlock } from '../../plugins/code-block/helpers';
|
|
9
9
|
import { toggleList } from '../../plugins/list/transforms';
|
|
10
10
|
import { setCheckListItemType } from '../../plugins/check-list/helpers';
|
|
11
|
-
import { ELEMENT_TYPE, INSERT_POSITION, LOCAL_IMAGE, SIDE_INSERT_MENUS_CONFIG } from '../../constants';
|
|
11
|
+
import { ELEMENT_TYPE, INSERT_POSITION, LOCAL_IMAGE, PARAGRAPH, SIDE_INSERT_MENUS_CONFIG } from '../../constants';
|
|
12
12
|
import EventBus from '../../../utils/event-bus';
|
|
13
13
|
import { INTERNAL_EVENT } from '../../../constants';
|
|
14
14
|
import DropdownMenuItem from '../../commons/dropdown-menu-item';
|
|
15
|
+
import { wrapCallout } from '../../plugins/callout/helper';
|
|
15
16
|
const InsertBlockMenu = _ref => {
|
|
16
17
|
let {
|
|
17
18
|
insertPosition,
|
|
@@ -65,6 +66,14 @@ const InsertBlockMenu = _ref => {
|
|
|
65
66
|
insertElement(editor, type, insertPosition);
|
|
66
67
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
67
68
|
}, [editor, insertPosition, slateNode]);
|
|
69
|
+
const onInsertCallout = useCallback(type => {
|
|
70
|
+
if (insertPosition === INSERT_POSITION.CURRENT) {
|
|
71
|
+
wrapCallout(editor);
|
|
72
|
+
} else if (insertPosition === INSERT_POSITION.AFTER) {
|
|
73
|
+
insertElement(editor, type, insertPosition);
|
|
74
|
+
wrapCallout(editor);
|
|
75
|
+
}
|
|
76
|
+
}, [editor, insertPosition]);
|
|
68
77
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(DropdownMenuItem, {
|
|
69
78
|
menuConfig: _objectSpread({}, SIDE_INSERT_MENUS_CONFIG[ELEMENT_TYPE.IMAGE]),
|
|
70
79
|
onClick: onInsertImageToggle
|
|
@@ -86,6 +95,9 @@ const InsertBlockMenu = _ref => {
|
|
|
86
95
|
}), /*#__PURE__*/React.createElement(DropdownMenuItem, {
|
|
87
96
|
menuConfig: _objectSpread({}, SIDE_INSERT_MENUS_CONFIG[ELEMENT_TYPE.CODE_BLOCK]),
|
|
88
97
|
onClick: onInsertCodeBlock
|
|
98
|
+
}), /*#__PURE__*/React.createElement(DropdownMenuItem, {
|
|
99
|
+
menuConfig: _objectSpread({}, SIDE_INSERT_MENUS_CONFIG[ELEMENT_TYPE.CALL_OUT]),
|
|
100
|
+
onClick: () => onInsertCallout(PARAGRAPH)
|
|
89
101
|
}), /*#__PURE__*/React.createElement(DropdownMenuItem, {
|
|
90
102
|
menuConfig: _objectSpread({}, SIDE_INSERT_MENUS_CONFIG[ELEMENT_TYPE.UNORDERED_LIST]),
|
|
91
103
|
onClick: () => {
|
package/package.json
CHANGED
|
@@ -414,5 +414,8 @@
|
|
|
414
414
|
"New": "New",
|
|
415
415
|
"Table_template": "Table template",
|
|
416
416
|
"Jump_to_original_doc": "Jump to the original document",
|
|
417
|
-
"Freezed": "Freezed"
|
|
417
|
+
"Freezed": "Freezed",
|
|
418
|
+
"Callout": "Callout",
|
|
419
|
+
"The_current_location_does_not_support_pasting": "The current location does not support pasting ",
|
|
420
|
+
"Please_enter...": "Please enter..."
|
|
418
421
|
}
|
|
Binary file
|