@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.
Files changed (45) hide show
  1. package/dist/basic-sdk/comment/components/comment-item-wrapper.js +13 -5
  2. package/dist/basic-sdk/comment/components/comment-list.css +15 -0
  3. package/dist/basic-sdk/comment/components/elements-comment-count/element-comment-count.js +3 -11
  4. package/dist/basic-sdk/comment/components/global-comment/index.css +12 -0
  5. package/dist/basic-sdk/comment/components/global-comment/index.js +12 -3
  6. package/dist/basic-sdk/comment/utils/index.js +13 -0
  7. package/dist/basic-sdk/constants/index.js +2 -1
  8. package/dist/basic-sdk/extension/constants/element-type.js +1 -0
  9. package/dist/basic-sdk/extension/constants/index.js +21 -3
  10. package/dist/basic-sdk/extension/constants/menus-config.js +16 -1
  11. package/dist/basic-sdk/extension/core/utils/index.js +7 -4
  12. package/dist/basic-sdk/extension/plugins/blockquote/helpers.js +11 -3
  13. package/dist/basic-sdk/extension/plugins/blockquote/plugin.js +9 -0
  14. package/dist/basic-sdk/extension/plugins/callout/constant.js +47 -0
  15. package/dist/basic-sdk/extension/plugins/callout/helper.js +117 -0
  16. package/dist/basic-sdk/extension/plugins/callout/index.js +12 -0
  17. package/dist/basic-sdk/extension/plugins/callout/menu/index.css +16 -0
  18. package/dist/basic-sdk/extension/plugins/callout/menu/index.js +40 -0
  19. package/dist/basic-sdk/extension/plugins/callout/plugin.js +57 -0
  20. package/dist/basic-sdk/extension/plugins/callout/render-elem/color-selector.js +51 -0
  21. package/dist/basic-sdk/extension/plugins/callout/render-elem/index.css +59 -0
  22. package/dist/basic-sdk/extension/plugins/callout/render-elem/index.js +82 -0
  23. package/dist/basic-sdk/extension/plugins/code-block/helpers.js +2 -0
  24. package/dist/basic-sdk/extension/plugins/index.js +3 -2
  25. package/dist/basic-sdk/extension/plugins/paragraph/render-elem.js +5 -3
  26. package/dist/basic-sdk/extension/plugins/table/helpers.js +1 -0
  27. package/dist/basic-sdk/extension/plugins/table/popover/table-size-popover/index.css +2 -1
  28. package/dist/basic-sdk/extension/plugins/table/popover/table-size-popover/index.js +27 -9
  29. package/dist/basic-sdk/extension/plugins/table/popover/table-template/index.css +8 -4
  30. package/dist/basic-sdk/extension/render/custom-element.js +15 -4
  31. package/dist/basic-sdk/extension/render/helper.js +37 -0
  32. package/dist/basic-sdk/extension/toolbar/header-toolbar/index.js +4 -0
  33. package/dist/basic-sdk/extension/toolbar/side-toolbar/event.js +5 -1
  34. package/dist/basic-sdk/extension/toolbar/side-toolbar/helpers.js +13 -3
  35. package/dist/basic-sdk/extension/toolbar/side-toolbar/index.js +7 -1
  36. package/dist/basic-sdk/extension/toolbar/side-toolbar/insert-block-menu.js +13 -1
  37. package/package.json +1 -1
  38. package/public/locales/en/sdoc-editor.json +4 -1
  39. package/public/locales/zh_CN/sdoc-editor.json +4 -1
  40. package/public/media/sdoc-editor-font/iconfont.eot +0 -0
  41. package/public/media/sdoc-editor-font/iconfont.svg +10 -0
  42. package/public/media/sdoc-editor-font/iconfont.ttf +0 -0
  43. package/public/media/sdoc-editor-font/iconfont.woff +0 -0
  44. package/public/media/sdoc-editor-font/iconfont.woff2 +0 -0
  45. 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
- const Plugins = [MarkDownPlugin, HtmlPlugin, HeaderPlugin, LinkPlugin, BlockquotePlugin, ListPlugin, CheckListPlugin, CodeBlockPlugin, ImagePlugin, TablePlugin, TextPlugin, TextAlignPlugin, FontPlugin, SdocLinkPlugin, FileLinkPlugin];
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
- "data-root": "true"
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
  },
@@ -54,7 +54,8 @@
54
54
  .sdoc-selected-table-size-popover .sdoc-selected-table-size-custom {
55
55
  display: flex;
56
56
  justify-content: space-between;
57
- padding: 5px 10px 0;
57
+ align-items: center;
58
+ padding: 0 10px;
58
59
  min-height: 32px;
59
60
  }
60
61
 
@@ -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("div", {
86
+ }, /*#__PURE__*/React.createElement(MenuItem, {
87
87
  id: "sdoc-table-template-review-btn",
88
- className: "sdoc-selected-table-size-custom"
89
- }, /*#__PURE__*/React.createElement("span", null, t('Table_template')), /*#__PURE__*/React.createElement("i", {
90
- className: "sdocfont sdoc-right-slide sdoc-dropdown-item-right-icon"
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: 20px;
5
- width: 430px;
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: 40px;
19
- height: 20px;
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 { onMouseEnter, onDragOver, onDragLeave, onDrop } from '../toolbar/side-toolbar/event';
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
- attributes['onMouseEnter'] = onMouseEnter;
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
- export const onMouseEnter = event => {
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
- return Node.string(node) === '' && !hasImage && !isTable && !isCodeBlock;
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seafile/sdoc-editor",
3
- "version": "0.3.11",
3
+ "version": "0.3.13",
4
4
  "private": false,
5
5
  "description": "This is a sdoc editor",
6
6
  "main": "dist/index.js",
@@ -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
  }
@@ -414,5 +414,8 @@
414
414
  "New": "新",
415
415
  "Table_template": "表格模版",
416
416
  "Jump_to_original_doc": "跳转到源文档",
417
- "Freezed": "已冻结"
417
+ "Freezed": "已冻结",
418
+ "Callout": "高亮块",
419
+ "The_current_location_does_not_support_pasting": "当前位置不支持粘贴",
420
+ "Please_enter...": "请输入..."
418
421
  }