@logicflow/extension
Version:
LogicFlow Extensions
298 lines (297 loc) • 15.2 kB
JavaScript
;
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Label = void 0;
var jsx_runtime_1 = require("preact/jsx-runtime");
var core_1 = require("@logicflow/core");
var classnames_1 = __importDefault(require("classnames"));
var lodash_es_1 = require("lodash-es");
var Label = /** @class */ (function (_super) {
__extends(Label, _super);
function Label(props) {
var _this = _super.call(this, props) || this;
_this.textRef = (0, core_1.createRef)();
_this.setHoverOn = function () {
var element = _this.props.element;
if (element.isDragging || _this.state.isHovered)
return; // 当节点或边在拖拽中时,不触发 hover 态
_this.setState({ isHovered: true });
element.setHovered(true);
};
_this.setHoverOff = function () {
var element = _this.props.element;
if (!_this.state.isHovered)
return;
_this.setState({ isHovered: false });
element.setHovered(false);
};
_this.handleMouseDown = function (e) {
var _a;
var _b = _this.props, label = _b.label, graphModel = _b.graphModel;
var nodeTextDraggable = graphModel.editConfigModel.nodeTextDraggable;
// 当 label 允许拖拽 且不处于拖拽状态、不处于编辑状态时, StepDrag 开启拖拽
if (((_a = label.draggable) !== null && _a !== void 0 ? _a : nodeTextDraggable) &&
!_this.state.isDragging &&
!_this.state.isEditing) {
_this.stepDrag.handleMouseDown(e);
}
};
_this.handleMouseUp = function (e) {
if (_this.state.isDragging) {
_this.stepDrag.handleMouseUp(e);
}
};
_this.handleDragging = function (_a) {
var deltaX = _a.deltaX, deltaY = _a.deltaY;
if (!_this.state.isDragging) {
_this.setState({ isDragging: true });
}
var _b = _this.props, label = _b.label, graphModel = _b.graphModel;
// DONE: 添加缩放时拖拽的逻辑,对 deltaX 和 deltaY 进行按比例缩放
var transformModel = graphModel.transformModel;
var _c = __read(transformModel.fixDeltaXY(deltaX, deltaY), 2), curDeltaX = _c[0], curDeltaY = _c[1];
_this.setElementModelLabelInfo({
x: label.x + curDeltaX,
y: label.y + curDeltaY,
});
graphModel.eventCenter.emit('label:drag', {
data: label.getData(),
model: label,
});
};
_this.handleDragEnd = function () {
_this.setState({ isDragging: false });
};
_this.handleClick = function (e) {
var _a = _this.props, label = _a.label, element = _a.element, graphModel = _a.graphModel;
// 更新当前Label选中状态
element.setSelected(!_this.state.isSelected);
_this.setState({ isSelected: !_this.state.isSelected });
_this.setElementModelLabelInfo({
isSelected: true,
});
graphModel.eventCenter.emit('label:click', {
data: label.getData(),
e: e,
model: element,
});
};
_this.handleDbClick = function (e) {
var _a = _this.props, label = _a.label, element = _a.element, graphModel = _a.graphModel;
graphModel.eventCenter.emit('label:dblclick', {
data: label.getData(),
e: e,
model: element,
});
if (!label.editable) {
element.setSelected(true);
return;
}
element.setSelected();
element.setElementState(core_1.ElementState.TEXT_EDIT);
_this.setState({ isEditing: true });
// DONE: 触发当前 label 的 focus 事件,设置内容可编辑,且在文本最后添加光标
if (_this.textRef.current) {
_this.textRef.current.contentEditable = 'true';
_this.textRef.current.focus();
var range = document.createRange();
var selection = window.getSelection();
range.selectNodeContents(_this.textRef.current);
range.collapse(false);
selection === null || selection === void 0 ? void 0 : selection.removeAllRanges();
selection === null || selection === void 0 ? void 0 : selection.addRange(range);
}
};
_this.handleBlur = function (e) {
var _a = _this.props, label = _a.label, element = _a.element, eventCenter = _a.graphModel.eventCenter;
// DONE: 触发 LABEL:BLUR 事件,并抛出相关的事件
eventCenter.emit('label:blur', {
e: e,
model: element,
data: label.getData(),
element: _this.textRef.current,
});
_this.setState({
isDragging: false,
isHovered: false,
isSelected: false,
});
};
_this.handleInput = function (e) {
var _a = _this.props, label = _a.label, graphModel = _a.graphModel;
graphModel.eventCenter.emit('label:input', {
e: e,
data: label.getData(),
});
};
// 重新计算 Label 大小
_this.reCalcLabelSize = function () { };
var label = props.label, _a = props.graphModel, gridSize = _a.gridSize, eventCenter = _a.eventCenter;
_this.stepDrag = new core_1.StepDrag({
onDragging: _this.handleDragging,
onDragEnd: _this.handleDragEnd,
step: gridSize,
eventType: 'LABEL',
model: label,
eventCenter: eventCenter,
});
_this.state = {
isEditing: false,
isHovered: false,
isDragging: false,
isSelected: false,
};
return _this;
}
Label.prototype.setElementModelLabelInfo = function (data) {
var _a = this.props, label = _a.label, element = _a.element, graphModel = _a.graphModel;
var _label = element.properties._label;
var elementLabel = _label;
var idx = (0, lodash_es_1.findIndex)(elementLabel, function (cur) { return cur.id === label.id; });
var target = elementLabel[idx];
elementLabel[idx] = __assign(__assign({}, target), data);
var targetElem = graphModel.getElement(element.id);
targetElem === null || targetElem === void 0 ? void 0 : targetElem.setProperty('_label', elementLabel);
};
// TODO:如何处理 Label zIndex 的问题, Label 永远会比节点层级高
// 当 Label 被元素遮盖时,隐藏它
Label.prototype.componentDidMount = function () {
var _this = this;
var _a = this.props, label = _a.label, element = _a.element, graphModel = _a.graphModel;
// 在点击元素、边或者画布 时,结束 Label 的编辑态
graphModel.eventCenter.on('blank:click,node:click,edge:click,label:click', function (_a) {
var _b, _c, _d, _e;
var data = _a.data;
// 点击的不是label 、点击的不是当前label、点击的是当前label,且当前 label 处于选中态
// 则取消选中态
if ((data === null || data === void 0 ? void 0 : data.type) !== 'label' ||
(data.type === 'label' && data.id !== label.id) ||
_this.state.isSelected) {
_this.setState({ isSelected: false });
}
// 点击的不是label 、点击的不是当前label、点击的是当前label,且当前 label 处于编辑态
// 则结束编辑态
if (((data === null || data === void 0 ? void 0 : data.type) !== 'label' ||
(data.type == 'label' && data.id !== label.id)) &&
_this.state.isEditing) {
_this.setState({ isEditing: false });
var value = (_c = (_b = _this.textRef.current) === null || _b === void 0 ? void 0 : _b.innerText) !== null && _c !== void 0 ? _c : '';
var content = (_e = (_d = _this.textRef.current) === null || _d === void 0 ? void 0 : _d.innerHTML) !== null && _e !== void 0 ? _e : '';
_this.setElementModelLabelInfo({
value: value,
content: content,
isSelected: false,
});
element.setElementState(core_1.ElementState.DEFAULT);
}
// 点击的不是label 、点击的不是当前label、点击的是当前label,且当前 label 的文本DOM存在
// 则结束文本DOM的编辑态
if (((data === null || data === void 0 ? void 0 : data.type) !== 'label' ||
(data.type == 'label' && data.id !== label.id)) &&
_this.textRef.current) {
_this.textRef.current.contentEditable = 'false';
}
});
// TODO: 节点拖拽结束后,更新 Label 的位置
// eventCenter.on('node:drag', () => {})
// eventCenter.on('node:drop', () => {})
// eventCenter.on('node:mousemove', () => {})
//
// eventCenter.on('node:properties-change,node:properties-delete', () => {})
};
Label.prototype.componentDidUpdate = function () {
// snapshot: any, // previousState: Readonly<ILabelState>, // previousProps: Readonly<ILabelProps>,
// console.log('Label componentDidUpdate')
// console.log('previousProps', previousProps)
// console.log('previousState', previousState)
// console.log('snapshot', snapshot)
};
Label.prototype.componentWillUnmount = function () {
var graphModel = this.props.graphModel;
graphModel.eventCenter.off('blank:click,node:click,edge:click');
};
// TODO: 当某一个标签更新时,如何避免其它标签的更新
// shouldComponentUpdate or memo
Label.prototype.render = function () {
var _a;
var _b = this.props, label = _b.label, element = _b.element, graphModel = _b.graphModel;
var _c = this.state, isDragging = _c.isDragging, isHovered = _c.isHovered, isSelected = _c.isSelected, isEditing = _c.isEditing;
var transformModel = graphModel.transformModel;
var transform = transformModel.getTransformStyle().transform;
var id = label.id, x = label.x, y = label.y, zIndex = label.zIndex, vertical = label.vertical, style = label.style, rotate = label.rotate, content = label.content, labelWidth = label.labelWidth, textOverflowMode = label.textOverflowMode;
var maxLabelWidth = labelWidth !== null && labelWidth !== void 0 ? labelWidth : (element.BaseType === 'node' ? element.width - 20 : 80);
var containerStyle = {
left: "".concat(x - maxLabelWidth / 2, "px"),
top: "".concat(y - 10, "px"),
width: "".concat(maxLabelWidth, "px"),
height: '20px',
zIndex: zIndex !== null && zIndex !== void 0 ? zIndex : 1,
transform: rotate
? "".concat(transform, " rotate(").concat(rotate, "deg)")
: "".concat(transform, " rotate(").concat(vertical ? -0.25 : 0, "turn)"),
};
return ((0, jsx_runtime_1.jsx)("div", { id: "element-container-".concat(id), className: (0, classnames_1.default)('lf-label-editor-container'), style: containerStyle, onMouseDown: this.handleMouseDown, onMouseUp: this.handleMouseUp, onClick: this.handleClick, onDblClick: this.handleDbClick, onBlur: this.handleBlur, onMouseEnter: this.setHoverOn, onMouseOver: this.setHoverOn, onMouseLeave: this.setHoverOff, children: (0, jsx_runtime_1.jsx)("div", { ref: this.textRef, id: "editor-container-".concat(id), className: (0, classnames_1.default)('lf-label-editor', (_a = {
'lf-label-editor-dragging': isDragging,
'lf-label-editor-editing': isEditing,
'lf-label-editor-hover': !isEditing && (isHovered || isSelected)
},
_a["lf-label-editor-".concat(textOverflowMode)] = !isEditing,
_a)), onInput: this.handleInput, style: __assign({ maxWidth: "".concat(maxLabelWidth, "px"), boxSizing: 'border-box', display: 'inline-block', background: isEditing || element.BaseType === 'edge' ? '#fff' : 'transparent' }, style), dangerouslySetInnerHTML: { __html: content } }) }));
};
Label = __decorate([
core_1.observer
], Label);
return Label;
}(core_1.Component));
exports.Label = Label;
exports.default = Label;