fix(editor): merge drag function and fix it (#9329)

This commit is contained in:
Flrande
2024-12-26 07:41:06 +00:00
parent cadb9211a6
commit cb4dd127fd
8 changed files with 74 additions and 177 deletions

View File

@@ -2,6 +2,7 @@ import type { BlockComponent } from '@blocksuite/block-std';
import { type Point, Rect } from '@blocksuite/global/utils';
import type { BlockModel } from '@blocksuite/store';
import { BLOCK_CHILDREN_CONTAINER_PADDING_LEFT } from '../../consts/index.js';
import {
getClosestBlockComponentByElement,
getRectByBlockComponent,
@@ -10,6 +11,24 @@ import { matchFlavours } from '../model/index.js';
import { getDropRectByPoint } from './get-drop-rect-by-point.js';
import { DropFlags, type DroppingType, type DropResult } from './types.js';
function getVisiblePreviousElementSibling(element: Element | null) {
if (!element) return null;
let prev = element.previousElementSibling;
while (prev && !prev.checkVisibility()) {
prev = prev.previousElementSibling;
}
return prev;
}
function getVisibleNextElementSibling(element: Element | null) {
if (!element) return null;
let next = element.nextElementSibling;
while (next && !next.checkVisibility()) {
next = next.nextElementSibling;
}
return next;
}
/**
* Calculates the drop target.
*/
@@ -19,7 +38,10 @@ export function calcDropTarget(
element: Element,
draggingElements: BlockComponent[] = [],
scale: number = 1,
flavour: string | null = null // for block-hub
/**
* Allow the dragging block to be dropped as sublist
*/
allowSublist: boolean = true
): DropResult | null {
const schema = model.doc.getSchemaByFlavour(
'affine:database' as BlockSuite.Flavour
@@ -28,14 +50,10 @@ export function calcDropTarget(
let shouldAppendToDatabase = true;
if (children.length) {
if (draggingElements.length) {
shouldAppendToDatabase = draggingElements
.map(el => el.model)
.every(m => children.includes(m.flavour));
} else if (flavour) {
shouldAppendToDatabase = children.includes(flavour);
}
if (children.length && draggingElements.length) {
shouldAppendToDatabase = draggingElements
.map(el => el.model)
.every(m => children.includes(m.flavour));
}
if (
@@ -107,7 +125,7 @@ export function calcDropTarget(
let prev;
let prevRect;
prev = element.previousElementSibling;
prev = getVisiblePreviousElementSibling(element);
if (prev) {
if (
draggingElements.length &&
@@ -118,7 +136,7 @@ export function calcDropTarget(
prevRect = getRectByBlockComponent(prev);
}
} else {
prev = element.parentElement?.previousElementSibling;
prev = getVisiblePreviousElementSibling(element.parentElement);
if (prev) {
prevRect = prev.getBoundingClientRect();
}
@@ -128,20 +146,37 @@ export function calcDropTarget(
offsetY = (domRect.top - prevRect.bottom) / 2;
}
} else {
// Only consider drop as children when target block is list block.
// To drop in, the position must after the target first
// If drop in target has children, we can use insert before or after of that children
// to achieve the same effect.
const hasChild = (element as BlockComponent).childBlocks.length;
if (
allowSublist &&
matchFlavours(model, ['affine:list']) &&
!hasChild &&
point.x > domRect.x + BLOCK_CHILDREN_CONTAINER_PADDING_LEFT
) {
type = 'in';
}
// after
let next;
let nextRect;
next = element.nextElementSibling;
next = getVisibleNextElementSibling(element);
if (next) {
if (draggingElements.length && next === draggingElements[0]) {
if (
type === 'after' &&
draggingElements.length &&
next === draggingElements[0]
) {
type = 'none';
next = null;
}
} else {
next = getClosestBlockComponentByElement(
element.parentElement
)?.nextElementSibling;
next = getVisibleNextElementSibling(
getClosestBlockComponentByElement(element.parentElement)
);
}
if (next) {
@@ -159,6 +194,11 @@ export function calcDropTarget(
top += domRect.height + offsetY;
}
if (type === 'in') {
domRect.x += BLOCK_CHILDREN_CONTAINER_PADDING_LEFT;
domRect.width -= BLOCK_CHILDREN_CONTAINER_PADDING_LEFT;
}
return {
type,
rect: Rect.fromLWTH(domRect.left, domRect.width, top - height / 2, height),

View File

@@ -1,3 +1,3 @@
export * from './calc-drop-target.js';
export * from './get-drop-rect-by-point.js';
export type { DropResult } from './types.js';
export * from './types.js';

View File

@@ -20,7 +20,7 @@ export enum DropFlags {
/**
* A dropping type.
*/
export type DroppingType = 'none' | 'before' | 'after' | 'database';
export type DroppingType = 'none' | 'before' | 'after' | 'database' | 'in';
export type DropResult = {
type: DroppingType;