UNPKG

jjb-lc-designable

Version:

基于alibaba-designable源码二次封装的表单设计器。

143 lines 3.66 kB
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); } }