Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an offset option for cursor location within mid-drag image #126

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 60 additions & 11 deletions packages/dragdrop/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ export class Drag implements IDisposable {
this.proposedAction = options.proposedAction || 'copy';
this.supportedActions = options.supportedActions || 'all';
this.source = options.source || null;
this._dragAdjustX = options.dragAdjustX || 0;
this._dragAdjustY = options.dragAdjustY || 0;
}

/**
Expand Down Expand Up @@ -232,6 +234,9 @@ export class Drag implements IDisposable {
return this._promise;
}

this._dragOffsetX = this._dragAdjustX ? this._dragAdjustX - clientX : 0;
this._dragOffsetY = this._dragAdjustY ? this._dragAdjustY - clientY : 0;

// Install the document listeners for the drag object.
this._addListeners();

Expand Down Expand Up @@ -290,8 +295,8 @@ export class Drag implements IDisposable {
return;
}
let style = this.dragImage.style;
style.top = `${clientY}px`;
style.left = `${clientX}px`;
style.top = `${clientY + this.dragOffsetY}px`;
style.left = `${clientX + this.dragOffsetX}px`;
}

/**
Expand All @@ -310,7 +315,10 @@ export class Drag implements IDisposable {

// Move the drag image to the specified client position. This is
// performed *after* dispatching to prevent unnecessary reflows.
this.moveDragImage(event.clientX, event.clientY);
this.moveDragImage(
event.clientX + this.dragOffsetX,
event.clientY + this.dragOffsetY
);
}

/**
Expand Down Expand Up @@ -404,7 +412,11 @@ export class Drag implements IDisposable {
*/
private _updateDragScroll(event: MouseEvent): void {
// Find the scroll target under the mouse.
let target = Private.findScrollTarget(event);
let target = Private.findScrollTarget(
event,
this.dragOffsetX,
this.dragOffsetY
);

// Bail if there is nothing to scroll.
if (!this._scrollTarget && !target) {
Expand Down Expand Up @@ -601,6 +613,14 @@ export class Drag implements IDisposable {
requestAnimationFrame(this._onScrollFrame);
};

get dragOffsetX(): number {
return this._dragOffsetX;
}

get dragOffsetY(): number {
return this._dragOffsetY;
}

private _disposed = false;
private _dropAction: DropAction = 'none';
private _override: IDisposable | null = null;
Expand All @@ -609,6 +629,10 @@ export class Drag implements IDisposable {
private _promise: Promise<DropAction> | null = null;
private _scrollTarget: Private.IScrollTarget | null = null;
private _resolve: ((value: DropAction) => void) | null = null;
private _dragAdjustX: number;
private _dragAdjustY: number;
private _dragOffsetX: number;
private _dragOffsetY: number;
}

/**
Expand Down Expand Up @@ -683,6 +707,20 @@ export namespace Drag {
* The default value is `null`.
*/
source?: any;

/**
* How many pixels to offset the drag/image in the x direction.
*
* The default value is 0.
*/
dragAdjustX?: number;

/**
* How many pixels to offset the drag/image in the y direction.
*
* The default value is 0.
*/
dragAdjustY?: number;
}

/**
Expand Down Expand Up @@ -816,18 +854,29 @@ namespace Private {

/**
* Find the drag scroll target under the mouse, if any.
*
* @param event - The mouse event related to the action.
*
* @param dragOffsetX - the number of pixels to offset the drag in the x direction.
*
* @param dragOffsetY - the number of pixels to offset the drag in the y direction.
*/
export function findScrollTarget(event: MouseEvent): IScrollTarget | null {
export function findScrollTarget(
event: MouseEvent,
dragOffsetX?: number,
dragOffsetY?: number
): IScrollTarget | null {
// Look up the client mouse position.
let x = event.clientX;
let y = event.clientY;
const x = event.clientX + (dragOffsetX !== undefined ? dragOffsetX : 0);
const y = event.clientY + (dragOffsetY !== undefined ? dragOffsetY : 0);

// Get the element under the mouse.
let element: Element | null = document.elementFromPoint(x, y);

// Search for a scrollable target based on the mouse position.
// The null assert in third clause of for-loop is required due to:
// https://github.com/Microsoft/TypeScript/issues/14143

for (; element; element = element!.parentElement) {
// Ignore elements which are not marked as scrollable.
if (!element.hasAttribute('data-lm-dragscroll')) {
Expand Down Expand Up @@ -1181,10 +1230,10 @@ namespace Private {
true,
window,
0,
event.screenX,
event.screenY,
event.clientX,
event.clientY,
event.screenX + drag.dragOffsetX,
event.screenY + drag.dragOffsetY,
event.clientX + drag.dragOffsetX,
event.clientY + drag.dragOffsetY,
event.ctrlKey,
event.altKey,
event.shiftKey,
Expand Down