react-kityminder
Version:
Mind map for react, based on kityminder.
491 lines (420 loc) • 13.3 kB
JavaScript
import 'kity';
import 'kityminder-core';
import { useEffect, useState, createElement, useRef, useMemo, useCallback, forwardRef } from 'react';
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
function useValue(minder, value) {
useEffect(function () {
if (minder) {
// const animationOptionName = 'layoutAnimationDuration'
// const animationDuration = minder.getOption(animationOptionName)
// if (animationDuration) {
// minder.setOption(animationOptionName, 0)
// }
minder.importJson(value); // if (animationDuration) {
// minder.setOption(animationOptionName, animationDuration)
// }
}
}, [minder, value]);
}
var eventHandlerPrefixRE = /^on(\w+)$/;
var getEventName = function getEventName(propName) {
var name = eventHandlerPrefixRE.exec(propName);
return name && name[1].toLowerCase();
};
var forEachHandler = function forEachHandler(minder, props, cb) {
if (minder) {
Object.keys(props).forEach(function (propName) {
var eventName = getEventName(propName);
if (eventName && handlerPropKeys.indexOf(eventName) >= 0) {
cb(eventName, propName);
}
});
}
};
var eventNames = ('click,dblclick,mousedown,mousemove,mouseup,mousewheel,keydown,keyup,keypress,touchstart,touchend,touchmove,' + 'execcommand,' + 'selectionchange,contentchange,interactchange,' + 'editnoterequest,shownoterequest,hidenoterequest,' + 'nodechange,editnode').split(',');
var handlerPropKeys = [];
eventNames.map(function (eventName) {
handlerPropKeys = handlerPropKeys.concat([eventName, "before" + eventName, "pre" + eventName, "after" + eventName]);
}); // 数据
function useEvents(minder, props) {
// 事件监听
useEffect(function () {
var handlers = {};
forEachHandler(minder, props, function (eventName, propName) {
handlers[eventName] = props[propName];
minder.on(eventName, props[propName]);
});
return function () {
forEachHandler(minder, props, function (eventName) {
minder.off(eventName, handlers[eventName]);
});
};
}, [minder].concat(handlerPropKeys.map(function (handlerProp) {
return props[handlerProp];
})));
}
function useChangeHandler(minder, onChange) {
useEffect(function () {
var changeHandler = function changeHandler(e) {
return onChange(e.minder.exportJson());
};
if (minder && onChange) {
minder.on('contentchange', changeHandler);
}
return function () {
if (minder && onChange) {
minder.off('contentchange', changeHandler);
}
};
}, [minder, onChange]);
}
function getKeyCode(evt) {
return evt.keyCode || evt.witch;
}
function Editor(props) {
var _useState = useState(props.initialValue),
value = _useState[0],
setValue = _useState[1];
var onKeydown = function onKeydown(evt) {
evt.stopPropagation();
var KeyMap = window.kityminder.KeyMap;
var keyCode = getKeyCode(evt);
if (keyCode === KeyMap.enter) {
props.onSubmit();
}
if (keyCode === KeyMap.esc) {
props.onCancel();
}
};
var onChange = function onChange(_ref) {
var value = _ref.target.value;
setValue(value);
props.onChange(value);
};
return /*#__PURE__*/createElement("input", {
value: value,
onChange: onChange,
onKeyDown: onKeydown,
onBlur: props.onSubmit
});
}
function isInputValue(e) {
var keyCode = getKeyCode(e); // a-zA-Z
if (keyCode >= 65 && keyCode <= 90) return true; // 0-9 以及其上面的符号
if (keyCode >= 48 && keyCode <= 57) return true; // 小键盘区域 (除回车外)
if (keyCode !== 108 && keyCode >= 96 && keyCode <= 111) return true;
return false;
}
function isIntendToInput(e) {
var keyCode = getKeyCode(e);
if (e.ctrlKey || e.metaKey || e.altKey) return false;
if (isInputValue(e)) return true; // 输入法
if (keyCode === 229 || keyCode === 0) return true;
return false;
}
function EditorWrapper(minder, props) {
var valueRef = useRef();
var editingNodeRef = useRef();
var editorRef = useRef();
var _useState = useState(),
initialValue = _useState[0],
setInitialValue = _useState[1];
var _useState2 = useState(),
editingNode = _useState2[0],
setEditingNode = _useState2[1];
var Editor = props.Editor,
onEdit = props.onEdit,
onEditEnd = props.onEditEnd;
var setEditorValue = function setEditorValue(v) {
valueRef.current = v;
};
var setEditorEditingNode = function setEditorEditingNode(v) {
editingNodeRef.current = v;
setEditingNode(v);
};
var exitEdit = function exitEdit() {
setEditorEditingNode();
minder.focus();
};
var onSubmit = function onSubmit() {
var _ref = editingNodeRef.current || {},
node = _ref.node;
if (node && (!onEditEnd || onEditEnd && onEditEnd.apply(void 0, [].slice.call(arguments)) !== false)) {
node.setText(valueRef.current);
minder.select(node, true);
minder.fire('nodechange', {
node: node
});
minder.fire('contentchange');
minder.getRoot().renderTree();
minder.layout(300);
}
exitEdit();
};
useEffect(function () {
var edit = function edit(e) {
if (onEdit && onEdit(e) !== false || !onEdit) {
var node = minder.getSelectedNode();
if (node) {
var box = node.getRenderer('OutlineRenderer').getRenderShape().getRenderBox('view');
var _node$data$text = node.data.text,
text = _node$data$text === void 0 ? '' : _node$data$text;
var _editingNode = {
node: node,
box: box
};
if (box.x > 0 || box.y > 0) {
var value = text;
if (props.appendKey) {
value += isInputValue(e.originEvent) ? e.originEvent.key : '';
}
setEditorEditingNode(_editingNode);
setInitialValue(value);
setEditorValue(value);
}
}
}
};
var editNodeName = 'editnode';
var editNodeHandler = edit;
var dblclickName = 'dblclick';
var dblclickHandler = edit;
var keydownName = 'keydown';
var keydownHandler = function keydownHandler(e) {
if (isIntendToInput(e.originEvent) && minder.getSelectedNode()) {
edit(e);
}
};
if (minder) {
minder.on(editNodeName, editNodeHandler);
minder.on(dblclickName, dblclickHandler);
minder.on(keydownName, keydownHandler);
}
return function () {
if (minder) {
minder.off(editNodeName, editNodeHandler);
minder.off(dblclickName, dblclickHandler);
minder.off(keydownName, keydownHandler);
}
};
}, [minder, onEdit]);
useEffect(function () {
var escHandler = function escHandler(evt) {
var keyCode = getKeyCode(evt);
if (keyCode === window.kityminder.KeyMap.esc) {
exitEdit();
}
};
document.addEventListener('keydown', escHandler);
return function () {
document.removeEventListener('keydown', escHandler);
};
}, [minder]);
useEffect(function () {
if (minder && editingNode && editorRef.current) {
var inputEl;
for (var _i = 0, _arr = ['input', 'textarea', 'select']; _i < _arr.length; _i++) {
var type = _arr[_i];
inputEl = editorRef.current.querySelector(type);
if (inputEl) {
inputEl.focus();
break;
}
}
}
}, [minder, Editor, initialValue, editingNode]);
return useMemo(function () {
return function (props) {
return editingNode ? /*#__PURE__*/createElement("div", {
style: {
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0
},
onClick: onSubmit
}, /*#__PURE__*/createElement("div", {
ref: editorRef,
style: {
position: 'absolute',
top: editingNode.box.y + editingNode.box.height / 2 + "px",
left: editingNode.box.x + "px",
transform: 'translateY(-50%)'
},
onClick: function onClick(e) {
return e.stopPropagation();
}
}, /*#__PURE__*/createElement(Editor, _extends({}, props, {
minder: minder,
initialValue: initialValue,
onSubmit: onSubmit,
onChange: setEditorValue,
onCancel: exitEdit
})))) : null;
};
}, [minder, Editor, initialValue, editingNode]);
}
function Note(props) {
return /*#__PURE__*/createElement("div", {
style: {
background: '#fff',
height: '100%'
}
}, props.node.data.note);
}
function NoteWrapper(minder, props) {
var _useState = useState(),
showingNode = _useState[0],
setShowingNode = _useState[1];
var Note = props.Note;
var showNote = useCallback(function (_ref) {
var node = _ref.node;
if (node) {
var box = node.getRenderer('OutlineRenderer').getRenderShape().getRenderBox('view');
var editingNode = {
node: node,
box: box
};
if (box.x > 0 || box.y > 0) {
setShowingNode(editingNode);
}
}
}, []);
var hideNote = useCallback(function () {
setShowingNode();
}, []);
useEffect(function () {
var showNodeName = 'shownoterequest';
var mousewheel = 'mousewheel';
if (minder) {
minder.on(showNodeName, showNote);
minder.on(mousewheel, hideNote);
document.addEventListener(mousewheel, hideNote);
}
return function () {
if (minder) {
minder.off(showNodeName, showNote);
minder.off(mousewheel, hideNote);
document.removeEventListener(mousewheel, hideNote);
}
};
}, [minder]);
return useMemo(function () {
return function (props) {
return showingNode ? /*#__PURE__*/createElement("div", {
style: {
position: 'absolute',
top: showingNode.box.y + showingNode.box.height / 2 + "px",
left: showingNode.box.x + "px",
width: showingNode.box.width + "px",
height: showingNode.box.height + "px",
transform: 'translateY(-50%)'
},
onMouseOut: hideNote
}, /*#__PURE__*/createElement(Note, _extends({}, props, {
node: showingNode.node
}))) : null;
};
}, [minder, Note, showingNode]);
}
var domPropNames = ['id', 'className', 'style', 'title', 'tabIndex'];
var Kityminder = /*#__PURE__*/forwardRef(function Kityminder(props, ref) {
var minderRef = useRef();
var minder = minderRef.current;
var domProps = {};
Object.keys(props).forEach(function (propKey) {
if (domPropNames.indexOf(propKey) >= 0) {
domProps[propKey] = props[propKey];
}
});
if (!minder) {
minder = minderRef.current = new window.kityminder.Minder(props);
if (props.onMinderChange) {
setTimeout(function () {
// fix warning: Cannot update a component while rendering a different component.
props.onMinderChange(minder);
}, 0);
}
if (ref) {
ref.current = minder;
}
}
useValue(minder, props.value);
useEvents(minder, props);
useChangeHandler(minder, props.onChange);
var EditorComponent = EditorWrapper(minder, Object.assign({
Editor: Editor
}, props));
var NoteComponent = NoteWrapper(minder, Object.assign({
Note: Note
}, props));
return /*#__PURE__*/createElement("div", _extends({}, domProps, {
style: _extends({
position: 'relative',
width: '100%',
height: '400px'
}, domProps.style)
}), useMemo(function () {
return /*#__PURE__*/createElement("div", {
ref: function ref(div) {
if (div) {
minder.renderTo(div);
var receiver = div.querySelector('.km-receiver');
if (receiver) {
Object.assign(receiver.style, {
position: 'absolute',
left: '-99999px',
top: '-99999px'
});
}
}
},
style: {
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0
}
});
}, [minder]), /*#__PURE__*/createElement(EditorComponent, props), /*#__PURE__*/createElement(NoteComponent, props));
});
function extendsKityminder(kityminder) {
// fix: detached node getMinder() returns undefined
kityminder.Minder.prototype.attachNode = function (node) {
var _this = this;
var rc = _this.getRenderContainer();
node.traverse(function (current) {
current.attached = true;
current.minder = _this;
rc.addShape(current.getRenderContainer());
});
rc.addShape(node.getRenderContainer());
_this.fire('nodeattach', {
node: node
});
};
kityminder.Node.prototype.getMinder = function () {
return this.getRoot().minder || this.minder;
};
}
var kity = window.kity;
var kityminder = window.kityminder;
extendsKityminder(kityminder);
export default Kityminder;
export { Kityminder, kity, kityminder };
//# sourceMappingURL=react-kityminder.esm.js.map