Skip to content

Commit

Permalink
feat: add scrollable
Browse files Browse the repository at this point in the history
  • Loading branch information
doouding committed Jan 13, 2025
1 parent 47876b6 commit 116dec2
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 50 deletions.
2 changes: 1 addition & 1 deletion blocksuite/affine/shared/src/utils/event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ export function requestConnectedFrame(
* A wrapper around `requestConnectedFrame` that only calls at most once in one frame
*/
export function requestThrottledConnectedFrame<
T extends (...args: unknown[]) => void,
T extends (...args: any[]) => void,
>(func: T, element?: HTMLElement): T {
let raqId: number | undefined = undefined;
let latestArgs: unknown[] = [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ import {
TelemetryProvider,
} from '@blocksuite/affine-shared/services';
import {
autoScroll,
captureEventTarget,
type DropResult,
getBlockComponentsExcludeSubtrees,
getRectByBlockComponent,
getScrollContainer,
matchFlavours,
requestThrottledConnectedFrame,
SpecProvider,
} from '@blocksuite/affine-shared/utils';
import {
Expand Down Expand Up @@ -61,10 +61,6 @@ export type DragBlockPayload = DragPayload<DragBlockEntity, DragFromBlockSuite>;
export class DragEventWatcher {
dropIndicator: null | DropIndicator = null;

lastDragPoint: Point | null = null;

rafID: number = 0;

get host() {
return this.widget.host;
}
Expand Down Expand Up @@ -122,23 +118,22 @@ export class DragEventWatcher {

private readonly _cleanup = () => {
this._clearDropIndicator();
this.clearRaf();
this.widget.hide(true);
this.std.selection.setGroup('gfx', []);
};

private readonly _onDragMove = (
point: Point,
payload: DragBlockPayload,
dropPayload: DropPayload,
block: BlockComponent
) => {
this._createDropIndicator();
this.clearRaf();
this.rafID = requestAnimationFrame(() => {
this._updateDropIndicator(point, payload, dropPayload, block, true);
});
};
private readonly _onDragMove = requestThrottledConnectedFrame(
(
point: Point,
payload: DragBlockPayload,
dropPayload: DropPayload,
block: BlockComponent
) => {
this._createDropIndicator();
this._updateDropIndicator(point, payload, dropPayload, block);
},
this.widget
);

/**
* When dragging, should update indicator position and target drop block id
Expand Down Expand Up @@ -220,8 +215,7 @@ export class DragEventWatcher {
point: Point,
dragPayload: DragBlockPayload,
dropPayload: DropPayload,
dropBlock: BlockComponent,
shouldAutoScroll: boolean = false
dropBlock: BlockComponent
) => {
const closestNoteBlock = dropBlock && getParentNoteBlock(dropBlock);

Expand All @@ -245,37 +239,8 @@ export class DragEventWatcher {
}

this.lastDragPoint = point;

if (this.mode === 'page') {
if (!shouldAutoScroll) return;

const scrollContainer = getScrollContainer(this.widget.rootComponent);
const result = autoScroll(scrollContainer, point.y);
if (!result) {
this.clearRaf();
return;
}
this.rafID = requestAnimationFrame(() =>
this._updateDropIndicator(
point,
dragPayload,
dropPayload,
dropBlock,
true
)
);
} else {
this.clearRaf();
}
};

clearRaf() {
if (this.rafID) {
cancelAnimationFrame(this.rafID);
this.rafID = 0;
}
}

private readonly _resetDropResult = () => {
if (this.dropIndicator) this.dropIndicator.rect = null;
};
Expand Down Expand Up @@ -670,6 +635,7 @@ export class DragEventWatcher {
const widget = this.widget;
const std = this.std;
const disposables = widget.disposables;
const scrollable = getScrollContainer(this.host);

disposables.add(
std.dnd.draggable<DragBlockEntity>({
Expand Down Expand Up @@ -718,6 +684,17 @@ export class DragEventWatcher {
})
);

if (scrollable) {
disposables.add(
std.dnd.autoScroll<DragBlockEntity>({
element: scrollable,
canScroll: ({ source }) => {
return source.data.draggable?.entity?.type === 'blocks';
},
})
);
}

// used to handle drag move and drop
disposables.add(
std.dnd.monitor<DragBlockEntity>({
Expand Down
1 change: 1 addition & 0 deletions blocksuite/framework/block-std/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"license": "MIT",
"dependencies": {
"@atlaskit/pragmatic-drag-and-drop": "^1.4.0",
"@atlaskit/pragmatic-drag-and-drop-auto-scroll": "^2.1.0",
"@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.0.3",
"@blocksuite/global": "workspace:*",
"@blocksuite/inline": "workspace:*",
Expand Down
25 changes: 25 additions & 0 deletions blocksuite/framework/block-std/src/extension/dnd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
import { disableNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/element/disable-native-drag-preview';
import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview';
import type { DropTargetRecord } from '@atlaskit/pragmatic-drag-and-drop/types';
import { autoScrollForElements } from '@atlaskit/pragmatic-drag-and-drop-auto-scroll/element';
import {
attachClosestEdge,
type Edge,
Expand All @@ -22,6 +23,7 @@ import type {
ElementDropEventMap,
ElementDropTargetFeedbackArgs,
ElementMonitorFeedbackArgs,
OriginalAutoScrollOption,
OriginalDraggableOption,
OriginalDropTargetOption,
OriginalMonitorOption,
Expand Down Expand Up @@ -173,6 +175,22 @@ export type MonitorOption<
) => boolean;
} & ElementDragEventMap<DragPayload<PayloadEntity, PayloadFrom>, DropPayload>;

export type AutoScroll<
PayloadEntity extends DragEntity,
PayloadFrom extends DragFrom,
> = {
element: HTMLElement;
canScroll?: (
args: ElementDragEventBaseArgs<DragPayload<PayloadEntity, PayloadFrom>>
) => void;
getAllowedAxis?: (
args: ElementDragEventBaseArgs<DragPayload<PayloadEntity, PayloadFrom>>
) => ReturnType<Required<OriginalAutoScrollOption>['getAllowedAxis']>;
getConfiguration?: (
args: ElementDragEventBaseArgs<DragPayload<PayloadEntity, PayloadFrom>>
) => ReturnType<Required<OriginalAutoScrollOption>['getConfiguration']>;
};

export const DndExtensionIdentifier = LifeCycleWatcherIdentifier(
'DndController'
) as ServiceIdentifier<DndController>;
Expand Down Expand Up @@ -289,4 +307,11 @@ export class DndController extends LifeCycleWatcher {
>(args: MonitorOption<PayloadEntity, PayloadFrom, DropPayload<DropData>>) {
return monitorForElements(args as OriginalMonitorOption);
}

autoScroll<
PayloadEntity extends DragEntity = DragEntity,
PayloadFrom extends DragFrom = DragFromBlockSuite,
>(options: AutoScroll<PayloadEntity, PayloadFrom>) {
return autoScrollForElements(options as OriginalAutoScrollOption);
}
}
5 changes: 5 additions & 0 deletions blocksuite/framework/block-std/src/extension/dnd/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type {
DropTargetRecord,
ElementDragType,
} from '@atlaskit/pragmatic-drag-and-drop/types';
import type { autoScrollForElements } from '@atlaskit/pragmatic-drag-and-drop-auto-scroll/element';

export type ElementDragEventBaseArgs<Payload, DropPayload = {}> = {
/**
Expand Down Expand Up @@ -111,3 +112,7 @@ export type OriginalDropTargetOption = Parameters<
>[0];

export type OriginalMonitorOption = Parameters<typeof monitorForElements>[0];

export type OriginalAutoScrollOption = Parameters<
typeof autoScrollForElements
>[0];
11 changes: 11 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1210,6 +1210,16 @@ __metadata:
languageName: node
linkType: hard

"@atlaskit/pragmatic-drag-and-drop-auto-scroll@npm:^2.1.0":
version: 2.1.0
resolution: "@atlaskit/pragmatic-drag-and-drop-auto-scroll@npm:2.1.0"
dependencies:
"@atlaskit/pragmatic-drag-and-drop": "npm:^1.4.0"
"@babel/runtime": "npm:^7.0.0"
checksum: 10/a137947d240b01414c8235d9b3a5c949456ef3877488abdbfa92c491631ade10dd7fd6b3dc5ca31077617067c44dd1e90b1f6d1049b71d05d7064db92bc7810b
languageName: node
linkType: hard

"@atlaskit/pragmatic-drag-and-drop-hitbox@npm:^1.0.3":
version: 1.0.3
resolution: "@atlaskit/pragmatic-drag-and-drop-hitbox@npm:1.0.3"
Expand Down Expand Up @@ -3813,6 +3823,7 @@ __metadata:
resolution: "@blocksuite/block-std@workspace:blocksuite/framework/block-std"
dependencies:
"@atlaskit/pragmatic-drag-and-drop": "npm:^1.4.0"
"@atlaskit/pragmatic-drag-and-drop-auto-scroll": "npm:^2.1.0"
"@atlaskit/pragmatic-drag-and-drop-hitbox": "npm:^1.0.3"
"@blocksuite/global": "workspace:*"
"@blocksuite/inline": "workspace:*"
Expand Down

0 comments on commit 116dec2

Please sign in to comment.