private getNear()

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,
      },
    });
  }