Skip to content

Commit

Permalink
refactor: remove legacy drag handle logic (#9246)
Browse files Browse the repository at this point in the history
  • Loading branch information
Saul-Mirone committed Dec 23, 2024
1 parent a187f23 commit 23dcaa9
Show file tree
Hide file tree
Showing 14 changed files with 237 additions and 718 deletions.
Original file line number Diff line number Diff line change
@@ -1,25 +1,14 @@
import {
getClosestBlockComponentByElement,
getRectByBlockComponent,
matchFlavours,
} from '@blocksuite/affine-shared/utils';
import type { BlockComponent } from '@blocksuite/block-std';
import { type Point, Rect } from '@blocksuite/global/utils';
import type { BlockModel } from '@blocksuite/store';

import type { EditingState } from '../types.js';
import { DropFlags, getDropRectByPoint } from './query.js';

/**
* A dropping type.
*/
export type DroppingType = 'none' | 'before' | 'after' | 'database';

export type DropResult = {
type: DroppingType;
rect: Rect;
modelState: EditingState;
};
import {
getClosestBlockComponentByElement,
getRectByBlockComponent,
} from '../dom/index.js';
import { matchFlavours } from '../model/index.js';
import { getDropRectByPoint } from './get-drop-rect-by-point.js';
import { DropFlags, type DroppingType, type DropResult } from './types.js';

/**
* Calculates the drop target.
Expand All @@ -32,7 +21,9 @@ export function calcDropTarget(
scale: number = 1,
flavour: string | null = null // for block-hub
): DropResult | null {
const schema = model.doc.getSchemaByFlavour('affine:database');
const schema = model.doc.getSchemaByFlavour(
'affine:database' as BlockSuite.Flavour
);
const children = schema?.model.children ?? [];

let shouldAppendToDatabase = true;
Expand All @@ -47,8 +38,12 @@ export function calcDropTarget(
}
}

if (!shouldAppendToDatabase && !matchFlavours(model, ['affine:database'])) {
const databaseBlockComponent = element.closest('affine-database');
if (
!shouldAppendToDatabase &&
!matchFlavours(model, ['affine:database' as BlockSuite.Flavour])
) {
const databaseBlockComponent =
element.closest<BlockComponent>('affine-database');
if (databaseBlockComponent) {
element = databaseBlockComponent;
model = databaseBlockComponent.model;
Expand All @@ -57,7 +52,9 @@ export function calcDropTarget(

let type: DroppingType = 'none';
const height = 3 * scale;
const { rect: domRect, flag } = getDropRectByPoint(point, model, element);
const dropResult = getDropRectByPoint(point, model, element);
if (!dropResult) return null;
const { rect: domRect, flag } = dropResult;

if (flag === DropFlags.EmptyDatabase) {
// empty database
Expand Down
161 changes: 161 additions & 0 deletions blocksuite/affine/shared/src/utils/dnd/get-drop-rect-by-point.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import { BLOCK_ID_ATTR } from '@blocksuite/block-std';
import type { Point } from '@blocksuite/global/utils';
import type { BlockModel } from '@blocksuite/store';

import { getRectByBlockComponent } from '../dom/index.js';
import { matchFlavours } from '../model/index.js';
import { DropFlags } from './types.js';

const ATTR_SELECTOR = `[${BLOCK_ID_ATTR}]`;

/**
* Gets the drop rect by block and point.
*/
export function getDropRectByPoint(
point: Point,
model: BlockModel,
element: Element
): null | {
rect: DOMRect;
flag: DropFlags;
} {
const result = {
rect: getRectByBlockComponent(element),
flag: DropFlags.Normal,
};

const isDatabase = matchFlavours(model, [
'affine:database' as BlockSuite.Flavour,
]);

if (isDatabase) {
const table = getDatabaseBlockTableElement(element);
if (!table) {
return result;
}

let bounds = table.getBoundingClientRect();
if (model.isEmpty.value) {
result.flag = DropFlags.EmptyDatabase;

if (point.y < bounds.top) return result;

const header = getDatabaseBlockColumnHeaderElement(element);
if (!header) {
return null;
}

bounds = header.getBoundingClientRect();
result.rect = new DOMRect(
result.rect.left,
bounds.bottom,
result.rect.width,
1
);

return result;
}

result.flag = DropFlags.Database;
const rows = getDatabaseBlockRowsElement(element);
if (!rows) {
return null;
}
const rowsBounds = rows.getBoundingClientRect();

if (point.y < rowsBounds.top || point.y > rowsBounds.bottom) return result;

const elements = document.elementsFromPoint(point.x, point.y);
const len = elements.length;
let e;
let i = 0;
for (; i < len; i++) {
e = elements[i];

if (e.classList.contains('affine-database-block-row-cell-content')) {
const cellRect = getCellRect(e, bounds);
if (!cellRect) {
return null;
}
result.rect = cellRect;
return result;
}

if (e.classList.contains('affine-database-block-row')) {
e = e.querySelector(ATTR_SELECTOR);
if (!e) {
return null;
}
const cellRect = getCellRect(e, bounds);
if (!cellRect) {
return null;
}
result.rect = cellRect;
return result;
}
}

return result;
}

const parent = element.parentElement;
if (parent?.classList.contains('affine-database-block-row-cell-content')) {
result.flag = DropFlags.Database;
const cellRect = getCellRect(parent);
if (!cellRect) {
return null;
}
result.rect = cellRect;
return result;
}

return result;
}

/**
* Gets the table of the database.
*/
function getDatabaseBlockTableElement(element: Element) {
return element.querySelector('.affine-database-block-table');
}

/**
* Gets the column header of the database.
*/
function getDatabaseBlockColumnHeaderElement(element: Element) {
return element.querySelector('.affine-database-column-header');
}

/**
* Gets the rows of the database.
*/
function getDatabaseBlockRowsElement(element: Element) {
return element.querySelector('.affine-database-block-rows');
}

function getCellRect(element: Element, bounds?: DOMRect) {
if (!bounds) {
const table = element.closest('.affine-database-block-table');
if (!table) {
return null;
}
bounds = table.getBoundingClientRect();
}
// affine-database-block-row-cell
const col = element.parentElement;
if (!col) {
return null;
}
// affine-database-block-row
const row = col.parentElement;
if (!row) {
return null;
}
const colRect = col.getBoundingClientRect();
return new DOMRect(
bounds.left,
colRect.top,
colRect.right - bounds.left,
colRect.height
);
}
3 changes: 3 additions & 0 deletions blocksuite/affine/shared/src/utils/dnd/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
export * from './calc-drop-target.js';
export * from './get-drop-rect-by-point.js';
export * from './legacy.js';
export type { DropResult } from './types.js';
29 changes: 29 additions & 0 deletions blocksuite/affine/shared/src/utils/dnd/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type { BlockComponent } from '@blocksuite/block-std';
import type { Rect } from '@blocksuite/global/utils';
import type { BlockModel } from '@blocksuite/store';

export interface EditingState {
element: BlockComponent;
model: BlockModel;
rect: DOMRect;
}

/**
* Returns a flag for the drop target.
*/
export enum DropFlags {
Normal,
Database,
EmptyDatabase,
}

/**
* A dropping type.
*/
export type DroppingType = 'none' | 'before' | 'after' | 'database';

export type DropResult = {
type: DroppingType;
rect: Rect;
modelState: EditingState;
};
4 changes: 2 additions & 2 deletions blocksuite/blocks/src/_common/components/file-drop-manager.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import type { DragIndicator } from '@blocksuite/affine-components/drag-indicator';
import {
calcDropTarget,
type DropResult,
getClosestBlockComponentByPoint,
isInsidePageEditor,
matchFlavours,
Expand All @@ -9,8 +11,6 @@ import type { IVec } from '@blocksuite/global/utils';
import { assertExists, Point } from '@blocksuite/global/utils';
import type { BlockModel } from '@blocksuite/store';

import { calcDropTarget, type DropResult } from '../../_common/utils/index.js';

export type onDropProps = {
files: File[];
targetModel: BlockModel | null;
Expand Down
1 change: 0 additions & 1 deletion blocksuite/blocks/src/_common/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Compat with SSR
export * from '../types.js';
export * from './drag-and-drop.js';
export * from './query.js';
export {
createButtonPopper,
Expand Down
Loading

0 comments on commit 23dcaa9

Please sign in to comment.