From 1d906b64ab807d7c95f7b38761f2b37b37bef703 Mon Sep 17 00:00:00 2001 From: timonkrebs Date: Fri, 2 Apr 2021 09:03:42 +0200 Subject: [PATCH] feat(cdk/drag-drop): added dropPoint to dropped event (#22347) * feat(cdk/drag-drop): added dropPoint to dropped * fix(cdk/drag-drop): fixed tests * feat(cdk/drag-drop): PR-Feedback renamed dropPoint to dropPosition * feat(cdk/drag-drop): added dropPosition also to CdkDragEnd * feat(cdk/drag-drop): fixed tests * feat(cdk/drag-drop): PR-Feedback renamed dropPosition back to dropPoint --- src/cdk/drag-drop/directives/drag.spec.ts | 82 +++++++++++++++-------- src/cdk/drag-drop/directives/drag.ts | 9 ++- src/cdk/drag-drop/directives/drop-list.ts | 3 +- src/cdk/drag-drop/drag-events.ts | 4 ++ src/cdk/drag-drop/drag-ref.ts | 16 +++-- src/cdk/drag-drop/drop-list-ref.ts | 6 +- tools/public_api_guard/cdk/drag-drop.d.ts | 13 +++- 7 files changed, 94 insertions(+), 39 deletions(-) diff --git a/src/cdk/drag-drop/directives/drag.spec.ts b/src/cdk/drag-drop/directives/drag.spec.ts index 085c6d77fb84..a6e6c9db099c 100644 --- a/src/cdk/drag-drop/directives/drag.spec.ts +++ b/src/cdk/drag-drop/directives/drag.spec.ts @@ -376,7 +376,8 @@ describe('CdkDrag', () => { // go into an infinite loop trying to stringify the event, if the test fails. expect(event).toEqual({ source: fixture.componentInstance.dragInstance, - distance: {x: jasmine.any(Number), y: jasmine.any(Number)} + distance: {x: jasmine.any(Number), y: jasmine.any(Number)}, + dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)} }); })); @@ -389,7 +390,8 @@ describe('CdkDrag', () => { expect(event).toEqual({ source: jasmine.anything(), - distance: {x: 25, y: 30} + distance: {x: 25, y: 30}, + dropPoint: {x: 25, y: 30} }); dragElementViaMouse(fixture, fixture.componentInstance.dragElement.nativeElement, 40, 50); @@ -397,7 +399,8 @@ describe('CdkDrag', () => { expect(event).toEqual({ source: jasmine.anything(), - distance: {x: 40, y: 50} + distance: {x: 40, y: 50}, + dropPoint: {x: 40, y: 50} }); })); @@ -1690,7 +1693,8 @@ describe('CdkDrag', () => { container: fixture.componentInstance.dropInstance, previousContainer: fixture.componentInstance.dropInstance, isPointerOverContainer: true, - distance: {x: jasmine.any(Number), y: jasmine.any(Number)} + distance: {x: jasmine.any(Number), y: jasmine.any(Number)}, + dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)} }); expect(dragItems.map(drag => drag.element.nativeElement.textContent!.trim())) @@ -1733,6 +1737,7 @@ describe('CdkDrag', () => { fixture.componentInstance.droppedSpy.calls.mostRecent().args[0]; expect(event.distance).toEqual({x: 50, y: 60}); + expect(event.dropPoint).toEqual({x: 50, y: 60}); })); it('should expose whether an item was dropped outside of a container', fakeAsync(() => { @@ -1816,7 +1821,8 @@ describe('CdkDrag', () => { container: fixture.componentInstance.dropInstance, previousContainer: fixture.componentInstance.dropInstance, isPointerOverContainer: false, - distance: {x: jasmine.any(Number), y: jasmine.any(Number)} + distance: {x: jasmine.any(Number), y: jasmine.any(Number)}, + dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)} }); expect(dragItems.map(drag => drag.element.nativeElement.textContent!.trim())) @@ -1875,7 +1881,8 @@ describe('CdkDrag', () => { container: fixture.componentInstance.dropInstance, previousContainer: fixture.componentInstance.dropInstance, isPointerOverContainer: true, - distance: {x: jasmine.any(Number), y: jasmine.any(Number)} + distance: {x: jasmine.any(Number), y: jasmine.any(Number)}, + dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)} }); expect(dragItems.map(drag => drag.element.nativeElement.textContent!.trim())) @@ -1916,7 +1923,8 @@ describe('CdkDrag', () => { container: fixture.componentInstance.dropInstance, previousContainer: fixture.componentInstance.dropInstance, isPointerOverContainer: true, - distance: {x: jasmine.any(Number), y: jasmine.any(Number)} + distance: {x: jasmine.any(Number), y: jasmine.any(Number)}, + dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)} }); expect(dragItems.map(drag => drag.element.nativeElement.textContent!.trim())) @@ -1953,7 +1961,8 @@ describe('CdkDrag', () => { container: fixture.componentInstance.dropInstance, previousContainer: fixture.componentInstance.dropInstance, isPointerOverContainer: false, - distance: {x: jasmine.any(Number), y: jasmine.any(Number)} + distance: {x: jasmine.any(Number), y: jasmine.any(Number)}, + dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)} }); expect(dragItems.map(drag => drag.element.nativeElement.textContent!.trim())) @@ -1996,7 +2005,8 @@ describe('CdkDrag', () => { container: fixture.componentInstance.dropInstance, previousContainer: fixture.componentInstance.dropInstance, isPointerOverContainer: jasmine.any(Boolean), - distance: {x: jasmine.any(Number), y: jasmine.any(Number)} + distance: {x: jasmine.any(Number), y: jasmine.any(Number)}, + dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)} }); })); @@ -2044,7 +2054,8 @@ describe('CdkDrag', () => { container: fixture.componentInstance.dropInstance, previousContainer: fixture.componentInstance.dropInstance, isPointerOverContainer: jasmine.any(Boolean), - distance: {x: jasmine.any(Number), y: jasmine.any(Number)} + distance: {x: jasmine.any(Number), y: jasmine.any(Number)}, + dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)} }); scrollTo(0, 0); @@ -3635,7 +3646,8 @@ describe('CdkDrag', () => { container: dropInstance, previousContainer: dropInstance, isPointerOverContainer: true, - distance: {x: jasmine.any(Number), y: jasmine.any(Number)} + distance: {x: jasmine.any(Number), y: jasmine.any(Number)}, + dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)} }); expect(dragItems.map(drag => drag.element.nativeElement.textContent!.trim())) @@ -4067,7 +4079,8 @@ describe('CdkDrag', () => { container: fixture.componentInstance.dropInstance, previousContainer: fixture.componentInstance.dropInstance, isPointerOverContainer: true, - distance: {x: jasmine.any(Number), y: jasmine.any(Number)} + distance: {x: jasmine.any(Number), y: jasmine.any(Number)}, + dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)} }); })); @@ -4290,7 +4303,8 @@ describe('CdkDrag', () => { container: fixture.componentInstance.dropInstance, previousContainer: fixture.componentInstance.dropInstance, isPointerOverContainer: jasmine.any(Boolean), - distance: {x: jasmine.any(Number), y: jasmine.any(Number)} + distance: {x: jasmine.any(Number), y: jasmine.any(Number)}, + dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)} }); })); @@ -4345,7 +4359,8 @@ describe('CdkDrag', () => { container: fixture.componentInstance.dropInstances.toArray()[1], previousContainer: fixture.componentInstance.dropInstances.first, isPointerOverContainer: true, - distance: {x: jasmine.any(Number), y: jasmine.any(Number)} + distance: {x: jasmine.any(Number), y: jasmine.any(Number)}, + dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)} }); })); @@ -4450,7 +4465,8 @@ describe('CdkDrag', () => { container: dropInstances[1], previousContainer: dropInstances[0], isPointerOverContainer: true, - distance: {x: jasmine.any(Number), y: jasmine.any(Number)} + distance: {x: jasmine.any(Number), y: jasmine.any(Number)}, + dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)} }); })); @@ -4481,7 +4497,8 @@ describe('CdkDrag', () => { container: dropInstances[0], previousContainer: dropInstances[0], isPointerOverContainer: false, - distance: {x: jasmine.any(Number), y: jasmine.any(Number)} + distance: {x: jasmine.any(Number), y: jasmine.any(Number)}, + dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)} }); })); @@ -4512,7 +4529,8 @@ describe('CdkDrag', () => { container: dropInstances[0], previousContainer: dropInstances[0], isPointerOverContainer: false, - distance: {x: jasmine.any(Number), y: jasmine.any(Number)} + distance: {x: jasmine.any(Number), y: jasmine.any(Number)}, + dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)} }); })); @@ -4648,7 +4666,8 @@ describe('CdkDrag', () => { container: dropInstances[1], previousContainer: dropInstances[0], isPointerOverContainer: true, - distance: {x: jasmine.any(Number), y: jasmine.any(Number)} + distance: {x: jasmine.any(Number), y: jasmine.any(Number)}, + dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)} }); })); @@ -4785,7 +4804,8 @@ describe('CdkDrag', () => { container: dropInstances[1], previousContainer: dropInstances[0], isPointerOverContainer: true, - distance: {x: jasmine.any(Number), y: jasmine.any(Number)} + distance: {x: jasmine.any(Number), y: jasmine.any(Number)}, + dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)} }); })); @@ -4812,7 +4832,8 @@ describe('CdkDrag', () => { container: dropInstances[1], previousContainer: dropInstances[0], isPointerOverContainer: true, - distance: {x: jasmine.any(Number), y: jasmine.any(Number)} + distance: {x: jasmine.any(Number), y: jasmine.any(Number)}, + dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)} }); })); @@ -4844,7 +4865,8 @@ describe('CdkDrag', () => { container: dropInstances[1], previousContainer: dropInstances[0], isPointerOverContainer: true, - distance: {x: jasmine.any(Number), y: jasmine.any(Number)} + distance: {x: jasmine.any(Number), y: jasmine.any(Number)}, + dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)} }); })); @@ -4880,7 +4902,8 @@ describe('CdkDrag', () => { container: fixture.componentInstance.dropInstances.toArray()[1], previousContainer: fixture.componentInstance.dropInstances.first, isPointerOverContainer: true, - distance: {x: jasmine.any(Number), y: jasmine.any(Number)} + distance: {x: jasmine.any(Number), y: jasmine.any(Number)}, + dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)} }); expect(dropContainers[0].contains(item.element.nativeElement)).toBe(true, @@ -4977,7 +5000,8 @@ describe('CdkDrag', () => { container: dropInstances[0], previousContainer: dropInstances[0], isPointerOverContainer: false, - distance: {x: jasmine.any(Number), y: jasmine.any(Number)} + distance: {x: jasmine.any(Number), y: jasmine.any(Number)}, + dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)} }); })); @@ -5159,7 +5183,8 @@ describe('CdkDrag', () => { container: dropInstances[2], previousContainer: dropInstances[0], isPointerOverContainer: false, - distance: {x: jasmine.any(Number), y: jasmine.any(Number)} + distance: {x: jasmine.any(Number), y: jasmine.any(Number)}, + dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)} })); })); @@ -5418,7 +5443,8 @@ describe('CdkDrag', () => { container: fixture.componentInstance.dropInstances.toArray()[1], previousContainer: fixture.componentInstance.dropInstances.first, isPointerOverContainer: true, - distance: {x: jasmine.any(Number), y: jasmine.any(Number)} + distance: {x: jasmine.any(Number), y: jasmine.any(Number)}, + dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)} }); cleanup(); @@ -5453,7 +5479,8 @@ describe('CdkDrag', () => { container: fixture.componentInstance.dropInstances.toArray()[1], previousContainer: fixture.componentInstance.dropInstances.first, isPointerOverContainer: true, - distance: {x: jasmine.any(Number), y: jasmine.any(Number)} + distance: {x: jasmine.any(Number), y: jasmine.any(Number)}, + dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)} }); })); @@ -5487,7 +5514,8 @@ describe('CdkDrag', () => { container: fixture.componentInstance.dropInstances.toArray()[1], previousContainer: fixture.componentInstance.dropInstances.first, isPointerOverContainer: true, - distance: {x: jasmine.any(Number), y: jasmine.any(Number)} + distance: {x: jasmine.any(Number), y: jasmine.any(Number)}, + dropPoint: {x: jasmine.any(Number), y: jasmine.any(Number)} }); })); diff --git a/src/cdk/drag-drop/directives/drag.ts b/src/cdk/drag-drop/directives/drag.ts index 588e4da21513..e00390f66696 100644 --- a/src/cdk/drag-drop/directives/drag.ts +++ b/src/cdk/drag-drop/directives/drag.ts @@ -459,7 +459,11 @@ export class CdkDrag implements AfterViewInit, OnChanges, OnDestroy { }); ref.ended.subscribe(event => { - this.ended.emit({source: this, distance: event.distance}); + this.ended.emit({ + source: this, + distance: event.distance, + dropPoint: event.dropPoint + }); // Since all of these events run outside of change detection, // we need to ensure that everything is marked correctly. @@ -489,7 +493,8 @@ export class CdkDrag implements AfterViewInit, OnChanges, OnDestroy { container: event.container.data, isPointerOverContainer: event.isPointerOverContainer, item: this, - distance: event.distance + distance: event.distance, + dropPoint: event.dropPoint }); }); } diff --git a/src/cdk/drag-drop/directives/drop-list.ts b/src/cdk/drag-drop/directives/drop-list.ts index 10ee6b8d48d3..c209436ae33d 100644 --- a/src/cdk/drag-drop/directives/drop-list.ts +++ b/src/cdk/drag-drop/directives/drop-list.ts @@ -358,7 +358,8 @@ export class CdkDropList implements OnDestroy { container: event.container.data, item: event.item.data, isPointerOverContainer: event.isPointerOverContainer, - distance: event.distance + distance: event.distance, + dropPoint: event.dropPoint }); // Mark for check since all of these events run outside of change diff --git a/src/cdk/drag-drop/drag-events.ts b/src/cdk/drag-drop/drag-events.ts index df6f74e33b61..cefe269a04d1 100644 --- a/src/cdk/drag-drop/drag-events.ts +++ b/src/cdk/drag-drop/drag-events.ts @@ -27,6 +27,8 @@ export interface CdkDragEnd { source: CdkDrag; /** Distance in pixels that the user has dragged since the drag sequence started. */ distance: {x: number, y: number}; + /** Position where the pointer was when the item was dropped */ + dropPoint: {x: number, y: number}; } /** Event emitted when the user moves an item into a new drop container. */ @@ -67,6 +69,8 @@ export interface CdkDragDrop { isPointerOverContainer: boolean; /** Distance in pixels that the user has dragged since the drag sequence started. */ distance: {x: number, y: number}; + /** Position where the pointer was when the item was dropped */ + dropPoint: {x: number, y: number}; } /** Event emitted as the user is dragging a draggable item. */ diff --git a/src/cdk/drag-drop/drag-ref.ts b/src/cdk/drag-drop/drag-ref.ts index fb784b2bff3f..863c1aa88d8d 100644 --- a/src/cdk/drag-drop/drag-ref.ts +++ b/src/cdk/drag-drop/drag-ref.ts @@ -294,7 +294,7 @@ export class DragRef { released = new Subject<{source: DragRef}>(); /** Emits when the user stops dragging an item in the container. */ - ended = new Subject<{source: DragRef, distance: Point}>(); + ended = new Subject<{source: DragRef, distance: Point, dropPoint: Point}>(); /** Emits when the user has moved the item into a new container. */ entered = new Subject<{container: DropListRef, item: DragRef, currentIndex: number}>(); @@ -310,6 +310,7 @@ export class DragRef { container: DropListRef; previousContainer: DropListRef; distance: Point; + dropPoint: Point; isPointerOverContainer: boolean; }>(); @@ -764,11 +765,13 @@ export class DragRef { // the user starts dragging the item, its position will be calculated relatively // to the new passive transform. this._passiveTransform.x = this._activeTransform.x; + const pointerPosition = this._getPointerPositionOnPage(event); this._passiveTransform.y = this._activeTransform.y; this._ngZone.run(() => { this.ended.next({ source: this, - distance: this._getDragDistance(this._getPointerPositionOnPage(event)) + distance: this._getDragDistance(pointerPosition), + dropPoint: pointerPosition }); }); this._cleanupCachedDimensions(); @@ -910,11 +913,11 @@ export class DragRef { const container = this._dropContainer!; const currentIndex = container.getItemIndex(this); const pointerPosition = this._getPointerPositionOnPage(event); - const distance = this._getDragDistance(this._getPointerPositionOnPage(event)); + const distance = this._getDragDistance(pointerPosition); const isPointerOverContainer = container._isOverContainer( pointerPosition.x, pointerPosition.y); - this.ended.next({source: this, distance}); + this.ended.next({source: this, distance, dropPoint: pointerPosition}); this.dropped.next({ item: this, currentIndex, @@ -922,10 +925,11 @@ export class DragRef { container: container, previousContainer: this._initialContainer, isPointerOverContainer, - distance + distance, + dropPoint: pointerPosition }); container.drop(this, currentIndex, this._initialIndex, this._initialContainer, - isPointerOverContainer, distance); + isPointerOverContainer, distance, pointerPosition); this._dropContainer = this._initialContainer; }); } diff --git a/src/cdk/drag-drop/drop-list-ref.ts b/src/cdk/drag-drop/drop-list-ref.ts index bff662f1baf6..e9aa5e832cf1 100644 --- a/src/cdk/drag-drop/drop-list-ref.ts +++ b/src/cdk/drag-drop/drop-list-ref.ts @@ -120,6 +120,7 @@ export class DropListRef { previousContainer: DropListRef, isPointerOverContainer: boolean, distance: Point; + dropPoint: Point; }>(); /** Emits as the user is swapping items while actively dragging. */ @@ -334,7 +335,7 @@ export class DropListRef { * @param distance Distance the user has dragged since the start of the dragging sequence. */ drop(item: DragRef, currentIndex: number, previousIndex: number, previousContainer: DropListRef, - isPointerOverContainer: boolean, distance: Point): void { + isPointerOverContainer: boolean, distance: Point, dropPoint: Point): void { this._reset(); this.dropped.next({ item, @@ -343,7 +344,8 @@ export class DropListRef { container: this, previousContainer, isPointerOverContainer, - distance + distance, + dropPoint }); } diff --git a/tools/public_api_guard/cdk/drag-drop.d.ts b/tools/public_api_guard/cdk/drag-drop.d.ts index d7244fafb1a2..c2a0c14e2d04 100644 --- a/tools/public_api_guard/cdk/drag-drop.d.ts +++ b/tools/public_api_guard/cdk/drag-drop.d.ts @@ -66,6 +66,10 @@ export interface CdkDragDrop { x: number; y: number; }; + dropPoint: { + x: number; + y: number; + }; isPointerOverContainer: boolean; item: CdkDrag; previousContainer: CdkDropList; @@ -77,6 +81,10 @@ export interface CdkDragEnd { x: number; y: number; }; + dropPoint: { + x: number; + y: number; + }; source: CdkDrag; } @@ -269,11 +277,13 @@ export declare class DragRef { container: DropListRef; previousContainer: DropListRef; distance: Point; + dropPoint: Point; isPointerOverContainer: boolean; }>; ended: Subject<{ source: DragRef; distance: Point; + dropPoint: Point; }>; entered: Subject<{ container: DropListRef; @@ -356,6 +366,7 @@ export declare class DropListRef { previousContainer: DropListRef; isPointerOverContainer: boolean; distance: Point; + dropPoint: Point; }>; element: HTMLElement | ElementRef; enterPredicate: (drag: DragRef, drop: DropListRef) => boolean; @@ -391,7 +402,7 @@ export declare class DropListRef { _stopScrolling(): void; connectedTo(connectedTo: DropListRef[]): this; dispose(): void; - drop(item: DragRef, currentIndex: number, previousIndex: number, previousContainer: DropListRef, isPointerOverContainer: boolean, distance: Point): void; + drop(item: DragRef, currentIndex: number, previousIndex: number, previousContainer: DropListRef, isPointerOverContainer: boolean, distance: Point, dropPoint: Point): void; enter(item: DragRef, pointerX: number, pointerY: number, index?: number): void; exit(item: DragRef): void; getItemIndex(item: DragRef): number;