Skip to content

Commit e65ead8

Browse files
authored
feat(cdk/drag-drop): support configurable scroll speed (#21400)
Adds the ability for the scrolling speed of a drop list to be configured. Fixes #19401.
1 parent 791af82 commit e65ead8

File tree

4 files changed

+44
-12
lines changed

4 files changed

+44
-12
lines changed

src/cdk/drag-drop/directives/drag.spec.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3978,6 +3978,25 @@ describe('CdkDrag', () => {
39783978
expect(container.scrollTop).toBeGreaterThan(0);
39793979
}));
39803980

3981+
it('should be able to configure the auto-scroll speed', fakeAsync(() => {
3982+
const fixture = createComponent(DraggableInScrollableVerticalDropZone);
3983+
fixture.detectChanges();
3984+
fixture.componentInstance.dropInstance.autoScrollStep = 20;
3985+
const item = fixture.componentInstance.dragItems.first.element.nativeElement;
3986+
const list = fixture.componentInstance.dropInstance.element.nativeElement;
3987+
const listRect = list.getBoundingClientRect();
3988+
3989+
expect(list.scrollTop).toBe(0);
3990+
3991+
startDraggingViaMouse(fixture, item);
3992+
dispatchMouseEvent(document, 'mousemove',
3993+
listRect.left + listRect.width / 2, listRect.top + listRect.height);
3994+
fixture.detectChanges();
3995+
tickAnimationFrames(10);
3996+
3997+
expect(list.scrollTop).toBeGreaterThan(100);
3998+
}));
3999+
39814000
it('should pick up descendants inside of containers', fakeAsync(() => {
39824001
const fixture = createComponent(DraggableInDropZoneWithContainer);
39834002
fixture.detectChanges();

src/cdk/drag-drop/directives/drop-list.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {BooleanInput, coerceArray, coerceBooleanProperty} from '@angular/cdk/coercion';
9+
import {
10+
BooleanInput,
11+
coerceArray,
12+
coerceNumberProperty,
13+
coerceBooleanProperty,
14+
NumberInput,
15+
} from '@angular/cdk/coercion';
1016
import {
1117
ElementRef,
1218
EventEmitter,
@@ -136,6 +142,10 @@ export class CdkDropList<T = any> implements OnDestroy {
136142
@Input('cdkDropListAutoScrollDisabled')
137143
autoScrollDisabled: boolean;
138144

145+
/** Number of pixels to scroll for each frame when auto-scrolling an element. */
146+
@Input('cdkDropListAutoScrollStep')
147+
autoScrollStep: number;
148+
139149
/** Emits when the user drops an item inside the container. */
140150
@Output('cdkDropListDropped')
141151
dropped: EventEmitter<CdkDragDrop<T, any>> = new EventEmitter<CdkDragDrop<T, any>>();
@@ -301,6 +311,7 @@ export class CdkDropList<T = any> implements OnDestroy {
301311
ref.lockAxis = this.lockAxis;
302312
ref.sortingDisabled = coerceBooleanProperty(this.sortingDisabled);
303313
ref.autoScrollDisabled = coerceBooleanProperty(this.autoScrollDisabled);
314+
ref.autoScrollStep = coerceNumberProperty(this.autoScrollStep, 2);
304315
ref
305316
.connectedTo(siblings.filter(drop => drop && drop !== this).map(list => list._dropListRef))
306317
.withOrientation(this.orientation);
@@ -380,4 +391,5 @@ export class CdkDropList<T = any> implements OnDestroy {
380391
static ngAcceptInputType_disabled: BooleanInput;
381392
static ngAcceptInputType_sortingDisabled: BooleanInput;
382393
static ngAcceptInputType_autoScrollDisabled: BooleanInput;
394+
static ngAcceptInputType_autoScrollStep: NumberInput;
383395
}

src/cdk/drag-drop/drop-list-ref.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,6 @@ const DROP_PROXIMITY_THRESHOLD = 0.05;
3737
*/
3838
const SCROLL_PROXIMITY_THRESHOLD = 0.05;
3939

40-
/**
41-
* Number of pixels to scroll for each frame when auto-scrolling an element.
42-
* The value comes from trying it out manually until it feels right.
43-
*/
44-
const AUTO_SCROLL_STEP = 2;
45-
4640
/**
4741
* Entry in the position cache for draggable items.
4842
* @docs-private
@@ -91,6 +85,9 @@ export class DropListRef<T = any> {
9185
*/
9286
autoScrollDisabled: boolean = false;
9387

88+
/** Number of pixels to scroll for each frame when auto-scrolling an element. */
89+
autoScrollStep: number = 2;
90+
9491
/**
9592
* Function that is used to determine whether an item
9693
* is allowed to be moved into a drop container.
@@ -788,17 +785,18 @@ export class DropListRef<T = any> {
788785
.pipe(takeUntil(this._stopScrollTimers))
789786
.subscribe(() => {
790787
const node = this._scrollNode;
788+
const scrollStep = this.autoScrollStep;
791789

792790
if (this._verticalScrollDirection === AutoScrollVerticalDirection.UP) {
793-
incrementVerticalScroll(node, -AUTO_SCROLL_STEP);
791+
incrementVerticalScroll(node, -scrollStep);
794792
} else if (this._verticalScrollDirection === AutoScrollVerticalDirection.DOWN) {
795-
incrementVerticalScroll(node, AUTO_SCROLL_STEP);
793+
incrementVerticalScroll(node, scrollStep);
796794
}
797795

798796
if (this._horizontalScrollDirection === AutoScrollHorizontalDirection.LEFT) {
799-
incrementHorizontalScroll(node, -AUTO_SCROLL_STEP);
797+
incrementHorizontalScroll(node, -scrollStep);
800798
} else if (this._horizontalScrollDirection === AutoScrollHorizontalDirection.RIGHT) {
801-
incrementHorizontalScroll(node, AUTO_SCROLL_STEP);
799+
incrementHorizontalScroll(node, scrollStep);
802800
}
803801
});
804802
}

tools/public_api_guard/cdk/drag-drop.d.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ export interface CdkDragStart<T = any> {
157157
export declare class CdkDropList<T = any> implements OnDestroy {
158158
_dropListRef: DropListRef<CdkDropList<T>>;
159159
autoScrollDisabled: boolean;
160+
autoScrollStep: number;
160161
connectedTo: (CdkDropList | string)[] | CdkDropList | string;
161162
data: T;
162163
get disabled(): boolean;
@@ -179,9 +180,10 @@ export declare class CdkDropList<T = any> implements OnDestroy {
179180
ngOnDestroy(): void;
180181
removeItem(item: CdkDrag): void;
181182
static ngAcceptInputType_autoScrollDisabled: BooleanInput;
183+
static ngAcceptInputType_autoScrollStep: NumberInput;
182184
static ngAcceptInputType_disabled: BooleanInput;
183185
static ngAcceptInputType_sortingDisabled: BooleanInput;
184-
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>;
186+
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>;
185187
static ɵfac: i0.ɵɵFactoryDef<CdkDropList<any>, [null, null, null, null, { optional: true; }, { optional: true; skipSelf: true; }, { optional: true; }]>;
186188
}
187189

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

338340
export declare class DropListRef<T = any> {
339341
autoScrollDisabled: boolean;
342+
autoScrollStep: number;
340343
beforeStarted: Subject<void>;
341344
data: T;
342345
disabled: boolean;

0 commit comments

Comments
 (0)