Skip to content

Commit

Permalink
feat(cdk/drag-drop): support configurable scroll speed (#21400)
Browse files Browse the repository at this point in the history
Adds the ability for the scrolling speed of a drop list to be configured.

Fixes #19401.
  • Loading branch information
crisbeto committed Jan 9, 2021
1 parent 791af82 commit e65ead8
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 12 deletions.
19 changes: 19 additions & 0 deletions src/cdk/drag-drop/directives/drag.spec.ts
Expand Up @@ -3978,6 +3978,25 @@ describe('CdkDrag', () => {
expect(container.scrollTop).toBeGreaterThan(0);
}));

it('should be able to configure the auto-scroll speed', fakeAsync(() => {
const fixture = createComponent(DraggableInScrollableVerticalDropZone);
fixture.detectChanges();
fixture.componentInstance.dropInstance.autoScrollStep = 20;
const item = fixture.componentInstance.dragItems.first.element.nativeElement;
const list = fixture.componentInstance.dropInstance.element.nativeElement;
const listRect = list.getBoundingClientRect();

expect(list.scrollTop).toBe(0);

startDraggingViaMouse(fixture, item);
dispatchMouseEvent(document, 'mousemove',
listRect.left + listRect.width / 2, listRect.top + listRect.height);
fixture.detectChanges();
tickAnimationFrames(10);

expect(list.scrollTop).toBeGreaterThan(100);
}));

it('should pick up descendants inside of containers', fakeAsync(() => {
const fixture = createComponent(DraggableInDropZoneWithContainer);
fixture.detectChanges();
Expand Down
14 changes: 13 additions & 1 deletion src/cdk/drag-drop/directives/drop-list.ts
Expand Up @@ -6,7 +6,13 @@
* found in the LICENSE file at https://angular.io/license
*/

import {BooleanInput, coerceArray, coerceBooleanProperty} from '@angular/cdk/coercion';
import {
BooleanInput,
coerceArray,
coerceNumberProperty,
coerceBooleanProperty,
NumberInput,
} from '@angular/cdk/coercion';
import {
ElementRef,
EventEmitter,
Expand Down Expand Up @@ -136,6 +142,10 @@ export class CdkDropList<T = any> implements OnDestroy {
@Input('cdkDropListAutoScrollDisabled')
autoScrollDisabled: boolean;

/** Number of pixels to scroll for each frame when auto-scrolling an element. */
@Input('cdkDropListAutoScrollStep')
autoScrollStep: number;

/** Emits when the user drops an item inside the container. */
@Output('cdkDropListDropped')
dropped: EventEmitter<CdkDragDrop<T, any>> = new EventEmitter<CdkDragDrop<T, any>>();
Expand Down Expand Up @@ -301,6 +311,7 @@ export class CdkDropList<T = any> implements OnDestroy {
ref.lockAxis = this.lockAxis;
ref.sortingDisabled = coerceBooleanProperty(this.sortingDisabled);
ref.autoScrollDisabled = coerceBooleanProperty(this.autoScrollDisabled);
ref.autoScrollStep = coerceNumberProperty(this.autoScrollStep, 2);
ref
.connectedTo(siblings.filter(drop => drop && drop !== this).map(list => list._dropListRef))
.withOrientation(this.orientation);
Expand Down Expand Up @@ -380,4 +391,5 @@ export class CdkDropList<T = any> implements OnDestroy {
static ngAcceptInputType_disabled: BooleanInput;
static ngAcceptInputType_sortingDisabled: BooleanInput;
static ngAcceptInputType_autoScrollDisabled: BooleanInput;
static ngAcceptInputType_autoScrollStep: NumberInput;
}
18 changes: 8 additions & 10 deletions src/cdk/drag-drop/drop-list-ref.ts
Expand Up @@ -37,12 +37,6 @@ const DROP_PROXIMITY_THRESHOLD = 0.05;
*/
const SCROLL_PROXIMITY_THRESHOLD = 0.05;

/**
* Number of pixels to scroll for each frame when auto-scrolling an element.
* The value comes from trying it out manually until it feels right.
*/
const AUTO_SCROLL_STEP = 2;

/**
* Entry in the position cache for draggable items.
* @docs-private
Expand Down Expand Up @@ -91,6 +85,9 @@ export class DropListRef<T = any> {
*/
autoScrollDisabled: boolean = false;

/** Number of pixels to scroll for each frame when auto-scrolling an element. */
autoScrollStep: number = 2;

/**
* Function that is used to determine whether an item
* is allowed to be moved into a drop container.
Expand Down Expand Up @@ -788,17 +785,18 @@ export class DropListRef<T = any> {
.pipe(takeUntil(this._stopScrollTimers))
.subscribe(() => {
const node = this._scrollNode;
const scrollStep = this.autoScrollStep;

if (this._verticalScrollDirection === AutoScrollVerticalDirection.UP) {
incrementVerticalScroll(node, -AUTO_SCROLL_STEP);
incrementVerticalScroll(node, -scrollStep);
} else if (this._verticalScrollDirection === AutoScrollVerticalDirection.DOWN) {
incrementVerticalScroll(node, AUTO_SCROLL_STEP);
incrementVerticalScroll(node, scrollStep);
}

if (this._horizontalScrollDirection === AutoScrollHorizontalDirection.LEFT) {
incrementHorizontalScroll(node, -AUTO_SCROLL_STEP);
incrementHorizontalScroll(node, -scrollStep);
} else if (this._horizontalScrollDirection === AutoScrollHorizontalDirection.RIGHT) {
incrementHorizontalScroll(node, AUTO_SCROLL_STEP);
incrementHorizontalScroll(node, scrollStep);
}
});
}
Expand Down
5 changes: 4 additions & 1 deletion tools/public_api_guard/cdk/drag-drop.d.ts
Expand Up @@ -157,6 +157,7 @@ export interface CdkDragStart<T = any> {
export declare class CdkDropList<T = any> implements OnDestroy {
_dropListRef: DropListRef<CdkDropList<T>>;
autoScrollDisabled: boolean;
autoScrollStep: number;
connectedTo: (CdkDropList | string)[] | CdkDropList | string;
data: T;
get disabled(): boolean;
Expand All @@ -179,9 +180,10 @@ export declare class CdkDropList<T = any> implements OnDestroy {
ngOnDestroy(): void;
removeItem(item: CdkDrag): void;
static ngAcceptInputType_autoScrollDisabled: BooleanInput;
static ngAcceptInputType_autoScrollStep: NumberInput;
static ngAcceptInputType_disabled: BooleanInput;
static ngAcceptInputType_sortingDisabled: BooleanInput;
static ɵdir: i0.ɵɵDirectiveDefWithMeta<CdkDropList<any>, "[cdkDropList], cdk-drop-list", ["cdkDropList"], { "connectedTo": "cdkDropListConnectedTo"; "data": "cdkDropListData"; "orientation": "cdkDropListOrientation"; "id": "id"; "lockAxis": "cdkDropListLockAxis"; "disabled": "cdkDropListDisabled"; "sortingDisabled": "cdkDropListSortingDisabled"; "enterPredicate": "cdkDropListEnterPredicate"; "sortPredicate": "cdkDropListSortPredicate"; "autoScrollDisabled": "cdkDropListAutoScrollDisabled"; }, { "dropped": "cdkDropListDropped"; "entered": "cdkDropListEntered"; "exited": "cdkDropListExited"; "sorted": "cdkDropListSorted"; }, never>;
static ɵdir: i0.ɵɵDirectiveDefWithMeta<CdkDropList<any>, "[cdkDropList], cdk-drop-list", ["cdkDropList"], { "connectedTo": "cdkDropListConnectedTo"; "data": "cdkDropListData"; "orientation": "cdkDropListOrientation"; "id": "id"; "lockAxis": "cdkDropListLockAxis"; "disabled": "cdkDropListDisabled"; "sortingDisabled": "cdkDropListSortingDisabled"; "enterPredicate": "cdkDropListEnterPredicate"; "sortPredicate": "cdkDropListSortPredicate"; "autoScrollDisabled": "cdkDropListAutoScrollDisabled"; "autoScrollStep": "cdkDropListAutoScrollStep"; }, { "dropped": "cdkDropListDropped"; "entered": "cdkDropListEntered"; "exited": "cdkDropListExited"; "sorted": "cdkDropListSorted"; }, never>;
static ɵfac: i0.ɵɵFactoryDef<CdkDropList<any>, [null, null, null, null, { optional: true; }, { optional: true; skipSelf: true; }, { optional: true; }]>;
}

Expand Down Expand Up @@ -337,6 +339,7 @@ export declare type DropListOrientation = 'horizontal' | 'vertical';

export declare class DropListRef<T = any> {
autoScrollDisabled: boolean;
autoScrollStep: number;
beforeStarted: Subject<void>;
data: T;
disabled: boolean;
Expand Down

0 comments on commit e65ead8

Please sign in to comment.