mirror of https://github.com/fantasticit/think.git
tiptap: fix mind
This commit is contained in:
parent
3b68238249
commit
acd266acc0
|
@ -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;
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,10 +77,15 @@ 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;
|
||||
|
||||
if (minder.getStatus() !== 'readonly') {
|
||||
updatePosition();
|
||||
}
|
||||
});
|
||||
if (minder.getStatus() !== 'readonly') {
|
||||
updatePosition();
|
||||
}
|
||||
}
|
||||
// edit entrance in hotbox
|
||||
function setupHotbox() {
|
||||
hotbox.state('main').button({
|
||||
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -46,7 +46,14 @@ export const MindSettingModal: React.FC<IProps> = ({ 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]);
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ const { Text } = Typography;
|
|||
const INHERIT_SIZE_STYLE = { width: '100%', height: '100%', maxWidth: '100%' };
|
||||
|
||||
export const MindWrapper = ({ editor, node, updateAttributes }) => {
|
||||
const $div = useRef(null);
|
||||
const $mind = useRef(null);
|
||||
const isEditable = editor.isEditable;
|
||||
const isActive = editor.isActive(Mind.name);
|
||||
|
@ -32,7 +33,7 @@ export const MindWrapper = ({ editor, node, updateAttributes }) => {
|
|||
const setCenter = useCallback(() => {
|
||||
const mind = $mind.current;
|
||||
if (!mind) return;
|
||||
mind.execCommand('camera');
|
||||
mind.execCommand('camera', mind.getRoot(), 600);
|
||||
}, []);
|
||||
|
||||
const setZoom = useCallback((type: 'minus' | 'plus') => {
|
||||
|
@ -55,29 +56,6 @@ export const MindWrapper = ({ editor, node, updateAttributes }) => {
|
|||
[updateAttributes, setCenter]
|
||||
);
|
||||
|
||||
const render = useCallback(
|
||||
(div) => {
|
||||
if (!div) return;
|
||||
|
||||
if (!$mind.current) {
|
||||
const graph = renderMind({
|
||||
container: div,
|
||||
data,
|
||||
isEditable: false,
|
||||
});
|
||||
$mind.current = graph;
|
||||
}
|
||||
},
|
||||
[data]
|
||||
);
|
||||
|
||||
const setMind = useCallback(
|
||||
(div) => {
|
||||
render(div);
|
||||
},
|
||||
[render]
|
||||
);
|
||||
|
||||
const onViewportChange = useCallback(
|
||||
(visible) => {
|
||||
if (visible) {
|
||||
|
@ -107,6 +85,19 @@ export const MindWrapper = ({ editor, node, updateAttributes }) => {
|
|||
setCenter();
|
||||
}, [width, height, setCenter]);
|
||||
|
||||
useEffect(() => {
|
||||
if (visible && !loading && !error) {
|
||||
if (!$mind.current) {
|
||||
const graph = renderMind({
|
||||
container: $div.current,
|
||||
data,
|
||||
isEditable: false,
|
||||
});
|
||||
$mind.current = graph;
|
||||
}
|
||||
}
|
||||
}, [visible, data, loading, error]);
|
||||
|
||||
return (
|
||||
<NodeViewWrapper className={cls(styles.wrap, isActive && styles.isActive)}>
|
||||
<VisibilitySensor onChange={onViewportChange}>
|
||||
|
@ -123,8 +114,8 @@ export const MindWrapper = ({ editor, node, updateAttributes }) => {
|
|||
|
||||
{loading && <Spin spinning style={INHERIT_SIZE_STYLE}></Spin>}
|
||||
|
||||
{!loading && !error && visible && (
|
||||
<div style={{ height: '100%', maxHeight: '100%', overflow: 'hidden' }} ref={setMind}></div>
|
||||
{!loading && !error && (
|
||||
<div style={{ height: '100%', maxHeight: '100%', overflow: 'hidden' }} ref={$div}></div>
|
||||
)}
|
||||
|
||||
<div className={styles.title}>
|
||||
|
|
Loading…
Reference in New Issue