diff --git a/packages/client/src/thirtypart/kityminder/index.ts b/packages/client/src/thirtypart/kityminder/index.ts index 07a6c01a..bcbb7fd3 100644 --- a/packages/client/src/thirtypart/kityminder/index.ts +++ b/packages/client/src/thirtypart/kityminder/index.ts @@ -24,15 +24,25 @@ export function renderMind(options: Options) { const Editor = window.kityminder.Editor; const editor = new Editor(options.container); const mind = editor.minder; + mind.editor = editor; options.data && mind.importJson(options.data); if (!options.isEditable) { mind.disable(); + mind.setStatus('readonly'); } setTimeout(() => { mind.execCommand('camera'); + + if (!options.isEditable) { + const selectedNodes = mind.getSelectedNodes(); + + if (selectedNodes.length) { + mind.removeSelectedNodes(selectedNodes); + } + } }, 0); return mind; diff --git a/packages/client/src/thirtypart/kityminder/kity-core/core/event.js b/packages/client/src/thirtypart/kityminder/kity-core/core/event.js index 043bcf57..83201fb3 100644 --- a/packages/client/src/thirtypart/kityminder/kity-core/core/event.js +++ b/packages/client/src/thirtypart/kityminder/kity-core/core/event.js @@ -138,6 +138,9 @@ define(function (require, exports, module) { }, _bindEvents: function () { + if (this.getStatus() === 'readonly') { + return this; + } /* jscs:disable maximumLineLength */ this._paper.on( 'click dblclick mousedown contextmenu mouseup mousemove mouseover mousewheel DOMMouseScroll touchstart touchmove touchend dragenter dragleave drop', diff --git a/packages/client/src/thirtypart/kityminder/kity-core/core/focus.js b/packages/client/src/thirtypart/kityminder/kity-core/core/focus.js index e9785b1b..d12ae91e 100644 --- a/packages/client/src/thirtypart/kityminder/kity-core/core/focus.js +++ b/packages/client/src/thirtypart/kityminder/kity-core/core/focus.js @@ -17,6 +17,10 @@ define(function (require, exports, module) { kity.extendClass(Minder, { focus: function () { + if (this.getStatus() === 'readonly') { + return this; + } + if (!this.isFocused()) { var renderTarget = this._renderTarget; renderTarget.classList.add('focus'); diff --git a/packages/client/src/thirtypart/kityminder/kity-core/core/keyreceiver.js b/packages/client/src/thirtypart/kityminder/kity-core/core/keyreceiver.js index 53b0663e..12d8796d 100644 --- a/packages/client/src/thirtypart/kityminder/kity-core/core/keyreceiver.js +++ b/packages/client/src/thirtypart/kityminder/kity-core/core/keyreceiver.js @@ -23,6 +23,10 @@ define(function (require, exports, module) { kity.extendClass(Minder, { _initKeyReceiver: function () { + if (this.getStatus() === 'readonly') { + return; + } + if (this._keyReceiver) return; var receiver = (this._keyReceiver = document.createElement('input')); @@ -34,6 +38,10 @@ define(function (require, exports, module) { var minder = this; listen(receiver, 'keydown keyup keypress copy paste blur focus input', function (e) { + if (minder.getStatus() === 'readonly') { + return; + } + switch (e.type) { case 'blur': minder.blur(); @@ -50,14 +58,24 @@ define(function (require, exports, module) { }); this.on('focus', function () { + if (this.getStatus() === 'readonly') { + return; + } receiver.select(); receiver.focus(); }); this.on('blur', function () { + if (this.getStatus() === 'readonly') { + return; + } receiver.blur(); }); if (this.isFocused()) { + if (this.getStatus() === 'readonly') { + return; + } + receiver.select(); receiver.focus(); } diff --git a/packages/client/src/thirtypart/kityminder/kity-core/module/expand.js b/packages/client/src/thirtypart/kityminder/kity-core/module/expand.js index e8fc84f1..880f4892 100644 --- a/packages/client/src/thirtypart/kityminder/kity-core/module/expand.js +++ b/packages/client/src/thirtypart/kityminder/kity-core/module/expand.js @@ -142,6 +142,8 @@ define(function (require, exports, module) { initEvent: function (node) { this.on('mousedown', function (e) { + if (minder._status === 'readonly') return; + minder.select([node], true); if (node.isExpanded()) { node.collapse(); diff --git a/packages/client/src/thirtypart/kityminder/kity-core/module/priority.js b/packages/client/src/thirtypart/kityminder/kity-core/module/priority.js index 7facd628..21e44fe6 100644 --- a/packages/client/src/thirtypart/kityminder/kity-core/module/priority.js +++ b/packages/client/src/thirtypart/kityminder/kity-core/module/priority.js @@ -82,7 +82,7 @@ define(function (require, exports, module) { mask.fill(color[0]); } - number.setContent(value); + number.setContent('P' + value); }, }); diff --git a/packages/client/src/thirtypart/kityminder/kity-editor/runtime/input.js b/packages/client/src/thirtypart/kityminder/kity-editor/runtime/input.js index 1bb3a9d2..9f5fc1d3 100644 --- a/packages/client/src/thirtypart/kityminder/kity-editor/runtime/input.js +++ b/packages/client/src/thirtypart/kityminder/kity-editor/runtime/input.js @@ -21,9 +21,11 @@ define(function (require, exports, module) { var receiverElement = receiver.element; var isGecko = window.kity.Browser.gecko; // setup everything to go + setupReciverElement(); setupFsm(); setupHotbox(); + // expose editText() this.editText = editText; // listen the fsm changes, make action. @@ -32,6 +34,8 @@ define(function (require, exports, module) { fsm.when('* -> input', enterInputMode); // when exited, commit or exit depends on the exit reason fsm.when('input -> *', function (exit, enter, reason) { + if (minder._status === 'readonly') return; + switch (reason) { case 'input-cancel': return exitInputMode(); @@ -43,11 +47,15 @@ define(function (require, exports, module) { }); // lost focus to commit receiver.onblur(function (e) { + if (minder._status === 'readonly') return; + if (fsm.state() == 'input') { fsm.jump('normal', 'input-commit'); } }); minder.on('beforemousedown', function () { + if (minder._status === 'readonly') return; + if (fsm.state() == 'input') { fsm.jump('normal', 'input-commit'); } @@ -69,9 +77,14 @@ define(function (require, exports, module) { minder.on('layoutallfinish viewchange viewchanged selectionchange', function (e) { // viewchange event is too frequenced, lazy it if (e.type == 'viewchange' && fsm.state() != 'input') return; - updatePosition(); + + if (minder.getStatus() !== 'readonly') { + updatePosition(); + } }); - updatePosition(); + if (minder.getStatus() !== 'readonly') { + updatePosition(); + } } // edit entrance in hotbox function setupHotbox() { @@ -121,6 +134,8 @@ define(function (require, exports, module) { * @Date 2015-12-2 */ function enterInputMode() { + if (minder._status === 'readonly') return; + var node = minder.getSelectedNode(); if (node) { var fontSize = node.getData('font-size') || node.getStyle('font-size'); @@ -141,6 +156,13 @@ define(function (require, exports, module) { * @Date: 2015.9.16 */ function commitInputText(textNodes) { + if (minder._status === 'readonly') return; + + var node = minder.getSelectedNode(); + if (!node) { + return; + } + var text = ''; var TAB_CHAR = '\t', ENTER_CHAR = '\n', @@ -282,6 +304,8 @@ define(function (require, exports, module) { * @Date: 2015.9.16 */ function commitInputNode(node, text) { + if (minder._status === 'readonly') return; + try { minder.decodeData('text', text).then(function (json) { function importText(node, json, minder) { @@ -309,6 +333,8 @@ define(function (require, exports, module) { } } function commitInputResult() { + if (minder._status === 'readonly') return; + /** * @Desc: 进行如下处理: * 根据用户的输入判断是否生成新的节点 @@ -338,10 +364,14 @@ define(function (require, exports, module) { } } function exitInputMode() { + if (minder._status === 'readonly') return; + receiverElement.classList.remove('input'); receiver.selectAll(); } function updatePosition() { + if (minder._status === 'readonly') return; + var planed = updatePosition; var focusNode = minder.getSelectedNode(); if (!focusNode) return; diff --git a/packages/client/src/thirtypart/kityminder/kity-editor/runtime/jumping.js b/packages/client/src/thirtypart/kityminder/kity-editor/runtime/jumping.js index 83e8426d..0b084efc 100644 --- a/packages/client/src/thirtypart/kityminder/kity-editor/runtime/jumping.js +++ b/packages/client/src/thirtypart/kityminder/kity-editor/runtime/jumping.js @@ -48,18 +48,26 @@ define(function (require, exports, module) { var receiverElement = receiver.element; var hotbox = this.hotbox; var compositionLock = false; + var that = this; // normal -> * receiver.listen('normal', function (e) { + if (minder._status === 'readonly') return; // 为了防止处理进入edit模式而丢失处理的首字母,此时receiver必须为enable receiver.enable(); // normal -> hotbox if (e.is('Space')) { + // 非编辑模式 + if (that.minder.getStatus() === 'readonly') { + return; + } + e.preventDefault(); // safari下Space触发hotbox,然而这时Space已在receiver上留下作案痕迹,因此抹掉 if (kity.Browser.safari) { receiverElement.innerHTML = ''; } + return fsm.jump('hotbox', 'space-trigger'); } @@ -91,6 +99,8 @@ define(function (require, exports, module) { // hotbox -> normal receiver.listen('hotbox', function (e) { + if (minder._status === 'readonly') return; + receiver.disable(); e.preventDefault(); var handleResult = hotbox.dispatch(e); @@ -101,6 +111,8 @@ define(function (require, exports, module) { // input => normal receiver.listen('input', function (e) { + if (minder._status === 'readonly') return; + receiver.enable(); if (e.type == 'keydown') { if (e.is('Enter')) { @@ -138,6 +150,8 @@ define(function (require, exports, module) { container.addEventListener( 'mousedown', function (e) { + if (minder._status === 'readonly') return; + if (e.button == MOUSE_RB) { e.preventDefault(); } @@ -155,6 +169,8 @@ define(function (require, exports, module) { container.addEventListener( 'mousewheel', function (e) { + if (minder._status === 'readonly') return; + if (fsm.state() == 'hotbox') { hotbox.active(Hotbox.STATE_IDLE); fsm.jump('normal', 'mousemove-blur'); @@ -164,12 +180,14 @@ define(function (require, exports, module) { ); container.addEventListener('contextmenu', function (e) { + if (minder._status === 'readonly') return; e.preventDefault(); }); container.addEventListener( 'mouseup', function (e) { + if (minder._status === 'readonly') return; if (fsm.state() != 'normal') { return; } @@ -186,6 +204,7 @@ define(function (require, exports, module) { // 阻止热盒事件冒泡,在热盒正确执行前导致热盒关闭 hotbox.$element.addEventListener('mousedown', function (e) { + if (minder._status === 'readonly') return; e.stopPropagation(); }); } diff --git a/packages/client/src/tiptap/core/extensions/callout.ts b/packages/client/src/tiptap/core/extensions/callout.ts index a3cc71e2..a587b39b 100644 --- a/packages/client/src/tiptap/core/extensions/callout.ts +++ b/packages/client/src/tiptap/core/extensions/callout.ts @@ -69,7 +69,7 @@ export const Callout = Node.create({ addInputRules() { return [ wrappingInputRule({ - find: /^\$callout $/, + find: /^\$callout\$$/, type: this.type, getAttributes: (match) => { return { type: match[1] }; diff --git a/packages/client/src/tiptap/core/extensions/columns.ts b/packages/client/src/tiptap/core/extensions/columns.ts index b3fd4842..b2ceb7bf 100644 --- a/packages/client/src/tiptap/core/extensions/columns.ts +++ b/packages/client/src/tiptap/core/extensions/columns.ts @@ -268,7 +268,7 @@ export const Columns = Node.create({ addInputRules() { return [ nodeInputRule({ - find: /^\$columns $/, + find: /^\$columns\$$/, type: this.type, getAttributes: () => { return { type: 'left-right', columns: 2 }; diff --git a/packages/client/src/tiptap/core/extensions/countdown.ts b/packages/client/src/tiptap/core/extensions/countdown.ts index 4e317301..02652611 100644 --- a/packages/client/src/tiptap/core/extensions/countdown.ts +++ b/packages/client/src/tiptap/core/extensions/countdown.ts @@ -78,7 +78,7 @@ export const Countdown = Node.create({ addInputRules() { return [ nodeInputRule({ - find: /^\$countdown $/, + find: /^\$countdown\$$/, type: this.type, getAttributes: () => { return { width: '100%' }; diff --git a/packages/client/src/tiptap/core/extensions/excalidraw.ts b/packages/client/src/tiptap/core/extensions/excalidraw.ts index 030d9bbe..d36da5c9 100644 --- a/packages/client/src/tiptap/core/extensions/excalidraw.ts +++ b/packages/client/src/tiptap/core/extensions/excalidraw.ts @@ -103,7 +103,7 @@ export const Excalidraw = Node.create({ addInputRules() { return [ nodeInputRule({ - find: /^\$excalidraw $/, + find: /^\$excalidraw\$$/, type: this.type, getAttributes: () => { return { width: '100%' }; diff --git a/packages/client/src/tiptap/core/extensions/flow.ts b/packages/client/src/tiptap/core/extensions/flow.ts index a4c8b97d..8c795cce 100644 --- a/packages/client/src/tiptap/core/extensions/flow.ts +++ b/packages/client/src/tiptap/core/extensions/flow.ts @@ -12,6 +12,11 @@ export interface IFlowAttrs { createUser?: IUser['id']; } +interface IFlowOptions { + HTMLAttributes: Record; + getCreateUserId: () => string | number; +} + declare module '@tiptap/core' { interface Commands { flow: { @@ -20,7 +25,7 @@ declare module '@tiptap/core' { } } -export const Flow = Node.create({ +export const Flow = Node.create({ name: 'flow', group: 'block', selectable: true, @@ -55,6 +60,7 @@ export const Flow = Node.create({ HTMLAttributes: { class: 'flow', }, + getCreateUserId: () => null, }; }, @@ -102,10 +108,10 @@ export const Flow = Node.create({ addInputRules() { return [ nodeInputRule({ - find: /^\$flow $/, + find: /^\$flow\$$/, type: this.type, getAttributes: () => { - return { width: '100%' }; + return { width: '100%', defaultShowPicker: true, createUser: this.options.getCreateUserId() }; }, }), ]; diff --git a/packages/client/src/tiptap/core/extensions/iframe.ts b/packages/client/src/tiptap/core/extensions/iframe.ts index ae8493ce..5b34c0c0 100644 --- a/packages/client/src/tiptap/core/extensions/iframe.ts +++ b/packages/client/src/tiptap/core/extensions/iframe.ts @@ -98,7 +98,7 @@ export const Iframe = Node.create({ addInputRules() { return [ nodeInputRule({ - find: /^\$iframe $/, + find: /^\$iframe\$$/, type: this.type, getAttributes: () => { return { width: '100%' }; diff --git a/packages/client/src/tiptap/core/extensions/katex.ts b/packages/client/src/tiptap/core/extensions/katex.ts index 249de386..7e655d9f 100644 --- a/packages/client/src/tiptap/core/extensions/katex.ts +++ b/packages/client/src/tiptap/core/extensions/katex.ts @@ -10,6 +10,11 @@ export type IKatexAttrs = { createUser?: IUser['id']; }; +interface IKatexOptions { + HTMLAttributes: Record; + getCreateUserId: () => string | number; +} + declare module '@tiptap/core' { interface Commands { katex: { @@ -18,7 +23,7 @@ declare module '@tiptap/core' { } } -export const Katex = Node.create({ +export const Katex = Node.create({ name: 'katex', group: 'block', selectable: true, @@ -30,6 +35,7 @@ export const Katex = Node.create({ HTMLAttributes: { class: 'katex', }, + getCreateUserId: () => null, }; }, @@ -72,8 +78,11 @@ export const Katex = Node.create({ addInputRules() { return [ nodeInputRule({ - find: /^\$katex $/, + find: /^\$katex\$$/, type: this.type, + getAttributes: () => { + return { defaultShowPicker: true, createUser: this.options.getCreateUserId() }; + }, }), ]; }, diff --git a/packages/client/src/tiptap/core/extensions/mind.ts b/packages/client/src/tiptap/core/extensions/mind.ts index 2dfc47eb..fcf3e57c 100644 --- a/packages/client/src/tiptap/core/extensions/mind.ts +++ b/packages/client/src/tiptap/core/extensions/mind.ts @@ -22,6 +22,11 @@ export interface IMindAttrs { zoom?: number; } +interface IMindOptions { + HTMLAttributes: Record; + getCreateUserId: () => string | number; +} + declare module '@tiptap/core' { interface Commands { mind: { @@ -30,7 +35,7 @@ declare module '@tiptap/core' { } } -export const Mind = Node.create({ +export const Mind = Node.create({ name: 'mind', group: 'block', selectable: true, @@ -66,6 +71,7 @@ export const Mind = Node.create({ HTMLAttributes: { class: 'mind', }, + getCreateUserId: () => null, }; }, @@ -113,10 +119,10 @@ export const Mind = Node.create({ addInputRules() { return [ nodeInputRule({ - find: /^\$mind $/, + find: /^\$mind\$$/, type: this.type, getAttributes: () => { - return { width: '100%' }; + return { width: '100%', defaultShowPicker: true, createUser: this.options.getCreateUserId() }; }, }), ]; diff --git a/packages/client/src/tiptap/core/extensions/placeholder.ts b/packages/client/src/tiptap/core/extensions/placeholder.ts index a60a49f5..794b5f31 100644 --- a/packages/client/src/tiptap/core/extensions/placeholder.ts +++ b/packages/client/src/tiptap/core/extensions/placeholder.ts @@ -1,3 +1,109 @@ -import BuiltInPlaceholder from '@tiptap/extension-placeholder'; +import { Editor, Extension } from '@tiptap/core'; +import { Node as ProsemirrorNode } from 'prosemirror-model'; +import { Plugin } from 'prosemirror-state'; +import { Decoration, DecorationSet } from 'prosemirror-view'; -export const Placeholder = BuiltInPlaceholder; +export interface PlaceholderOptions { + emptyEditorClass: string; + emptyNodeClass: string; + placeholder: ((PlaceholderProps: { editor: Editor; node: ProsemirrorNode; pos: number }) => string) | string; + showOnlyWhenEditable: boolean; + showOnlyCurrent: boolean; + includeChildren: boolean; +} + +export const Placeholder = Extension.create({ + name: 'placeholder', + + addOptions() { + return { + emptyEditorClass: 'is-editor-empty', + emptyNodeClass: 'is-empty', + placeholder: 'Write something …', + showOnlyWhenEditable: true, + showOnlyCurrent: true, + includeChildren: false, + }; + }, + + addStorage() { + return new Map(); + }, + + addProseMirrorPlugins() { + return [ + new Plugin({ + props: { + decorations: ({ doc, selection }) => { + const active = this.editor.isEditable || !this.options.showOnlyWhenEditable; + const { anchor } = selection; + const decorations: Decoration[] = []; + + if (!active) { + return; + } + + doc.descendants((node, pos) => { + const hasAnchor = anchor >= pos && anchor <= pos + node.nodeSize; + const isEmpty = !node.isLeaf && !node.childCount; + + if ((hasAnchor || !this.options.showOnlyCurrent) && isEmpty) { + const classes = [this.options.emptyNodeClass]; + + if (this.editor.isEmpty) { + classes.push(this.options.emptyEditorClass); + } + + const start = pos; + const end = pos + node.nodeSize; + let placeholder = ''; + + if (this.editor.isEditable) { + const key = `${start}-${end}`; + + if (!this.editor.storage[this.name].has(key)) { + this.editor.storage[this.name].set( + key, + typeof this.options.placeholder === 'function' + ? this.options.placeholder({ + editor: this.editor, + node, + pos, + }) + : this.options.placeholder + ); + } + placeholder = this.editor.storage[this.name].get(key); + + setTimeout(() => { + this.editor.storage[this.name].delete(key); + }, 500); + } else { + placeholder = + typeof this.options.placeholder === 'function' + ? this.options.placeholder({ + editor: this.editor, + node, + pos, + }) + : this.options.placeholder; + } + + const decoration = Decoration.node(start, end, { + 'class': classes.join(' '), + 'data-placeholder': placeholder, + }); + + decorations.push(decoration); + } + + return this.options.includeChildren; + }); + + return DecorationSet.create(doc, decorations); + }, + }, + }), + ]; + }, +}); diff --git a/packages/client/src/tiptap/core/extensions/quick-insert.ts b/packages/client/src/tiptap/core/extensions/quick-insert.ts index 5df5eb7a..95692f83 100644 --- a/packages/client/src/tiptap/core/extensions/quick-insert.ts +++ b/packages/client/src/tiptap/core/extensions/quick-insert.ts @@ -8,7 +8,7 @@ import { insertMenuLRUCache, QUICK_INSERT_COMMANDS, transformToCommands } from ' import { MenuList } from 'tiptap/core/wrappers/menu-list'; export const QuickInsertPluginKey = new PluginKey('quickInsert'); -const extensionName = 'quickInsert' +const extensionName = 'quickInsert'; export const QuickInsert = Node.create({ name: extensionName, @@ -63,8 +63,8 @@ export const QuickInsert = Node.create({ top: 0, right: 0, bottom: 0, - } - } + }, + }; }, }).configure({ suggestion: { diff --git a/packages/client/src/tiptap/core/menus/excalidraw/modal.tsx b/packages/client/src/tiptap/core/menus/excalidraw/modal.tsx index 0cf5b897..8f11c87a 100644 --- a/packages/client/src/tiptap/core/menus/excalidraw/modal.tsx +++ b/packages/client/src/tiptap/core/menus/excalidraw/modal.tsx @@ -32,7 +32,6 @@ export const ExcalidrawSettingModal: React.FC = ({ editor }) => { ); const renderExcalidraw = useCallback((app) => { - console.log('render', app); setTimeout(() => { app.refresh(); }); @@ -54,7 +53,14 @@ export const ExcalidrawSettingModal: React.FC = ({ editor }) => { return; } + /** + * FIXME: 绘图更新后会滚动 dom 到顶点,原因未知,在此 hack 修复下! + */ + const currentScrollTop = document.querySelector('main#js-tocs-container')?.scrollTop; editor.chain().focus().setExcalidraw({ data }).run(); + setTimeout(() => { + document.querySelector('main#js-tocs-container').scrollTop = currentScrollTop; + }); toggleVisible(false); }, [Excalidraw, editor, data, toggleVisible]); diff --git a/packages/client/src/tiptap/core/menus/katex/bubble.tsx b/packages/client/src/tiptap/core/menus/katex/bubble.tsx index 5572b702..6d888b46 100644 --- a/packages/client/src/tiptap/core/menus/katex/bubble.tsx +++ b/packages/client/src/tiptap/core/menus/katex/bubble.tsx @@ -43,7 +43,7 @@ export const KatexBubbleMenu: React.FC<{ editor: Editor }> = ({ editor }) => { useEffect(() => { if (visible) { - setTimeout(() => ref.current?.focus(), 100); + setTimeout(() => ref.current?.focus(), 200); } }, [visible]); diff --git a/packages/client/src/tiptap/core/menus/mind/constant.ts b/packages/client/src/tiptap/core/menus/mind/constant.ts index 9d8fbda7..25e3367c 100644 --- a/packages/client/src/tiptap/core/menus/mind/constant.ts +++ b/packages/client/src/tiptap/core/menus/mind/constant.ts @@ -1,3 +1,36 @@ +const getProgressTitle = (index) => { + switch (index) { + case 0: + return '移除进度'; + case 1: + return '未开始'; + case 9: + return '全部完成'; + default: + return '完成' + (index - 1) + '/8'; + } +}; + +export const PROGRESSES = Array.from({ length: 10 }, (_, i) => { + return { + text: getProgressTitle(i), + value: i, + }; +}); + +export const PRIORITIES = [ + { + text: '移除优先级', + value: 0, + }, + ...Array.from({ length: 9 }, (_, i) => { + return { + text: `P${i + 1}`, + value: i + 1, + }; + }), +]; + export const TEMPLATES = [ { label: '经典', diff --git a/packages/client/src/tiptap/core/menus/mind/modal.tsx b/packages/client/src/tiptap/core/menus/mind/modal.tsx index d8ecf19e..63cc322a 100644 --- a/packages/client/src/tiptap/core/menus/mind/modal.tsx +++ b/packages/client/src/tiptap/core/menus/mind/modal.tsx @@ -46,7 +46,14 @@ export const MindSettingModal: React.FC = ({ editor }) => { return; } const data = mind.exportJson(); + /** + * FIXME: 百度脑图更新后会滚动 dom 到顶点,原因未知,在此 hack 修复下! + */ + const currentScrollTop = document.querySelector('main#js-tocs-container')?.scrollTop; editor.chain().focus().setMind({ data }).run(); + setTimeout(() => { + document.querySelector('main#js-tocs-container').scrollTop = currentScrollTop; + }); toggleVisible(false); }, [editor, toggleVisible, mind]); @@ -65,6 +72,12 @@ export const MindSettingModal: React.FC = ({ editor }) => { }; }, [editor, toggleVisible]); + useEffect(() => { + if (!visible && mind) { + mind.destroy(); + } + }, [visible, mind]); + return ( = ({ editor }) => { onOk={save} okText="保存" cancelText="退出" + motion={false} >
{ + return ( + { + setBackgroundColor(color); + }} + > + +
+ } + /> + + + ); +}; diff --git a/packages/client/src/tiptap/core/menus/mind/toolbar/font-color.tsx b/packages/client/src/tiptap/core/menus/mind/toolbar/font-color.tsx new file mode 100644 index 00000000..f3b38948 --- /dev/null +++ b/packages/client/src/tiptap/core/menus/mind/toolbar/font-color.tsx @@ -0,0 +1,39 @@ +import { IconFont } from '@douyinfe/semi-icons'; +import { Button, Tooltip } from '@douyinfe/semi-ui'; +import { ColorPicker } from 'components/color-picker'; + +export const FontColor = ({ selectedNode, setFontColor, textColor }) => { + return ( + { + setFontColor(color); + }} + > + +