Skip to content

Commit 087bbb5

Browse files
committed
refactor(drag-drop): expose more private apis as protected
Exposes more of the private drag&drop APIs as protected ones, in order to make it easier for people to implement their custom directives based on the CDK ones. Also moves out some of the private helper methods into functions. Fixes #14113.
1 parent 63be232 commit 087bbb5

File tree

4 files changed

+76
-56
lines changed

4 files changed

+76
-56
lines changed

src/cdk/drag-drop/drag.ts

+32-32
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ export class CdkDrag<T = any> implements AfterViewInit, OnDestroy {
332332
rootElement.addEventListener('mousedown', this._pointerDown, activeEventListenerOptions);
333333
rootElement.addEventListener('touchstart', this._pointerDown, passiveEventListenerOptions);
334334
this._handles.changes.pipe(startWith(null)).subscribe(() =>
335-
toggleNativeDragInteractions(rootElement, this.getChildHandles().length > 0));
335+
toggleNativeDragInteractions(rootElement, this._getChildHandles().length > 0));
336336
});
337337
}
338338

@@ -349,7 +349,7 @@ export class CdkDrag<T = any> implements AfterViewInit, OnDestroy {
349349
if (this._isDragging()) {
350350
// Since we move out the element to the end of the body while it's being
351351
// dragged, we have to make sure that it's removed if it gets destroyed.
352-
this._removeElement(this._rootElement);
352+
removeElement(this._rootElement);
353353
}
354354
}
355355

@@ -368,13 +368,13 @@ export class CdkDrag<T = any> implements AfterViewInit, OnDestroy {
368368
}
369369

370370
/** Gets only handles that are not inside descendant `CdkDrag` instances. */
371-
private getChildHandles() {
371+
protected _getChildHandles() {
372372
return this._handles.filter(handle => handle._parentDrag === this);
373373
}
374374

375375
/** Handler for the `mousedown`/`touchstart` events. */
376376
_pointerDown = (event: MouseEvent | TouchEvent) => {
377-
const handles = this.getChildHandles();
377+
const handles = this._getChildHandles();
378378

379379
// Delegate the event based on whether it started from a handle or the element itself.
380380
if (handles.length) {
@@ -398,16 +398,16 @@ export class CdkDrag<T = any> implements AfterViewInit, OnDestroy {
398398
* @param referenceElement Element that started the drag sequence.
399399
* @param event Browser event object that started the sequence.
400400
*/
401-
private _initializeDragSequence(referenceElement: HTMLElement, event: MouseEvent | TouchEvent) {
401+
protected _initializeDragSequence(referenceElement: HTMLElement, event: MouseEvent | TouchEvent) {
402402
// Always stop propagation for the event that initializes
403403
// the dragging sequence, in order to prevent it from potentially
404404
// starting another sequence for a draggable parent somewhere up the DOM tree.
405405
event.stopPropagation();
406406

407407
const isDragging = this._isDragging();
408-
const isTouchEvent = this._isTouchEvent(event);
409-
const isAuxiliaryMouseButton = !isTouchEvent && (event as MouseEvent).button !== 0;
410-
const isSyntheticEvent = !isTouchEvent && this._lastTouchEventTime &&
408+
const wasTouchEvent = isTouchEvent(event);
409+
const isAuxiliaryMouseButton = !wasTouchEvent && (event as MouseEvent).button !== 0;
410+
const isSyntheticEvent = !wasTouchEvent && this._lastTouchEventTime &&
411411
this._lastTouchEventTime + MOUSE_EVENT_IGNORE_TIME > Date.now();
412412

413413
// If the event started from an element with the native HTML drag&drop, it'll interfere
@@ -453,11 +453,11 @@ export class CdkDrag<T = any> implements AfterViewInit, OnDestroy {
453453
}
454454

455455
/** Starts the dragging sequence. */
456-
private _startDragSequence(event: MouseEvent | TouchEvent) {
456+
protected _startDragSequence(event: MouseEvent | TouchEvent) {
457457
// Emit the event on the item before the one on the container.
458458
this.started.emit({source: this});
459459

460-
if (this._isTouchEvent(event)) {
460+
if (isTouchEvent(event)) {
461461
this._lastTouchEventTime = Date.now();
462462
}
463463

@@ -482,7 +482,7 @@ export class CdkDrag<T = any> implements AfterViewInit, OnDestroy {
482482
}
483483

484484
/** Handler that is invoked when the user moves their pointer after they've initiated a drag. */
485-
private _pointerMove = (event: MouseEvent | TouchEvent) => {
485+
protected _pointerMove = (event: MouseEvent | TouchEvent) => {
486486
if (!this._hasStartedDragging) {
487487
const pointerPosition = this._getPointerPositionOnPage(event);
488488
const distanceX = Math.abs(pointerPosition.x - this._pickupPositionOnPage.x);
@@ -551,7 +551,7 @@ export class CdkDrag<T = any> implements AfterViewInit, OnDestroy {
551551
}
552552

553553
/** Handler that is invoked when the user lifts their pointer up, after initiating a drag. */
554-
private _pointerUp = (event: MouseEvent | TouchEvent) => {
554+
protected _pointerUp = (event: MouseEvent | TouchEvent) => {
555555
if (!this._isDragging()) {
556556
return;
557557
}
@@ -721,7 +721,7 @@ export class CdkDrag<T = any> implements AfterViewInit, OnDestroy {
721721
const elementRect = this._rootElement.getBoundingClientRect();
722722
const handleElement = referenceElement === this._rootElement ? null : referenceElement;
723723
const referenceRect = handleElement ? handleElement.getBoundingClientRect() : elementRect;
724-
const point = this._isTouchEvent(event) ? event.targetTouches[0] : event;
724+
const point = isTouchEvent(event) ? event.targetTouches[0] : event;
725725
const x = point.pageX - referenceRect.left - this._scrollPosition.left;
726726
const y = point.pageY - referenceRect.top - this._scrollPosition.top;
727727

@@ -778,20 +778,10 @@ export class CdkDrag<T = any> implements AfterViewInit, OnDestroy {
778778
});
779779
}
780780

781-
/**
782-
* Helper to remove an element from the DOM and to do all the necessary null checks.
783-
* @param element Element to be removed.
784-
*/
785-
private _removeElement(element: HTMLElement | null) {
786-
if (element && element.parentNode) {
787-
element.parentNode.removeChild(element);
788-
}
789-
}
790-
791781
/** Determines the point of the page that was touched by the user. */
792782
private _getPointerPositionOnPage(event: MouseEvent | TouchEvent): Point {
793783
// `touches` will be empty for start/end events so we have to fall back to `changedTouches`.
794-
const point = this._isTouchEvent(event) ? (event.touches[0] || event.changedTouches[0]) : event;
784+
const point = isTouchEvent(event) ? (event.touches[0] || event.changedTouches[0]) : event;
795785

796786
return {
797787
x: point.pageX - this._scrollPosition.left,
@@ -826,15 +816,10 @@ export class CdkDrag<T = any> implements AfterViewInit, OnDestroy {
826816
return point;
827817
}
828818

829-
/** Determines whether an event is a touch event. */
830-
private _isTouchEvent(event: MouseEvent | TouchEvent): event is TouchEvent {
831-
return event.type.startsWith('touch');
832-
}
833-
834819
/** Destroys the preview element and its ViewRef. */
835820
private _destroyPreview() {
836821
if (this._preview) {
837-
this._removeElement(this._preview);
822+
removeElement(this._preview);
838823
}
839824

840825
if (this._previewRef) {
@@ -847,7 +832,7 @@ export class CdkDrag<T = any> implements AfterViewInit, OnDestroy {
847832
/** Destroys the placeholder element and its ViewRef. */
848833
private _destroyPlaceholder() {
849834
if (this._placeholder) {
850-
this._removeElement(this._placeholder);
835+
removeElement(this._placeholder);
851836
}
852837

853838
if (this._placeholderRef) {
@@ -885,7 +870,7 @@ export class CdkDrag<T = any> implements AfterViewInit, OnDestroy {
885870
}
886871

887872
/** Gets the root draggable element, based on the `rootElementSelector`. */
888-
private _getRootElement(): HTMLElement {
873+
protected _getRootElement(): HTMLElement {
889874
const element = this.element.nativeElement;
890875
const rootElement = this.rootElementSelector ?
891876
getClosestMatchingAncestor(element, this.rootElementSelector) : null;
@@ -950,3 +935,18 @@ function getClosestMatchingAncestor(element: HTMLElement, selector: string) {
950935
currentElement = currentElement.parentElement;
951936
}
952937
}
938+
939+
/**
940+
* Helper to remove an element from the DOM and to do all the necessary null checks.
941+
* @param element Element to be removed.
942+
*/
943+
function removeElement(element: HTMLElement | null) {
944+
if (element && element.parentNode) {
945+
element.parentNode.removeChild(element);
946+
}
947+
}
948+
949+
/** Determines whether an event is a touch event. */
950+
function isTouchEvent(event: MouseEvent | TouchEvent): event is TouchEvent {
951+
return event.type.startsWith('touch');
952+
}

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

+24-24
Original file line numberDiff line numberDiff line change
@@ -196,14 +196,14 @@ export class CdkDropList<T = any> implements OnInit, OnDestroy {
196196
_dragging = false;
197197

198198
/** Cache of the dimensions of all the items and the sibling containers. */
199-
private _positionCache: PositionCache = {items: [], siblings: [], self: {} as ClientRect};
199+
protected _positionCache: PositionCache = {items: [], siblings: [], self: {} as ClientRect};
200200

201201
/**
202202
* Draggable items that are currently active inside the container. Includes the items
203203
* from `_draggables`, as well as any items that have been dragged in, but haven't
204204
* been dropped yet.
205205
*/
206-
private _activeDraggables: CdkDrag[];
206+
protected _activeDraggables: CdkDrag[];
207207

208208
/**
209209
* Keeps track of the item that was last swapped with the dragged item, as
@@ -382,10 +382,10 @@ export class CdkDropList<T = any> implements OnInit, OnDestroy {
382382
// Round the transforms since some browsers will
383383
// blur the elements, for sub-pixel transforms.
384384
elementToOffset.style.transform = `translate3d(${Math.round(sibling.offset)}px, 0, 0)`;
385-
this._adjustClientRect(sibling.clientRect, 0, offset);
385+
adjustClientRect(sibling.clientRect, 0, offset);
386386
} else {
387387
elementToOffset.style.transform = `translate3d(0, ${Math.round(sibling.offset)}px, 0)`;
388-
this._adjustClientRect(sibling.clientRect, offset, 0);
388+
adjustClientRect(sibling.clientRect, offset, 0);
389389
}
390390
});
391391
}
@@ -487,7 +487,7 @@ export class CdkDropList<T = any> implements OnInit, OnDestroy {
487487
}
488488

489489
/** Resets the container to its initial state. */
490-
private _reset() {
490+
protected _reset() {
491491
this._dragging = false;
492492

493493
// TODO(crisbeto): may have to wait for the animations to finish.
@@ -499,28 +499,14 @@ export class CdkDropList<T = any> implements OnInit, OnDestroy {
499499
this._previousSwap.delta = 0;
500500
}
501501

502-
/**
503-
* Updates the top/left positions of a `ClientRect`, as well as their bottom/right counterparts.
504-
* @param clientRect `ClientRect` that should be updated.
505-
* @param top Amount to add to the `top` position.
506-
* @param left Amount to add to the `left` position.
507-
*/
508-
private _adjustClientRect(clientRect: ClientRect, top: number, left: number) {
509-
clientRect.top += top;
510-
clientRect.bottom = clientRect.top + clientRect.height;
511-
512-
clientRect.left += left;
513-
clientRect.right = clientRect.left + clientRect.width;
514-
}
515-
516502
/**
517503
* Gets the index of an item in the drop container, based on the position of the user's pointer.
518504
* @param item Item that is being sorted.
519505
* @param pointerX Position of the user's pointer along the X axis.
520506
* @param pointerY Position of the user's pointer along the Y axis.
521507
* @param delta Direction in which the user is moving their pointer.
522508
*/
523-
private _getItemIndexFromPointerPosition(item: CdkDrag, pointerX: number, pointerY: number,
509+
protected _getItemIndexFromPointerPosition(item: CdkDrag, pointerX: number, pointerY: number,
524510
delta?: {x: number, y: number}) {
525511

526512
const isHorizontal = this.orientation === 'horizontal';
@@ -555,7 +541,7 @@ export class CdkDropList<T = any> implements OnInit, OnDestroy {
555541
* @param pointerX Coordinates along the X axis.
556542
* @param pointerY Coordinates along the Y axis.
557543
*/
558-
private _isPointerNearDropContainer(pointerX: number, pointerY: number): boolean {
544+
protected _isPointerNearDropContainer(pointerX: number, pointerY: number): boolean {
559545
const {top, right, bottom, left, width, height} = this._positionCache.self;
560546
const xThreshold = width * DROP_PROXIMITY_THRESHOLD;
561547
const yThreshold = height * DROP_PROXIMITY_THRESHOLD;
@@ -570,7 +556,7 @@ export class CdkDropList<T = any> implements OnInit, OnDestroy {
570556
* @param newPosition Position of the item where the current item should be moved.
571557
* @param delta Direction in which the user is moving.
572558
*/
573-
private _getItemOffsetPx(currentPosition: ClientRect, newPosition: ClientRect, delta: 1 | -1) {
559+
protected _getItemOffsetPx(currentPosition: ClientRect, newPosition: ClientRect, delta: 1 | -1) {
574560
const isHorizontal = this.orientation === 'horizontal';
575561
let itemOffset = isHorizontal ? newPosition.left - currentPosition.left :
576562
newPosition.top - currentPosition.top;
@@ -590,7 +576,7 @@ export class CdkDropList<T = any> implements OnInit, OnDestroy {
590576
* @param siblings All of the items in the list.
591577
* @param delta Direction in which the user is moving.
592578
*/
593-
private _getSiblingOffsetPx(currentIndex: number,
579+
protected _getSiblingOffsetPx(currentIndex: number,
594580
siblings: ItemPositionCacheEntry[],
595581
delta: 1 | -1) {
596582

@@ -618,7 +604,7 @@ export class CdkDropList<T = any> implements OnInit, OnDestroy {
618604
}
619605

620606
/** Gets an array of unique drop lists that the current list is connected to. */
621-
private _getConnectedLists(): CdkDropList[] {
607+
protected _getConnectedLists(): CdkDropList[] {
622608
const siblings = coerceArray(this.connectedTo).map(drop => {
623609
return typeof drop === 'string' ? this._dragDropRegistry.getDropContainer(drop)! : drop;
624610
});
@@ -665,3 +651,17 @@ function isInsideClientRect(clientRect: ClientRect, x: number, y: number) {
665651
const {top, bottom, left, right} = clientRect;
666652
return y >= top && y <= bottom && x >= left && x <= right;
667653
}
654+
655+
/**
656+
* Updates the top/left positions of a `ClientRect`, as well as their bottom/right counterparts.
657+
* @param clientRect `ClientRect` that should be updated.
658+
* @param top Amount to add to the `top` position.
659+
* @param left Amount to add to the `left` position.
660+
*/
661+
function adjustClientRect(clientRect: ClientRect, top: number, left: number) {
662+
clientRect.top += top;
663+
clientRect.bottom = clientRect.top + clientRect.height;
664+
665+
clientRect.left += left;
666+
clientRect.right = clientRect.left + clientRect.width;
667+
}

src/cdk/drag-drop/public-api.ts

+1
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ export * from './drag-preview';
1717
export * from './drag-placeholder';
1818
export * from './drag-drop-module';
1919
export * from './drag-drop-registry';
20+
export * from './drag-parent';

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

+19
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@ export declare const CDK_DRAG_CONFIG: InjectionToken<CdkDragConfig>;
22

33
export declare function CDK_DRAG_CONFIG_FACTORY(): CdkDragConfig;
44

5+
export declare const CDK_DRAG_PARENT: InjectionToken<{}>;
6+
57
export declare const CDK_DROP_LIST_CONTAINER: InjectionToken<CdkDropListContainer<any>>;
68

79
export declare class CdkDrag<T = any> implements AfterViewInit, OnDestroy {
810
_handles: QueryList<CdkDragHandle>;
911
_hasStartedDragging: boolean;
1012
_placeholderTemplate: CdkDragPlaceholder;
1113
_pointerDown: (event: TouchEvent | MouseEvent) => void;
14+
protected _pointerMove: (event: TouchEvent | MouseEvent) => void;
15+
protected _pointerUp: (event: TouchEvent | MouseEvent) => void;
1216
_previewTemplate: CdkDragPreview;
1317
boundaryElementSelector: string;
1418
data: T;
@@ -26,7 +30,11 @@ export declare class CdkDrag<T = any> implements AfterViewInit, OnDestroy {
2630
constructor(
2731
element: ElementRef<HTMLElement>,
2832
dropContainer: CdkDropListContainer, document: any, _ngZone: NgZone, _viewContainerRef: ViewContainerRef, _viewportRuler: ViewportRuler, _dragDropRegistry: DragDropRegistry<CdkDrag<T>, CdkDropListContainer>, _config: CdkDragConfig, _dir: Directionality);
33+
protected _getChildHandles(): CdkDragHandle[];
34+
protected _getRootElement(): HTMLElement;
35+
protected _initializeDragSequence(referenceElement: HTMLElement, event: MouseEvent | TouchEvent): void;
2936
_isDragging(): boolean;
37+
protected _startDragSequence(event: MouseEvent | TouchEvent): void;
3038
getPlaceholderElement(): HTMLElement;
3139
getRootElement(): HTMLElement;
3240
ngAfterViewInit(): void;
@@ -106,8 +114,10 @@ export interface CdkDragStart<T = any> {
106114
}
107115

108116
export declare class CdkDropList<T = any> implements OnInit, OnDestroy {
117+
protected _activeDraggables: CdkDrag[];
109118
_draggables: QueryList<CdkDrag>;
110119
_dragging: boolean;
120+
protected _positionCache: PositionCache;
111121
connectedTo: (CdkDropList | string)[] | CdkDropList | string;
112122
data: T;
113123
disabled: boolean;
@@ -121,8 +131,17 @@ export declare class CdkDropList<T = any> implements OnInit, OnDestroy {
121131
orientation: 'horizontal' | 'vertical';
122132
sorted: EventEmitter<CdkDragSortEvent<T>>;
123133
constructor(element: ElementRef<HTMLElement>, _dragDropRegistry: DragDropRegistry<CdkDrag, CdkDropList<T>>, _changeDetectorRef: ChangeDetectorRef, _dir?: Directionality | undefined, _group?: CdkDropListGroup<CdkDropList<any>> | undefined, _document?: any);
134+
protected _getConnectedLists(): CdkDropList[];
135+
protected _getItemIndexFromPointerPosition(item: CdkDrag, pointerX: number, pointerY: number, delta?: {
136+
x: number;
137+
y: number;
138+
}): number;
139+
protected _getItemOffsetPx(currentPosition: ClientRect, newPosition: ClientRect, delta: 1 | -1): number;
124140
_getSiblingContainerFromPosition(item: CdkDrag, x: number, y: number): CdkDropList | null;
141+
protected _getSiblingOffsetPx(currentIndex: number, siblings: ItemPositionCacheEntry[], delta: 1 | -1): number;
125142
_isOverContainer(x: number, y: number): boolean;
143+
protected _isPointerNearDropContainer(pointerX: number, pointerY: number): boolean;
144+
protected _reset(): void;
126145
_sortItem(item: CdkDrag, pointerX: number, pointerY: number, pointerDelta: {
127146
x: number;
128147
y: number;

0 commit comments

Comments
 (0)