jjb-lc-designable
Version:
基于alibaba-designable源码二次封装的表单设计器。
143 lines • 3.66 kB
JavaScript
import { observable, define, action } from 'jjb-lc-formily/reactive';
import { SelectNodeEvent, UnSelectNodeEvent } from '../events';
import { isStr, isArr } from 'jjb-lc-designable/shared';
export class Selection {
selected = [];
indexes = {};
constructor(props) {
if (props.selected) {
this.selected = props.selected;
}
if (props.operation) {
this.operation = props.operation;
}
this.makeObservable();
}
makeObservable() {
define(this, {
selected: observable,
select: action,
batchSelect: action,
add: action,
remove: action,
clear: action,
crossAddTo: action
});
}
trigger(type = SelectNodeEvent) {
return this.operation.dispatch(new type({
target: this.operation.tree,
source: this.selectedNodes
}));
}
select(id) {
if (isStr(id)) {
if (this.selected.length === 1 && this.selected.includes(id)) {
this.trigger(SelectNodeEvent);
return;
}
this.selected = [id];
this.indexes = {
[id]: true
};
this.trigger(SelectNodeEvent);
} else {
this.select(id?.id);
}
}
safeSelect(id) {
if (!id) return;
this.select(id);
}
mapIds(ids) {
return isArr(ids) ? ids.map(node => isStr(node) ? node : node?.id) : [];
}
batchSelect(ids) {
this.selected = this.mapIds(ids);
this.indexes = this.selected.reduce((buf, id) => {
buf[id] = true;
return buf;
}, {});
this.trigger(SelectNodeEvent);
}
batchSafeSelect(ids) {
if (!ids?.length) return;
this.batchSelect(ids);
}
get selectedNodes() {
return this.selected.map(id => this.operation.tree.findById(id));
}
get first() {
if (this.selected && this.selected.length) return this.selected[0];
}
get last() {
if (this.selected && this.selected.length) return this.selected[this.selected.length - 1];
}
get length() {
return this.selected.length;
}
add(...ids) {
this.mapIds(ids).forEach(id => {
if (isStr(id)) {
if (!this.selected.includes(id)) {
this.selected.push(id);
this.indexes[id] = true;
}
} else {
this.add(id?.id);
}
});
this.trigger();
}
crossAddTo(node) {
if (node.parent) {
const selectedNodes = this.selectedNodes;
if (this.has(node)) {
this.remove(node);
} else {
const minDistanceNode = selectedNodes.reduce((minDistanceNode, item) => {
return item.distanceTo(node) < minDistanceNode.distanceTo(node) ? item : minDistanceNode;
}, selectedNodes[0]);
if (minDistanceNode) {
const crossNodes = node.crossSiblings(minDistanceNode);
crossNodes.forEach(node => {
if (!this.has(node.id)) {
this.selected.push(node.id);
this.indexes[node.id] = true;
}
});
}
if (!this.has(node.id)) {
this.selected.push(node.id);
this.indexes[node.id] = true;
}
}
}
}
remove(...ids) {
this.mapIds(ids).forEach(id => {
if (isStr(id)) {
this.selected = this.selected.filter(item => item !== id);
delete this.indexes[id];
} else {
this.remove(id?.id);
}
});
this.trigger(UnSelectNodeEvent);
}
has(...ids) {
return this.mapIds(ids).some(id => {
if (isStr(id)) {
return this.indexes[id];
} else {
if (!id?.id) return false;
return this.has(id?.id);
}
});
}
clear() {
this.selected = [];
this.indexes = {};
this.trigger(UnSelectNodeEvent);
}
}