in packages/plugin-outline-pane/src/controllers/pane-controller.ts [350:452]
private getNear(treeNode: TreeNode, e: IPublicModelLocateEvent, originalIndex?: number, originalRect?: DOMRect) {
const { canvas, project } = this.pluginContext;
const document = project.getCurrentDocument();
const { globalY, dragObject } = e;
if (!dragObject) {
return null;
}
// TODO: check dragObject is anyData
const { node, expanded } = treeNode;
let rect = originalRect;
if (!rect) {
rect = this.getTreeNodeRect(treeNode);
if (!rect) {
return null;
}
}
let index = originalIndex;
if (index == null) {
index = node.index;
}
if (node.isSlotNode) {
// 是个插槽根节点
if (!treeNode.isContainer() && !treeNode.hasSlots()) {
return canvas.createLocation({
target: node.parent!,
source: this.id,
event: e,
detail: {
type: IPublicTypeLocationDetailType.Children,
index: null,
near: { node, pos: 'replace' },
valid: true, // TODO: future validation the slot limit
},
});
}
const loc1 = this.drillLocate(treeNode, e);
if (loc1) {
return loc1;
}
return canvas.createLocation({
target: node.parent!,
source: this.id,
event: e,
detail: {
type: IPublicTypeLocationDetailType.Children,
index: null,
valid: false,
focus: { type: 'slots' },
},
});
}
let focusNode: IPublicModelNode | undefined;
// focus
if (!expanded && (treeNode.isContainer() || treeNode.hasSlots())) {
focusNode = node;
}
// before
const titleRect = this.getTreeTitleRect(treeNode) || rect;
if (globalY < titleRect.top + titleRect.height / 2) {
return canvas.createLocation({
target: node.parent!,
source: this.id,
event: e,
detail: {
type: IPublicTypeLocationDetailType.Children,
index,
valid: document?.checkNesting(node.parent!, dragObject as any),
near: { node, pos: 'before' },
focus: checkRecursion(focusNode, dragObject) ? { type: 'node', node: focusNode } : undefined,
},
});
}
if (globalY > titleRect.bottom) {
focusNode = undefined;
}
if (expanded) {
// drill
const loc = this.drillLocate(treeNode, e);
if (loc) {
return loc;
}
}
// after
return canvas.createLocation({
target: node.parent!,
source: this.id,
event: e,
detail: {
type: IPublicTypeLocationDetailType.Children,
index: (index || 0) + 1,
valid: document?.checkNesting(node.parent!, dragObject as any),
near: { node, pos: 'after' },
focus: checkRecursion(focusNode, dragObject) ? { type: 'node', node: focusNode } : undefined,
},
});
}