@angular/cdk 7.1.1 → 7.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/_a11y.scss +1 -1
- package/a11y/typings/focus-monitor/focus-monitor.d.ts +0 -1
- package/a11y/typings/focus-trap/focus-trap.d.ts +2 -0
- package/a11y/typings/index.metadata.json +1 -1
- package/bundles/cdk-a11y.umd.js +30 -24
- package/bundles/cdk-a11y.umd.js.map +1 -1
- package/bundles/cdk-a11y.umd.min.js +1 -1
- package/bundles/cdk-a11y.umd.min.js.map +1 -1
- package/bundles/cdk-coercion.umd.js +20 -4
- package/bundles/cdk-coercion.umd.js.map +1 -1
- package/bundles/cdk-coercion.umd.min.js +1 -1
- package/bundles/cdk-coercion.umd.min.js.map +1 -1
- package/bundles/cdk-drag-drop.umd.js +3246 -1894
- package/bundles/cdk-drag-drop.umd.js.map +1 -1
- package/bundles/cdk-drag-drop.umd.min.js +2 -1
- package/bundles/cdk-drag-drop.umd.min.js.map +1 -1
- package/bundles/cdk-observers.umd.js +2 -2
- package/bundles/cdk-observers.umd.js.map +1 -1
- package/bundles/cdk-observers.umd.min.js +1 -1
- package/bundles/cdk-observers.umd.min.js.map +1 -1
- package/bundles/cdk-overlay.umd.js +107 -45
- package/bundles/cdk-overlay.umd.js.map +1 -1
- package/bundles/cdk-overlay.umd.min.js +2 -2
- package/bundles/cdk-overlay.umd.min.js.map +1 -1
- package/bundles/cdk-portal.umd.js +3 -3
- package/bundles/cdk-portal.umd.js.map +1 -1
- package/bundles/cdk-portal.umd.min.js.map +1 -1
- package/bundles/cdk-scrolling.umd.js +9 -6
- package/bundles/cdk-scrolling.umd.js.map +1 -1
- package/bundles/cdk-scrolling.umd.min.js +1 -1
- package/bundles/cdk-scrolling.umd.min.js.map +1 -1
- package/bundles/cdk-stepper.umd.js +36 -16
- package/bundles/cdk-stepper.umd.js.map +1 -1
- package/bundles/cdk-stepper.umd.min.js +1 -1
- package/bundles/cdk-stepper.umd.min.js.map +1 -1
- package/bundles/cdk-table.umd.js +8 -4
- package/bundles/cdk-table.umd.js.map +1 -1
- package/bundles/cdk-table.umd.min.js +1 -1
- package/bundles/cdk-table.umd.min.js.map +1 -1
- package/bundles/cdk-text-field.umd.js +47 -22
- package/bundles/cdk-text-field.umd.js.map +1 -1
- package/bundles/cdk-text-field.umd.min.js +1 -1
- package/bundles/cdk-text-field.umd.min.js.map +1 -1
- package/bundles/cdk-tree.umd.js +1 -1
- package/bundles/cdk-tree.umd.js.map +1 -1
- package/bundles/cdk-tree.umd.min.js +1 -1
- package/bundles/cdk-tree.umd.min.js.map +1 -1
- package/bundles/cdk.umd.js +1 -1
- package/bundles/cdk.umd.js.map +1 -1
- package/bundles/cdk.umd.min.js +1 -1
- package/bundles/cdk.umd.min.js.map +1 -1
- package/coercion/typings/element.d.ts +13 -0
- package/coercion/typings/index.metadata.json +1 -1
- package/coercion/typings/public-api.d.ts +1 -0
- package/drag-drop/typings/{drag-handle.d.ts → directives/drag-handle.d.ts} +6 -2
- package/drag-drop/typings/{drag-placeholder.d.ts → directives/drag-placeholder.d.ts} +0 -0
- package/drag-drop/typings/{drag-preview.d.ts → directives/drag-preview.d.ts} +0 -0
- package/drag-drop/typings/directives/drag.d.ts +114 -0
- package/{typings/esm5/drag-drop → drag-drop/typings/directives}/drop-list-group.d.ts +3 -0
- package/drag-drop/typings/{drop-list.d.ts → directives/drop-list.d.ts} +44 -70
- package/drag-drop/typings/drag-drop-registry.d.ts +8 -3
- package/drag-drop/typings/drag-drop.d.ts +33 -0
- package/drag-drop/typings/drag-events.d.ts +14 -7
- package/{typings/esm5/drag-drop/drag.d.ts → drag-drop/typings/drag-ref.d.ts} +162 -86
- package/drag-drop/typings/drop-list-container.d.ts +19 -3
- package/drag-drop/typings/drop-list-ref.d.ts +238 -0
- package/drag-drop/typings/index.d.ts +2 -1
- package/drag-drop/typings/index.metadata.json +1 -1
- package/drag-drop/typings/public-api.d.ts +16 -6
- package/esm2015/a11y.js +30 -20
- package/esm2015/a11y.js.map +1 -1
- package/esm2015/cdk.js +1 -1
- package/esm2015/cdk.js.map +1 -1
- package/esm2015/coercion.js +18 -1
- package/esm2015/coercion.js.map +1 -1
- package/esm2015/drag-drop.js +2281 -1289
- package/esm2015/drag-drop.js.map +1 -1
- package/esm2015/observers.js +3 -3
- package/esm2015/observers.js.map +1 -1
- package/esm2015/overlay.js +75 -31
- package/esm2015/overlay.js.map +1 -1
- package/esm2015/portal.js +1 -1
- package/esm2015/portal.js.map +1 -1
- package/esm2015/scrolling.js +9 -6
- package/esm2015/scrolling.js.map +1 -1
- package/esm2015/stepper.js +30 -16
- package/esm2015/stepper.js.map +1 -1
- package/esm2015/table.js +8 -4
- package/esm2015/table.js.map +1 -1
- package/esm2015/text-field.js +31 -19
- package/esm2015/text-field.js.map +1 -1
- package/esm2015/tree.js +2 -2
- package/esm2015/tree.js.map +1 -1
- package/esm5/a11y.es5.js +31 -25
- package/esm5/a11y.es5.js.map +1 -1
- package/esm5/cdk.es5.js +1 -1
- package/esm5/cdk.es5.js.map +1 -1
- package/esm5/coercion.es5.js +18 -1
- package/esm5/coercion.es5.js.map +1 -1
- package/esm5/drag-drop.es5.js +3247 -1899
- package/esm5/drag-drop.es5.js.map +1 -1
- package/esm5/observers.es5.js +3 -3
- package/esm5/observers.es5.js.map +1 -1
- package/esm5/overlay.es5.js +107 -45
- package/esm5/overlay.es5.js.map +1 -1
- package/esm5/portal.es5.js +3 -3
- package/esm5/portal.es5.js.map +1 -1
- package/esm5/scrolling.es5.js +9 -6
- package/esm5/scrolling.es5.js.map +1 -1
- package/esm5/stepper.es5.js +36 -17
- package/esm5/stepper.es5.js.map +1 -1
- package/esm5/table.es5.js +8 -4
- package/esm5/table.es5.js.map +1 -1
- package/esm5/text-field.es5.js +44 -19
- package/esm5/text-field.es5.js.map +1 -1
- package/esm5/tree.es5.js +2 -2
- package/esm5/tree.es5.js.map +1 -1
- package/overlay/typings/index.metadata.json +1 -1
- package/overlay/typings/overlay-directives.d.ts +0 -2
- package/overlay/typings/overlay-ref.d.ts +5 -1
- package/overlay/typings/position/flexible-connected-position-strategy.d.ts +17 -4
- package/overlay/typings/position/overlay-position-builder.d.ts +3 -3
- package/package.json +4 -4
- package/portal/typings/portal.d.ts +1 -1
- package/schematics/migration.json +5 -0
- package/schematics/ng-generate/drag-drop/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.component.ts +2 -2
- package/schematics/ng-update/index.d.ts +2 -0
- package/schematics/ng-update/index.js +5 -0
- package/schematics/ng-update/index.js.map +1 -1
- package/schematics/ng-update/target-version.d.ts +7 -1
- package/schematics/ng-update/target-version.js +10 -0
- package/schematics/ng-update/target-version.js.map +1 -1
- package/schematics/ng-update/upgrade-data.js +2 -1
- package/schematics/ng-update/upgrade-data.js.map +1 -1
- package/schematics/ng-update/upgrade-rules/index.js +3 -2
- package/schematics/ng-update/upgrade-rules/index.js.map +1 -1
- package/schematics/utils/ast/ng-module-imports.d.ts +1 -1
- package/schematics/utils/ast/ng-module-imports.js +25 -13
- package/schematics/utils/ast/ng-module-imports.js.map +1 -1
- package/schematics/utils/get-project.js +2 -1
- package/schematics/utils/get-project.js.map +1 -1
- package/schematics/utils/parse5-element.js +3 -2
- package/schematics/utils/parse5-element.js.map +1 -1
- package/schematics/utils/project-targets.js +2 -1
- package/schematics/utils/project-targets.js.map +1 -1
- package/schematics/utils/version-agnostic-typescript.js +3 -2
- package/schematics/utils/version-agnostic-typescript.js.map +1 -1
- package/stepper/typings/index.metadata.json +1 -1
- package/stepper/typings/stepper.d.ts +14 -2
- package/text-field/typings/autosize.d.ts +6 -0
- package/text-field/typings/index.metadata.json +1 -1
- package/tree/typings/control/base-tree-control.d.ts +1 -1
- package/tree/typings/control/nested-tree-control.d.ts +2 -2
- package/tree/typings/control/tree-control.d.ts +1 -1
- package/typings/a11y/focus-monitor/focus-monitor.d.ts +0 -1
- package/typings/a11y/focus-trap/focus-trap.d.ts +2 -0
- package/typings/a11y/index.metadata.json +1 -1
- package/typings/coercion/element.d.ts +13 -0
- package/typings/coercion/index.metadata.json +1 -1
- package/typings/coercion/public-api.d.ts +1 -0
- package/typings/drag-drop/{drag-handle.d.ts → directives/drag-handle.d.ts} +6 -2
- package/typings/drag-drop/{drag-placeholder.d.ts → directives/drag-placeholder.d.ts} +0 -0
- package/typings/drag-drop/{drag-preview.d.ts → directives/drag-preview.d.ts} +0 -0
- package/typings/drag-drop/directives/drag.d.ts +114 -0
- package/typings/drag-drop/{drop-list-group.d.ts → directives/drop-list-group.d.ts} +3 -0
- package/typings/{esm5/drag-drop → drag-drop/directives}/drop-list.d.ts +44 -70
- package/typings/drag-drop/drag-drop-registry.d.ts +8 -3
- package/typings/drag-drop/drag-drop.d.ts +33 -0
- package/typings/drag-drop/drag-events.d.ts +14 -7
- package/typings/drag-drop/{drag.d.ts → drag-ref.d.ts} +162 -86
- package/typings/drag-drop/drop-list-container.d.ts +19 -3
- package/typings/drag-drop/drop-list-ref.d.ts +238 -0
- package/typings/drag-drop/index.d.ts +2 -1
- package/typings/drag-drop/index.metadata.json +1 -1
- package/typings/drag-drop/public-api.d.ts +16 -6
- package/typings/esm5/a11y/focus-monitor/focus-monitor.d.ts +0 -1
- package/typings/esm5/a11y/focus-trap/focus-trap.d.ts +2 -0
- package/typings/esm5/a11y/index.metadata.json +1 -1
- package/typings/esm5/coercion/element.d.ts +13 -0
- package/typings/esm5/coercion/index.metadata.json +1 -1
- package/typings/esm5/coercion/public-api.d.ts +1 -0
- package/typings/esm5/drag-drop/{drag-handle.d.ts → directives/drag-handle.d.ts} +6 -2
- package/typings/esm5/drag-drop/{drag-placeholder.d.ts → directives/drag-placeholder.d.ts} +0 -0
- package/typings/esm5/drag-drop/{drag-preview.d.ts → directives/drag-preview.d.ts} +0 -0
- package/typings/esm5/drag-drop/directives/drag.d.ts +114 -0
- package/{drag-drop/typings → typings/esm5/drag-drop/directives}/drop-list-group.d.ts +3 -0
- package/typings/{drag-drop → esm5/drag-drop/directives}/drop-list.d.ts +44 -70
- package/typings/esm5/drag-drop/drag-drop-registry.d.ts +8 -3
- package/typings/esm5/drag-drop/drag-drop.d.ts +33 -0
- package/typings/esm5/drag-drop/drag-events.d.ts +14 -7
- package/{drag-drop/typings/drag.d.ts → typings/esm5/drag-drop/drag-ref.d.ts} +162 -86
- package/typings/esm5/drag-drop/drop-list-container.d.ts +19 -3
- package/typings/esm5/drag-drop/drop-list-ref.d.ts +238 -0
- package/typings/esm5/drag-drop/index.d.ts +2 -1
- package/typings/esm5/drag-drop/index.metadata.json +1 -1
- package/typings/esm5/drag-drop/public-api.d.ts +16 -6
- package/typings/esm5/index.metadata.json +1 -1
- package/typings/esm5/overlay/index.metadata.json +1 -1
- package/typings/esm5/overlay/overlay-directives.d.ts +0 -2
- package/typings/esm5/overlay/overlay-ref.d.ts +5 -1
- package/typings/esm5/overlay/position/flexible-connected-position-strategy.d.ts +17 -4
- package/typings/esm5/overlay/position/overlay-position-builder.d.ts +3 -3
- package/typings/esm5/portal/portal.d.ts +1 -1
- package/typings/esm5/stepper/index.metadata.json +1 -1
- package/typings/esm5/stepper/stepper.d.ts +14 -2
- package/typings/esm5/text-field/autosize.d.ts +6 -0
- package/typings/esm5/text-field/index.metadata.json +1 -1
- package/typings/esm5/tree/control/base-tree-control.d.ts +1 -1
- package/typings/esm5/tree/control/nested-tree-control.d.ts +2 -2
- package/typings/esm5/tree/control/tree-control.d.ts +1 -1
- package/typings/index.metadata.json +1 -1
- package/typings/overlay/index.metadata.json +1 -1
- package/typings/overlay/overlay-directives.d.ts +0 -2
- package/typings/overlay/overlay-ref.d.ts +5 -1
- package/typings/overlay/position/flexible-connected-position-strategy.d.ts +17 -4
- package/typings/overlay/position/overlay-position-builder.d.ts +3 -3
- package/typings/portal/portal.d.ts +1 -1
- package/typings/schematics/ng-update/index.d.ts +2 -0
- package/typings/schematics/ng-update/target-version.d.ts +7 -1
- package/typings/schematics/utils/ast/ng-module-imports.d.ts +1 -1
- package/typings/stepper/index.metadata.json +1 -1
- package/typings/stepper/stepper.d.ts +14 -2
- package/typings/text-field/autosize.d.ts +6 -0
- package/typings/text-field/index.metadata.json +1 -1
- package/typings/tree/control/base-tree-control.d.ts +1 -1
- package/typings/tree/control/nested-tree-control.d.ts +2 -2
- package/typings/tree/control/tree-control.d.ts +1 -1
package/esm2015/drag-drop.js
CHANGED
|
@@ -5,243 +5,14 @@
|
|
|
5
5
|
* Use of this source code is governed by an MIT-style license that can be
|
|
6
6
|
* found in the LICENSE file at https://angular.io/license
|
|
7
7
|
*/
|
|
8
|
-
import { Injectable, NgZone, Inject, ContentChildren, ElementRef, EventEmitter, forwardRef, Input, Output, Optional, Directive, ChangeDetectorRef, SkipSelf, ContentChild, InjectionToken, ViewContainerRef, TemplateRef, NgModule, defineInjectable, inject } from '@angular/core';
|
|
9
|
-
import { DOCUMENT } from '@angular/common';
|
|
10
8
|
import { normalizePassiveListenerOptions } from '@angular/cdk/platform';
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
9
|
+
import { coerceBooleanProperty, coerceElement, coerceArray } from '@angular/cdk/coercion';
|
|
10
|
+
import { Subscription, Subject, Observable, merge } from 'rxjs';
|
|
11
|
+
import { ElementRef, Injectable, NgZone, Inject, InjectionToken, NgModule, ContentChildren, EventEmitter, forwardRef, Input, Output, Optional, Directive, ChangeDetectorRef, SkipSelf, ContentChild, ViewContainerRef, TemplateRef, defineInjectable, inject } from '@angular/core';
|
|
12
|
+
import { DOCUMENT } from '@angular/common';
|
|
14
13
|
import { ViewportRuler } from '@angular/cdk/scrolling';
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* @fileoverview added by tsickle
|
|
19
|
-
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
20
|
-
*/
|
|
21
|
-
/**
|
|
22
|
-
* Event options that can be used to bind an active, capturing event.
|
|
23
|
-
* @type {?}
|
|
24
|
-
*/
|
|
25
|
-
const activeCapturingEventOptions = normalizePassiveListenerOptions({
|
|
26
|
-
passive: false,
|
|
27
|
-
capture: true
|
|
28
|
-
});
|
|
29
|
-
/**
|
|
30
|
-
* Service that keeps track of all the drag item and drop container
|
|
31
|
-
* instances, and manages global event listeners on the `document`.
|
|
32
|
-
* \@docs-private
|
|
33
|
-
* @template I, C
|
|
34
|
-
*/
|
|
35
|
-
// Note: this class is generic, rather than referencing CdkDrag and CdkDropList directly, in order
|
|
36
|
-
// to avoid circular imports. If we were to reference them here, importing the registry into the
|
|
37
|
-
// classes that are registering themselves will introduce a circular import.
|
|
38
|
-
class DragDropRegistry {
|
|
39
|
-
/**
|
|
40
|
-
* @param {?} _ngZone
|
|
41
|
-
* @param {?} _document
|
|
42
|
-
*/
|
|
43
|
-
constructor(_ngZone, _document) {
|
|
44
|
-
this._ngZone = _ngZone;
|
|
45
|
-
/**
|
|
46
|
-
* Registered drop container instances.
|
|
47
|
-
*/
|
|
48
|
-
this._dropInstances = new Set();
|
|
49
|
-
/**
|
|
50
|
-
* Registered drag item instances.
|
|
51
|
-
*/
|
|
52
|
-
this._dragInstances = new Set();
|
|
53
|
-
/**
|
|
54
|
-
* Drag item instances that are currently being dragged.
|
|
55
|
-
*/
|
|
56
|
-
this._activeDragInstances = new Set();
|
|
57
|
-
/**
|
|
58
|
-
* Keeps track of the event listeners that we've bound to the `document`.
|
|
59
|
-
*/
|
|
60
|
-
this._globalListeners = new Map();
|
|
61
|
-
/**
|
|
62
|
-
* Emits the `touchmove` or `mousemove` events that are dispatched
|
|
63
|
-
* while the user is dragging a drag item instance.
|
|
64
|
-
*/
|
|
65
|
-
this.pointerMove = new Subject();
|
|
66
|
-
/**
|
|
67
|
-
* Emits the `touchend` or `mouseup` events that are dispatched
|
|
68
|
-
* while the user is dragging a drag item instance.
|
|
69
|
-
*/
|
|
70
|
-
this.pointerUp = new Subject();
|
|
71
|
-
/**
|
|
72
|
-
* Listener used to prevent `touchmove` and `wheel` events while the element is being dragged.
|
|
73
|
-
*/
|
|
74
|
-
this._preventScrollListener = (event) => {
|
|
75
|
-
if (this._activeDragInstances.size) {
|
|
76
|
-
event.preventDefault();
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
this._document = _document;
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Adds a drop container to the registry.
|
|
83
|
-
* @param {?} drop
|
|
84
|
-
* @return {?}
|
|
85
|
-
*/
|
|
86
|
-
registerDropContainer(drop) {
|
|
87
|
-
if (!this._dropInstances.has(drop)) {
|
|
88
|
-
if (this.getDropContainer(drop.id)) {
|
|
89
|
-
throw Error(`Drop instance with id "${drop.id}" has already been registered.`);
|
|
90
|
-
}
|
|
91
|
-
this._dropInstances.add(drop);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Adds a drag item instance to the registry.
|
|
96
|
-
* @param {?} drag
|
|
97
|
-
* @return {?}
|
|
98
|
-
*/
|
|
99
|
-
registerDragItem(drag) {
|
|
100
|
-
this._dragInstances.add(drag);
|
|
101
|
-
// The `touchmove` event gets bound once, ahead of time, because WebKit
|
|
102
|
-
// won't preventDefault on a dynamically-added `touchmove` listener.
|
|
103
|
-
// See https://bugs.webkit.org/show_bug.cgi?id=184250.
|
|
104
|
-
if (this._dragInstances.size === 1) {
|
|
105
|
-
this._ngZone.runOutsideAngular(() => {
|
|
106
|
-
// The event handler has to be explicitly active,
|
|
107
|
-
// because newer browsers make it passive by default.
|
|
108
|
-
this._document.addEventListener('touchmove', this._preventScrollListener, activeCapturingEventOptions);
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* Removes a drop container from the registry.
|
|
114
|
-
* @param {?} drop
|
|
115
|
-
* @return {?}
|
|
116
|
-
*/
|
|
117
|
-
removeDropContainer(drop) {
|
|
118
|
-
this._dropInstances.delete(drop);
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* Removes a drag item instance from the registry.
|
|
122
|
-
* @param {?} drag
|
|
123
|
-
* @return {?}
|
|
124
|
-
*/
|
|
125
|
-
removeDragItem(drag) {
|
|
126
|
-
this._dragInstances.delete(drag);
|
|
127
|
-
this.stopDragging(drag);
|
|
128
|
-
if (this._dragInstances.size === 0) {
|
|
129
|
-
this._document.removeEventListener('touchmove', this._preventScrollListener, activeCapturingEventOptions);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* Starts the dragging sequence for a drag instance.
|
|
134
|
-
* @param {?} drag Drag instance which is being dragged.
|
|
135
|
-
* @param {?} event Event that initiated the dragging.
|
|
136
|
-
* @return {?}
|
|
137
|
-
*/
|
|
138
|
-
startDragging(drag, event) {
|
|
139
|
-
this._activeDragInstances.add(drag);
|
|
140
|
-
if (this._activeDragInstances.size === 1) {
|
|
141
|
-
/** @type {?} */
|
|
142
|
-
const isTouchEvent = event.type.startsWith('touch');
|
|
143
|
-
/** @type {?} */
|
|
144
|
-
const moveEvent = isTouchEvent ? 'touchmove' : 'mousemove';
|
|
145
|
-
/** @type {?} */
|
|
146
|
-
const upEvent = isTouchEvent ? 'touchend' : 'mouseup';
|
|
147
|
-
// We explicitly bind __active__ listeners here, because newer browsers will default to
|
|
148
|
-
// passive ones for `mousemove` and `touchmove`. The events need to be active, because we
|
|
149
|
-
// use `preventDefault` to prevent the page from scrolling while the user is dragging.
|
|
150
|
-
this._globalListeners
|
|
151
|
-
.set(moveEvent, {
|
|
152
|
-
handler: e => this.pointerMove.next(e),
|
|
153
|
-
options: activeCapturingEventOptions
|
|
154
|
-
})
|
|
155
|
-
.set(upEvent, {
|
|
156
|
-
handler: e => this.pointerUp.next(e),
|
|
157
|
-
options: true
|
|
158
|
-
});
|
|
159
|
-
// TODO(crisbeto): prevent mouse wheel scrolling while
|
|
160
|
-
// dragging until we've set up proper scroll handling.
|
|
161
|
-
if (!isTouchEvent) {
|
|
162
|
-
this._globalListeners.set('wheel', {
|
|
163
|
-
handler: this._preventScrollListener,
|
|
164
|
-
options: activeCapturingEventOptions
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
this._ngZone.runOutsideAngular(() => {
|
|
168
|
-
this._globalListeners.forEach((config, name) => {
|
|
169
|
-
this._document.addEventListener(name, config.handler, config.options);
|
|
170
|
-
});
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
/**
|
|
175
|
-
* Stops dragging a drag item instance.
|
|
176
|
-
* @param {?} drag
|
|
177
|
-
* @return {?}
|
|
178
|
-
*/
|
|
179
|
-
stopDragging(drag) {
|
|
180
|
-
this._activeDragInstances.delete(drag);
|
|
181
|
-
if (this._activeDragInstances.size === 0) {
|
|
182
|
-
this._clearGlobalListeners();
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
/**
|
|
186
|
-
* Gets whether a drag item instance is currently being dragged.
|
|
187
|
-
* @param {?} drag
|
|
188
|
-
* @return {?}
|
|
189
|
-
*/
|
|
190
|
-
isDragging(drag) {
|
|
191
|
-
return this._activeDragInstances.has(drag);
|
|
192
|
-
}
|
|
193
|
-
/**
|
|
194
|
-
* Gets a drop container by its id.
|
|
195
|
-
* @param {?} id
|
|
196
|
-
* @return {?}
|
|
197
|
-
*/
|
|
198
|
-
getDropContainer(id) {
|
|
199
|
-
return Array.from(this._dropInstances).find(instance => instance.id === id);
|
|
200
|
-
}
|
|
201
|
-
/**
|
|
202
|
-
* @return {?}
|
|
203
|
-
*/
|
|
204
|
-
ngOnDestroy() {
|
|
205
|
-
this._dragInstances.forEach(instance => this.removeDragItem(instance));
|
|
206
|
-
this._dropInstances.forEach(instance => this.removeDropContainer(instance));
|
|
207
|
-
this._clearGlobalListeners();
|
|
208
|
-
this.pointerMove.complete();
|
|
209
|
-
this.pointerUp.complete();
|
|
210
|
-
}
|
|
211
|
-
/**
|
|
212
|
-
* Clears out the global event listeners from the `document`.
|
|
213
|
-
* @private
|
|
214
|
-
* @return {?}
|
|
215
|
-
*/
|
|
216
|
-
_clearGlobalListeners() {
|
|
217
|
-
this._globalListeners.forEach((config, name) => {
|
|
218
|
-
this._document.removeEventListener(name, config.handler, config.options);
|
|
219
|
-
});
|
|
220
|
-
this._globalListeners.clear();
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
DragDropRegistry.decorators = [
|
|
224
|
-
{ type: Injectable, args: [{ providedIn: 'root' },] },
|
|
225
|
-
];
|
|
226
|
-
/** @nocollapse */
|
|
227
|
-
DragDropRegistry.ctorParameters = () => [
|
|
228
|
-
{ type: NgZone },
|
|
229
|
-
{ type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] }
|
|
230
|
-
];
|
|
231
|
-
/** @nocollapse */ DragDropRegistry.ngInjectableDef = defineInjectable({ factory: function DragDropRegistry_Factory() { return new DragDropRegistry(inject(NgZone), inject(DOCUMENT)); }, token: DragDropRegistry, providedIn: "root" });
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* @fileoverview added by tsickle
|
|
235
|
-
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
236
|
-
*/
|
|
237
|
-
/**
|
|
238
|
-
* Injection token that can be used for a `CdkDrag` to provide itself as a parent to the
|
|
239
|
-
* drag-specific child directive (`CdkDragHandle`, `CdkDragPreview` etc.). Used primarily
|
|
240
|
-
* to avoid circular imports.
|
|
241
|
-
* \@docs-private
|
|
242
|
-
* @type {?}
|
|
243
|
-
*/
|
|
244
|
-
const CDK_DRAG_PARENT = new InjectionToken('CDK_DRAG_PARENT');
|
|
14
|
+
import { Directionality } from '@angular/cdk/bidi';
|
|
15
|
+
import { startWith, take, map, takeUntil, switchMap, tap } from 'rxjs/operators';
|
|
245
16
|
|
|
246
17
|
/**
|
|
247
18
|
* @fileoverview added by tsickle
|
|
@@ -287,130 +58,11 @@ function toggleNativeDragInteractions(element, enable) {
|
|
|
287
58
|
* @fileoverview added by tsickle
|
|
288
59
|
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
289
60
|
*/
|
|
61
|
+
|
|
290
62
|
/**
|
|
291
|
-
*
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* @param {?} element
|
|
296
|
-
* @param {?=} parentDrag
|
|
297
|
-
*/
|
|
298
|
-
constructor(element, parentDrag) {
|
|
299
|
-
this.element = element;
|
|
300
|
-
this._disabled = false;
|
|
301
|
-
this._parentDrag = parentDrag;
|
|
302
|
-
toggleNativeDragInteractions(element.nativeElement, false);
|
|
303
|
-
}
|
|
304
|
-
/**
|
|
305
|
-
* Whether starting to drag through this handle is disabled.
|
|
306
|
-
* @return {?}
|
|
307
|
-
*/
|
|
308
|
-
get disabled() { return this._disabled; }
|
|
309
|
-
/**
|
|
310
|
-
* @param {?} value
|
|
311
|
-
* @return {?}
|
|
312
|
-
*/
|
|
313
|
-
set disabled(value) {
|
|
314
|
-
this._disabled = coerceBooleanProperty(value);
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
CdkDragHandle.decorators = [
|
|
318
|
-
{ type: Directive, args: [{
|
|
319
|
-
selector: '[cdkDragHandle]',
|
|
320
|
-
host: {
|
|
321
|
-
'class': 'cdk-drag-handle'
|
|
322
|
-
}
|
|
323
|
-
},] },
|
|
324
|
-
];
|
|
325
|
-
/** @nocollapse */
|
|
326
|
-
CdkDragHandle.ctorParameters = () => [
|
|
327
|
-
{ type: ElementRef },
|
|
328
|
-
{ type: undefined, decorators: [{ type: Inject, args: [CDK_DRAG_PARENT,] }, { type: Optional }] }
|
|
329
|
-
];
|
|
330
|
-
CdkDragHandle.propDecorators = {
|
|
331
|
-
disabled: [{ type: Input, args: ['cdkDragHandleDisabled',] }]
|
|
332
|
-
};
|
|
333
|
-
|
|
334
|
-
/**
|
|
335
|
-
* @fileoverview added by tsickle
|
|
336
|
-
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
337
|
-
*/
|
|
338
|
-
/**
|
|
339
|
-
* Element that will be used as a template for the placeholder of a CdkDrag when
|
|
340
|
-
* it is being dragged. The placeholder is displayed in place of the element being dragged.
|
|
341
|
-
* @template T
|
|
342
|
-
*/
|
|
343
|
-
class CdkDragPlaceholder {
|
|
344
|
-
/**
|
|
345
|
-
* @param {?} templateRef
|
|
346
|
-
*/
|
|
347
|
-
constructor(templateRef) {
|
|
348
|
-
this.templateRef = templateRef;
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
CdkDragPlaceholder.decorators = [
|
|
352
|
-
{ type: Directive, args: [{
|
|
353
|
-
selector: 'ng-template[cdkDragPlaceholder]'
|
|
354
|
-
},] },
|
|
355
|
-
];
|
|
356
|
-
/** @nocollapse */
|
|
357
|
-
CdkDragPlaceholder.ctorParameters = () => [
|
|
358
|
-
{ type: TemplateRef }
|
|
359
|
-
];
|
|
360
|
-
CdkDragPlaceholder.propDecorators = {
|
|
361
|
-
data: [{ type: Input }]
|
|
362
|
-
};
|
|
363
|
-
|
|
364
|
-
/**
|
|
365
|
-
* @fileoverview added by tsickle
|
|
366
|
-
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
367
|
-
*/
|
|
368
|
-
/**
|
|
369
|
-
* Element that will be used as a template for the preview
|
|
370
|
-
* of a CdkDrag when it is being dragged.
|
|
371
|
-
* @template T
|
|
372
|
-
*/
|
|
373
|
-
class CdkDragPreview {
|
|
374
|
-
/**
|
|
375
|
-
* @param {?} templateRef
|
|
376
|
-
*/
|
|
377
|
-
constructor(templateRef) {
|
|
378
|
-
this.templateRef = templateRef;
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
CdkDragPreview.decorators = [
|
|
382
|
-
{ type: Directive, args: [{
|
|
383
|
-
selector: 'ng-template[cdkDragPreview]'
|
|
384
|
-
},] },
|
|
385
|
-
];
|
|
386
|
-
/** @nocollapse */
|
|
387
|
-
CdkDragPreview.ctorParameters = () => [
|
|
388
|
-
{ type: TemplateRef }
|
|
389
|
-
];
|
|
390
|
-
CdkDragPreview.propDecorators = {
|
|
391
|
-
data: [{ type: Input }]
|
|
392
|
-
};
|
|
393
|
-
|
|
394
|
-
/**
|
|
395
|
-
* @fileoverview added by tsickle
|
|
396
|
-
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
397
|
-
*/
|
|
398
|
-
/**
|
|
399
|
-
* Injection token that is used to provide a CdkDropList instance to CdkDrag.
|
|
400
|
-
* Used for avoiding circular imports.
|
|
401
|
-
* @type {?}
|
|
402
|
-
*/
|
|
403
|
-
const CDK_DROP_LIST_CONTAINER = new InjectionToken('CDK_DROP_LIST_CONTAINER');
|
|
404
|
-
|
|
405
|
-
/**
|
|
406
|
-
* @fileoverview added by tsickle
|
|
407
|
-
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
408
|
-
*/
|
|
409
|
-
|
|
410
|
-
/**
|
|
411
|
-
* Parses a CSS time value to milliseconds.
|
|
412
|
-
* @param {?} value
|
|
413
|
-
* @return {?}
|
|
63
|
+
* Parses a CSS time value to milliseconds.
|
|
64
|
+
* @param {?} value
|
|
65
|
+
* @return {?}
|
|
414
66
|
*/
|
|
415
67
|
function parseCssTimeUnitsToMs(value) {
|
|
416
68
|
// Some browsers will return it in seconds, whereas others will return milliseconds.
|
|
@@ -461,21 +113,6 @@ function parseCssPropertyValue(computedStyle, name) {
|
|
|
461
113
|
* @fileoverview added by tsickle
|
|
462
114
|
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
463
115
|
*/
|
|
464
|
-
/**
|
|
465
|
-
* Injection token that can be used to configure the behavior of `CdkDrag`.
|
|
466
|
-
* @type {?}
|
|
467
|
-
*/
|
|
468
|
-
const CDK_DRAG_CONFIG = new InjectionToken('CDK_DRAG_CONFIG', {
|
|
469
|
-
providedIn: 'root',
|
|
470
|
-
factory: CDK_DRAG_CONFIG_FACTORY
|
|
471
|
-
});
|
|
472
|
-
/**
|
|
473
|
-
* \@docs-private
|
|
474
|
-
* @return {?}
|
|
475
|
-
*/
|
|
476
|
-
function CDK_DRAG_CONFIG_FACTORY() {
|
|
477
|
-
return { dragStartThreshold: 5, pointerDirectionChangeThreshold: 5 };
|
|
478
|
-
}
|
|
479
116
|
/**
|
|
480
117
|
* Options that can be used to bind a passive event listener.
|
|
481
118
|
* @type {?}
|
|
@@ -495,30 +132,25 @@ const activeEventListenerOptions = normalizePassiveListenerOptions({ passive: fa
|
|
|
495
132
|
*/
|
|
496
133
|
const MOUSE_EVENT_IGNORE_TIME = 800;
|
|
497
134
|
/**
|
|
498
|
-
*
|
|
135
|
+
* Reference to a draggable item. Used to manipulate or dispose of the item.
|
|
136
|
+
* \@docs-private
|
|
499
137
|
* @template T
|
|
500
138
|
*/
|
|
501
|
-
class
|
|
139
|
+
class DragRef {
|
|
502
140
|
/**
|
|
503
141
|
* @param {?} element
|
|
504
|
-
* @param {?}
|
|
505
|
-
* @param {?}
|
|
142
|
+
* @param {?} _config
|
|
143
|
+
* @param {?} _document
|
|
506
144
|
* @param {?} _ngZone
|
|
507
|
-
* @param {?} _viewContainerRef
|
|
508
145
|
* @param {?} _viewportRuler
|
|
509
146
|
* @param {?} _dragDropRegistry
|
|
510
|
-
* @param {?} _config
|
|
511
|
-
* @param {?} _dir
|
|
512
147
|
*/
|
|
513
|
-
constructor(element,
|
|
514
|
-
this.
|
|
515
|
-
this.
|
|
148
|
+
constructor(element, _config, _document, _ngZone, _viewportRuler, _dragDropRegistry) {
|
|
149
|
+
this._config = _config;
|
|
150
|
+
this._document = _document;
|
|
516
151
|
this._ngZone = _ngZone;
|
|
517
|
-
this._viewContainerRef = _viewContainerRef;
|
|
518
152
|
this._viewportRuler = _viewportRuler;
|
|
519
153
|
this._dragDropRegistry = _dragDropRegistry;
|
|
520
|
-
this._config = _config;
|
|
521
|
-
this._dir = _dir;
|
|
522
154
|
/**
|
|
523
155
|
* CSS `transform` applied to the element when it isn't being dragged. We need a
|
|
524
156
|
* passive transform in order for the dragged element to retain its new position
|
|
@@ -548,35 +180,59 @@ class CdkDrag {
|
|
|
548
180
|
*/
|
|
549
181
|
this._pointerUpSubscription = Subscription.EMPTY;
|
|
550
182
|
/**
|
|
551
|
-
*
|
|
183
|
+
* Cached reference to the boundary element.
|
|
184
|
+
*/
|
|
185
|
+
this._boundaryElement = null;
|
|
186
|
+
/**
|
|
187
|
+
* Whether the native dragging interactions have been enabled on the root element.
|
|
188
|
+
*/
|
|
189
|
+
this._nativeInteractionsEnabled = true;
|
|
190
|
+
/**
|
|
191
|
+
* Elements that can be used to drag the draggable item.
|
|
192
|
+
*/
|
|
193
|
+
this._handles = [];
|
|
194
|
+
/**
|
|
195
|
+
* Registered handles that are currently disabled.
|
|
196
|
+
*/
|
|
197
|
+
this._disabledHandles = new Set();
|
|
198
|
+
/**
|
|
199
|
+
* Layout direction of the item.
|
|
552
200
|
*/
|
|
553
|
-
this.
|
|
201
|
+
this._direction = 'ltr';
|
|
554
202
|
this._disabled = false;
|
|
203
|
+
/**
|
|
204
|
+
* Emits as the drag sequence is being prepared.
|
|
205
|
+
*/
|
|
206
|
+
this.beforeStarted = new Subject();
|
|
555
207
|
/**
|
|
556
208
|
* Emits when the user starts dragging the item.
|
|
557
209
|
*/
|
|
558
|
-
this.started = new
|
|
210
|
+
this.started = new Subject();
|
|
211
|
+
/**
|
|
212
|
+
* Emits when the user has released a drag item, before any animations have started.
|
|
213
|
+
*/
|
|
214
|
+
this.released = new Subject();
|
|
559
215
|
/**
|
|
560
216
|
* Emits when the user stops dragging an item in the container.
|
|
561
217
|
*/
|
|
562
|
-
this.ended = new
|
|
218
|
+
this.ended = new Subject();
|
|
563
219
|
/**
|
|
564
220
|
* Emits when the user has moved the item into a new container.
|
|
565
221
|
*/
|
|
566
|
-
this.entered = new
|
|
222
|
+
this.entered = new Subject();
|
|
567
223
|
/**
|
|
568
224
|
* Emits when the user removes the item its container by dragging it into another container.
|
|
569
225
|
*/
|
|
570
|
-
this.exited = new
|
|
226
|
+
this.exited = new Subject();
|
|
571
227
|
/**
|
|
572
228
|
* Emits when the user drops the item inside a container.
|
|
573
229
|
*/
|
|
574
|
-
this.dropped = new
|
|
230
|
+
this.dropped = new Subject();
|
|
575
231
|
/**
|
|
576
232
|
* Emits as the user is dragging the item. Use with caution,
|
|
577
233
|
* because this event will fire for every pixel that the user has dragged.
|
|
578
234
|
*/
|
|
579
|
-
this.moved = Observable
|
|
235
|
+
this.moved = new Observable((observer) => {
|
|
580
236
|
/** @type {?} */
|
|
581
237
|
const subscription = this._moveEvents.subscribe(observer);
|
|
582
238
|
this._moveEventSubscriptions++;
|
|
@@ -589,20 +245,17 @@ class CdkDrag {
|
|
|
589
245
|
* Handler for the `mousedown`/`touchstart` events.
|
|
590
246
|
*/
|
|
591
247
|
this._pointerDown = (event) => {
|
|
592
|
-
|
|
593
|
-
const handles = this.getChildHandles();
|
|
248
|
+
this.beforeStarted.next();
|
|
594
249
|
// Delegate the event based on whether it started from a handle or the element itself.
|
|
595
|
-
if (
|
|
250
|
+
if (this._handles.length) {
|
|
596
251
|
/** @type {?} */
|
|
597
|
-
const targetHandle =
|
|
598
|
-
/** @type {?} */
|
|
599
|
-
const element = handle.element.nativeElement;
|
|
252
|
+
const targetHandle = this._handles.find(handle => {
|
|
600
253
|
/** @type {?} */
|
|
601
254
|
const target = event.target;
|
|
602
|
-
return !!target && (target ===
|
|
255
|
+
return !!target && (target === handle || handle.contains((/** @type {?} */ (target))));
|
|
603
256
|
});
|
|
604
|
-
if (targetHandle && !targetHandle
|
|
605
|
-
this._initializeDragSequence(targetHandle
|
|
257
|
+
if (targetHandle && !this._disabledHandles.has(targetHandle) && !this.disabled) {
|
|
258
|
+
this._initializeDragSequence(targetHandle, event);
|
|
606
259
|
}
|
|
607
260
|
}
|
|
608
261
|
else if (!this.disabled) {
|
|
@@ -613,9 +266,9 @@ class CdkDrag {
|
|
|
613
266
|
* Handler that is invoked when the user moves their pointer after they've initiated a drag.
|
|
614
267
|
*/
|
|
615
268
|
this._pointerMove = (event) => {
|
|
616
|
-
/** @type {?} */
|
|
617
|
-
const pointerPosition = this._getConstrainedPointerPosition(event);
|
|
618
269
|
if (!this._hasStartedDragging) {
|
|
270
|
+
/** @type {?} */
|
|
271
|
+
const pointerPosition = this._getPointerPositionOnPage(event);
|
|
619
272
|
/** @type {?} */
|
|
620
273
|
const distanceX = Math.abs(pointerPosition.x - this._pickupPositionOnPage.x);
|
|
621
274
|
/** @type {?} */
|
|
@@ -630,24 +283,36 @@ class CdkDrag {
|
|
|
630
283
|
}
|
|
631
284
|
return;
|
|
632
285
|
}
|
|
286
|
+
// We only need the preview dimensions if we have a boundary element.
|
|
287
|
+
if (this._boundaryElement) {
|
|
288
|
+
// Cache the preview element rect if we haven't cached it already or if
|
|
289
|
+
// we cached it too early before the element dimensions were computed.
|
|
290
|
+
if (!this._previewRect || (!this._previewRect.width && !this._previewRect.height)) {
|
|
291
|
+
this._previewRect = (this._preview || this._rootElement).getBoundingClientRect();
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
/** @type {?} */
|
|
295
|
+
const constrainedPointerPosition = this._getConstrainedPointerPosition(event);
|
|
633
296
|
this._hasMoved = true;
|
|
634
297
|
event.preventDefault();
|
|
635
|
-
this._updatePointerDirectionDelta(
|
|
636
|
-
if (this.
|
|
637
|
-
this._updateActiveDropContainer(
|
|
298
|
+
this._updatePointerDirectionDelta(constrainedPointerPosition);
|
|
299
|
+
if (this._dropContainer) {
|
|
300
|
+
this._updateActiveDropContainer(constrainedPointerPosition);
|
|
638
301
|
}
|
|
639
302
|
else {
|
|
640
303
|
/** @type {?} */
|
|
641
304
|
const activeTransform = this._activeTransform;
|
|
642
305
|
activeTransform.x =
|
|
643
|
-
|
|
306
|
+
constrainedPointerPosition.x - this._pickupPositionOnPage.x + this._passiveTransform.x;
|
|
644
307
|
activeTransform.y =
|
|
645
|
-
|
|
308
|
+
constrainedPointerPosition.y - this._pickupPositionOnPage.y + this._passiveTransform.y;
|
|
646
309
|
/** @type {?} */
|
|
647
310
|
const transform = getTransform(activeTransform.x, activeTransform.y);
|
|
648
|
-
// Preserve the previous `transform` value, if there was one.
|
|
311
|
+
// Preserve the previous `transform` value, if there was one. Note that we apply our own
|
|
312
|
+
// transform before the user's, because things like rotation can affect which direction
|
|
313
|
+
// the element will be translated towards.
|
|
649
314
|
this._rootElement.style.transform = this._initialTransform ?
|
|
650
|
-
|
|
315
|
+
transform + ' ' + this._initialTransform : transform;
|
|
651
316
|
// Apply transform as attribute if dragging and svg element to work for IE
|
|
652
317
|
if (typeof SVGElement !== 'undefined' && this._rootElement instanceof SVGElement) {
|
|
653
318
|
/** @type {?} */
|
|
@@ -662,7 +327,7 @@ class CdkDrag {
|
|
|
662
327
|
this._ngZone.run(() => {
|
|
663
328
|
this._moveEvents.next({
|
|
664
329
|
source: this,
|
|
665
|
-
pointerPosition,
|
|
330
|
+
pointerPosition: constrainedPointerPosition,
|
|
666
331
|
event,
|
|
667
332
|
delta: this._pointerDirectionDelta
|
|
668
333
|
});
|
|
@@ -672,31 +337,39 @@ class CdkDrag {
|
|
|
672
337
|
/**
|
|
673
338
|
* Handler that is invoked when the user lifts their pointer up, after initiating a drag.
|
|
674
339
|
*/
|
|
675
|
-
this._pointerUp = () => {
|
|
676
|
-
|
|
340
|
+
this._pointerUp = (event) => {
|
|
341
|
+
// Note that here we use `isDragging` from the service, rather than from `this`.
|
|
342
|
+
// The difference is that the one from the service reflects whether a dragging sequence
|
|
343
|
+
// has been initiated, whereas the one on `this` includes whether the user has passed
|
|
344
|
+
// the minimum dragging threshold.
|
|
345
|
+
if (!this._dragDropRegistry.isDragging(this)) {
|
|
677
346
|
return;
|
|
678
347
|
}
|
|
679
348
|
this._removeSubscriptions();
|
|
680
349
|
this._dragDropRegistry.stopDragging(this);
|
|
350
|
+
if (this._handles) {
|
|
351
|
+
this._rootElement.style.webkitTapHighlightColor = this._rootElementTapHighlight;
|
|
352
|
+
}
|
|
681
353
|
if (!this._hasStartedDragging) {
|
|
682
354
|
return;
|
|
683
355
|
}
|
|
684
|
-
|
|
356
|
+
this.released.next({ source: this });
|
|
357
|
+
if (!this._dropContainer) {
|
|
685
358
|
// Convert the active transform into a passive one. This means that next time
|
|
686
359
|
// the user starts dragging the item, its position will be calculated relatively
|
|
687
360
|
// to the new passive transform.
|
|
688
361
|
this._passiveTransform.x = this._activeTransform.x;
|
|
689
362
|
this._passiveTransform.y = this._activeTransform.y;
|
|
690
|
-
this._ngZone.run(() => this.ended.
|
|
363
|
+
this._ngZone.run(() => this.ended.next({ source: this }));
|
|
691
364
|
this._dragDropRegistry.stopDragging(this);
|
|
692
365
|
return;
|
|
693
366
|
}
|
|
694
367
|
this._animatePreviewToPlaceholder().then(() => {
|
|
695
|
-
this._cleanupDragArtifacts();
|
|
368
|
+
this._cleanupDragArtifacts(event);
|
|
696
369
|
this._dragDropRegistry.stopDragging(this);
|
|
697
370
|
});
|
|
698
371
|
};
|
|
699
|
-
this.
|
|
372
|
+
this.withRootElement(element);
|
|
700
373
|
_dragDropRegistry.registerDragItem(this);
|
|
701
374
|
}
|
|
702
375
|
/**
|
|
@@ -704,14 +377,19 @@ class CdkDrag {
|
|
|
704
377
|
* @return {?}
|
|
705
378
|
*/
|
|
706
379
|
get disabled() {
|
|
707
|
-
return this._disabled || (this.
|
|
380
|
+
return this._disabled || !!(this._dropContainer && this._dropContainer.disabled);
|
|
708
381
|
}
|
|
709
382
|
/**
|
|
710
383
|
* @param {?} value
|
|
711
384
|
* @return {?}
|
|
712
385
|
*/
|
|
713
386
|
set disabled(value) {
|
|
714
|
-
|
|
387
|
+
/** @type {?} */
|
|
388
|
+
const newValue = coerceBooleanProperty(value);
|
|
389
|
+
if (newValue !== this._disabled) {
|
|
390
|
+
this._disabled = newValue;
|
|
391
|
+
this._toggleNativeDragInteractions();
|
|
392
|
+
}
|
|
715
393
|
}
|
|
716
394
|
/**
|
|
717
395
|
* Returns the element that is being used as a placeholder
|
|
@@ -729,163 +407,302 @@ class CdkDrag {
|
|
|
729
407
|
return this._rootElement;
|
|
730
408
|
}
|
|
731
409
|
/**
|
|
732
|
-
*
|
|
733
|
-
* @
|
|
410
|
+
* Registers the handles that can be used to drag the element.
|
|
411
|
+
* @template THIS
|
|
412
|
+
* @this {THIS}
|
|
413
|
+
* @param {?} handles
|
|
414
|
+
* @return {THIS}
|
|
734
415
|
*/
|
|
735
|
-
|
|
736
|
-
this.
|
|
737
|
-
|
|
738
|
-
|
|
416
|
+
withHandles(handles) {
|
|
417
|
+
(/** @type {?} */ (this))._handles = handles.map(handle => coerceElement(handle));
|
|
418
|
+
(/** @type {?} */ (this))._handles.forEach(handle => toggleNativeDragInteractions(handle, false));
|
|
419
|
+
(/** @type {?} */ (this))._toggleNativeDragInteractions();
|
|
420
|
+
return (/** @type {?} */ (this));
|
|
739
421
|
}
|
|
740
422
|
/**
|
|
741
|
-
*
|
|
423
|
+
* Registers the template that should be used for the drag preview.
|
|
424
|
+
* @template THIS
|
|
425
|
+
* @this {THIS}
|
|
426
|
+
* @param {?} template Template that from which to stamp out the preview.
|
|
427
|
+
* @return {THIS}
|
|
742
428
|
*/
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
// for draggable elements inside portals since they get stamped out in
|
|
747
|
-
// their original DOM position and then they get transferred to the portal.
|
|
748
|
-
this._rootElementInitSubscription = this._ngZone.onStable.asObservable()
|
|
749
|
-
.pipe(take(1))
|
|
750
|
-
.subscribe(() => {
|
|
751
|
-
/** @type {?} */
|
|
752
|
-
const rootElement = this._rootElement = this._getRootElement();
|
|
753
|
-
rootElement.addEventListener('mousedown', this._pointerDown, activeEventListenerOptions);
|
|
754
|
-
rootElement.addEventListener('touchstart', this._pointerDown, passiveEventListenerOptions);
|
|
755
|
-
this._handles.changes.pipe(startWith(null)).subscribe(() => toggleNativeDragInteractions(rootElement, this.getChildHandles().length > 0));
|
|
756
|
-
});
|
|
429
|
+
withPreviewTemplate(template) {
|
|
430
|
+
(/** @type {?} */ (this))._previewTemplate = template;
|
|
431
|
+
return (/** @type {?} */ (this));
|
|
757
432
|
}
|
|
758
433
|
/**
|
|
759
|
-
*
|
|
434
|
+
* Registers the template that should be used for the drag placeholder.
|
|
435
|
+
* @template THIS
|
|
436
|
+
* @this {THIS}
|
|
437
|
+
* @param {?} template Template that from which to stamp out the placeholder.
|
|
438
|
+
* @return {THIS}
|
|
760
439
|
*/
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
440
|
+
withPlaceholderTemplate(template) {
|
|
441
|
+
(/** @type {?} */ (this))._placeholderTemplate = template;
|
|
442
|
+
return (/** @type {?} */ (this));
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Sets an alternate drag root element. The root element is the element that will be moved as
|
|
446
|
+
* the user is dragging. Passing an alternate root element is useful when trying to enable
|
|
447
|
+
* dragging on an element that you might not have access to.
|
|
448
|
+
* @template THIS
|
|
449
|
+
* @this {THIS}
|
|
450
|
+
* @param {?} rootElement
|
|
451
|
+
* @return {THIS}
|
|
452
|
+
*/
|
|
453
|
+
withRootElement(rootElement) {
|
|
454
|
+
/** @type {?} */
|
|
455
|
+
const element = coerceElement(rootElement);
|
|
456
|
+
if (element !== (/** @type {?} */ (this))._rootElement) {
|
|
457
|
+
if ((/** @type {?} */ (this))._rootElement) {
|
|
458
|
+
(/** @type {?} */ (this))._removeRootElementListeners((/** @type {?} */ (this))._rootElement);
|
|
772
459
|
}
|
|
460
|
+
element.addEventListener('mousedown', (/** @type {?} */ (this))._pointerDown, activeEventListenerOptions);
|
|
461
|
+
element.addEventListener('touchstart', (/** @type {?} */ (this))._pointerDown, passiveEventListenerOptions);
|
|
462
|
+
(/** @type {?} */ (this))._initialTransform = undefined;
|
|
463
|
+
(/** @type {?} */ (this))._rootElement = element;
|
|
464
|
+
}
|
|
465
|
+
return (/** @type {?} */ (this));
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Element to which the draggable's position will be constrained.
|
|
469
|
+
* @template THIS
|
|
470
|
+
* @this {THIS}
|
|
471
|
+
* @param {?} boundaryElement
|
|
472
|
+
* @return {THIS}
|
|
473
|
+
*/
|
|
474
|
+
withBoundaryElement(boundaryElement) {
|
|
475
|
+
(/** @type {?} */ (this))._boundaryElement = boundaryElement ? coerceElement(boundaryElement) : null;
|
|
476
|
+
return (/** @type {?} */ (this));
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* Removes the dragging functionality from the DOM element.
|
|
480
|
+
* @return {?}
|
|
481
|
+
*/
|
|
482
|
+
dispose() {
|
|
483
|
+
this._removeRootElementListeners(this._rootElement);
|
|
484
|
+
// Do this check before removing from the registry since it'll
|
|
485
|
+
// stop being considered as dragged once it is removed.
|
|
486
|
+
if (this.isDragging()) {
|
|
487
|
+
// Since we move out the element to the end of the body while it's being
|
|
488
|
+
// dragged, we have to make sure that it's removed if it gets destroyed.
|
|
489
|
+
removeElement(this._rootElement);
|
|
773
490
|
}
|
|
774
|
-
this._rootElementInitSubscription.unsubscribe();
|
|
775
491
|
this._destroyPreview();
|
|
776
492
|
this._destroyPlaceholder();
|
|
777
|
-
this._nextSibling = null;
|
|
778
493
|
this._dragDropRegistry.removeDragItem(this);
|
|
779
494
|
this._removeSubscriptions();
|
|
495
|
+
this.beforeStarted.complete();
|
|
496
|
+
this.started.complete();
|
|
497
|
+
this.released.complete();
|
|
498
|
+
this.ended.complete();
|
|
499
|
+
this.entered.complete();
|
|
500
|
+
this.exited.complete();
|
|
501
|
+
this.dropped.complete();
|
|
780
502
|
this._moveEvents.complete();
|
|
503
|
+
this._handles = [];
|
|
504
|
+
this._disabledHandles.clear();
|
|
505
|
+
this._dropContainer = undefined;
|
|
506
|
+
this._boundaryElement = this._rootElement = this._placeholderTemplate =
|
|
507
|
+
this._previewTemplate = this._nextSibling = (/** @type {?} */ (null));
|
|
781
508
|
}
|
|
782
509
|
/**
|
|
783
510
|
* Checks whether the element is currently being dragged.
|
|
784
511
|
* @return {?}
|
|
785
512
|
*/
|
|
786
|
-
|
|
787
|
-
return this._dragDropRegistry.isDragging(this);
|
|
513
|
+
isDragging() {
|
|
514
|
+
return this._hasStartedDragging && this._dragDropRegistry.isDragging(this);
|
|
788
515
|
}
|
|
789
516
|
/**
|
|
790
|
-
*
|
|
791
|
-
* @private
|
|
517
|
+
* Resets a standalone drag item to its initial position.
|
|
792
518
|
* @return {?}
|
|
793
519
|
*/
|
|
794
|
-
|
|
795
|
-
|
|
520
|
+
reset() {
|
|
521
|
+
this._rootElement.style.transform = this._initialTransform || '';
|
|
522
|
+
this._activeTransform = { x: 0, y: 0 };
|
|
523
|
+
this._passiveTransform = { x: 0, y: 0 };
|
|
796
524
|
}
|
|
797
525
|
/**
|
|
798
|
-
* Sets
|
|
799
|
-
*
|
|
800
|
-
* @private
|
|
801
|
-
* @param {?} referenceElement Element that started the drag sequence.
|
|
802
|
-
* @param {?} event Browser event object that started the sequence.
|
|
526
|
+
* Sets a handle as disabled. While a handle is disabled, it'll capture and interrupt dragging.
|
|
527
|
+
* @param {?} handle Handle element that should be disabled.
|
|
803
528
|
* @return {?}
|
|
804
529
|
*/
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
// starting another sequence for a draggable parent somewhere up the DOM tree.
|
|
809
|
-
event.stopPropagation();
|
|
810
|
-
/** @type {?} */
|
|
811
|
-
const isDragging = this._isDragging();
|
|
812
|
-
/** @type {?} */
|
|
813
|
-
const isTouchEvent = this._isTouchEvent(event);
|
|
814
|
-
/** @type {?} */
|
|
815
|
-
const isAuxiliaryMouseButton = !isTouchEvent && ((/** @type {?} */ (event))).button !== 0;
|
|
816
|
-
/** @type {?} */
|
|
817
|
-
const isSyntheticEvent = !isTouchEvent && this._lastTouchEventTime &&
|
|
818
|
-
this._lastTouchEventTime + MOUSE_EVENT_IGNORE_TIME > Date.now();
|
|
819
|
-
// If the event started from an element with the native HTML drag&drop, it'll interfere
|
|
820
|
-
// with our own dragging (e.g. `img` tags do it by default). Prevent the default action
|
|
821
|
-
// to stop it from happening. Note that preventing on `dragstart` also seems to work, but
|
|
822
|
-
// it's flaky and it fails if the user drags it away quickly. Also note that we only want
|
|
823
|
-
// to do this for `mousedown` since doing the same for `touchstart` will stop any `click`
|
|
824
|
-
// events from firing on touch devices.
|
|
825
|
-
if (event.target && ((/** @type {?} */ (event.target))).draggable && event.type === 'mousedown') {
|
|
826
|
-
event.preventDefault();
|
|
827
|
-
}
|
|
828
|
-
// Abort if the user is already dragging or is using a mouse button other than the primary one.
|
|
829
|
-
if (isDragging || isAuxiliaryMouseButton || isSyntheticEvent) {
|
|
830
|
-
return;
|
|
530
|
+
disableHandle(handle) {
|
|
531
|
+
if (this._handles.indexOf(handle) > -1) {
|
|
532
|
+
this._disabledHandles.add(handle);
|
|
831
533
|
}
|
|
832
|
-
// Cache the previous transform amount only after the first drag sequence, because
|
|
833
|
-
// we don't want our own transforms to stack on top of each other.
|
|
834
|
-
if (this._initialTransform == null) {
|
|
835
|
-
this._initialTransform = this._rootElement.style.transform || '';
|
|
836
|
-
}
|
|
837
|
-
this._hasStartedDragging = this._hasMoved = false;
|
|
838
|
-
this._initialContainer = this.dropContainer;
|
|
839
|
-
this._pointerMoveSubscription = this._dragDropRegistry.pointerMove.subscribe(this._pointerMove);
|
|
840
|
-
this._pointerUpSubscription = this._dragDropRegistry.pointerUp.subscribe(this._pointerUp);
|
|
841
|
-
this._scrollPosition = this._viewportRuler.getViewportScrollPosition();
|
|
842
|
-
// If we have a custom preview template, the element won't be visible anyway so we avoid the
|
|
843
|
-
// extra `getBoundingClientRect` calls and just move the preview next to the cursor.
|
|
844
|
-
this._pickupPositionInElement = this._previewTemplate ? { x: 0, y: 0 } :
|
|
845
|
-
this._getPointerPositionInElement(referenceElement, event);
|
|
846
|
-
/** @type {?} */
|
|
847
|
-
const pointerPosition = this._pickupPositionOnPage = this._getPointerPositionOnPage(event);
|
|
848
|
-
this._pointerDirectionDelta = { x: 0, y: 0 };
|
|
849
|
-
this._pointerPositionAtLastDirectionChange = { x: pointerPosition.x, y: pointerPosition.y };
|
|
850
|
-
this._dragDropRegistry.startDragging(this, event);
|
|
851
534
|
}
|
|
852
535
|
/**
|
|
853
|
-
*
|
|
854
|
-
* @
|
|
855
|
-
* @param {?} event
|
|
536
|
+
* Enables a handle, if it has been disabled.
|
|
537
|
+
* @param {?} handle Handle element to be enabled.
|
|
856
538
|
* @return {?}
|
|
857
539
|
*/
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
540
|
+
enableHandle(handle) {
|
|
541
|
+
this._disabledHandles.delete(handle);
|
|
542
|
+
}
|
|
543
|
+
/**
|
|
544
|
+
* Sets the layout direction of the draggable item.
|
|
545
|
+
* @template THIS
|
|
546
|
+
* @this {THIS}
|
|
547
|
+
* @param {?} direction
|
|
548
|
+
* @return {THIS}
|
|
549
|
+
*/
|
|
550
|
+
withDirection(direction) {
|
|
551
|
+
(/** @type {?} */ (this))._direction = direction;
|
|
552
|
+
return (/** @type {?} */ (this));
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* Sets the container that the item is part of.
|
|
556
|
+
* @param {?} container
|
|
557
|
+
* @return {?}
|
|
558
|
+
*/
|
|
559
|
+
_withDropContainer(container) {
|
|
560
|
+
this._dropContainer = container;
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* Unsubscribes from the global subscriptions.
|
|
564
|
+
* @private
|
|
565
|
+
* @return {?}
|
|
566
|
+
*/
|
|
567
|
+
_removeSubscriptions() {
|
|
568
|
+
this._pointerMoveSubscription.unsubscribe();
|
|
569
|
+
this._pointerUpSubscription.unsubscribe();
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Destroys the preview element and its ViewRef.
|
|
573
|
+
* @private
|
|
574
|
+
* @return {?}
|
|
575
|
+
*/
|
|
576
|
+
_destroyPreview() {
|
|
577
|
+
if (this._preview) {
|
|
578
|
+
removeElement(this._preview);
|
|
579
|
+
}
|
|
580
|
+
if (this._previewRef) {
|
|
581
|
+
this._previewRef.destroy();
|
|
582
|
+
}
|
|
583
|
+
this._preview = this._previewRef = (/** @type {?} */ (null));
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* Destroys the placeholder element and its ViewRef.
|
|
587
|
+
* @private
|
|
588
|
+
* @return {?}
|
|
589
|
+
*/
|
|
590
|
+
_destroyPlaceholder() {
|
|
591
|
+
if (this._placeholder) {
|
|
592
|
+
removeElement(this._placeholder);
|
|
593
|
+
}
|
|
594
|
+
if (this._placeholderRef) {
|
|
595
|
+
this._placeholderRef.destroy();
|
|
596
|
+
}
|
|
597
|
+
this._placeholder = this._placeholderRef = (/** @type {?} */ (null));
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* Starts the dragging sequence.
|
|
601
|
+
* @private
|
|
602
|
+
* @param {?} event
|
|
603
|
+
* @return {?}
|
|
604
|
+
*/
|
|
605
|
+
_startDragSequence(event) {
|
|
606
|
+
// Emit the event on the item before the one on the container.
|
|
607
|
+
this.started.next({ source: this });
|
|
608
|
+
if (isTouchEvent(event)) {
|
|
609
|
+
this._lastTouchEventTime = Date.now();
|
|
610
|
+
}
|
|
611
|
+
if (this._dropContainer) {
|
|
612
|
+
/** @type {?} */
|
|
613
|
+
const element = this._rootElement;
|
|
614
|
+
// Grab the `nextSibling` before the preview and placeholder
|
|
615
|
+
// have been created so we don't get the preview by accident.
|
|
616
|
+
this._nextSibling = element.nextSibling;
|
|
617
|
+
/** @type {?} */
|
|
618
|
+
const preview = this._preview = this._createPreviewElement();
|
|
619
|
+
/** @type {?} */
|
|
620
|
+
const placeholder = this._placeholder = this._createPlaceholderElement();
|
|
621
|
+
// We move the element out at the end of the body and we make it hidden, because keeping it in
|
|
622
|
+
// place will throw off the consumer's `:last-child` selectors. We can't remove the element
|
|
623
|
+
// from the DOM completely, because iOS will stop firing all subsequent events in the chain.
|
|
624
|
+
element.style.display = 'none';
|
|
625
|
+
this._document.body.appendChild((/** @type {?} */ (element.parentNode)).replaceChild(placeholder, element));
|
|
626
|
+
this._document.body.appendChild(preview);
|
|
627
|
+
this._dropContainer.start();
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
/**
|
|
631
|
+
* Sets up the different variables and subscriptions
|
|
632
|
+
* that will be necessary for the dragging sequence.
|
|
633
|
+
* @private
|
|
634
|
+
* @param {?} referenceElement Element that started the drag sequence.
|
|
635
|
+
* @param {?} event Browser event object that started the sequence.
|
|
636
|
+
* @return {?}
|
|
637
|
+
*/
|
|
638
|
+
_initializeDragSequence(referenceElement, event) {
|
|
639
|
+
// Always stop propagation for the event that initializes
|
|
640
|
+
// the dragging sequence, in order to prevent it from potentially
|
|
641
|
+
// starting another sequence for a draggable parent somewhere up the DOM tree.
|
|
642
|
+
event.stopPropagation();
|
|
643
|
+
/** @type {?} */
|
|
644
|
+
const isDragging = this.isDragging();
|
|
645
|
+
/** @type {?} */
|
|
646
|
+
const isTouchSequence = isTouchEvent(event);
|
|
647
|
+
/** @type {?} */
|
|
648
|
+
const isAuxiliaryMouseButton = !isTouchSequence && ((/** @type {?} */ (event))).button !== 0;
|
|
649
|
+
/** @type {?} */
|
|
650
|
+
const rootElement = this._rootElement;
|
|
651
|
+
/** @type {?} */
|
|
652
|
+
const isSyntheticEvent = !isTouchSequence && this._lastTouchEventTime &&
|
|
653
|
+
this._lastTouchEventTime + MOUSE_EVENT_IGNORE_TIME > Date.now();
|
|
654
|
+
// If the event started from an element with the native HTML drag&drop, it'll interfere
|
|
655
|
+
// with our own dragging (e.g. `img` tags do it by default). Prevent the default action
|
|
656
|
+
// to stop it from happening. Note that preventing on `dragstart` also seems to work, but
|
|
657
|
+
// it's flaky and it fails if the user drags it away quickly. Also note that we only want
|
|
658
|
+
// to do this for `mousedown` since doing the same for `touchstart` will stop any `click`
|
|
659
|
+
// events from firing on touch devices.
|
|
660
|
+
if (event.target && ((/** @type {?} */ (event.target))).draggable && event.type === 'mousedown') {
|
|
661
|
+
event.preventDefault();
|
|
662
|
+
}
|
|
663
|
+
// Abort if the user is already dragging or is using a mouse button other than the primary one.
|
|
664
|
+
if (isDragging || isAuxiliaryMouseButton || isSyntheticEvent) {
|
|
665
|
+
return;
|
|
666
|
+
}
|
|
667
|
+
// Cache the previous transform amount only after the first drag sequence, because
|
|
668
|
+
// we don't want our own transforms to stack on top of each other.
|
|
669
|
+
if (this._initialTransform == null) {
|
|
670
|
+
this._initialTransform = this._rootElement.style.transform || '';
|
|
671
|
+
}
|
|
672
|
+
// If we've got handles, we need to disable the tap highlight on the entire root element,
|
|
673
|
+
// otherwise iOS will still add it, even though all the drag interactions on the handle
|
|
674
|
+
// are disabled.
|
|
675
|
+
if (this._handles.length) {
|
|
676
|
+
this._rootElementTapHighlight = rootElement.style.webkitTapHighlightColor;
|
|
677
|
+
rootElement.style.webkitTapHighlightColor = 'transparent';
|
|
678
|
+
}
|
|
679
|
+
this._toggleNativeDragInteractions();
|
|
680
|
+
this._hasStartedDragging = this._hasMoved = false;
|
|
681
|
+
this._initialContainer = (/** @type {?} */ (this._dropContainer));
|
|
682
|
+
this._pointerMoveSubscription = this._dragDropRegistry.pointerMove.subscribe(this._pointerMove);
|
|
683
|
+
this._pointerUpSubscription = this._dragDropRegistry.pointerUp.subscribe(this._pointerUp);
|
|
684
|
+
this._scrollPosition = this._viewportRuler.getViewportScrollPosition();
|
|
685
|
+
if (this._boundaryElement) {
|
|
686
|
+
this._boundaryRect = this._boundaryElement.getBoundingClientRect();
|
|
687
|
+
}
|
|
688
|
+
// If we have a custom preview template, the element won't be visible anyway so we avoid the
|
|
689
|
+
// extra `getBoundingClientRect` calls and just move the preview next to the cursor.
|
|
690
|
+
this._pickupPositionInElement = this._previewTemplate && this._previewTemplate.template ?
|
|
691
|
+
{ x: 0, y: 0 } :
|
|
692
|
+
this._getPointerPositionInElement(referenceElement, event);
|
|
693
|
+
/** @type {?} */
|
|
694
|
+
const pointerPosition = this._pickupPositionOnPage = this._getPointerPositionOnPage(event);
|
|
695
|
+
this._pointerDirectionDelta = { x: 0, y: 0 };
|
|
696
|
+
this._pointerPositionAtLastDirectionChange = { x: pointerPosition.x, y: pointerPosition.y };
|
|
697
|
+
this._dragDropRegistry.startDragging(this, event);
|
|
882
698
|
}
|
|
883
699
|
/**
|
|
884
700
|
* Cleans up the DOM artifacts that were added to facilitate the element being dragged.
|
|
885
701
|
* @private
|
|
702
|
+
* @param {?} event
|
|
886
703
|
* @return {?}
|
|
887
704
|
*/
|
|
888
|
-
_cleanupDragArtifacts() {
|
|
705
|
+
_cleanupDragArtifacts(event) {
|
|
889
706
|
// Restore the element's visibility and insert it at its old position in the DOM.
|
|
890
707
|
// It's important that we maintain the position, because moving the element around in the DOM
|
|
891
708
|
// can throw off `NgFor` which does smart diffing and re-creates elements only when necessary,
|
|
@@ -895,24 +712,31 @@ class CdkDrag {
|
|
|
895
712
|
(/** @type {?} */ (this._nextSibling.parentNode)).insertBefore(this._rootElement, this._nextSibling);
|
|
896
713
|
}
|
|
897
714
|
else {
|
|
898
|
-
this._initialContainer.element.
|
|
715
|
+
this._initialContainer.element.appendChild(this._rootElement);
|
|
899
716
|
}
|
|
900
717
|
this._destroyPreview();
|
|
901
718
|
this._destroyPlaceholder();
|
|
719
|
+
this._boundaryRect = this._previewRect = undefined;
|
|
902
720
|
// Re-enter the NgZone since we bound `document` events on the outside.
|
|
903
721
|
this._ngZone.run(() => {
|
|
904
722
|
/** @type {?} */
|
|
905
|
-
const
|
|
906
|
-
|
|
907
|
-
|
|
723
|
+
const container = (/** @type {?} */ (this._dropContainer));
|
|
724
|
+
/** @type {?} */
|
|
725
|
+
const currentIndex = container.getItemIndex(this);
|
|
726
|
+
const { x, y } = this._getPointerPositionOnPage(event);
|
|
727
|
+
/** @type {?} */
|
|
728
|
+
const isPointerOverContainer = container._isOverContainer(x, y);
|
|
729
|
+
this.ended.next({ source: this });
|
|
730
|
+
this.dropped.next({
|
|
908
731
|
item: this,
|
|
909
732
|
currentIndex,
|
|
910
733
|
previousIndex: this._initialContainer.getItemIndex(this),
|
|
911
|
-
container:
|
|
912
|
-
previousContainer: this._initialContainer
|
|
734
|
+
container: container,
|
|
735
|
+
previousContainer: this._initialContainer,
|
|
736
|
+
isPointerOverContainer
|
|
913
737
|
});
|
|
914
|
-
|
|
915
|
-
this.
|
|
738
|
+
container.drop(this, currentIndex, this._initialContainer, isPointerOverContainer);
|
|
739
|
+
this._dropContainer = this._initialContainer;
|
|
916
740
|
});
|
|
917
741
|
}
|
|
918
742
|
/**
|
|
@@ -925,27 +749,28 @@ class CdkDrag {
|
|
|
925
749
|
_updateActiveDropContainer({ x, y }) {
|
|
926
750
|
// Drop container that draggable has been moved into.
|
|
927
751
|
/** @type {?} */
|
|
928
|
-
let newContainer = this.
|
|
752
|
+
let newContainer = (/** @type {?} */ (this._dropContainer))._getSiblingContainerFromPosition(this, x, y) ||
|
|
753
|
+
this._initialContainer._getSiblingContainerFromPosition(this, x, y);
|
|
929
754
|
// If we couldn't find a new container to move the item into, and the item has left it's
|
|
930
|
-
// initial container, check whether the it's
|
|
931
|
-
//
|
|
932
|
-
//
|
|
933
|
-
if (!newContainer && this.
|
|
934
|
-
this._initialContainer.
|
|
755
|
+
// initial container, check whether the it's over the initial container. This handles the
|
|
756
|
+
// case where two containers are connected one way and the user tries to undo dragging an
|
|
757
|
+
// item into a new container.
|
|
758
|
+
if (!newContainer && this._dropContainer !== this._initialContainer &&
|
|
759
|
+
this._initialContainer._isOverContainer(x, y)) {
|
|
935
760
|
newContainer = this._initialContainer;
|
|
936
761
|
}
|
|
937
|
-
if (newContainer) {
|
|
762
|
+
if (newContainer && newContainer !== this._dropContainer) {
|
|
938
763
|
this._ngZone.run(() => {
|
|
939
764
|
// Notify the old container that the item has left.
|
|
940
|
-
this.exited.
|
|
941
|
-
this.
|
|
765
|
+
this.exited.next({ item: this, container: (/** @type {?} */ (this._dropContainer)) });
|
|
766
|
+
(/** @type {?} */ (this._dropContainer)).exit(this);
|
|
942
767
|
// Notify the new container that the item has entered.
|
|
943
|
-
this.entered.
|
|
944
|
-
this.
|
|
945
|
-
this.
|
|
768
|
+
this.entered.next({ item: this, container: (/** @type {?} */ (newContainer)) });
|
|
769
|
+
this._dropContainer = (/** @type {?} */ (newContainer));
|
|
770
|
+
this._dropContainer.enter(this, x, y);
|
|
946
771
|
});
|
|
947
772
|
}
|
|
948
|
-
this.
|
|
773
|
+
(/** @type {?} */ (this._dropContainer))._sortItem(this, x, y, this._pointerDirectionDelta);
|
|
949
774
|
this._preview.style.transform =
|
|
950
775
|
getTransform(x - this._pickupPositionInElement.x, y - this._pickupPositionInElement.y);
|
|
951
776
|
}
|
|
@@ -956,11 +781,15 @@ class CdkDrag {
|
|
|
956
781
|
* @return {?}
|
|
957
782
|
*/
|
|
958
783
|
_createPreviewElement() {
|
|
784
|
+
/** @type {?} */
|
|
785
|
+
const previewConfig = this._previewTemplate;
|
|
786
|
+
/** @type {?} */
|
|
787
|
+
const previewTemplate = previewConfig ? previewConfig.template : null;
|
|
959
788
|
/** @type {?} */
|
|
960
789
|
let preview;
|
|
961
|
-
if (
|
|
790
|
+
if (previewTemplate) {
|
|
962
791
|
/** @type {?} */
|
|
963
|
-
const viewRef =
|
|
792
|
+
const viewRef = (/** @type {?} */ (previewConfig)).viewContainer.createEmbeddedView(previewTemplate, (/** @type {?} */ (previewConfig)).context);
|
|
964
793
|
preview = viewRef.rootNodes[0];
|
|
965
794
|
this._previewRef = viewRef;
|
|
966
795
|
preview.style.transform =
|
|
@@ -977,244 +806,1716 @@ class CdkDrag {
|
|
|
977
806
|
preview.style.transform = getTransform(elementRect.left, elementRect.top);
|
|
978
807
|
}
|
|
979
808
|
extendStyles(preview.style, {
|
|
809
|
+
// It's important that we disable the pointer events on the preview, because
|
|
810
|
+
// it can throw off the `document.elementFromPoint` calls in the `CdkDropList`.
|
|
811
|
+
pointerEvents: 'none',
|
|
980
812
|
position: 'fixed',
|
|
981
813
|
top: '0',
|
|
982
814
|
left: '0',
|
|
983
815
|
zIndex: '1000'
|
|
984
816
|
});
|
|
817
|
+
toggleNativeDragInteractions(preview, false);
|
|
985
818
|
preview.classList.add('cdk-drag-preview');
|
|
986
|
-
preview.setAttribute('dir', this.
|
|
819
|
+
preview.setAttribute('dir', this._direction);
|
|
987
820
|
return preview;
|
|
988
821
|
}
|
|
822
|
+
/**
|
|
823
|
+
* Animates the preview element from its current position to the location of the drop placeholder.
|
|
824
|
+
* @private
|
|
825
|
+
* @return {?} Promise that resolves when the animation completes.
|
|
826
|
+
*/
|
|
827
|
+
_animatePreviewToPlaceholder() {
|
|
828
|
+
// If the user hasn't moved yet, the transitionend event won't fire.
|
|
829
|
+
if (!this._hasMoved) {
|
|
830
|
+
return Promise.resolve();
|
|
831
|
+
}
|
|
832
|
+
/** @type {?} */
|
|
833
|
+
const placeholderRect = this._placeholder.getBoundingClientRect();
|
|
834
|
+
// Apply the class that adds a transition to the preview.
|
|
835
|
+
this._preview.classList.add('cdk-drag-animating');
|
|
836
|
+
// Move the preview to the placeholder position.
|
|
837
|
+
this._preview.style.transform = getTransform(placeholderRect.left, placeholderRect.top);
|
|
838
|
+
// If the element doesn't have a `transition`, the `transitionend` event won't fire. Since
|
|
839
|
+
// we need to trigger a style recalculation in order for the `cdk-drag-animating` class to
|
|
840
|
+
// apply its style, we take advantage of the available info to figure out whether we need to
|
|
841
|
+
// bind the event in the first place.
|
|
842
|
+
/** @type {?} */
|
|
843
|
+
const duration = getTransformTransitionDurationInMs(this._preview);
|
|
844
|
+
if (duration === 0) {
|
|
845
|
+
return Promise.resolve();
|
|
846
|
+
}
|
|
847
|
+
return this._ngZone.runOutsideAngular(() => {
|
|
848
|
+
return new Promise(resolve => {
|
|
849
|
+
/** @type {?} */
|
|
850
|
+
const handler = (/** @type {?} */ (((event) => {
|
|
851
|
+
if (!event || (event.target === this._preview && event.propertyName === 'transform')) {
|
|
852
|
+
this._preview.removeEventListener('transitionend', handler);
|
|
853
|
+
resolve();
|
|
854
|
+
clearTimeout(timeout);
|
|
855
|
+
}
|
|
856
|
+
})));
|
|
857
|
+
// If a transition is short enough, the browser might not fire the `transitionend` event.
|
|
858
|
+
// Since we know how long it's supposed to take, add a timeout with a 50% buffer that'll
|
|
859
|
+
// fire if the transition hasn't completed when it was supposed to.
|
|
860
|
+
/** @type {?} */
|
|
861
|
+
const timeout = setTimeout((/** @type {?} */ (handler)), duration * 1.5);
|
|
862
|
+
this._preview.addEventListener('transitionend', handler);
|
|
863
|
+
});
|
|
864
|
+
});
|
|
865
|
+
}
|
|
989
866
|
/**
|
|
990
867
|
* Creates an element that will be shown instead of the current element while dragging.
|
|
991
868
|
* @private
|
|
992
869
|
* @return {?}
|
|
993
870
|
*/
|
|
994
871
|
_createPlaceholderElement() {
|
|
872
|
+
/** @type {?} */
|
|
873
|
+
const placeholderConfig = this._placeholderTemplate;
|
|
874
|
+
/** @type {?} */
|
|
875
|
+
const placeholderTemplate = placeholderConfig ? placeholderConfig.template : null;
|
|
995
876
|
/** @type {?} */
|
|
996
877
|
let placeholder;
|
|
997
|
-
if (
|
|
998
|
-
this._placeholderRef =
|
|
878
|
+
if (placeholderTemplate) {
|
|
879
|
+
this._placeholderRef = (/** @type {?} */ (placeholderConfig)).viewContainer.createEmbeddedView(placeholderTemplate, (/** @type {?} */ (placeholderConfig)).context);
|
|
999
880
|
placeholder = this._placeholderRef.rootNodes[0];
|
|
1000
881
|
}
|
|
1001
882
|
else {
|
|
1002
|
-
placeholder = deepCloneNode(this._rootElement);
|
|
883
|
+
placeholder = deepCloneNode(this._rootElement);
|
|
884
|
+
}
|
|
885
|
+
placeholder.classList.add('cdk-drag-placeholder');
|
|
886
|
+
return placeholder;
|
|
887
|
+
}
|
|
888
|
+
/**
|
|
889
|
+
* Figures out the coordinates at which an element was picked up.
|
|
890
|
+
* @private
|
|
891
|
+
* @param {?} referenceElement Element that initiated the dragging.
|
|
892
|
+
* @param {?} event Event that initiated the dragging.
|
|
893
|
+
* @return {?}
|
|
894
|
+
*/
|
|
895
|
+
_getPointerPositionInElement(referenceElement, event) {
|
|
896
|
+
/** @type {?} */
|
|
897
|
+
const elementRect = this._rootElement.getBoundingClientRect();
|
|
898
|
+
/** @type {?} */
|
|
899
|
+
const handleElement = referenceElement === this._rootElement ? null : referenceElement;
|
|
900
|
+
/** @type {?} */
|
|
901
|
+
const referenceRect = handleElement ? handleElement.getBoundingClientRect() : elementRect;
|
|
902
|
+
/** @type {?} */
|
|
903
|
+
const point = isTouchEvent(event) ? event.targetTouches[0] : event;
|
|
904
|
+
/** @type {?} */
|
|
905
|
+
const x = point.pageX - referenceRect.left - this._scrollPosition.left;
|
|
906
|
+
/** @type {?} */
|
|
907
|
+
const y = point.pageY - referenceRect.top - this._scrollPosition.top;
|
|
908
|
+
return {
|
|
909
|
+
x: referenceRect.left - elementRect.left + x,
|
|
910
|
+
y: referenceRect.top - elementRect.top + y
|
|
911
|
+
};
|
|
912
|
+
}
|
|
913
|
+
/**
|
|
914
|
+
* Determines the point of the page that was touched by the user.
|
|
915
|
+
* @private
|
|
916
|
+
* @param {?} event
|
|
917
|
+
* @return {?}
|
|
918
|
+
*/
|
|
919
|
+
_getPointerPositionOnPage(event) {
|
|
920
|
+
// `touches` will be empty for start/end events so we have to fall back to `changedTouches`.
|
|
921
|
+
/** @type {?} */
|
|
922
|
+
const point = isTouchEvent(event) ? (event.touches[0] || event.changedTouches[0]) : event;
|
|
923
|
+
return {
|
|
924
|
+
x: point.pageX - this._scrollPosition.left,
|
|
925
|
+
y: point.pageY - this._scrollPosition.top
|
|
926
|
+
};
|
|
927
|
+
}
|
|
928
|
+
/**
|
|
929
|
+
* Gets the pointer position on the page, accounting for any position constraints.
|
|
930
|
+
* @private
|
|
931
|
+
* @param {?} event
|
|
932
|
+
* @return {?}
|
|
933
|
+
*/
|
|
934
|
+
_getConstrainedPointerPosition(event) {
|
|
935
|
+
/** @type {?} */
|
|
936
|
+
const point = this._getPointerPositionOnPage(event);
|
|
937
|
+
/** @type {?} */
|
|
938
|
+
const dropContainerLock = this._dropContainer ? this._dropContainer.lockAxis : null;
|
|
939
|
+
if (this.lockAxis === 'x' || dropContainerLock === 'x') {
|
|
940
|
+
point.y = this._pickupPositionOnPage.y;
|
|
941
|
+
}
|
|
942
|
+
else if (this.lockAxis === 'y' || dropContainerLock === 'y') {
|
|
943
|
+
point.x = this._pickupPositionOnPage.x;
|
|
944
|
+
}
|
|
945
|
+
if (this._boundaryRect) {
|
|
946
|
+
const { x: pickupX, y: pickupY } = this._pickupPositionInElement;
|
|
947
|
+
/** @type {?} */
|
|
948
|
+
const boundaryRect = this._boundaryRect;
|
|
949
|
+
/** @type {?} */
|
|
950
|
+
const previewRect = (/** @type {?} */ (this._previewRect));
|
|
951
|
+
/** @type {?} */
|
|
952
|
+
const minY = boundaryRect.top + pickupY;
|
|
953
|
+
/** @type {?} */
|
|
954
|
+
const maxY = boundaryRect.bottom - (previewRect.height - pickupY);
|
|
955
|
+
/** @type {?} */
|
|
956
|
+
const minX = boundaryRect.left + pickupX;
|
|
957
|
+
/** @type {?} */
|
|
958
|
+
const maxX = boundaryRect.right - (previewRect.width - pickupX);
|
|
959
|
+
point.x = clamp(point.x, minX, maxX);
|
|
960
|
+
point.y = clamp(point.y, minY, maxY);
|
|
961
|
+
}
|
|
962
|
+
return point;
|
|
963
|
+
}
|
|
964
|
+
/**
|
|
965
|
+
* Updates the current drag delta, based on the user's current pointer position on the page.
|
|
966
|
+
* @private
|
|
967
|
+
* @param {?} pointerPositionOnPage
|
|
968
|
+
* @return {?}
|
|
969
|
+
*/
|
|
970
|
+
_updatePointerDirectionDelta(pointerPositionOnPage) {
|
|
971
|
+
const { x, y } = pointerPositionOnPage;
|
|
972
|
+
/** @type {?} */
|
|
973
|
+
const delta = this._pointerDirectionDelta;
|
|
974
|
+
/** @type {?} */
|
|
975
|
+
const positionSinceLastChange = this._pointerPositionAtLastDirectionChange;
|
|
976
|
+
// Amount of pixels the user has dragged since the last time the direction changed.
|
|
977
|
+
/** @type {?} */
|
|
978
|
+
const changeX = Math.abs(x - positionSinceLastChange.x);
|
|
979
|
+
/** @type {?} */
|
|
980
|
+
const changeY = Math.abs(y - positionSinceLastChange.y);
|
|
981
|
+
// Because we handle pointer events on a per-pixel basis, we don't want the delta
|
|
982
|
+
// to change for every pixel, otherwise anything that depends on it can look erratic.
|
|
983
|
+
// To make the delta more consistent, we track how much the user has moved since the last
|
|
984
|
+
// delta change and we only update it after it has reached a certain threshold.
|
|
985
|
+
if (changeX > this._config.pointerDirectionChangeThreshold) {
|
|
986
|
+
delta.x = x > positionSinceLastChange.x ? 1 : -1;
|
|
987
|
+
positionSinceLastChange.x = x;
|
|
988
|
+
}
|
|
989
|
+
if (changeY > this._config.pointerDirectionChangeThreshold) {
|
|
990
|
+
delta.y = y > positionSinceLastChange.y ? 1 : -1;
|
|
991
|
+
positionSinceLastChange.y = y;
|
|
992
|
+
}
|
|
993
|
+
return delta;
|
|
994
|
+
}
|
|
995
|
+
/**
|
|
996
|
+
* Toggles the native drag interactions, based on how many handles are registered.
|
|
997
|
+
* @private
|
|
998
|
+
* @return {?}
|
|
999
|
+
*/
|
|
1000
|
+
_toggleNativeDragInteractions() {
|
|
1001
|
+
if (!this._rootElement || !this._handles) {
|
|
1002
|
+
return;
|
|
1003
|
+
}
|
|
1004
|
+
/** @type {?} */
|
|
1005
|
+
const shouldEnable = this.disabled || this._handles.length > 0;
|
|
1006
|
+
if (shouldEnable !== this._nativeInteractionsEnabled) {
|
|
1007
|
+
this._nativeInteractionsEnabled = shouldEnable;
|
|
1008
|
+
toggleNativeDragInteractions(this._rootElement, shouldEnable);
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
/**
|
|
1012
|
+
* Removes the manually-added event listeners from the root element.
|
|
1013
|
+
* @private
|
|
1014
|
+
* @param {?} element
|
|
1015
|
+
* @return {?}
|
|
1016
|
+
*/
|
|
1017
|
+
_removeRootElementListeners(element) {
|
|
1018
|
+
element.removeEventListener('mousedown', this._pointerDown, activeEventListenerOptions);
|
|
1019
|
+
element.removeEventListener('touchstart', this._pointerDown, passiveEventListenerOptions);
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
/**
|
|
1023
|
+
* Gets a 3d `transform` that can be applied to an element.
|
|
1024
|
+
* @param {?} x Desired position of the element along the X axis.
|
|
1025
|
+
* @param {?} y Desired position of the element along the Y axis.
|
|
1026
|
+
* @return {?}
|
|
1027
|
+
*/
|
|
1028
|
+
function getTransform(x, y) {
|
|
1029
|
+
// Round the transforms since some browsers will
|
|
1030
|
+
// blur the elements for sub-pixel transforms.
|
|
1031
|
+
return `translate3d(${Math.round(x)}px, ${Math.round(y)}px, 0)`;
|
|
1032
|
+
}
|
|
1033
|
+
/**
|
|
1034
|
+
* Creates a deep clone of an element.
|
|
1035
|
+
* @param {?} node
|
|
1036
|
+
* @return {?}
|
|
1037
|
+
*/
|
|
1038
|
+
function deepCloneNode(node) {
|
|
1039
|
+
/** @type {?} */
|
|
1040
|
+
const clone = (/** @type {?} */ (node.cloneNode(true)));
|
|
1041
|
+
// Remove the `id` to avoid having multiple elements with the same id on the page.
|
|
1042
|
+
clone.removeAttribute('id');
|
|
1043
|
+
return clone;
|
|
1044
|
+
}
|
|
1045
|
+
/**
|
|
1046
|
+
* Clamps a value between a minimum and a maximum.
|
|
1047
|
+
* @param {?} value
|
|
1048
|
+
* @param {?} min
|
|
1049
|
+
* @param {?} max
|
|
1050
|
+
* @return {?}
|
|
1051
|
+
*/
|
|
1052
|
+
function clamp(value, min, max) {
|
|
1053
|
+
return Math.max(min, Math.min(max, value));
|
|
1054
|
+
}
|
|
1055
|
+
/**
|
|
1056
|
+
* Helper to remove an element from the DOM and to do all the necessary null checks.
|
|
1057
|
+
* @param {?} element Element to be removed.
|
|
1058
|
+
* @return {?}
|
|
1059
|
+
*/
|
|
1060
|
+
function removeElement(element) {
|
|
1061
|
+
if (element && element.parentNode) {
|
|
1062
|
+
element.parentNode.removeChild(element);
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
/**
|
|
1066
|
+
* Determines whether an event is a touch event.
|
|
1067
|
+
* @param {?} event
|
|
1068
|
+
* @return {?}
|
|
1069
|
+
*/
|
|
1070
|
+
function isTouchEvent(event) {
|
|
1071
|
+
return event.type.startsWith('touch');
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
/**
|
|
1075
|
+
* @fileoverview added by tsickle
|
|
1076
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
1077
|
+
*/
|
|
1078
|
+
|
|
1079
|
+
/**
|
|
1080
|
+
* Moves an item one index in an array to another.
|
|
1081
|
+
* @template T
|
|
1082
|
+
* @param {?} array Array in which to move the item.
|
|
1083
|
+
* @param {?} fromIndex Starting index of the item.
|
|
1084
|
+
* @param {?} toIndex Index to which the item should be moved.
|
|
1085
|
+
* @return {?}
|
|
1086
|
+
*/
|
|
1087
|
+
function moveItemInArray(array, fromIndex, toIndex) {
|
|
1088
|
+
/** @type {?} */
|
|
1089
|
+
const from = clamp$1(fromIndex, array.length - 1);
|
|
1090
|
+
/** @type {?} */
|
|
1091
|
+
const to = clamp$1(toIndex, array.length - 1);
|
|
1092
|
+
if (from === to) {
|
|
1093
|
+
return;
|
|
1094
|
+
}
|
|
1095
|
+
/** @type {?} */
|
|
1096
|
+
const target = array[from];
|
|
1097
|
+
/** @type {?} */
|
|
1098
|
+
const delta = to < from ? -1 : 1;
|
|
1099
|
+
for (let i = from; i !== to; i += delta) {
|
|
1100
|
+
array[i] = array[i + delta];
|
|
1101
|
+
}
|
|
1102
|
+
array[to] = target;
|
|
1103
|
+
}
|
|
1104
|
+
/**
|
|
1105
|
+
* Moves an item from one array to another.
|
|
1106
|
+
* @template T
|
|
1107
|
+
* @param {?} currentArray Array from which to transfer the item.
|
|
1108
|
+
* @param {?} targetArray Array into which to put the item.
|
|
1109
|
+
* @param {?} currentIndex Index of the item in its current array.
|
|
1110
|
+
* @param {?} targetIndex Index at which to insert the item.
|
|
1111
|
+
* @return {?}
|
|
1112
|
+
*/
|
|
1113
|
+
function transferArrayItem(currentArray, targetArray, currentIndex, targetIndex) {
|
|
1114
|
+
/** @type {?} */
|
|
1115
|
+
const from = clamp$1(currentIndex, currentArray.length - 1);
|
|
1116
|
+
/** @type {?} */
|
|
1117
|
+
const to = clamp$1(targetIndex, targetArray.length);
|
|
1118
|
+
if (currentArray.length) {
|
|
1119
|
+
targetArray.splice(to, 0, currentArray.splice(from, 1)[0]);
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
/**
|
|
1123
|
+
* Copies an item from one array to another, leaving it in its
|
|
1124
|
+
* original position in current array.
|
|
1125
|
+
* @template T
|
|
1126
|
+
* @param {?} currentArray Array from which to copy the item.
|
|
1127
|
+
* @param {?} targetArray Array into which is copy the item.
|
|
1128
|
+
* @param {?} currentIndex Index of the item in its current array.
|
|
1129
|
+
* @param {?} targetIndex Index at which to insert the item.
|
|
1130
|
+
*
|
|
1131
|
+
* @return {?}
|
|
1132
|
+
*/
|
|
1133
|
+
function copyArrayItem(currentArray, targetArray, currentIndex, targetIndex) {
|
|
1134
|
+
/** @type {?} */
|
|
1135
|
+
const to = clamp$1(targetIndex, targetArray.length);
|
|
1136
|
+
if (currentArray.length) {
|
|
1137
|
+
targetArray.splice(to, 0, currentArray[currentIndex]);
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
/**
|
|
1141
|
+
* Clamps a number between zero and a maximum.
|
|
1142
|
+
* @param {?} value
|
|
1143
|
+
* @param {?} max
|
|
1144
|
+
* @return {?}
|
|
1145
|
+
*/
|
|
1146
|
+
function clamp$1(value, max) {
|
|
1147
|
+
return Math.max(0, Math.min(max, value));
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
/**
|
|
1151
|
+
* @fileoverview added by tsickle
|
|
1152
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
1153
|
+
*/
|
|
1154
|
+
/**
|
|
1155
|
+
* Counter used to generate unique ids for drop refs.
|
|
1156
|
+
* @type {?}
|
|
1157
|
+
*/
|
|
1158
|
+
let _uniqueIdCounter = 0;
|
|
1159
|
+
/**
|
|
1160
|
+
* Proximity, as a ratio to width/height, at which a
|
|
1161
|
+
* dragged item will affect the drop container.
|
|
1162
|
+
* @type {?}
|
|
1163
|
+
*/
|
|
1164
|
+
const DROP_PROXIMITY_THRESHOLD = 0.05;
|
|
1165
|
+
/**
|
|
1166
|
+
* Reference to a drop list. Used to manipulate or dispose of the container.
|
|
1167
|
+
* \@docs-private
|
|
1168
|
+
* @template T
|
|
1169
|
+
*/
|
|
1170
|
+
class DropListRef {
|
|
1171
|
+
/**
|
|
1172
|
+
* @param {?} element
|
|
1173
|
+
* @param {?} _dragDropRegistry
|
|
1174
|
+
* @param {?} _document
|
|
1175
|
+
*/
|
|
1176
|
+
constructor(element, _dragDropRegistry, _document) {
|
|
1177
|
+
this._dragDropRegistry = _dragDropRegistry;
|
|
1178
|
+
/**
|
|
1179
|
+
* Unique ID for the drop list.
|
|
1180
|
+
* @deprecated No longer being used. To be removed.
|
|
1181
|
+
* \@breaking-change 8.0.0
|
|
1182
|
+
*/
|
|
1183
|
+
this.id = `cdk-drop-list-ref-${_uniqueIdCounter++}`;
|
|
1184
|
+
/**
|
|
1185
|
+
* Whether starting a dragging sequence from this container is disabled.
|
|
1186
|
+
*/
|
|
1187
|
+
this.disabled = false;
|
|
1188
|
+
/**
|
|
1189
|
+
* Function that is used to determine whether an item
|
|
1190
|
+
* is allowed to be moved into a drop container.
|
|
1191
|
+
*/
|
|
1192
|
+
this.enterPredicate = () => true;
|
|
1193
|
+
/**
|
|
1194
|
+
* Emits right before dragging has started.
|
|
1195
|
+
*/
|
|
1196
|
+
this.beforeStarted = new Subject();
|
|
1197
|
+
/**
|
|
1198
|
+
* Emits when the user has moved a new drag item into this container.
|
|
1199
|
+
*/
|
|
1200
|
+
this.entered = new Subject();
|
|
1201
|
+
/**
|
|
1202
|
+
* Emits when the user removes an item from the container
|
|
1203
|
+
* by dragging it into another container.
|
|
1204
|
+
*/
|
|
1205
|
+
this.exited = new Subject();
|
|
1206
|
+
/**
|
|
1207
|
+
* Emits when the user drops an item inside the container.
|
|
1208
|
+
*/
|
|
1209
|
+
this.dropped = new Subject();
|
|
1210
|
+
/**
|
|
1211
|
+
* Emits as the user is swapping items while actively dragging.
|
|
1212
|
+
*/
|
|
1213
|
+
this.sorted = new Subject();
|
|
1214
|
+
/**
|
|
1215
|
+
* Whether an item in the list is being dragged.
|
|
1216
|
+
*/
|
|
1217
|
+
this._isDragging = false;
|
|
1218
|
+
/**
|
|
1219
|
+
* Cache of the dimensions of all the items inside the container.
|
|
1220
|
+
*/
|
|
1221
|
+
this._itemPositions = [];
|
|
1222
|
+
/**
|
|
1223
|
+
* Keeps track of the item that was last swapped with the dragged item, as
|
|
1224
|
+
* well as what direction the pointer was moving in when the swap occured.
|
|
1225
|
+
*/
|
|
1226
|
+
this._previousSwap = { drag: (/** @type {?} */ (null)), delta: 0 };
|
|
1227
|
+
/**
|
|
1228
|
+
* Drop lists that are connected to the current one.
|
|
1229
|
+
*/
|
|
1230
|
+
this._siblings = [];
|
|
1231
|
+
/**
|
|
1232
|
+
* Direction in which the list is oriented.
|
|
1233
|
+
*/
|
|
1234
|
+
this._orientation = 'vertical';
|
|
1235
|
+
/**
|
|
1236
|
+
* Connected siblings that currently have a dragged item.
|
|
1237
|
+
*/
|
|
1238
|
+
this._activeSiblings = new Set();
|
|
1239
|
+
/**
|
|
1240
|
+
* Layout direction of the drop list.
|
|
1241
|
+
*/
|
|
1242
|
+
this._direction = 'ltr';
|
|
1243
|
+
_dragDropRegistry.registerDropContainer(this);
|
|
1244
|
+
this._document = _document;
|
|
1245
|
+
this.element = element instanceof ElementRef ? element.nativeElement : element;
|
|
1246
|
+
}
|
|
1247
|
+
/**
|
|
1248
|
+
* Removes the drop list functionality from the DOM element.
|
|
1249
|
+
* @return {?}
|
|
1250
|
+
*/
|
|
1251
|
+
dispose() {
|
|
1252
|
+
this.beforeStarted.complete();
|
|
1253
|
+
this.entered.complete();
|
|
1254
|
+
this.exited.complete();
|
|
1255
|
+
this.dropped.complete();
|
|
1256
|
+
this.sorted.complete();
|
|
1257
|
+
this._activeSiblings.clear();
|
|
1258
|
+
this._dragDropRegistry.removeDropContainer(this);
|
|
1259
|
+
}
|
|
1260
|
+
/**
|
|
1261
|
+
* Whether an item from this list is currently being dragged.
|
|
1262
|
+
* @return {?}
|
|
1263
|
+
*/
|
|
1264
|
+
isDragging() {
|
|
1265
|
+
return this._isDragging;
|
|
1266
|
+
}
|
|
1267
|
+
/**
|
|
1268
|
+
* Starts dragging an item.
|
|
1269
|
+
* @return {?}
|
|
1270
|
+
*/
|
|
1271
|
+
start() {
|
|
1272
|
+
this.beforeStarted.next();
|
|
1273
|
+
this._isDragging = true;
|
|
1274
|
+
this._activeDraggables = this._draggables.slice();
|
|
1275
|
+
this._cacheOwnPosition();
|
|
1276
|
+
this._cacheItemPositions();
|
|
1277
|
+
this._siblings.forEach(sibling => sibling._startReceiving(this));
|
|
1278
|
+
}
|
|
1279
|
+
/**
|
|
1280
|
+
* Emits an event to indicate that the user moved an item into the container.
|
|
1281
|
+
* @param {?} item Item that was moved into the container.
|
|
1282
|
+
* @param {?} pointerX Position of the item along the X axis.
|
|
1283
|
+
* @param {?} pointerY Position of the item along the Y axis.
|
|
1284
|
+
* @return {?}
|
|
1285
|
+
*/
|
|
1286
|
+
enter(item, pointerX, pointerY) {
|
|
1287
|
+
this.entered.next({ item, container: this });
|
|
1288
|
+
this.start();
|
|
1289
|
+
// We use the coordinates of where the item entered the drop
|
|
1290
|
+
// zone to figure out at which index it should be inserted.
|
|
1291
|
+
/** @type {?} */
|
|
1292
|
+
const newIndex = this._getItemIndexFromPointerPosition(item, pointerX, pointerY);
|
|
1293
|
+
/** @type {?} */
|
|
1294
|
+
const currentIndex = this._activeDraggables.indexOf(item);
|
|
1295
|
+
/** @type {?} */
|
|
1296
|
+
const newPositionReference = this._activeDraggables[newIndex];
|
|
1297
|
+
/** @type {?} */
|
|
1298
|
+
const placeholder = item.getPlaceholderElement();
|
|
1299
|
+
// Since the item may be in the `activeDraggables` already (e.g. if the user dragged it
|
|
1300
|
+
// into another container and back again), we have to ensure that it isn't duplicated.
|
|
1301
|
+
if (currentIndex > -1) {
|
|
1302
|
+
this._activeDraggables.splice(currentIndex, 1);
|
|
1303
|
+
}
|
|
1304
|
+
// Don't use items that are being dragged as a reference, because
|
|
1305
|
+
// their element has been moved down to the bottom of the body.
|
|
1306
|
+
if (newPositionReference && !this._dragDropRegistry.isDragging(newPositionReference)) {
|
|
1307
|
+
/** @type {?} */
|
|
1308
|
+
const element = newPositionReference.getRootElement();
|
|
1309
|
+
(/** @type {?} */ (element.parentElement)).insertBefore(placeholder, element);
|
|
1310
|
+
this._activeDraggables.splice(newIndex, 0, item);
|
|
1311
|
+
}
|
|
1312
|
+
else {
|
|
1313
|
+
this.element.appendChild(placeholder);
|
|
1314
|
+
this._activeDraggables.push(item);
|
|
1315
|
+
}
|
|
1316
|
+
// The transform needs to be cleared so it doesn't throw off the measurements.
|
|
1317
|
+
placeholder.style.transform = '';
|
|
1318
|
+
// Note that the positions were already cached when we called `start` above,
|
|
1319
|
+
// but we need to refresh them since the amount of items has changed.
|
|
1320
|
+
this._cacheItemPositions();
|
|
1321
|
+
}
|
|
1322
|
+
/**
|
|
1323
|
+
* Removes an item from the container after it was dragged into another container by the user.
|
|
1324
|
+
* @param {?} item Item that was dragged out.
|
|
1325
|
+
* @return {?}
|
|
1326
|
+
*/
|
|
1327
|
+
exit(item) {
|
|
1328
|
+
this._reset();
|
|
1329
|
+
this.exited.next({ item, container: this });
|
|
1330
|
+
}
|
|
1331
|
+
/**
|
|
1332
|
+
* Drops an item into this container.
|
|
1333
|
+
* @param {?} item Item being dropped into the container.
|
|
1334
|
+
* @param {?} currentIndex Index at which the item should be inserted.
|
|
1335
|
+
* @param {?} previousContainer Container from which the item got dragged in.
|
|
1336
|
+
* @param {?} isPointerOverContainer Whether the user's pointer was over the
|
|
1337
|
+
* container when the item was dropped.
|
|
1338
|
+
* @return {?}
|
|
1339
|
+
*/
|
|
1340
|
+
drop(item, currentIndex, previousContainer, isPointerOverContainer) {
|
|
1341
|
+
this._reset();
|
|
1342
|
+
this.dropped.next({
|
|
1343
|
+
item,
|
|
1344
|
+
currentIndex,
|
|
1345
|
+
previousIndex: previousContainer.getItemIndex(item),
|
|
1346
|
+
container: this,
|
|
1347
|
+
previousContainer,
|
|
1348
|
+
isPointerOverContainer
|
|
1349
|
+
});
|
|
1350
|
+
}
|
|
1351
|
+
/**
|
|
1352
|
+
* Sets the draggable items that are a part of this list.
|
|
1353
|
+
* @template THIS
|
|
1354
|
+
* @this {THIS}
|
|
1355
|
+
* @param {?} items Items that are a part of this list.
|
|
1356
|
+
* @return {THIS}
|
|
1357
|
+
*/
|
|
1358
|
+
withItems(items) {
|
|
1359
|
+
(/** @type {?} */ (this))._draggables = items.slice();
|
|
1360
|
+
items.forEach(item => item._withDropContainer((/** @type {?} */ (this))));
|
|
1361
|
+
return (/** @type {?} */ (this));
|
|
1362
|
+
}
|
|
1363
|
+
/**
|
|
1364
|
+
* Sets the layout direction of the drop list.
|
|
1365
|
+
* @template THIS
|
|
1366
|
+
* @this {THIS}
|
|
1367
|
+
* @param {?} direction
|
|
1368
|
+
* @return {THIS}
|
|
1369
|
+
*/
|
|
1370
|
+
withDirection(direction) {
|
|
1371
|
+
(/** @type {?} */ (this))._direction = direction;
|
|
1372
|
+
return (/** @type {?} */ (this));
|
|
1373
|
+
}
|
|
1374
|
+
/**
|
|
1375
|
+
* Sets the containers that are connected to this one. When two or more containers are
|
|
1376
|
+
* connected, the user will be allowed to transfer items between them.
|
|
1377
|
+
* @template THIS
|
|
1378
|
+
* @this {THIS}
|
|
1379
|
+
* @param {?} connectedTo Other containers that the current containers should be connected to.
|
|
1380
|
+
* @return {THIS}
|
|
1381
|
+
*/
|
|
1382
|
+
connectedTo(connectedTo) {
|
|
1383
|
+
(/** @type {?} */ (this))._siblings = connectedTo.slice();
|
|
1384
|
+
return (/** @type {?} */ (this));
|
|
1385
|
+
}
|
|
1386
|
+
/**
|
|
1387
|
+
* Sets the orientation of the container.
|
|
1388
|
+
* @template THIS
|
|
1389
|
+
* @this {THIS}
|
|
1390
|
+
* @param {?} orientation New orientation for the container.
|
|
1391
|
+
* @return {THIS}
|
|
1392
|
+
*/
|
|
1393
|
+
withOrientation(orientation) {
|
|
1394
|
+
(/** @type {?} */ (this))._orientation = orientation;
|
|
1395
|
+
return (/** @type {?} */ (this));
|
|
1396
|
+
}
|
|
1397
|
+
/**
|
|
1398
|
+
* Figures out the index of an item in the container.
|
|
1399
|
+
* @param {?} item Item whose index should be determined.
|
|
1400
|
+
* @return {?}
|
|
1401
|
+
*/
|
|
1402
|
+
getItemIndex(item) {
|
|
1403
|
+
if (!this._isDragging) {
|
|
1404
|
+
return this._draggables.indexOf(item);
|
|
1405
|
+
}
|
|
1406
|
+
// Items are sorted always by top/left in the cache, however they flow differently in RTL.
|
|
1407
|
+
// The rest of the logic still stands no matter what orientation we're in, however
|
|
1408
|
+
// we need to invert the array when determining the index.
|
|
1409
|
+
/** @type {?} */
|
|
1410
|
+
const items = this._orientation === 'horizontal' && this._direction === 'rtl' ?
|
|
1411
|
+
this._itemPositions.slice().reverse() : this._itemPositions;
|
|
1412
|
+
return findIndex(items, currentItem => currentItem.drag === item);
|
|
1413
|
+
}
|
|
1414
|
+
/**
|
|
1415
|
+
* Whether the list is able to receive the item that
|
|
1416
|
+
* is currently being dragged inside a connected drop list.
|
|
1417
|
+
* @return {?}
|
|
1418
|
+
*/
|
|
1419
|
+
isReceiving() {
|
|
1420
|
+
return this._activeSiblings.size > 0;
|
|
1421
|
+
}
|
|
1422
|
+
/**
|
|
1423
|
+
* Sorts an item inside the container based on its position.
|
|
1424
|
+
* @param {?} item Item to be sorted.
|
|
1425
|
+
* @param {?} pointerX Position of the item along the X axis.
|
|
1426
|
+
* @param {?} pointerY Position of the item along the Y axis.
|
|
1427
|
+
* @param {?} pointerDelta Direction in which the pointer is moving along each axis.
|
|
1428
|
+
* @return {?}
|
|
1429
|
+
*/
|
|
1430
|
+
_sortItem(item, pointerX, pointerY, pointerDelta) {
|
|
1431
|
+
// Don't sort the item if it's out of range.
|
|
1432
|
+
if (!this._isPointerNearDropContainer(pointerX, pointerY)) {
|
|
1433
|
+
return;
|
|
1434
|
+
}
|
|
1435
|
+
/** @type {?} */
|
|
1436
|
+
const siblings = this._itemPositions;
|
|
1437
|
+
/** @type {?} */
|
|
1438
|
+
const newIndex = this._getItemIndexFromPointerPosition(item, pointerX, pointerY, pointerDelta);
|
|
1439
|
+
if (newIndex === -1 && siblings.length > 0) {
|
|
1440
|
+
return;
|
|
1441
|
+
}
|
|
1442
|
+
/** @type {?} */
|
|
1443
|
+
const isHorizontal = this._orientation === 'horizontal';
|
|
1444
|
+
/** @type {?} */
|
|
1445
|
+
const currentIndex = findIndex(siblings, currentItem => currentItem.drag === item);
|
|
1446
|
+
/** @type {?} */
|
|
1447
|
+
const siblingAtNewPosition = siblings[newIndex];
|
|
1448
|
+
/** @type {?} */
|
|
1449
|
+
const currentPosition = siblings[currentIndex].clientRect;
|
|
1450
|
+
/** @type {?} */
|
|
1451
|
+
const newPosition = siblingAtNewPosition.clientRect;
|
|
1452
|
+
/** @type {?} */
|
|
1453
|
+
const delta = currentIndex > newIndex ? 1 : -1;
|
|
1454
|
+
this._previousSwap.drag = siblingAtNewPosition.drag;
|
|
1455
|
+
this._previousSwap.delta = isHorizontal ? pointerDelta.x : pointerDelta.y;
|
|
1456
|
+
// How many pixels the item's placeholder should be offset.
|
|
1457
|
+
/** @type {?} */
|
|
1458
|
+
const itemOffset = this._getItemOffsetPx(currentPosition, newPosition, delta);
|
|
1459
|
+
// How many pixels all the other items should be offset.
|
|
1460
|
+
/** @type {?} */
|
|
1461
|
+
const siblingOffset = this._getSiblingOffsetPx(currentIndex, siblings, delta);
|
|
1462
|
+
// Save the previous order of the items before moving the item to its new index.
|
|
1463
|
+
// We use this to check whether an item has been moved as a result of the sorting.
|
|
1464
|
+
/** @type {?} */
|
|
1465
|
+
const oldOrder = siblings.slice();
|
|
1466
|
+
// Shuffle the array in place.
|
|
1467
|
+
moveItemInArray(siblings, currentIndex, newIndex);
|
|
1468
|
+
this.sorted.next({
|
|
1469
|
+
previousIndex: currentIndex,
|
|
1470
|
+
currentIndex: newIndex,
|
|
1471
|
+
container: this,
|
|
1472
|
+
item
|
|
1473
|
+
});
|
|
1474
|
+
siblings.forEach((sibling, index) => {
|
|
1475
|
+
// Don't do anything if the position hasn't changed.
|
|
1476
|
+
if (oldOrder[index] === sibling) {
|
|
1477
|
+
return;
|
|
1478
|
+
}
|
|
1479
|
+
/** @type {?} */
|
|
1480
|
+
const isDraggedItem = sibling.drag === item;
|
|
1481
|
+
/** @type {?} */
|
|
1482
|
+
const offset = isDraggedItem ? itemOffset : siblingOffset;
|
|
1483
|
+
/** @type {?} */
|
|
1484
|
+
const elementToOffset = isDraggedItem ? item.getPlaceholderElement() :
|
|
1485
|
+
sibling.drag.getRootElement();
|
|
1486
|
+
// Update the offset to reflect the new position.
|
|
1487
|
+
sibling.offset += offset;
|
|
1488
|
+
// Since we're moving the items with a `transform`, we need to adjust their cached
|
|
1489
|
+
// client rects to reflect their new position, as well as swap their positions in the cache.
|
|
1490
|
+
// Note that we shouldn't use `getBoundingClientRect` here to update the cache, because the
|
|
1491
|
+
// elements may be mid-animation which will give us a wrong result.
|
|
1492
|
+
if (isHorizontal) {
|
|
1493
|
+
// Round the transforms since some browsers will
|
|
1494
|
+
// blur the elements, for sub-pixel transforms.
|
|
1495
|
+
elementToOffset.style.transform = `translate3d(${Math.round(sibling.offset)}px, 0, 0)`;
|
|
1496
|
+
adjustClientRect(sibling.clientRect, 0, offset);
|
|
1497
|
+
}
|
|
1498
|
+
else {
|
|
1499
|
+
elementToOffset.style.transform = `translate3d(0, ${Math.round(sibling.offset)}px, 0)`;
|
|
1500
|
+
adjustClientRect(sibling.clientRect, offset, 0);
|
|
1501
|
+
}
|
|
1502
|
+
});
|
|
1503
|
+
}
|
|
1504
|
+
/**
|
|
1505
|
+
* Caches the position of the drop list.
|
|
1506
|
+
* @private
|
|
1507
|
+
* @return {?}
|
|
1508
|
+
*/
|
|
1509
|
+
_cacheOwnPosition() {
|
|
1510
|
+
this._clientRect = this.element.getBoundingClientRect();
|
|
1511
|
+
}
|
|
1512
|
+
/**
|
|
1513
|
+
* Refreshes the position cache of the items and sibling containers.
|
|
1514
|
+
* @private
|
|
1515
|
+
* @return {?}
|
|
1516
|
+
*/
|
|
1517
|
+
_cacheItemPositions() {
|
|
1518
|
+
/** @type {?} */
|
|
1519
|
+
const isHorizontal = this._orientation === 'horizontal';
|
|
1520
|
+
this._itemPositions = this._activeDraggables.map(drag => {
|
|
1521
|
+
/** @type {?} */
|
|
1522
|
+
const elementToMeasure = this._dragDropRegistry.isDragging(drag) ?
|
|
1523
|
+
// If the element is being dragged, we have to measure the
|
|
1524
|
+
// placeholder, because the element is hidden.
|
|
1525
|
+
drag.getPlaceholderElement() :
|
|
1526
|
+
drag.getRootElement();
|
|
1527
|
+
/** @type {?} */
|
|
1528
|
+
const clientRect = elementToMeasure.getBoundingClientRect();
|
|
1529
|
+
return {
|
|
1530
|
+
drag,
|
|
1531
|
+
offset: 0,
|
|
1532
|
+
// We need to clone the `clientRect` here, because all the values on it are readonly
|
|
1533
|
+
// and we need to be able to update them. Also we can't use a spread here, because
|
|
1534
|
+
// the values on a `ClientRect` aren't own properties. See:
|
|
1535
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect#Notes
|
|
1536
|
+
clientRect: {
|
|
1537
|
+
top: clientRect.top,
|
|
1538
|
+
right: clientRect.right,
|
|
1539
|
+
bottom: clientRect.bottom,
|
|
1540
|
+
left: clientRect.left,
|
|
1541
|
+
width: clientRect.width,
|
|
1542
|
+
height: clientRect.height
|
|
1543
|
+
}
|
|
1544
|
+
};
|
|
1545
|
+
}).sort((a, b) => {
|
|
1546
|
+
return isHorizontal ? a.clientRect.left - b.clientRect.left :
|
|
1547
|
+
a.clientRect.top - b.clientRect.top;
|
|
1548
|
+
});
|
|
1549
|
+
}
|
|
1550
|
+
/**
|
|
1551
|
+
* Resets the container to its initial state.
|
|
1552
|
+
* @private
|
|
1553
|
+
* @return {?}
|
|
1554
|
+
*/
|
|
1555
|
+
_reset() {
|
|
1556
|
+
this._isDragging = false;
|
|
1557
|
+
// TODO(crisbeto): may have to wait for the animations to finish.
|
|
1558
|
+
this._activeDraggables.forEach(item => item.getRootElement().style.transform = '');
|
|
1559
|
+
this._siblings.forEach(sibling => sibling._stopReceiving(this));
|
|
1560
|
+
this._activeDraggables = [];
|
|
1561
|
+
this._itemPositions = [];
|
|
1562
|
+
this._previousSwap.drag = null;
|
|
1563
|
+
this._previousSwap.delta = 0;
|
|
1564
|
+
}
|
|
1565
|
+
/**
|
|
1566
|
+
* Gets the offset in pixels by which the items that aren't being dragged should be moved.
|
|
1567
|
+
* @private
|
|
1568
|
+
* @param {?} currentIndex Index of the item currently being dragged.
|
|
1569
|
+
* @param {?} siblings All of the items in the list.
|
|
1570
|
+
* @param {?} delta Direction in which the user is moving.
|
|
1571
|
+
* @return {?}
|
|
1572
|
+
*/
|
|
1573
|
+
_getSiblingOffsetPx(currentIndex, siblings, delta) {
|
|
1574
|
+
/** @type {?} */
|
|
1575
|
+
const isHorizontal = this._orientation === 'horizontal';
|
|
1576
|
+
/** @type {?} */
|
|
1577
|
+
const currentPosition = siblings[currentIndex].clientRect;
|
|
1578
|
+
/** @type {?} */
|
|
1579
|
+
const immediateSibling = siblings[currentIndex + delta * -1];
|
|
1580
|
+
/** @type {?} */
|
|
1581
|
+
let siblingOffset = currentPosition[isHorizontal ? 'width' : 'height'] * delta;
|
|
1582
|
+
if (immediateSibling) {
|
|
1583
|
+
/** @type {?} */
|
|
1584
|
+
const start = isHorizontal ? 'left' : 'top';
|
|
1585
|
+
/** @type {?} */
|
|
1586
|
+
const end = isHorizontal ? 'right' : 'bottom';
|
|
1587
|
+
// Get the spacing between the start of the current item and the end of the one immediately
|
|
1588
|
+
// after it in the direction in which the user is dragging, or vice versa. We add it to the
|
|
1589
|
+
// offset in order to push the element to where it will be when it's inline and is influenced
|
|
1590
|
+
// by the `margin` of its siblings.
|
|
1591
|
+
if (delta === -1) {
|
|
1592
|
+
siblingOffset -= immediateSibling.clientRect[start] - currentPosition[end];
|
|
1593
|
+
}
|
|
1594
|
+
else {
|
|
1595
|
+
siblingOffset += currentPosition[start] - immediateSibling.clientRect[end];
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
return siblingOffset;
|
|
1599
|
+
}
|
|
1600
|
+
/**
|
|
1601
|
+
* Checks whether the pointer coordinates are close to the drop container.
|
|
1602
|
+
* @private
|
|
1603
|
+
* @param {?} pointerX Coordinates along the X axis.
|
|
1604
|
+
* @param {?} pointerY Coordinates along the Y axis.
|
|
1605
|
+
* @return {?}
|
|
1606
|
+
*/
|
|
1607
|
+
_isPointerNearDropContainer(pointerX, pointerY) {
|
|
1608
|
+
const { top, right, bottom, left, width, height } = this._clientRect;
|
|
1609
|
+
/** @type {?} */
|
|
1610
|
+
const xThreshold = width * DROP_PROXIMITY_THRESHOLD;
|
|
1611
|
+
/** @type {?} */
|
|
1612
|
+
const yThreshold = height * DROP_PROXIMITY_THRESHOLD;
|
|
1613
|
+
return pointerY > top - yThreshold && pointerY < bottom + yThreshold &&
|
|
1614
|
+
pointerX > left - xThreshold && pointerX < right + xThreshold;
|
|
1615
|
+
}
|
|
1616
|
+
/**
|
|
1617
|
+
* Gets the offset in pixels by which the item that is being dragged should be moved.
|
|
1618
|
+
* @private
|
|
1619
|
+
* @param {?} currentPosition Current position of the item.
|
|
1620
|
+
* @param {?} newPosition Position of the item where the current item should be moved.
|
|
1621
|
+
* @param {?} delta Direction in which the user is moving.
|
|
1622
|
+
* @return {?}
|
|
1623
|
+
*/
|
|
1624
|
+
_getItemOffsetPx(currentPosition, newPosition, delta) {
|
|
1625
|
+
/** @type {?} */
|
|
1626
|
+
const isHorizontal = this._orientation === 'horizontal';
|
|
1627
|
+
/** @type {?} */
|
|
1628
|
+
let itemOffset = isHorizontal ? newPosition.left - currentPosition.left :
|
|
1629
|
+
newPosition.top - currentPosition.top;
|
|
1630
|
+
// Account for differences in the item width/height.
|
|
1631
|
+
if (delta === -1) {
|
|
1632
|
+
itemOffset += isHorizontal ? newPosition.width - currentPosition.width :
|
|
1633
|
+
newPosition.height - currentPosition.height;
|
|
1634
|
+
}
|
|
1635
|
+
return itemOffset;
|
|
1636
|
+
}
|
|
1637
|
+
/**
|
|
1638
|
+
* Gets the index of an item in the drop container, based on the position of the user's pointer.
|
|
1639
|
+
* @private
|
|
1640
|
+
* @param {?} item Item that is being sorted.
|
|
1641
|
+
* @param {?} pointerX Position of the user's pointer along the X axis.
|
|
1642
|
+
* @param {?} pointerY Position of the user's pointer along the Y axis.
|
|
1643
|
+
* @param {?=} delta Direction in which the user is moving their pointer.
|
|
1644
|
+
* @return {?}
|
|
1645
|
+
*/
|
|
1646
|
+
_getItemIndexFromPointerPosition(item, pointerX, pointerY, delta) {
|
|
1647
|
+
/** @type {?} */
|
|
1648
|
+
const isHorizontal = this._orientation === 'horizontal';
|
|
1649
|
+
return findIndex(this._itemPositions, ({ drag, clientRect }, _, array) => {
|
|
1650
|
+
if (drag === item) {
|
|
1651
|
+
// If there's only one item left in the container, it must be
|
|
1652
|
+
// the dragged item itself so we use it as a reference.
|
|
1653
|
+
return array.length < 2;
|
|
1654
|
+
}
|
|
1655
|
+
if (delta) {
|
|
1656
|
+
/** @type {?} */
|
|
1657
|
+
const direction = isHorizontal ? delta.x : delta.y;
|
|
1658
|
+
// If the user is still hovering over the same item as last time, and they didn't change
|
|
1659
|
+
// the direction in which they're dragging, we don't consider it a direction swap.
|
|
1660
|
+
if (drag === this._previousSwap.drag && direction === this._previousSwap.delta) {
|
|
1661
|
+
return false;
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
return isHorizontal ?
|
|
1665
|
+
// Round these down since most browsers report client rects with
|
|
1666
|
+
// sub-pixel precision, whereas the pointer coordinates are rounded to pixels.
|
|
1667
|
+
pointerX >= Math.floor(clientRect.left) && pointerX <= Math.floor(clientRect.right) :
|
|
1668
|
+
pointerY >= Math.floor(clientRect.top) && pointerY <= Math.floor(clientRect.bottom);
|
|
1669
|
+
});
|
|
1670
|
+
}
|
|
1671
|
+
/**
|
|
1672
|
+
* Checks whether the user's pointer is positioned over the container.
|
|
1673
|
+
* @param {?} x Pointer position along the X axis.
|
|
1674
|
+
* @param {?} y Pointer position along the Y axis.
|
|
1675
|
+
* @return {?}
|
|
1676
|
+
*/
|
|
1677
|
+
_isOverContainer(x, y) {
|
|
1678
|
+
return isInsideClientRect(this._clientRect, x, y);
|
|
1679
|
+
}
|
|
1680
|
+
/**
|
|
1681
|
+
* Figures out whether an item should be moved into a sibling
|
|
1682
|
+
* drop container, based on its current position.
|
|
1683
|
+
* @param {?} item Drag item that is being moved.
|
|
1684
|
+
* @param {?} x Position of the item along the X axis.
|
|
1685
|
+
* @param {?} y Position of the item along the Y axis.
|
|
1686
|
+
* @return {?}
|
|
1687
|
+
*/
|
|
1688
|
+
_getSiblingContainerFromPosition(item, x, y) {
|
|
1689
|
+
return this._siblings.find(sibling => sibling._canReceive(item, x, y));
|
|
1690
|
+
}
|
|
1691
|
+
/**
|
|
1692
|
+
* Checks whether the drop list can receive the passed-in item.
|
|
1693
|
+
* @param {?} item Item that is being dragged into the list.
|
|
1694
|
+
* @param {?} x Position of the item along the X axis.
|
|
1695
|
+
* @param {?} y Position of the item along the Y axis.
|
|
1696
|
+
* @return {?}
|
|
1697
|
+
*/
|
|
1698
|
+
_canReceive(item, x, y) {
|
|
1699
|
+
if (!this.enterPredicate(item, this) || !isInsideClientRect(this._clientRect, x, y)) {
|
|
1700
|
+
return false;
|
|
1701
|
+
}
|
|
1702
|
+
/** @type {?} */
|
|
1703
|
+
const elementFromPoint = this._document.elementFromPoint(x, y);
|
|
1704
|
+
// If there's no element at the pointer position, then
|
|
1705
|
+
// the client rect is probably scrolled out of the view.
|
|
1706
|
+
if (!elementFromPoint) {
|
|
1707
|
+
return false;
|
|
1708
|
+
}
|
|
1709
|
+
// The `ClientRect`, that we're using to find the container over which the user is
|
|
1710
|
+
// hovering, doesn't give us any information on whether the element has been scrolled
|
|
1711
|
+
// out of the view or whether it's overlapping with other containers. This means that
|
|
1712
|
+
// we could end up transferring the item into a container that's invisible or is positioned
|
|
1713
|
+
// below another one. We use the result from `elementFromPoint` to get the top-most element
|
|
1714
|
+
// at the pointer position and to find whether it's one of the intersecting drop containers.
|
|
1715
|
+
return elementFromPoint === this.element || this.element.contains(elementFromPoint);
|
|
1716
|
+
}
|
|
1717
|
+
/**
|
|
1718
|
+
* Called by one of the connected drop lists when a dragging sequence has started.
|
|
1719
|
+
* @param {?} sibling Sibling in which dragging has started.
|
|
1720
|
+
* @return {?}
|
|
1721
|
+
*/
|
|
1722
|
+
_startReceiving(sibling) {
|
|
1723
|
+
/** @type {?} */
|
|
1724
|
+
const activeSiblings = this._activeSiblings;
|
|
1725
|
+
if (!activeSiblings.has(sibling)) {
|
|
1726
|
+
activeSiblings.add(sibling);
|
|
1727
|
+
this._cacheOwnPosition();
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
/**
|
|
1731
|
+
* Called by a connected drop list when dragging has stopped.
|
|
1732
|
+
* @param {?} sibling Sibling whose dragging has stopped.
|
|
1733
|
+
* @return {?}
|
|
1734
|
+
*/
|
|
1735
|
+
_stopReceiving(sibling) {
|
|
1736
|
+
this._activeSiblings.delete(sibling);
|
|
1737
|
+
}
|
|
1738
|
+
}
|
|
1739
|
+
/**
|
|
1740
|
+
* Updates the top/left positions of a `ClientRect`, as well as their bottom/right counterparts.
|
|
1741
|
+
* @param {?} clientRect `ClientRect` that should be updated.
|
|
1742
|
+
* @param {?} top Amount to add to the `top` position.
|
|
1743
|
+
* @param {?} left Amount to add to the `left` position.
|
|
1744
|
+
* @return {?}
|
|
1745
|
+
*/
|
|
1746
|
+
function adjustClientRect(clientRect, top, left) {
|
|
1747
|
+
clientRect.top += top;
|
|
1748
|
+
clientRect.bottom = clientRect.top + clientRect.height;
|
|
1749
|
+
clientRect.left += left;
|
|
1750
|
+
clientRect.right = clientRect.left + clientRect.width;
|
|
1751
|
+
}
|
|
1752
|
+
/**
|
|
1753
|
+
* Finds the index of an item that matches a predicate function. Used as an equivalent
|
|
1754
|
+
* of `Array.prototype.find` which isn't part of the standard Google typings.
|
|
1755
|
+
* @template T
|
|
1756
|
+
* @param {?} array Array in which to look for matches.
|
|
1757
|
+
* @param {?} predicate Function used to determine whether an item is a match.
|
|
1758
|
+
* @return {?}
|
|
1759
|
+
*/
|
|
1760
|
+
function findIndex(array, predicate) {
|
|
1761
|
+
for (let i = 0; i < array.length; i++) {
|
|
1762
|
+
if (predicate(array[i], i, array)) {
|
|
1763
|
+
return i;
|
|
1764
|
+
}
|
|
1765
|
+
}
|
|
1766
|
+
return -1;
|
|
1767
|
+
}
|
|
1768
|
+
/**
|
|
1769
|
+
* Checks whether some coordinates are within a `ClientRect`.
|
|
1770
|
+
* @param {?} clientRect ClientRect that is being checked.
|
|
1771
|
+
* @param {?} x Coordinates along the X axis.
|
|
1772
|
+
* @param {?} y Coordinates along the Y axis.
|
|
1773
|
+
* @return {?}
|
|
1774
|
+
*/
|
|
1775
|
+
function isInsideClientRect(clientRect, x, y) {
|
|
1776
|
+
const { top, bottom, left, right } = clientRect;
|
|
1777
|
+
return y >= top && y <= bottom && x >= left && x <= right;
|
|
1778
|
+
}
|
|
1779
|
+
|
|
1780
|
+
/**
|
|
1781
|
+
* @fileoverview added by tsickle
|
|
1782
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
1783
|
+
*/
|
|
1784
|
+
/**
|
|
1785
|
+
* Event options that can be used to bind an active, capturing event.
|
|
1786
|
+
* @type {?}
|
|
1787
|
+
*/
|
|
1788
|
+
const activeCapturingEventOptions = normalizePassiveListenerOptions({
|
|
1789
|
+
passive: false,
|
|
1790
|
+
capture: true
|
|
1791
|
+
});
|
|
1792
|
+
/**
|
|
1793
|
+
* Service that keeps track of all the drag item and drop container
|
|
1794
|
+
* instances, and manages global event listeners on the `document`.
|
|
1795
|
+
* \@docs-private
|
|
1796
|
+
* @template I, C
|
|
1797
|
+
*/
|
|
1798
|
+
// Note: this class is generic, rather than referencing CdkDrag and CdkDropList directly, in order
|
|
1799
|
+
// to avoid circular imports. If we were to reference them here, importing the registry into the
|
|
1800
|
+
// classes that are registering themselves will introduce a circular import.
|
|
1801
|
+
class DragDropRegistry {
|
|
1802
|
+
/**
|
|
1803
|
+
* @param {?} _ngZone
|
|
1804
|
+
* @param {?} _document
|
|
1805
|
+
*/
|
|
1806
|
+
constructor(_ngZone, _document) {
|
|
1807
|
+
this._ngZone = _ngZone;
|
|
1808
|
+
/**
|
|
1809
|
+
* Registered drop container instances.
|
|
1810
|
+
*/
|
|
1811
|
+
this._dropInstances = new Set();
|
|
1812
|
+
/**
|
|
1813
|
+
* Registered drag item instances.
|
|
1814
|
+
*/
|
|
1815
|
+
this._dragInstances = new Set();
|
|
1816
|
+
/**
|
|
1817
|
+
* Drag item instances that are currently being dragged.
|
|
1818
|
+
*/
|
|
1819
|
+
this._activeDragInstances = new Set();
|
|
1820
|
+
/**
|
|
1821
|
+
* Keeps track of the event listeners that we've bound to the `document`.
|
|
1822
|
+
*/
|
|
1823
|
+
this._globalListeners = new Map();
|
|
1824
|
+
/**
|
|
1825
|
+
* Emits the `touchmove` or `mousemove` events that are dispatched
|
|
1826
|
+
* while the user is dragging a drag item instance.
|
|
1827
|
+
*/
|
|
1828
|
+
this.pointerMove = new Subject();
|
|
1829
|
+
/**
|
|
1830
|
+
* Emits the `touchend` or `mouseup` events that are dispatched
|
|
1831
|
+
* while the user is dragging a drag item instance.
|
|
1832
|
+
*/
|
|
1833
|
+
this.pointerUp = new Subject();
|
|
1834
|
+
/**
|
|
1835
|
+
* Event listener that will prevent the default browser action while the user is dragging.
|
|
1836
|
+
* @param event Event whose default action should be prevented.
|
|
1837
|
+
*/
|
|
1838
|
+
this._preventDefaultWhileDragging = (event) => {
|
|
1839
|
+
if (this._activeDragInstances.size) {
|
|
1840
|
+
event.preventDefault();
|
|
1841
|
+
}
|
|
1842
|
+
};
|
|
1843
|
+
this._document = _document;
|
|
1844
|
+
}
|
|
1845
|
+
/**
|
|
1846
|
+
* Adds a drop container to the registry.
|
|
1847
|
+
* @param {?} drop
|
|
1848
|
+
* @return {?}
|
|
1849
|
+
*/
|
|
1850
|
+
registerDropContainer(drop) {
|
|
1851
|
+
if (!this._dropInstances.has(drop)) {
|
|
1852
|
+
if (this.getDropContainer(drop.id)) {
|
|
1853
|
+
throw Error(`Drop instance with id "${drop.id}" has already been registered.`);
|
|
1854
|
+
}
|
|
1855
|
+
this._dropInstances.add(drop);
|
|
1856
|
+
}
|
|
1857
|
+
}
|
|
1858
|
+
/**
|
|
1859
|
+
* Adds a drag item instance to the registry.
|
|
1860
|
+
* @param {?} drag
|
|
1861
|
+
* @return {?}
|
|
1862
|
+
*/
|
|
1863
|
+
registerDragItem(drag) {
|
|
1864
|
+
this._dragInstances.add(drag);
|
|
1865
|
+
// The `touchmove` event gets bound once, ahead of time, because WebKit
|
|
1866
|
+
// won't preventDefault on a dynamically-added `touchmove` listener.
|
|
1867
|
+
// See https://bugs.webkit.org/show_bug.cgi?id=184250.
|
|
1868
|
+
if (this._dragInstances.size === 1) {
|
|
1869
|
+
this._ngZone.runOutsideAngular(() => {
|
|
1870
|
+
// The event handler has to be explicitly active,
|
|
1871
|
+
// because newer browsers make it passive by default.
|
|
1872
|
+
this._document.addEventListener('touchmove', this._preventDefaultWhileDragging, activeCapturingEventOptions);
|
|
1873
|
+
});
|
|
1874
|
+
}
|
|
1875
|
+
}
|
|
1876
|
+
/**
|
|
1877
|
+
* Removes a drop container from the registry.
|
|
1878
|
+
* @param {?} drop
|
|
1879
|
+
* @return {?}
|
|
1880
|
+
*/
|
|
1881
|
+
removeDropContainer(drop) {
|
|
1882
|
+
this._dropInstances.delete(drop);
|
|
1883
|
+
}
|
|
1884
|
+
/**
|
|
1885
|
+
* Removes a drag item instance from the registry.
|
|
1886
|
+
* @param {?} drag
|
|
1887
|
+
* @return {?}
|
|
1888
|
+
*/
|
|
1889
|
+
removeDragItem(drag) {
|
|
1890
|
+
this._dragInstances.delete(drag);
|
|
1891
|
+
this.stopDragging(drag);
|
|
1892
|
+
if (this._dragInstances.size === 0) {
|
|
1893
|
+
this._document.removeEventListener('touchmove', this._preventDefaultWhileDragging, activeCapturingEventOptions);
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1896
|
+
/**
|
|
1897
|
+
* Starts the dragging sequence for a drag instance.
|
|
1898
|
+
* @param {?} drag Drag instance which is being dragged.
|
|
1899
|
+
* @param {?} event Event that initiated the dragging.
|
|
1900
|
+
* @return {?}
|
|
1901
|
+
*/
|
|
1902
|
+
startDragging(drag, event) {
|
|
1903
|
+
this._activeDragInstances.add(drag);
|
|
1904
|
+
if (this._activeDragInstances.size === 1) {
|
|
1905
|
+
/** @type {?} */
|
|
1906
|
+
const isTouchEvent = event.type.startsWith('touch');
|
|
1907
|
+
/** @type {?} */
|
|
1908
|
+
const moveEvent = isTouchEvent ? 'touchmove' : 'mousemove';
|
|
1909
|
+
/** @type {?} */
|
|
1910
|
+
const upEvent = isTouchEvent ? 'touchend' : 'mouseup';
|
|
1911
|
+
// We explicitly bind __active__ listeners here, because newer browsers will default to
|
|
1912
|
+
// passive ones for `mousemove` and `touchmove`. The events need to be active, because we
|
|
1913
|
+
// use `preventDefault` to prevent the page from scrolling while the user is dragging.
|
|
1914
|
+
this._globalListeners
|
|
1915
|
+
.set(moveEvent, {
|
|
1916
|
+
handler: (e) => this.pointerMove.next((/** @type {?} */ (e))),
|
|
1917
|
+
options: activeCapturingEventOptions
|
|
1918
|
+
})
|
|
1919
|
+
.set(upEvent, {
|
|
1920
|
+
handler: (e) => this.pointerUp.next((/** @type {?} */ (e))),
|
|
1921
|
+
options: true
|
|
1922
|
+
})
|
|
1923
|
+
// Preventing the default action on `mousemove` isn't enough to disable text selection
|
|
1924
|
+
// on Safari so we need to prevent the selection event as well. Alternatively this can
|
|
1925
|
+
// be done by setting `user-select: none` on the `body`, however it has causes a style
|
|
1926
|
+
// recalculation which can be expensive on pages with a lot of elements.
|
|
1927
|
+
.set('selectstart', {
|
|
1928
|
+
handler: this._preventDefaultWhileDragging,
|
|
1929
|
+
options: activeCapturingEventOptions
|
|
1930
|
+
});
|
|
1931
|
+
// TODO(crisbeto): prevent mouse wheel scrolling while
|
|
1932
|
+
// dragging until we've set up proper scroll handling.
|
|
1933
|
+
if (!isTouchEvent) {
|
|
1934
|
+
this._globalListeners.set('wheel', {
|
|
1935
|
+
handler: this._preventDefaultWhileDragging,
|
|
1936
|
+
options: activeCapturingEventOptions
|
|
1937
|
+
});
|
|
1938
|
+
}
|
|
1939
|
+
this._ngZone.runOutsideAngular(() => {
|
|
1940
|
+
this._globalListeners.forEach((config, name) => {
|
|
1941
|
+
this._document.addEventListener(name, config.handler, config.options);
|
|
1942
|
+
});
|
|
1943
|
+
});
|
|
1944
|
+
}
|
|
1945
|
+
}
|
|
1946
|
+
/**
|
|
1947
|
+
* Stops dragging a drag item instance.
|
|
1948
|
+
* @param {?} drag
|
|
1949
|
+
* @return {?}
|
|
1950
|
+
*/
|
|
1951
|
+
stopDragging(drag) {
|
|
1952
|
+
this._activeDragInstances.delete(drag);
|
|
1953
|
+
if (this._activeDragInstances.size === 0) {
|
|
1954
|
+
this._clearGlobalListeners();
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1957
|
+
/**
|
|
1958
|
+
* Gets whether a drag item instance is currently being dragged.
|
|
1959
|
+
* @param {?} drag
|
|
1960
|
+
* @return {?}
|
|
1961
|
+
*/
|
|
1962
|
+
isDragging(drag) {
|
|
1963
|
+
return this._activeDragInstances.has(drag);
|
|
1964
|
+
}
|
|
1965
|
+
/**
|
|
1966
|
+
* Gets a drop container by its id.
|
|
1967
|
+
* @deprecated No longer being used. To be removed.
|
|
1968
|
+
* \@breaking-change 8.0.0
|
|
1969
|
+
* @param {?} id
|
|
1970
|
+
* @return {?}
|
|
1971
|
+
*/
|
|
1972
|
+
getDropContainer(id) {
|
|
1973
|
+
return Array.from(this._dropInstances).find(instance => instance.id === id);
|
|
1974
|
+
}
|
|
1975
|
+
/**
|
|
1976
|
+
* @return {?}
|
|
1977
|
+
*/
|
|
1978
|
+
ngOnDestroy() {
|
|
1979
|
+
this._dragInstances.forEach(instance => this.removeDragItem(instance));
|
|
1980
|
+
this._dropInstances.forEach(instance => this.removeDropContainer(instance));
|
|
1981
|
+
this._clearGlobalListeners();
|
|
1982
|
+
this.pointerMove.complete();
|
|
1983
|
+
this.pointerUp.complete();
|
|
1984
|
+
}
|
|
1985
|
+
/**
|
|
1986
|
+
* Clears out the global event listeners from the `document`.
|
|
1987
|
+
* @private
|
|
1988
|
+
* @return {?}
|
|
1989
|
+
*/
|
|
1990
|
+
_clearGlobalListeners() {
|
|
1991
|
+
this._globalListeners.forEach((config, name) => {
|
|
1992
|
+
this._document.removeEventListener(name, config.handler, config.options);
|
|
1993
|
+
});
|
|
1994
|
+
this._globalListeners.clear();
|
|
1995
|
+
}
|
|
1996
|
+
}
|
|
1997
|
+
DragDropRegistry.decorators = [
|
|
1998
|
+
{ type: Injectable, args: [{ providedIn: 'root' },] },
|
|
1999
|
+
];
|
|
2000
|
+
/** @nocollapse */
|
|
2001
|
+
DragDropRegistry.ctorParameters = () => [
|
|
2002
|
+
{ type: NgZone },
|
|
2003
|
+
{ type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] }
|
|
2004
|
+
];
|
|
2005
|
+
/** @nocollapse */ DragDropRegistry.ngInjectableDef = defineInjectable({ factory: function DragDropRegistry_Factory() { return new DragDropRegistry(inject(NgZone), inject(DOCUMENT)); }, token: DragDropRegistry, providedIn: "root" });
|
|
2006
|
+
|
|
2007
|
+
/**
|
|
2008
|
+
* @fileoverview added by tsickle
|
|
2009
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
2010
|
+
*/
|
|
2011
|
+
/**
|
|
2012
|
+
* Default configuration to be used when creating a `DragRef`.
|
|
2013
|
+
* @type {?}
|
|
2014
|
+
*/
|
|
2015
|
+
const DEFAULT_CONFIG = {
|
|
2016
|
+
dragStartThreshold: 5,
|
|
2017
|
+
pointerDirectionChangeThreshold: 5
|
|
2018
|
+
};
|
|
2019
|
+
/**
|
|
2020
|
+
* Service that allows for drag-and-drop functionality to be attached to DOM elements.
|
|
2021
|
+
*/
|
|
2022
|
+
class DragDrop {
|
|
2023
|
+
/**
|
|
2024
|
+
* @param {?} _document
|
|
2025
|
+
* @param {?} _ngZone
|
|
2026
|
+
* @param {?} _viewportRuler
|
|
2027
|
+
* @param {?} _dragDropRegistry
|
|
2028
|
+
*/
|
|
2029
|
+
constructor(_document, _ngZone, _viewportRuler, _dragDropRegistry) {
|
|
2030
|
+
this._document = _document;
|
|
2031
|
+
this._ngZone = _ngZone;
|
|
2032
|
+
this._viewportRuler = _viewportRuler;
|
|
2033
|
+
this._dragDropRegistry = _dragDropRegistry;
|
|
2034
|
+
}
|
|
2035
|
+
/**
|
|
2036
|
+
* Turns an element into a draggable item.
|
|
2037
|
+
* @template T
|
|
2038
|
+
* @param {?} element Element to which to attach the dragging functionality.
|
|
2039
|
+
* @param {?=} config Object used to configure the dragging behavior.
|
|
2040
|
+
* @return {?}
|
|
2041
|
+
*/
|
|
2042
|
+
createDrag(element, config = DEFAULT_CONFIG) {
|
|
2043
|
+
return new DragRef(element, config, this._document, this._ngZone, this._viewportRuler, this._dragDropRegistry);
|
|
2044
|
+
}
|
|
2045
|
+
/**
|
|
2046
|
+
* Turns an element into a drop list.
|
|
2047
|
+
* @template T
|
|
2048
|
+
* @param {?} element Element to which to attach the drop list functionality.
|
|
2049
|
+
* @return {?}
|
|
2050
|
+
*/
|
|
2051
|
+
createDropList(element) {
|
|
2052
|
+
return new DropListRef(element, this._dragDropRegistry, this._document);
|
|
2053
|
+
}
|
|
2054
|
+
}
|
|
2055
|
+
DragDrop.decorators = [
|
|
2056
|
+
{ type: Injectable, args: [{ providedIn: 'root' },] },
|
|
2057
|
+
];
|
|
2058
|
+
/** @nocollapse */
|
|
2059
|
+
DragDrop.ctorParameters = () => [
|
|
2060
|
+
{ type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] },
|
|
2061
|
+
{ type: NgZone },
|
|
2062
|
+
{ type: ViewportRuler },
|
|
2063
|
+
{ type: DragDropRegistry }
|
|
2064
|
+
];
|
|
2065
|
+
/** @nocollapse */ DragDrop.ngInjectableDef = defineInjectable({ factory: function DragDrop_Factory() { return new DragDrop(inject(DOCUMENT), inject(NgZone), inject(ViewportRuler), inject(DragDropRegistry)); }, token: DragDrop, providedIn: "root" });
|
|
2066
|
+
|
|
2067
|
+
/**
|
|
2068
|
+
* @fileoverview added by tsickle
|
|
2069
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
2070
|
+
*/
|
|
2071
|
+
/**
|
|
2072
|
+
* Injection token that is used to provide a CdkDropList instance to CdkDrag.
|
|
2073
|
+
* Used for avoiding circular imports.
|
|
2074
|
+
* @type {?}
|
|
2075
|
+
*/
|
|
2076
|
+
const CDK_DROP_LIST = new InjectionToken('CDK_DROP_LIST');
|
|
2077
|
+
/**
|
|
2078
|
+
* Injection token that is used to provide a CdkDropList instance to CdkDrag.
|
|
2079
|
+
* Used for avoiding circular imports.
|
|
2080
|
+
* @deprecated Use `CDK_DROP_LIST` instead.
|
|
2081
|
+
* \@breaking-change 8.0.0
|
|
2082
|
+
* @type {?}
|
|
2083
|
+
*/
|
|
2084
|
+
const CDK_DROP_LIST_CONTAINER = CDK_DROP_LIST;
|
|
2085
|
+
|
|
2086
|
+
/**
|
|
2087
|
+
* @fileoverview added by tsickle
|
|
2088
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
2089
|
+
*/
|
|
2090
|
+
|
|
2091
|
+
/**
|
|
2092
|
+
* @fileoverview added by tsickle
|
|
2093
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
2094
|
+
*/
|
|
2095
|
+
/**
|
|
2096
|
+
* Injection token that can be used for a `CdkDrag` to provide itself as a parent to the
|
|
2097
|
+
* drag-specific child directive (`CdkDragHandle`, `CdkDragPreview` etc.). Used primarily
|
|
2098
|
+
* to avoid circular imports.
|
|
2099
|
+
* \@docs-private
|
|
2100
|
+
* @type {?}
|
|
2101
|
+
*/
|
|
2102
|
+
const CDK_DRAG_PARENT = new InjectionToken('CDK_DRAG_PARENT');
|
|
2103
|
+
|
|
2104
|
+
/**
|
|
2105
|
+
* @fileoverview added by tsickle
|
|
2106
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
2107
|
+
*/
|
|
2108
|
+
/**
|
|
2109
|
+
* Handle that can be used to drag and CdkDrag instance.
|
|
2110
|
+
*/
|
|
2111
|
+
class CdkDragHandle {
|
|
2112
|
+
/**
|
|
2113
|
+
* @param {?} element
|
|
2114
|
+
* @param {?=} parentDrag
|
|
2115
|
+
*/
|
|
2116
|
+
constructor(element, parentDrag) {
|
|
2117
|
+
this.element = element;
|
|
2118
|
+
/**
|
|
2119
|
+
* Emits when the state of the handle has changed.
|
|
2120
|
+
*/
|
|
2121
|
+
this._stateChanges = new Subject();
|
|
2122
|
+
this._disabled = false;
|
|
2123
|
+
this._parentDrag = parentDrag;
|
|
2124
|
+
toggleNativeDragInteractions(element.nativeElement, false);
|
|
2125
|
+
}
|
|
2126
|
+
/**
|
|
2127
|
+
* Whether starting to drag through this handle is disabled.
|
|
2128
|
+
* @return {?}
|
|
2129
|
+
*/
|
|
2130
|
+
get disabled() { return this._disabled; }
|
|
2131
|
+
/**
|
|
2132
|
+
* @param {?} value
|
|
2133
|
+
* @return {?}
|
|
2134
|
+
*/
|
|
2135
|
+
set disabled(value) {
|
|
2136
|
+
this._disabled = coerceBooleanProperty(value);
|
|
2137
|
+
this._stateChanges.next(this);
|
|
2138
|
+
}
|
|
2139
|
+
/**
|
|
2140
|
+
* @return {?}
|
|
2141
|
+
*/
|
|
2142
|
+
ngOnDestroy() {
|
|
2143
|
+
this._stateChanges.complete();
|
|
2144
|
+
}
|
|
2145
|
+
}
|
|
2146
|
+
CdkDragHandle.decorators = [
|
|
2147
|
+
{ type: Directive, args: [{
|
|
2148
|
+
selector: '[cdkDragHandle]',
|
|
2149
|
+
host: {
|
|
2150
|
+
'class': 'cdk-drag-handle'
|
|
2151
|
+
}
|
|
2152
|
+
},] },
|
|
2153
|
+
];
|
|
2154
|
+
/** @nocollapse */
|
|
2155
|
+
CdkDragHandle.ctorParameters = () => [
|
|
2156
|
+
{ type: ElementRef },
|
|
2157
|
+
{ type: undefined, decorators: [{ type: Inject, args: [CDK_DRAG_PARENT,] }, { type: Optional }] }
|
|
2158
|
+
];
|
|
2159
|
+
CdkDragHandle.propDecorators = {
|
|
2160
|
+
disabled: [{ type: Input, args: ['cdkDragHandleDisabled',] }]
|
|
2161
|
+
};
|
|
2162
|
+
|
|
2163
|
+
/**
|
|
2164
|
+
* @fileoverview added by tsickle
|
|
2165
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
2166
|
+
*/
|
|
2167
|
+
/**
|
|
2168
|
+
* Element that will be used as a template for the placeholder of a CdkDrag when
|
|
2169
|
+
* it is being dragged. The placeholder is displayed in place of the element being dragged.
|
|
2170
|
+
* @template T
|
|
2171
|
+
*/
|
|
2172
|
+
class CdkDragPlaceholder {
|
|
2173
|
+
/**
|
|
2174
|
+
* @param {?} templateRef
|
|
2175
|
+
*/
|
|
2176
|
+
constructor(templateRef) {
|
|
2177
|
+
this.templateRef = templateRef;
|
|
2178
|
+
}
|
|
2179
|
+
}
|
|
2180
|
+
CdkDragPlaceholder.decorators = [
|
|
2181
|
+
{ type: Directive, args: [{
|
|
2182
|
+
selector: 'ng-template[cdkDragPlaceholder]'
|
|
2183
|
+
},] },
|
|
2184
|
+
];
|
|
2185
|
+
/** @nocollapse */
|
|
2186
|
+
CdkDragPlaceholder.ctorParameters = () => [
|
|
2187
|
+
{ type: TemplateRef }
|
|
2188
|
+
];
|
|
2189
|
+
CdkDragPlaceholder.propDecorators = {
|
|
2190
|
+
data: [{ type: Input }]
|
|
2191
|
+
};
|
|
2192
|
+
|
|
2193
|
+
/**
|
|
2194
|
+
* @fileoverview added by tsickle
|
|
2195
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
2196
|
+
*/
|
|
2197
|
+
/**
|
|
2198
|
+
* Element that will be used as a template for the preview
|
|
2199
|
+
* of a CdkDrag when it is being dragged.
|
|
2200
|
+
* @template T
|
|
2201
|
+
*/
|
|
2202
|
+
class CdkDragPreview {
|
|
2203
|
+
/**
|
|
2204
|
+
* @param {?} templateRef
|
|
2205
|
+
*/
|
|
2206
|
+
constructor(templateRef) {
|
|
2207
|
+
this.templateRef = templateRef;
|
|
2208
|
+
}
|
|
2209
|
+
}
|
|
2210
|
+
CdkDragPreview.decorators = [
|
|
2211
|
+
{ type: Directive, args: [{
|
|
2212
|
+
selector: 'ng-template[cdkDragPreview]'
|
|
2213
|
+
},] },
|
|
2214
|
+
];
|
|
2215
|
+
/** @nocollapse */
|
|
2216
|
+
CdkDragPreview.ctorParameters = () => [
|
|
2217
|
+
{ type: TemplateRef }
|
|
2218
|
+
];
|
|
2219
|
+
CdkDragPreview.propDecorators = {
|
|
2220
|
+
data: [{ type: Input }]
|
|
2221
|
+
};
|
|
2222
|
+
|
|
2223
|
+
/**
|
|
2224
|
+
* @fileoverview added by tsickle
|
|
2225
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
2226
|
+
*/
|
|
2227
|
+
/**
|
|
2228
|
+
* Injection token that can be used to configure the behavior of `CdkDrag`.
|
|
2229
|
+
* @type {?}
|
|
2230
|
+
*/
|
|
2231
|
+
const CDK_DRAG_CONFIG = new InjectionToken('CDK_DRAG_CONFIG', {
|
|
2232
|
+
providedIn: 'root',
|
|
2233
|
+
factory: CDK_DRAG_CONFIG_FACTORY
|
|
2234
|
+
});
|
|
2235
|
+
/**
|
|
2236
|
+
* \@docs-private
|
|
2237
|
+
* @return {?}
|
|
2238
|
+
*/
|
|
2239
|
+
function CDK_DRAG_CONFIG_FACTORY() {
|
|
2240
|
+
return { dragStartThreshold: 5, pointerDirectionChangeThreshold: 5 };
|
|
2241
|
+
}
|
|
2242
|
+
/**
|
|
2243
|
+
* Element that can be moved inside a CdkDropList container.
|
|
2244
|
+
* @template T
|
|
2245
|
+
*/
|
|
2246
|
+
class CdkDrag {
|
|
2247
|
+
/**
|
|
2248
|
+
* @param {?} element
|
|
2249
|
+
* @param {?} dropContainer
|
|
2250
|
+
* @param {?} _document
|
|
2251
|
+
* @param {?} _ngZone
|
|
2252
|
+
* @param {?} _viewContainerRef
|
|
2253
|
+
* @param {?} viewportRuler
|
|
2254
|
+
* @param {?} dragDropRegistry
|
|
2255
|
+
* @param {?} config
|
|
2256
|
+
* @param {?} _dir
|
|
2257
|
+
* @param {?=} dragDrop
|
|
2258
|
+
*/
|
|
2259
|
+
constructor(element, dropContainer, _document, _ngZone, _viewContainerRef, viewportRuler, dragDropRegistry, config, _dir,
|
|
2260
|
+
/**
|
|
2261
|
+
* @deprecated `viewportRuler` and `dragDropRegistry` parameters
|
|
2262
|
+
* to be removed. Also `dragDrop` parameter to be made required.
|
|
2263
|
+
* @breaking-change 8.0.0.
|
|
2264
|
+
*/
|
|
2265
|
+
dragDrop) {
|
|
2266
|
+
this.element = element;
|
|
2267
|
+
this.dropContainer = dropContainer;
|
|
2268
|
+
this._document = _document;
|
|
2269
|
+
this._ngZone = _ngZone;
|
|
2270
|
+
this._viewContainerRef = _viewContainerRef;
|
|
2271
|
+
this._dir = _dir;
|
|
2272
|
+
this._destroyed = new Subject();
|
|
2273
|
+
this._disabled = false;
|
|
2274
|
+
/**
|
|
2275
|
+
* Emits when the user starts dragging the item.
|
|
2276
|
+
*/
|
|
2277
|
+
this.started = new EventEmitter();
|
|
2278
|
+
/**
|
|
2279
|
+
* Emits when the user has released a drag item, before any animations have started.
|
|
2280
|
+
*/
|
|
2281
|
+
this.released = new EventEmitter();
|
|
2282
|
+
/**
|
|
2283
|
+
* Emits when the user stops dragging an item in the container.
|
|
2284
|
+
*/
|
|
2285
|
+
this.ended = new EventEmitter();
|
|
2286
|
+
/**
|
|
2287
|
+
* Emits when the user has moved the item into a new container.
|
|
2288
|
+
*/
|
|
2289
|
+
this.entered = new EventEmitter();
|
|
2290
|
+
/**
|
|
2291
|
+
* Emits when the user removes the item its container by dragging it into another container.
|
|
2292
|
+
*/
|
|
2293
|
+
this.exited = new EventEmitter();
|
|
2294
|
+
/**
|
|
2295
|
+
* Emits when the user drops the item inside a container.
|
|
2296
|
+
*/
|
|
2297
|
+
this.dropped = new EventEmitter();
|
|
2298
|
+
/**
|
|
2299
|
+
* Emits as the user is dragging the item. Use with caution,
|
|
2300
|
+
* because this event will fire for every pixel that the user has dragged.
|
|
2301
|
+
*/
|
|
2302
|
+
this.moved = new Observable((observer) => {
|
|
2303
|
+
/** @type {?} */
|
|
2304
|
+
const subscription = this._dragRef.moved.pipe(map(movedEvent => ({
|
|
2305
|
+
source: this,
|
|
2306
|
+
pointerPosition: movedEvent.pointerPosition,
|
|
2307
|
+
event: movedEvent.event,
|
|
2308
|
+
delta: movedEvent.delta
|
|
2309
|
+
}))).subscribe(observer);
|
|
2310
|
+
return () => {
|
|
2311
|
+
subscription.unsubscribe();
|
|
2312
|
+
};
|
|
2313
|
+
});
|
|
2314
|
+
// @breaking-change 8.0.0 Remove null check once the paramter is made required.
|
|
2315
|
+
if (dragDrop) {
|
|
2316
|
+
this._dragRef = dragDrop.createDrag(element, config);
|
|
2317
|
+
}
|
|
2318
|
+
else {
|
|
2319
|
+
this._dragRef = new DragRef(element, config, _document, _ngZone, viewportRuler, dragDropRegistry);
|
|
1003
2320
|
}
|
|
1004
|
-
|
|
1005
|
-
|
|
2321
|
+
this._dragRef.data = this;
|
|
2322
|
+
this._syncInputs(this._dragRef);
|
|
2323
|
+
this._proxyEvents(this._dragRef);
|
|
1006
2324
|
}
|
|
1007
2325
|
/**
|
|
1008
|
-
*
|
|
1009
|
-
* @private
|
|
1010
|
-
* @param {?} referenceElement Element that initiated the dragging.
|
|
1011
|
-
* @param {?} event Event that initiated the dragging.
|
|
2326
|
+
* Whether starting to drag this element is disabled.
|
|
1012
2327
|
* @return {?}
|
|
1013
2328
|
*/
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
const elementRect = this._rootElement.getBoundingClientRect();
|
|
1017
|
-
/** @type {?} */
|
|
1018
|
-
const handleElement = referenceElement === this._rootElement ? null : referenceElement;
|
|
1019
|
-
/** @type {?} */
|
|
1020
|
-
const referenceRect = handleElement ? handleElement.getBoundingClientRect() : elementRect;
|
|
1021
|
-
/** @type {?} */
|
|
1022
|
-
const point = this._isTouchEvent(event) ? event.targetTouches[0] : event;
|
|
1023
|
-
/** @type {?} */
|
|
1024
|
-
const x = point.pageX - referenceRect.left - this._scrollPosition.left;
|
|
1025
|
-
/** @type {?} */
|
|
1026
|
-
const y = point.pageY - referenceRect.top - this._scrollPosition.top;
|
|
1027
|
-
return {
|
|
1028
|
-
x: referenceRect.left - elementRect.left + x,
|
|
1029
|
-
y: referenceRect.top - elementRect.top + y
|
|
1030
|
-
};
|
|
2329
|
+
get disabled() {
|
|
2330
|
+
return this._disabled || (this.dropContainer && this.dropContainer.disabled);
|
|
1031
2331
|
}
|
|
1032
2332
|
/**
|
|
1033
|
-
*
|
|
1034
|
-
* @
|
|
1035
|
-
* @return {?} Promise that resolves when the animation completes.
|
|
2333
|
+
* @param {?} value
|
|
2334
|
+
* @return {?}
|
|
1036
2335
|
*/
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
return Promise.resolve();
|
|
1041
|
-
}
|
|
1042
|
-
/** @type {?} */
|
|
1043
|
-
const placeholderRect = this._placeholder.getBoundingClientRect();
|
|
1044
|
-
// Apply the class that adds a transition to the preview.
|
|
1045
|
-
this._preview.classList.add('cdk-drag-animating');
|
|
1046
|
-
// Move the preview to the placeholder position.
|
|
1047
|
-
this._preview.style.transform = getTransform(placeholderRect.left, placeholderRect.top);
|
|
1048
|
-
// If the element doesn't have a `transition`, the `transitionend` event won't fire. Since
|
|
1049
|
-
// we need to trigger a style recalculation in order for the `cdk-drag-animating` class to
|
|
1050
|
-
// apply its style, we take advantage of the available info to figure out whether we need to
|
|
1051
|
-
// bind the event in the first place.
|
|
1052
|
-
/** @type {?} */
|
|
1053
|
-
const duration = getTransformTransitionDurationInMs(this._preview);
|
|
1054
|
-
if (duration === 0) {
|
|
1055
|
-
return Promise.resolve();
|
|
1056
|
-
}
|
|
1057
|
-
return this._ngZone.runOutsideAngular(() => {
|
|
1058
|
-
return new Promise(resolve => {
|
|
1059
|
-
/** @type {?} */
|
|
1060
|
-
const handler = (/** @type {?} */ (((event) => {
|
|
1061
|
-
if (!event || (event.target === this._preview && event.propertyName === 'transform')) {
|
|
1062
|
-
this._preview.removeEventListener('transitionend', handler);
|
|
1063
|
-
resolve();
|
|
1064
|
-
clearTimeout(timeout);
|
|
1065
|
-
}
|
|
1066
|
-
})));
|
|
1067
|
-
// If a transition is short enough, the browser might not fire the `transitionend` event.
|
|
1068
|
-
// Since we know how long it's supposed to take, add a timeout with a 50% buffer that'll
|
|
1069
|
-
// fire if the transition hasn't completed when it was supposed to.
|
|
1070
|
-
/** @type {?} */
|
|
1071
|
-
const timeout = setTimeout((/** @type {?} */ (handler)), duration * 1.5);
|
|
1072
|
-
this._preview.addEventListener('transitionend', handler);
|
|
1073
|
-
});
|
|
1074
|
-
});
|
|
2336
|
+
set disabled(value) {
|
|
2337
|
+
this._disabled = coerceBooleanProperty(value);
|
|
2338
|
+
this._dragRef.disabled = this._disabled;
|
|
1075
2339
|
}
|
|
1076
2340
|
/**
|
|
1077
|
-
*
|
|
1078
|
-
*
|
|
1079
|
-
* @param {?} element Element to be removed.
|
|
2341
|
+
* Returns the element that is being used as a placeholder
|
|
2342
|
+
* while the current element is being dragged.
|
|
1080
2343
|
* @return {?}
|
|
1081
2344
|
*/
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
element.parentNode.removeChild(element);
|
|
1085
|
-
}
|
|
2345
|
+
getPlaceholderElement() {
|
|
2346
|
+
return this._dragRef.getPlaceholderElement();
|
|
1086
2347
|
}
|
|
1087
2348
|
/**
|
|
1088
|
-
*
|
|
1089
|
-
* @private
|
|
1090
|
-
* @param {?} event
|
|
2349
|
+
* Returns the root draggable element.
|
|
1091
2350
|
* @return {?}
|
|
1092
2351
|
*/
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
const point = this._isTouchEvent(event) ? event.touches[0] : event;
|
|
1096
|
-
return {
|
|
1097
|
-
x: point.pageX - this._scrollPosition.left,
|
|
1098
|
-
y: point.pageY - this._scrollPosition.top
|
|
1099
|
-
};
|
|
2352
|
+
getRootElement() {
|
|
2353
|
+
return this._dragRef.getRootElement();
|
|
1100
2354
|
}
|
|
1101
2355
|
/**
|
|
1102
|
-
*
|
|
1103
|
-
* @private
|
|
1104
|
-
* @param {?} event
|
|
2356
|
+
* Resets a standalone drag item to its initial position.
|
|
1105
2357
|
* @return {?}
|
|
1106
2358
|
*/
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
const point = this._getPointerPositionOnPage(event);
|
|
1110
|
-
/** @type {?} */
|
|
1111
|
-
const dropContainerLock = this.dropContainer ? this.dropContainer.lockAxis : null;
|
|
1112
|
-
if (this.lockAxis === 'x' || dropContainerLock === 'x') {
|
|
1113
|
-
point.y = this._pickupPositionOnPage.y;
|
|
1114
|
-
}
|
|
1115
|
-
else if (this.lockAxis === 'y' || dropContainerLock === 'y') {
|
|
1116
|
-
point.x = this._pickupPositionOnPage.x;
|
|
1117
|
-
}
|
|
1118
|
-
return point;
|
|
2359
|
+
reset() {
|
|
2360
|
+
this._dragRef.reset();
|
|
1119
2361
|
}
|
|
1120
2362
|
/**
|
|
1121
|
-
* Determines whether an event is a touch event.
|
|
1122
|
-
* @private
|
|
1123
|
-
* @param {?} event
|
|
1124
2363
|
* @return {?}
|
|
1125
2364
|
*/
|
|
1126
|
-
|
|
1127
|
-
|
|
2365
|
+
ngAfterViewInit() {
|
|
2366
|
+
// We need to wait for the zone to stabilize, in order for the reference
|
|
2367
|
+
// element to be in the proper place in the DOM. This is mostly relevant
|
|
2368
|
+
// for draggable elements inside portals since they get stamped out in
|
|
2369
|
+
// their original DOM position and then they get transferred to the portal.
|
|
2370
|
+
this._ngZone.onStable.asObservable()
|
|
2371
|
+
.pipe(take(1), takeUntil(this._destroyed))
|
|
2372
|
+
.subscribe(() => {
|
|
2373
|
+
this._updateRootElement();
|
|
2374
|
+
// Listen for any newly-added handles.
|
|
2375
|
+
this._handles.changes.pipe(startWith(this._handles),
|
|
2376
|
+
// Sync the new handles with the DragRef.
|
|
2377
|
+
tap((handles) => {
|
|
2378
|
+
/** @type {?} */
|
|
2379
|
+
const childHandleElements = handles
|
|
2380
|
+
.filter(handle => handle._parentDrag === this)
|
|
2381
|
+
.map(handle => handle.element);
|
|
2382
|
+
this._dragRef.withHandles(childHandleElements);
|
|
2383
|
+
}),
|
|
2384
|
+
// Listen if the state of any of the handles changes.
|
|
2385
|
+
switchMap((handles) => {
|
|
2386
|
+
return merge(...handles.map(item => item._stateChanges));
|
|
2387
|
+
}), takeUntil(this._destroyed)).subscribe(handleInstance => {
|
|
2388
|
+
// Enabled/disable the handle that changed in the DragRef.
|
|
2389
|
+
/** @type {?} */
|
|
2390
|
+
const dragRef = this._dragRef;
|
|
2391
|
+
/** @type {?} */
|
|
2392
|
+
const handle = handleInstance.element.nativeElement;
|
|
2393
|
+
handleInstance.disabled ? dragRef.disableHandle(handle) : dragRef.enableHandle(handle);
|
|
2394
|
+
});
|
|
2395
|
+
});
|
|
1128
2396
|
}
|
|
1129
2397
|
/**
|
|
1130
|
-
*
|
|
1131
|
-
* @private
|
|
2398
|
+
* @param {?} changes
|
|
1132
2399
|
* @return {?}
|
|
1133
2400
|
*/
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
2401
|
+
ngOnChanges(changes) {
|
|
2402
|
+
/** @type {?} */
|
|
2403
|
+
const rootSelectorChange = changes.rootElementSelector;
|
|
2404
|
+
// We don't have to react to the first change since it's being
|
|
2405
|
+
// handled in `ngAfterViewInit` where it needs to be deferred.
|
|
2406
|
+
if (rootSelectorChange && !rootSelectorChange.firstChange) {
|
|
2407
|
+
this._updateRootElement();
|
|
1140
2408
|
}
|
|
1141
|
-
this._preview = this._previewRef = (/** @type {?} */ (null));
|
|
1142
2409
|
}
|
|
1143
2410
|
/**
|
|
1144
|
-
* Destroys the placeholder element and its ViewRef.
|
|
1145
|
-
* @private
|
|
1146
2411
|
* @return {?}
|
|
1147
2412
|
*/
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
if (this._placeholderRef) {
|
|
1153
|
-
this._placeholderRef.destroy();
|
|
1154
|
-
}
|
|
1155
|
-
this._placeholder = this._placeholderRef = (/** @type {?} */ (null));
|
|
2413
|
+
ngOnDestroy() {
|
|
2414
|
+
this._destroyed.next();
|
|
2415
|
+
this._destroyed.complete();
|
|
2416
|
+
this._dragRef.dispose();
|
|
1156
2417
|
}
|
|
1157
2418
|
/**
|
|
1158
|
-
*
|
|
2419
|
+
* Syncs the root element with the `DragRef`.
|
|
1159
2420
|
* @private
|
|
1160
|
-
* @param {?} pointerPositionOnPage
|
|
1161
2421
|
* @return {?}
|
|
1162
2422
|
*/
|
|
1163
|
-
|
|
1164
|
-
const { x, y } = pointerPositionOnPage;
|
|
1165
|
-
/** @type {?} */
|
|
1166
|
-
const delta = this._pointerDirectionDelta;
|
|
1167
|
-
/** @type {?} */
|
|
1168
|
-
const positionSinceLastChange = this._pointerPositionAtLastDirectionChange;
|
|
1169
|
-
// Amount of pixels the user has dragged since the last time the direction changed.
|
|
2423
|
+
_updateRootElement() {
|
|
1170
2424
|
/** @type {?} */
|
|
1171
|
-
const
|
|
2425
|
+
const element = this.element.nativeElement;
|
|
1172
2426
|
/** @type {?} */
|
|
1173
|
-
const
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
if (changeX > this._config.pointerDirectionChangeThreshold) {
|
|
1179
|
-
delta.x = x > positionSinceLastChange.x ? 1 : -1;
|
|
1180
|
-
positionSinceLastChange.x = x;
|
|
1181
|
-
}
|
|
1182
|
-
if (changeY > this._config.pointerDirectionChangeThreshold) {
|
|
1183
|
-
delta.y = y > positionSinceLastChange.y ? 1 : -1;
|
|
1184
|
-
positionSinceLastChange.y = y;
|
|
2427
|
+
const rootElement = this.rootElementSelector ?
|
|
2428
|
+
getClosestMatchingAncestor(element, this.rootElementSelector) : element;
|
|
2429
|
+
if (rootElement && rootElement.nodeType !== this._document.ELEMENT_NODE) {
|
|
2430
|
+
throw Error(`cdkDrag must be attached to an element node. ` +
|
|
2431
|
+
`Currently attached to "${rootElement.nodeName}".`);
|
|
1185
2432
|
}
|
|
1186
|
-
|
|
2433
|
+
this._dragRef.withRootElement(rootElement || element);
|
|
1187
2434
|
}
|
|
1188
2435
|
/**
|
|
1189
|
-
* Gets the
|
|
2436
|
+
* Gets the boundary element, based on the `boundaryElementSelector`.
|
|
1190
2437
|
* @private
|
|
1191
2438
|
* @return {?}
|
|
1192
2439
|
*/
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
2440
|
+
_getBoundaryElement() {
|
|
2441
|
+
/** @type {?} */
|
|
2442
|
+
const selector = this.boundaryElementSelector;
|
|
2443
|
+
return selector ? getClosestMatchingAncestor(this.element.nativeElement, selector) : null;
|
|
2444
|
+
}
|
|
2445
|
+
/**
|
|
2446
|
+
* Syncs the inputs of the CdkDrag with the options of the underlying DragRef.
|
|
2447
|
+
* @private
|
|
2448
|
+
* @param {?} ref
|
|
2449
|
+
* @return {?}
|
|
2450
|
+
*/
|
|
2451
|
+
_syncInputs(ref) {
|
|
2452
|
+
ref.beforeStarted.subscribe(() => {
|
|
2453
|
+
if (!ref.isDragging()) {
|
|
2454
|
+
/** @type {?} */
|
|
2455
|
+
const dir = this._dir;
|
|
2456
|
+
/** @type {?} */
|
|
2457
|
+
const placeholder = this._placeholderTemplate ? {
|
|
2458
|
+
template: this._placeholderTemplate.templateRef,
|
|
2459
|
+
context: this._placeholderTemplate.data,
|
|
2460
|
+
viewContainer: this._viewContainerRef
|
|
2461
|
+
} : null;
|
|
2462
|
+
/** @type {?} */
|
|
2463
|
+
const preview = this._previewTemplate ? {
|
|
2464
|
+
template: this._previewTemplate.templateRef,
|
|
2465
|
+
context: this._previewTemplate.data,
|
|
2466
|
+
viewContainer: this._viewContainerRef
|
|
2467
|
+
} : null;
|
|
2468
|
+
ref.disabled = this.disabled;
|
|
2469
|
+
ref.lockAxis = this.lockAxis;
|
|
2470
|
+
ref
|
|
2471
|
+
.withBoundaryElement(this._getBoundaryElement())
|
|
2472
|
+
.withPlaceholderTemplate(placeholder)
|
|
2473
|
+
.withPreviewTemplate(preview);
|
|
2474
|
+
if (dir) {
|
|
2475
|
+
ref.withDirection(dir.value);
|
|
1204
2476
|
}
|
|
1205
|
-
currentElement = currentElement.parentElement;
|
|
1206
2477
|
}
|
|
1207
|
-
}
|
|
1208
|
-
return this.element.nativeElement;
|
|
2478
|
+
});
|
|
1209
2479
|
}
|
|
1210
2480
|
/**
|
|
1211
|
-
*
|
|
2481
|
+
* Proxies the events from a DragRef to events that
|
|
2482
|
+
* match the interfaces of the CdkDrag outputs.
|
|
1212
2483
|
* @private
|
|
2484
|
+
* @param {?} ref
|
|
1213
2485
|
* @return {?}
|
|
1214
2486
|
*/
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
2487
|
+
_proxyEvents(ref) {
|
|
2488
|
+
ref.started.subscribe(() => {
|
|
2489
|
+
this.started.emit({ source: this });
|
|
2490
|
+
});
|
|
2491
|
+
ref.released.subscribe(() => {
|
|
2492
|
+
this.released.emit({ source: this });
|
|
2493
|
+
});
|
|
2494
|
+
ref.ended.subscribe(() => {
|
|
2495
|
+
this.ended.emit({ source: this });
|
|
2496
|
+
});
|
|
2497
|
+
ref.entered.subscribe(event => {
|
|
2498
|
+
this.entered.emit({
|
|
2499
|
+
container: event.container.data,
|
|
2500
|
+
item: this
|
|
2501
|
+
});
|
|
2502
|
+
});
|
|
2503
|
+
ref.exited.subscribe(event => {
|
|
2504
|
+
this.exited.emit({
|
|
2505
|
+
container: event.container.data,
|
|
2506
|
+
item: this
|
|
2507
|
+
});
|
|
2508
|
+
});
|
|
2509
|
+
ref.dropped.subscribe(event => {
|
|
2510
|
+
this.dropped.emit({
|
|
2511
|
+
previousIndex: event.previousIndex,
|
|
2512
|
+
currentIndex: event.currentIndex,
|
|
2513
|
+
previousContainer: event.previousContainer.data,
|
|
2514
|
+
container: event.container.data,
|
|
2515
|
+
isPointerOverContainer: event.isPointerOverContainer,
|
|
2516
|
+
item: this
|
|
2517
|
+
});
|
|
2518
|
+
});
|
|
1218
2519
|
}
|
|
1219
2520
|
}
|
|
1220
2521
|
CdkDrag.decorators = [
|
|
@@ -1223,25 +2524,23 @@ CdkDrag.decorators = [
|
|
|
1223
2524
|
exportAs: 'cdkDrag',
|
|
1224
2525
|
host: {
|
|
1225
2526
|
'class': 'cdk-drag',
|
|
1226
|
-
'[class.cdk-drag-dragging]': '
|
|
2527
|
+
'[class.cdk-drag-dragging]': '_dragRef.isDragging()',
|
|
1227
2528
|
},
|
|
1228
|
-
providers: [{
|
|
1229
|
-
provide: CDK_DRAG_PARENT,
|
|
1230
|
-
useExisting: CdkDrag
|
|
1231
|
-
}]
|
|
2529
|
+
providers: [{ provide: CDK_DRAG_PARENT, useExisting: CdkDrag }]
|
|
1232
2530
|
},] },
|
|
1233
2531
|
];
|
|
1234
2532
|
/** @nocollapse */
|
|
1235
2533
|
CdkDrag.ctorParameters = () => [
|
|
1236
2534
|
{ type: ElementRef },
|
|
1237
|
-
{ type: undefined, decorators: [{ type: Inject, args: [
|
|
2535
|
+
{ type: undefined, decorators: [{ type: Inject, args: [CDK_DROP_LIST,] }, { type: Optional }, { type: SkipSelf }] },
|
|
1238
2536
|
{ type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] },
|
|
1239
2537
|
{ type: NgZone },
|
|
1240
2538
|
{ type: ViewContainerRef },
|
|
1241
2539
|
{ type: ViewportRuler },
|
|
1242
2540
|
{ type: DragDropRegistry },
|
|
1243
2541
|
{ type: undefined, decorators: [{ type: Inject, args: [CDK_DRAG_CONFIG,] }] },
|
|
1244
|
-
{ type: Directionality, decorators: [{ type: Optional }] }
|
|
2542
|
+
{ type: Directionality, decorators: [{ type: Optional }] },
|
|
2543
|
+
{ type: DragDrop }
|
|
1245
2544
|
];
|
|
1246
2545
|
CdkDrag.propDecorators = {
|
|
1247
2546
|
_handles: [{ type: ContentChildren, args: [CdkDragHandle, { descendants: true },] }],
|
|
@@ -1250,8 +2549,10 @@ CdkDrag.propDecorators = {
|
|
|
1250
2549
|
data: [{ type: Input, args: ['cdkDragData',] }],
|
|
1251
2550
|
lockAxis: [{ type: Input, args: ['cdkDragLockAxis',] }],
|
|
1252
2551
|
rootElementSelector: [{ type: Input, args: ['cdkDragRootElement',] }],
|
|
2552
|
+
boundaryElementSelector: [{ type: Input, args: ['cdkDragBoundary',] }],
|
|
1253
2553
|
disabled: [{ type: Input, args: ['cdkDragDisabled',] }],
|
|
1254
2554
|
started: [{ type: Output, args: ['cdkDragStarted',] }],
|
|
2555
|
+
released: [{ type: Output, args: ['cdkDragReleased',] }],
|
|
1255
2556
|
ended: [{ type: Output, args: ['cdkDragEnded',] }],
|
|
1256
2557
|
entered: [{ type: Output, args: ['cdkDragEntered',] }],
|
|
1257
2558
|
exited: [{ type: Output, args: ['cdkDragExited',] }],
|
|
@@ -1259,103 +2560,23 @@ CdkDrag.propDecorators = {
|
|
|
1259
2560
|
moved: [{ type: Output, args: ['cdkDragMoved',] }]
|
|
1260
2561
|
};
|
|
1261
2562
|
/**
|
|
1262
|
-
* Gets
|
|
1263
|
-
* @param {?}
|
|
1264
|
-
* @param {?}
|
|
1265
|
-
* @return {?}
|
|
1266
|
-
*/
|
|
1267
|
-
function getTransform(x, y) {
|
|
1268
|
-
// Round the transforms since some browsers will
|
|
1269
|
-
// blur the elements, for sub-pixel transforms.
|
|
1270
|
-
return `translate3d(${Math.round(x)}px, ${Math.round(y)}px, 0)`;
|
|
1271
|
-
}
|
|
1272
|
-
/**
|
|
1273
|
-
* Creates a deep clone of an element.
|
|
1274
|
-
* @param {?} node
|
|
1275
|
-
* @return {?}
|
|
1276
|
-
*/
|
|
1277
|
-
function deepCloneNode(node) {
|
|
1278
|
-
/** @type {?} */
|
|
1279
|
-
const clone = (/** @type {?} */ (node.cloneNode(true)));
|
|
1280
|
-
// Remove the `id` to avoid having multiple elements with the same id on the page.
|
|
1281
|
-
clone.removeAttribute('id');
|
|
1282
|
-
return clone;
|
|
1283
|
-
}
|
|
1284
|
-
|
|
1285
|
-
/**
|
|
1286
|
-
* @fileoverview added by tsickle
|
|
1287
|
-
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
1288
|
-
*/
|
|
1289
|
-
|
|
1290
|
-
/**
|
|
1291
|
-
* Moves an item one index in an array to another.
|
|
1292
|
-
* @template T
|
|
1293
|
-
* @param {?} array Array in which to move the item.
|
|
1294
|
-
* @param {?} fromIndex Starting index of the item.
|
|
1295
|
-
* @param {?} toIndex Index to which the item should be moved.
|
|
1296
|
-
* @return {?}
|
|
1297
|
-
*/
|
|
1298
|
-
function moveItemInArray(array, fromIndex, toIndex) {
|
|
1299
|
-
/** @type {?} */
|
|
1300
|
-
const from = clamp(fromIndex, array.length - 1);
|
|
1301
|
-
/** @type {?} */
|
|
1302
|
-
const to = clamp(toIndex, array.length - 1);
|
|
1303
|
-
if (from === to) {
|
|
1304
|
-
return;
|
|
1305
|
-
}
|
|
1306
|
-
/** @type {?} */
|
|
1307
|
-
const target = array[from];
|
|
1308
|
-
/** @type {?} */
|
|
1309
|
-
const delta = to < from ? -1 : 1;
|
|
1310
|
-
for (let i = from; i !== to; i += delta) {
|
|
1311
|
-
array[i] = array[i + delta];
|
|
1312
|
-
}
|
|
1313
|
-
array[to] = target;
|
|
1314
|
-
}
|
|
1315
|
-
/**
|
|
1316
|
-
* Moves an item from one array to another.
|
|
1317
|
-
* @template T
|
|
1318
|
-
* @param {?} currentArray Array from which to transfer the item.
|
|
1319
|
-
* @param {?} targetArray Array into which to put the item.
|
|
1320
|
-
* @param {?} currentIndex Index of the item in its current array.
|
|
1321
|
-
* @param {?} targetIndex Index at which to insert the item.
|
|
1322
|
-
* @return {?}
|
|
1323
|
-
*/
|
|
1324
|
-
function transferArrayItem(currentArray, targetArray, currentIndex, targetIndex) {
|
|
1325
|
-
/** @type {?} */
|
|
1326
|
-
const from = clamp(currentIndex, currentArray.length - 1);
|
|
1327
|
-
/** @type {?} */
|
|
1328
|
-
const to = clamp(targetIndex, targetArray.length);
|
|
1329
|
-
if (currentArray.length) {
|
|
1330
|
-
targetArray.splice(to, 0, currentArray.splice(from, 1)[0]);
|
|
1331
|
-
}
|
|
1332
|
-
}
|
|
1333
|
-
/**
|
|
1334
|
-
* Copies an item from one array to another, leaving it in its
|
|
1335
|
-
* original position in current array.
|
|
1336
|
-
* @template T
|
|
1337
|
-
* @param {?} currentArray Array from which to copy the item.
|
|
1338
|
-
* @param {?} targetArray Array into which is copy the item.
|
|
1339
|
-
* @param {?} currentIndex Index of the item in its current array.
|
|
1340
|
-
* @param {?} targetIndex Index at which to insert the item.
|
|
1341
|
-
*
|
|
2563
|
+
* Gets the closest ancestor of an element that matches a selector.
|
|
2564
|
+
* @param {?} element
|
|
2565
|
+
* @param {?} selector
|
|
1342
2566
|
* @return {?}
|
|
1343
2567
|
*/
|
|
1344
|
-
function
|
|
2568
|
+
function getClosestMatchingAncestor(element, selector) {
|
|
1345
2569
|
/** @type {?} */
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
2570
|
+
let currentElement = (/** @type {?} */ (element.parentElement));
|
|
2571
|
+
while (currentElement) {
|
|
2572
|
+
// IE doesn't support `matches` so we have to fall back to `msMatchesSelector`.
|
|
2573
|
+
if (currentElement.matches ? currentElement.matches(selector) :
|
|
2574
|
+
((/** @type {?} */ (currentElement))).msMatchesSelector(selector)) {
|
|
2575
|
+
return currentElement;
|
|
2576
|
+
}
|
|
2577
|
+
currentElement = currentElement.parentElement;
|
|
1349
2578
|
}
|
|
1350
|
-
|
|
1351
|
-
/**
|
|
1352
|
-
* Clamps a number between zero and a maximum.
|
|
1353
|
-
* @param {?} value
|
|
1354
|
-
* @param {?} max
|
|
1355
|
-
* @return {?}
|
|
1356
|
-
*/
|
|
1357
|
-
function clamp(value, max) {
|
|
1358
|
-
return Math.max(0, Math.min(max, value));
|
|
2579
|
+
return null;
|
|
1359
2580
|
}
|
|
1360
2581
|
|
|
1361
2582
|
/**
|
|
@@ -1375,6 +2596,19 @@ class CdkDropListGroup {
|
|
|
1375
2596
|
* Drop lists registered inside the group.
|
|
1376
2597
|
*/
|
|
1377
2598
|
this._items = new Set();
|
|
2599
|
+
this._disabled = false;
|
|
2600
|
+
}
|
|
2601
|
+
/**
|
|
2602
|
+
* Whether starting a dragging sequence from inside this group is disabled.
|
|
2603
|
+
* @return {?}
|
|
2604
|
+
*/
|
|
2605
|
+
get disabled() { return this._disabled; }
|
|
2606
|
+
/**
|
|
2607
|
+
* @param {?} value
|
|
2608
|
+
* @return {?}
|
|
2609
|
+
*/
|
|
2610
|
+
set disabled(value) {
|
|
2611
|
+
this._disabled = coerceBooleanProperty(value);
|
|
1378
2612
|
}
|
|
1379
2613
|
/**
|
|
1380
2614
|
* @return {?}
|
|
@@ -1389,6 +2623,9 @@ CdkDropListGroup.decorators = [
|
|
|
1389
2623
|
exportAs: 'cdkDropListGroup',
|
|
1390
2624
|
},] },
|
|
1391
2625
|
];
|
|
2626
|
+
CdkDropListGroup.propDecorators = {
|
|
2627
|
+
disabled: [{ type: Input, args: ['cdkDropListGroupDisabled',] }]
|
|
2628
|
+
};
|
|
1392
2629
|
|
|
1393
2630
|
/**
|
|
1394
2631
|
* @fileoverview added by tsickle
|
|
@@ -1398,14 +2635,11 @@ CdkDropListGroup.decorators = [
|
|
|
1398
2635
|
* Counter used to generate unique ids for drop zones.
|
|
1399
2636
|
* @type {?}
|
|
1400
2637
|
*/
|
|
1401
|
-
let _uniqueIdCounter = 0;
|
|
1402
|
-
/**
|
|
1403
|
-
* Proximity, as a ratio to width/height, at which a
|
|
1404
|
-
* dragged item will affect the drop container.
|
|
1405
|
-
* @type {?}
|
|
1406
|
-
*/
|
|
1407
|
-
const DROP_PROXIMITY_THRESHOLD = 0.05;
|
|
2638
|
+
let _uniqueIdCounter$1 = 0;
|
|
1408
2639
|
const ɵ0 = undefined;
|
|
2640
|
+
// @breaking-change 8.0.0 `CdkDropList` implements `CdkDropListContainer` for backwards
|
|
2641
|
+
// compatiblity. The implements clause, as well as all the methods that it enforces can
|
|
2642
|
+
// be removed when `CdkDropListContainer` is deleted.
|
|
1409
2643
|
/**
|
|
1410
2644
|
* Container that wraps a set of draggable items.
|
|
1411
2645
|
* @template T
|
|
@@ -1413,17 +2647,28 @@ const ɵ0 = undefined;
|
|
|
1413
2647
|
class CdkDropList {
|
|
1414
2648
|
/**
|
|
1415
2649
|
* @param {?} element
|
|
1416
|
-
* @param {?}
|
|
2650
|
+
* @param {?} dragDropRegistry
|
|
1417
2651
|
* @param {?} _changeDetectorRef
|
|
1418
2652
|
* @param {?=} _dir
|
|
1419
2653
|
* @param {?=} _group
|
|
2654
|
+
* @param {?=} _document
|
|
2655
|
+
* @param {?=} dragDrop
|
|
2656
|
+
*/
|
|
2657
|
+
constructor(element, dragDropRegistry, _changeDetectorRef, _dir, _group, _document,
|
|
2658
|
+
/**
|
|
2659
|
+
* @deprecated `dragDropRegistry` and `_document` parameters to be removed.
|
|
2660
|
+
* Also `dragDrop` parameter to be made required.
|
|
2661
|
+
* @breaking-change 8.0.0.
|
|
1420
2662
|
*/
|
|
1421
|
-
|
|
2663
|
+
dragDrop) {
|
|
1422
2664
|
this.element = element;
|
|
1423
|
-
this._dragDropRegistry = _dragDropRegistry;
|
|
1424
2665
|
this._changeDetectorRef = _changeDetectorRef;
|
|
1425
2666
|
this._dir = _dir;
|
|
1426
2667
|
this._group = _group;
|
|
2668
|
+
/**
|
|
2669
|
+
* Emits when the list has been destroyed.
|
|
2670
|
+
*/
|
|
2671
|
+
this._destroyed = new Subject();
|
|
1427
2672
|
/**
|
|
1428
2673
|
* Other draggable containers that this container is connected to and into which the
|
|
1429
2674
|
* container's items can be transferred. Can either be references to other drop containers,
|
|
@@ -1438,477 +2683,246 @@ class CdkDropList {
|
|
|
1438
2683
|
* Unique ID for the drop zone. Can be used as a reference
|
|
1439
2684
|
* in the `connectedTo` of another `CdkDropList`.
|
|
1440
2685
|
*/
|
|
1441
|
-
this.id = `cdk-drop-list-${_uniqueIdCounter++}`;
|
|
2686
|
+
this.id = `cdk-drop-list-${_uniqueIdCounter$1++}`;
|
|
1442
2687
|
this._disabled = false;
|
|
1443
2688
|
/**
|
|
1444
2689
|
* Function that is used to determine whether an item
|
|
1445
2690
|
* is allowed to be moved into a drop container.
|
|
1446
2691
|
*/
|
|
1447
2692
|
this.enterPredicate = () => true;
|
|
1448
|
-
/**
|
|
1449
|
-
* Emits when the user drops an item inside the container.
|
|
1450
|
-
*/
|
|
1451
|
-
this.dropped = new EventEmitter();
|
|
1452
|
-
/**
|
|
1453
|
-
* Emits when the user has moved a new drag item into this container.
|
|
1454
|
-
*/
|
|
1455
|
-
this.entered = new EventEmitter();
|
|
1456
|
-
/**
|
|
1457
|
-
* Emits when the user removes an item from the container
|
|
1458
|
-
* by dragging it into another container.
|
|
1459
|
-
*/
|
|
1460
|
-
this.exited = new EventEmitter();
|
|
1461
|
-
/**
|
|
1462
|
-
* Emits as the user is swapping items while actively dragging.
|
|
1463
|
-
*/
|
|
1464
|
-
this.sorted = new EventEmitter();
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
this.
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
this.
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
* @
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
* @return {?}
|
|
1493
|
-
*/
|
|
1494
|
-
|
|
1495
|
-
this.
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
if (this._group) {
|
|
1506
|
-
this._group._items.delete(this);
|
|
1507
|
-
}
|
|
1508
|
-
}
|
|
1509
|
-
/**
|
|
1510
|
-
* Starts dragging an item.
|
|
1511
|
-
* @return {?}
|
|
1512
|
-
*/
|
|
1513
|
-
start() {
|
|
1514
|
-
this._dragging = true;
|
|
1515
|
-
this._activeDraggables = this._draggables.toArray();
|
|
1516
|
-
this._cachePositions();
|
|
1517
|
-
this._changeDetectorRef.markForCheck();
|
|
1518
|
-
}
|
|
1519
|
-
/**
|
|
1520
|
-
* Drops an item into this container.
|
|
1521
|
-
* @param {?} item Item being dropped into the container.
|
|
1522
|
-
* @param {?} currentIndex Index at which the item should be inserted.
|
|
1523
|
-
* @param {?} previousContainer Container from which the item got dragged in.
|
|
1524
|
-
* @return {?}
|
|
1525
|
-
*/
|
|
1526
|
-
drop(item, currentIndex, previousContainer) {
|
|
1527
|
-
this._reset();
|
|
1528
|
-
this.dropped.emit({
|
|
1529
|
-
item,
|
|
1530
|
-
currentIndex,
|
|
1531
|
-
previousIndex: previousContainer.getItemIndex(item),
|
|
1532
|
-
container: this,
|
|
1533
|
-
// TODO(crisbeto): reconsider whether to make this null if the containers are the same.
|
|
1534
|
-
previousContainer
|
|
1535
|
-
});
|
|
1536
|
-
}
|
|
1537
|
-
/**
|
|
1538
|
-
* Emits an event to indicate that the user moved an item into the container.
|
|
1539
|
-
* @param {?} item Item that was moved into the container.
|
|
1540
|
-
* @param {?} pointerX Position of the item along the X axis.
|
|
1541
|
-
* @param {?} pointerY Position of the item along the Y axis.
|
|
1542
|
-
* @return {?}
|
|
1543
|
-
*/
|
|
1544
|
-
enter(item, pointerX, pointerY) {
|
|
1545
|
-
this.entered.emit({ item, container: this });
|
|
1546
|
-
this.start();
|
|
1547
|
-
// We use the coordinates of where the item entered the drop
|
|
1548
|
-
// zone to figure out at which index it should be inserted.
|
|
1549
|
-
/** @type {?} */
|
|
1550
|
-
const newIndex = this._getItemIndexFromPointerPosition(item, pointerX, pointerY);
|
|
1551
|
-
/** @type {?} */
|
|
1552
|
-
const currentIndex = this._activeDraggables.indexOf(item);
|
|
1553
|
-
/** @type {?} */
|
|
1554
|
-
const newPositionReference = this._activeDraggables[newIndex];
|
|
1555
|
-
/** @type {?} */
|
|
1556
|
-
const placeholder = item.getPlaceholderElement();
|
|
1557
|
-
// Since the item may be in the `activeDraggables` already (e.g. if the user dragged it
|
|
1558
|
-
// into another container and back again), we have to ensure that it isn't duplicated.
|
|
1559
|
-
if (currentIndex > -1) {
|
|
1560
|
-
this._activeDraggables.splice(currentIndex, 1);
|
|
1561
|
-
}
|
|
1562
|
-
// Don't use items that are being dragged as a reference, because
|
|
1563
|
-
// their element has been moved down to the bottom of the body.
|
|
1564
|
-
if (newPositionReference && !this._dragDropRegistry.isDragging(newPositionReference)) {
|
|
1565
|
-
/** @type {?} */
|
|
1566
|
-
const element = newPositionReference.getRootElement();
|
|
1567
|
-
(/** @type {?} */ (element.parentElement)).insertBefore(placeholder, element);
|
|
1568
|
-
this._activeDraggables.splice(newIndex, 0, item);
|
|
1569
|
-
}
|
|
1570
|
-
else {
|
|
1571
|
-
this.element.nativeElement.appendChild(placeholder);
|
|
1572
|
-
this._activeDraggables.push(item);
|
|
1573
|
-
}
|
|
1574
|
-
// The transform needs to be cleared so it doesn't throw off the measurements.
|
|
1575
|
-
placeholder.style.transform = '';
|
|
1576
|
-
// Note that the positions were already cached when we called `start` above,
|
|
1577
|
-
// but we need to refresh them since the amount of items has changed.
|
|
1578
|
-
this._cachePositions();
|
|
1579
|
-
}
|
|
1580
|
-
/**
|
|
1581
|
-
* Removes an item from the container after it was dragged into another container by the user.
|
|
1582
|
-
* @param {?} item Item that was dragged out.
|
|
1583
|
-
* @return {?}
|
|
1584
|
-
*/
|
|
1585
|
-
exit(item) {
|
|
1586
|
-
this._reset();
|
|
1587
|
-
this.exited.emit({ item, container: this });
|
|
1588
|
-
}
|
|
1589
|
-
/**
|
|
1590
|
-
* Figures out the index of an item in the container.
|
|
1591
|
-
* @param {?} item Item whose index should be determined.
|
|
1592
|
-
* @return {?}
|
|
1593
|
-
*/
|
|
1594
|
-
getItemIndex(item) {
|
|
1595
|
-
if (!this._dragging) {
|
|
1596
|
-
return this._draggables.toArray().indexOf(item);
|
|
1597
|
-
}
|
|
1598
|
-
// Items are sorted always by top/left in the cache, however they flow differently in RTL.
|
|
1599
|
-
// The rest of the logic still stands no matter what orientation we're in, however
|
|
1600
|
-
// we need to invert the array when determining the index.
|
|
1601
|
-
/** @type {?} */
|
|
1602
|
-
const items = this.orientation === 'horizontal' && this._dir && this._dir.value === 'rtl' ?
|
|
1603
|
-
this._positionCache.items.slice().reverse() : this._positionCache.items;
|
|
1604
|
-
return findIndex(items, currentItem => currentItem.drag === item);
|
|
1605
|
-
}
|
|
1606
|
-
/**
|
|
1607
|
-
* Sorts an item inside the container based on its position.
|
|
1608
|
-
* @param {?} item Item to be sorted.
|
|
1609
|
-
* @param {?} pointerX Position of the item along the X axis.
|
|
1610
|
-
* @param {?} pointerY Position of the item along the Y axis.
|
|
1611
|
-
* @param {?} pointerDelta
|
|
1612
|
-
* @return {?}
|
|
1613
|
-
*/
|
|
1614
|
-
_sortItem(item, pointerX, pointerY, pointerDelta) {
|
|
1615
|
-
// Don't sort the item if it's out of range.
|
|
1616
|
-
if (!this._isPointerNearDropContainer(pointerX, pointerY)) {
|
|
1617
|
-
return;
|
|
1618
|
-
}
|
|
1619
|
-
/** @type {?} */
|
|
1620
|
-
const siblings = this._positionCache.items;
|
|
1621
|
-
/** @type {?} */
|
|
1622
|
-
const newIndex = this._getItemIndexFromPointerPosition(item, pointerX, pointerY, pointerDelta);
|
|
1623
|
-
if (newIndex === -1 && siblings.length > 0) {
|
|
1624
|
-
return;
|
|
1625
|
-
}
|
|
1626
|
-
/** @type {?} */
|
|
1627
|
-
const isHorizontal = this.orientation === 'horizontal';
|
|
1628
|
-
/** @type {?} */
|
|
1629
|
-
const currentIndex = findIndex(siblings, currentItem => currentItem.drag === item);
|
|
1630
|
-
/** @type {?} */
|
|
1631
|
-
const siblingAtNewPosition = siblings[newIndex];
|
|
1632
|
-
/** @type {?} */
|
|
1633
|
-
const currentPosition = siblings[currentIndex].clientRect;
|
|
1634
|
-
/** @type {?} */
|
|
1635
|
-
const newPosition = siblingAtNewPosition.clientRect;
|
|
1636
|
-
/** @type {?} */
|
|
1637
|
-
const delta = currentIndex > newIndex ? 1 : -1;
|
|
1638
|
-
this._previousSwap.drag = siblingAtNewPosition.drag;
|
|
1639
|
-
this._previousSwap.delta = isHorizontal ? pointerDelta.x : pointerDelta.y;
|
|
1640
|
-
// How many pixels the item's placeholder should be offset.
|
|
1641
|
-
/** @type {?} */
|
|
1642
|
-
const itemOffset = this._getItemOffsetPx(currentPosition, newPosition, delta);
|
|
1643
|
-
// How many pixels all the other items should be offset.
|
|
1644
|
-
/** @type {?} */
|
|
1645
|
-
const siblingOffset = this._getSiblingOffsetPx(currentIndex, siblings, delta);
|
|
1646
|
-
// Save the previous order of the items before moving the item to its new index.
|
|
1647
|
-
// We use this to check whether an item has been moved as a result of the sorting.
|
|
1648
|
-
/** @type {?} */
|
|
1649
|
-
const oldOrder = siblings.slice();
|
|
1650
|
-
// Shuffle the array in place.
|
|
1651
|
-
moveItemInArray(siblings, currentIndex, newIndex);
|
|
1652
|
-
this.sorted.emit({
|
|
1653
|
-
previousIndex: currentIndex,
|
|
1654
|
-
currentIndex: newIndex,
|
|
1655
|
-
container: this,
|
|
1656
|
-
item
|
|
1657
|
-
});
|
|
1658
|
-
siblings.forEach((sibling, index) => {
|
|
1659
|
-
// Don't do anything if the position hasn't changed.
|
|
1660
|
-
if (oldOrder[index] === sibling) {
|
|
1661
|
-
return;
|
|
1662
|
-
}
|
|
1663
|
-
/** @type {?} */
|
|
1664
|
-
const isDraggedItem = sibling.drag === item;
|
|
1665
|
-
/** @type {?} */
|
|
1666
|
-
const offset = isDraggedItem ? itemOffset : siblingOffset;
|
|
1667
|
-
/** @type {?} */
|
|
1668
|
-
const elementToOffset = isDraggedItem ? item.getPlaceholderElement() :
|
|
1669
|
-
sibling.drag.getRootElement();
|
|
1670
|
-
// Update the offset to reflect the new position.
|
|
1671
|
-
sibling.offset += offset;
|
|
1672
|
-
// Since we're moving the items with a `transform`, we need to adjust their cached
|
|
1673
|
-
// client rects to reflect their new position, as well as swap their positions in the cache.
|
|
1674
|
-
// Note that we shouldn't use `getBoundingClientRect` here to update the cache, because the
|
|
1675
|
-
// elements may be mid-animation which will give us a wrong result.
|
|
1676
|
-
if (isHorizontal) {
|
|
1677
|
-
// Round the transforms since some browsers will
|
|
1678
|
-
// blur the elements, for sub-pixel transforms.
|
|
1679
|
-
elementToOffset.style.transform = `translate3d(${Math.round(sibling.offset)}px, 0, 0)`;
|
|
1680
|
-
this._adjustClientRect(sibling.clientRect, 0, offset);
|
|
1681
|
-
}
|
|
1682
|
-
else {
|
|
1683
|
-
elementToOffset.style.transform = `translate3d(0, ${Math.round(sibling.offset)}px, 0)`;
|
|
1684
|
-
this._adjustClientRect(sibling.clientRect, offset, 0);
|
|
1685
|
-
}
|
|
2693
|
+
/**
|
|
2694
|
+
* Emits when the user drops an item inside the container.
|
|
2695
|
+
*/
|
|
2696
|
+
this.dropped = new EventEmitter();
|
|
2697
|
+
/**
|
|
2698
|
+
* Emits when the user has moved a new drag item into this container.
|
|
2699
|
+
*/
|
|
2700
|
+
this.entered = new EventEmitter();
|
|
2701
|
+
/**
|
|
2702
|
+
* Emits when the user removes an item from the container
|
|
2703
|
+
* by dragging it into another container.
|
|
2704
|
+
*/
|
|
2705
|
+
this.exited = new EventEmitter();
|
|
2706
|
+
/**
|
|
2707
|
+
* Emits as the user is swapping items while actively dragging.
|
|
2708
|
+
*/
|
|
2709
|
+
this.sorted = new EventEmitter();
|
|
2710
|
+
// @breaking-change 8.0.0 Remove null check once `dragDrop` parameter is made required.
|
|
2711
|
+
if (dragDrop) {
|
|
2712
|
+
this._dropListRef = dragDrop.createDropList(element);
|
|
2713
|
+
}
|
|
2714
|
+
else {
|
|
2715
|
+
this._dropListRef = new DropListRef(element, dragDropRegistry, _document || document);
|
|
2716
|
+
}
|
|
2717
|
+
this._dropListRef.data = this;
|
|
2718
|
+
this._dropListRef.enterPredicate = (drag, drop) => {
|
|
2719
|
+
return this.enterPredicate(drag.data, drop.data);
|
|
2720
|
+
};
|
|
2721
|
+
this._syncInputs(this._dropListRef);
|
|
2722
|
+
this._handleEvents(this._dropListRef);
|
|
2723
|
+
CdkDropList._dropLists.push(this);
|
|
2724
|
+
if (_group) {
|
|
2725
|
+
_group._items.add(this);
|
|
2726
|
+
}
|
|
2727
|
+
}
|
|
2728
|
+
/**
|
|
2729
|
+
* Whether starting a dragging sequence from this container is disabled.
|
|
2730
|
+
* @return {?}
|
|
2731
|
+
*/
|
|
2732
|
+
get disabled() {
|
|
2733
|
+
return this._disabled || (!!this._group && this._group.disabled);
|
|
2734
|
+
}
|
|
2735
|
+
/**
|
|
2736
|
+
* @param {?} value
|
|
2737
|
+
* @return {?}
|
|
2738
|
+
*/
|
|
2739
|
+
set disabled(value) {
|
|
2740
|
+
this._disabled = coerceBooleanProperty(value);
|
|
2741
|
+
}
|
|
2742
|
+
/**
|
|
2743
|
+
* @return {?}
|
|
2744
|
+
*/
|
|
2745
|
+
ngAfterContentInit() {
|
|
2746
|
+
this._draggables.changes
|
|
2747
|
+
.pipe(startWith(this._draggables), takeUntil(this._destroyed))
|
|
2748
|
+
.subscribe((items) => {
|
|
2749
|
+
this._dropListRef.withItems(items.map(drag => drag._dragRef));
|
|
1686
2750
|
});
|
|
1687
2751
|
}
|
|
1688
2752
|
/**
|
|
1689
|
-
* Figures out whether an item should be moved into a sibling
|
|
1690
|
-
* drop container, based on its current position.
|
|
1691
|
-
* @param {?} item Drag item that is being moved.
|
|
1692
|
-
* @param {?} x Position of the item along the X axis.
|
|
1693
|
-
* @param {?} y Position of the item along the Y axis.
|
|
1694
2753
|
* @return {?}
|
|
1695
2754
|
*/
|
|
1696
|
-
|
|
2755
|
+
ngOnDestroy() {
|
|
1697
2756
|
/** @type {?} */
|
|
1698
|
-
const
|
|
1699
|
-
|
|
1700
|
-
|
|
2757
|
+
const index = CdkDropList._dropLists.indexOf(this);
|
|
2758
|
+
if (index > -1) {
|
|
2759
|
+
CdkDropList._dropLists.splice(index, 1);
|
|
2760
|
+
}
|
|
2761
|
+
if (this._group) {
|
|
2762
|
+
this._group._items.delete(this);
|
|
2763
|
+
}
|
|
2764
|
+
this._dropListRef.dispose();
|
|
2765
|
+
this._destroyed.next();
|
|
2766
|
+
this._destroyed.complete();
|
|
1701
2767
|
}
|
|
1702
2768
|
/**
|
|
1703
|
-
*
|
|
1704
|
-
* after it was moved out into another container.
|
|
1705
|
-
* @param {?} x Position of the item along the X axis.
|
|
1706
|
-
* @param {?} y Position of the item along the Y axis.
|
|
2769
|
+
* Starts dragging an item.
|
|
1707
2770
|
* @return {?}
|
|
1708
2771
|
*/
|
|
1709
|
-
|
|
1710
|
-
|
|
2772
|
+
start() {
|
|
2773
|
+
this._dropListRef.start();
|
|
1711
2774
|
}
|
|
1712
2775
|
/**
|
|
1713
|
-
*
|
|
1714
|
-
* @
|
|
2776
|
+
* Drops an item into this container.
|
|
2777
|
+
* @param {?} item Item being dropped into the container.
|
|
2778
|
+
* @param {?} currentIndex Index at which the item should be inserted.
|
|
2779
|
+
* @param {?} previousContainer Container from which the item got dragged in.
|
|
2780
|
+
* @param {?} isPointerOverContainer Whether the user's pointer was over the
|
|
2781
|
+
* container when the item was dropped.
|
|
1715
2782
|
* @return {?}
|
|
1716
2783
|
*/
|
|
1717
|
-
|
|
1718
|
-
/** @type {?} */
|
|
1719
|
-
const isHorizontal = this.orientation === 'horizontal';
|
|
1720
|
-
this._positionCache.self = this.element.nativeElement.getBoundingClientRect();
|
|
1721
|
-
this._positionCache.items = this._activeDraggables
|
|
1722
|
-
.map(drag => {
|
|
1723
|
-
/** @type {?} */
|
|
1724
|
-
const elementToMeasure = this._dragDropRegistry.isDragging(drag) ?
|
|
1725
|
-
// If the element is being dragged, we have to measure the
|
|
1726
|
-
// placeholder, because the element is hidden.
|
|
1727
|
-
drag.getPlaceholderElement() :
|
|
1728
|
-
drag.getRootElement();
|
|
1729
|
-
/** @type {?} */
|
|
1730
|
-
const clientRect = elementToMeasure.getBoundingClientRect();
|
|
1731
|
-
return {
|
|
1732
|
-
drag,
|
|
1733
|
-
offset: 0,
|
|
1734
|
-
// We need to clone the `clientRect` here, because all the values on it are readonly
|
|
1735
|
-
// and we need to be able to update them. Also we can't use a spread here, because
|
|
1736
|
-
// the values on a `ClientRect` aren't own properties. See:
|
|
1737
|
-
// https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect#Notes
|
|
1738
|
-
clientRect: {
|
|
1739
|
-
top: clientRect.top,
|
|
1740
|
-
right: clientRect.right,
|
|
1741
|
-
bottom: clientRect.bottom,
|
|
1742
|
-
left: clientRect.left,
|
|
1743
|
-
width: clientRect.width,
|
|
1744
|
-
height: clientRect.height
|
|
1745
|
-
}
|
|
1746
|
-
};
|
|
1747
|
-
})
|
|
1748
|
-
.sort((a, b) => {
|
|
1749
|
-
return isHorizontal ? a.clientRect.left - b.clientRect.left :
|
|
1750
|
-
a.clientRect.top - b.clientRect.top;
|
|
1751
|
-
});
|
|
1752
|
-
this._positionCache.siblings = this._getConnectedLists().map(drop => ({
|
|
1753
|
-
drop,
|
|
1754
|
-
clientRect: drop.element.nativeElement.getBoundingClientRect()
|
|
1755
|
-
}));
|
|
2784
|
+
drop(item, currentIndex, previousContainer, isPointerOverContainer) {
|
|
2785
|
+
this._dropListRef.drop(item._dragRef, currentIndex, ((/** @type {?} */ (previousContainer)))._dropListRef, isPointerOverContainer);
|
|
1756
2786
|
}
|
|
1757
2787
|
/**
|
|
1758
|
-
*
|
|
1759
|
-
* @
|
|
2788
|
+
* Emits an event to indicate that the user moved an item into the container.
|
|
2789
|
+
* @param {?} item Item that was moved into the container.
|
|
2790
|
+
* @param {?} pointerX Position of the item along the X axis.
|
|
2791
|
+
* @param {?} pointerY Position of the item along the Y axis.
|
|
1760
2792
|
* @return {?}
|
|
1761
2793
|
*/
|
|
1762
|
-
|
|
1763
|
-
this.
|
|
1764
|
-
// TODO(crisbeto): may have to wait for the animations to finish.
|
|
1765
|
-
this._activeDraggables.forEach(item => item.getRootElement().style.transform = '');
|
|
1766
|
-
this._activeDraggables = [];
|
|
1767
|
-
this._positionCache.items = [];
|
|
1768
|
-
this._positionCache.siblings = [];
|
|
1769
|
-
this._previousSwap.drag = null;
|
|
1770
|
-
this._previousSwap.delta = 0;
|
|
2794
|
+
enter(item, pointerX, pointerY) {
|
|
2795
|
+
this._dropListRef.enter(item._dragRef, pointerX, pointerY);
|
|
1771
2796
|
}
|
|
1772
2797
|
/**
|
|
1773
|
-
*
|
|
1774
|
-
* @
|
|
1775
|
-
* @param {?} clientRect `ClientRect` that should be updated.
|
|
1776
|
-
* @param {?} top Amount to add to the `top` position.
|
|
1777
|
-
* @param {?} left Amount to add to the `left` position.
|
|
2798
|
+
* Removes an item from the container after it was dragged into another container by the user.
|
|
2799
|
+
* @param {?} item Item that was dragged out.
|
|
1778
2800
|
* @return {?}
|
|
1779
2801
|
*/
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
clientRect.bottom = clientRect.top + clientRect.height;
|
|
1783
|
-
clientRect.left += left;
|
|
1784
|
-
clientRect.right = clientRect.left + clientRect.width;
|
|
2802
|
+
exit(item) {
|
|
2803
|
+
this._dropListRef.exit(item._dragRef);
|
|
1785
2804
|
}
|
|
1786
2805
|
/**
|
|
1787
|
-
*
|
|
1788
|
-
* @
|
|
1789
|
-
* @param {?} item Item that is being sorted.
|
|
1790
|
-
* @param {?} pointerX Position of the user's pointer along the X axis.
|
|
1791
|
-
* @param {?} pointerY Position of the user's pointer along the Y axis.
|
|
1792
|
-
* @param {?=} delta Direction in which the user is moving their pointer.
|
|
2806
|
+
* Figures out the index of an item in the container.
|
|
2807
|
+
* @param {?} item Item whose index should be determined.
|
|
1793
2808
|
* @return {?}
|
|
1794
2809
|
*/
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
const isHorizontal = this.orientation === 'horizontal';
|
|
1798
|
-
return findIndex(this._positionCache.items, ({ drag, clientRect }, _, array) => {
|
|
1799
|
-
if (drag === item) {
|
|
1800
|
-
// If there's only one item left in the container, it must be
|
|
1801
|
-
// the dragged item itself so we use it as a reference.
|
|
1802
|
-
return array.length < 2;
|
|
1803
|
-
}
|
|
1804
|
-
if (delta) {
|
|
1805
|
-
/** @type {?} */
|
|
1806
|
-
const direction = isHorizontal ? delta.x : delta.y;
|
|
1807
|
-
// If the user is still hovering over the same item as last time, and they didn't change
|
|
1808
|
-
// the direction in which they're dragging, we don't consider it a direction swap.
|
|
1809
|
-
if (drag === this._previousSwap.drag && direction === this._previousSwap.delta) {
|
|
1810
|
-
return false;
|
|
1811
|
-
}
|
|
1812
|
-
}
|
|
1813
|
-
return isHorizontal ?
|
|
1814
|
-
// Round these down since most browsers report client rects with
|
|
1815
|
-
// sub-pixel precision, whereas the pointer coordinates are rounded to pixels.
|
|
1816
|
-
pointerX >= Math.floor(clientRect.left) && pointerX <= Math.floor(clientRect.right) :
|
|
1817
|
-
pointerY >= Math.floor(clientRect.top) && pointerY <= Math.floor(clientRect.bottom);
|
|
1818
|
-
});
|
|
2810
|
+
getItemIndex(item) {
|
|
2811
|
+
return this._dropListRef.getItemIndex(item._dragRef);
|
|
1819
2812
|
}
|
|
1820
2813
|
/**
|
|
1821
|
-
*
|
|
1822
|
-
* @
|
|
1823
|
-
* @param {?} pointerX
|
|
1824
|
-
* @param {?} pointerY
|
|
2814
|
+
* Sorts an item inside the container based on its position.
|
|
2815
|
+
* @param {?} item Item to be sorted.
|
|
2816
|
+
* @param {?} pointerX Position of the item along the X axis.
|
|
2817
|
+
* @param {?} pointerY Position of the item along the Y axis.
|
|
2818
|
+
* @param {?} pointerDelta Direction in which the pointer is moving along each axis.
|
|
1825
2819
|
* @return {?}
|
|
1826
2820
|
*/
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
/** @type {?} */
|
|
1830
|
-
const xThreshold = width * DROP_PROXIMITY_THRESHOLD;
|
|
1831
|
-
/** @type {?} */
|
|
1832
|
-
const yThreshold = height * DROP_PROXIMITY_THRESHOLD;
|
|
1833
|
-
return pointerY > top - yThreshold && pointerY < bottom + yThreshold &&
|
|
1834
|
-
pointerX > left - xThreshold && pointerX < right + xThreshold;
|
|
2821
|
+
_sortItem(item, pointerX, pointerY, pointerDelta) {
|
|
2822
|
+
return this._dropListRef._sortItem(item._dragRef, pointerX, pointerY, pointerDelta);
|
|
1835
2823
|
}
|
|
1836
2824
|
/**
|
|
1837
|
-
*
|
|
1838
|
-
*
|
|
1839
|
-
* @param {?}
|
|
1840
|
-
* @param {?}
|
|
1841
|
-
* @param {?}
|
|
2825
|
+
* Figures out whether an item should be moved into a sibling
|
|
2826
|
+
* drop container, based on its current position.
|
|
2827
|
+
* @param {?} item Drag item that is being moved.
|
|
2828
|
+
* @param {?} x Position of the item along the X axis.
|
|
2829
|
+
* @param {?} y Position of the item along the Y axis.
|
|
1842
2830
|
* @return {?}
|
|
1843
2831
|
*/
|
|
1844
|
-
|
|
1845
|
-
/** @type {?} */
|
|
1846
|
-
const isHorizontal = this.orientation === 'horizontal';
|
|
2832
|
+
_getSiblingContainerFromPosition(item, x, y) {
|
|
1847
2833
|
/** @type {?} */
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
// Account for differences in the item width/height.
|
|
1851
|
-
if (delta === -1) {
|
|
1852
|
-
itemOffset += isHorizontal ? newPosition.width - currentPosition.width :
|
|
1853
|
-
newPosition.height - currentPosition.height;
|
|
1854
|
-
}
|
|
1855
|
-
return itemOffset;
|
|
2834
|
+
const result = this._dropListRef._getSiblingContainerFromPosition(item._dragRef, x, y);
|
|
2835
|
+
return result ? result.data : null;
|
|
1856
2836
|
}
|
|
1857
2837
|
/**
|
|
1858
|
-
*
|
|
2838
|
+
* Checks whether the user's pointer is positioned over the container.
|
|
2839
|
+
* @param {?} x Pointer position along the X axis.
|
|
2840
|
+
* @param {?} y Pointer position along the Y axis.
|
|
2841
|
+
* @return {?}
|
|
2842
|
+
*/
|
|
2843
|
+
_isOverContainer(x, y) {
|
|
2844
|
+
return this._dropListRef._isOverContainer(x, y);
|
|
2845
|
+
}
|
|
2846
|
+
/**
|
|
2847
|
+
* Syncs the inputs of the CdkDropList with the options of the underlying DropListRef.
|
|
1859
2848
|
* @private
|
|
1860
|
-
* @param {?}
|
|
1861
|
-
* @param {?} siblings All of the items in the list.
|
|
1862
|
-
* @param {?} delta Direction in which the user is moving.
|
|
2849
|
+
* @param {?} ref
|
|
1863
2850
|
* @return {?}
|
|
1864
2851
|
*/
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
/** @type {?} */
|
|
1873
|
-
let siblingOffset = currentPosition[isHorizontal ? 'width' : 'height'] * delta;
|
|
1874
|
-
if (immediateSibling) {
|
|
1875
|
-
/** @type {?} */
|
|
1876
|
-
const start = isHorizontal ? 'left' : 'top';
|
|
2852
|
+
_syncInputs(ref) {
|
|
2853
|
+
if (this._dir) {
|
|
2854
|
+
this._dir.change
|
|
2855
|
+
.pipe(startWith(this._dir.value), takeUntil(this._destroyed))
|
|
2856
|
+
.subscribe(value => ref.withDirection(value));
|
|
2857
|
+
}
|
|
2858
|
+
ref.beforeStarted.subscribe(() => {
|
|
1877
2859
|
/** @type {?} */
|
|
1878
|
-
const
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
2860
|
+
const siblings = coerceArray(this.connectedTo).map(drop => {
|
|
2861
|
+
return typeof drop === 'string' ?
|
|
2862
|
+
(/** @type {?} */ (CdkDropList._dropLists.find(list => list.id === drop))) : drop;
|
|
2863
|
+
});
|
|
2864
|
+
if (this._group) {
|
|
2865
|
+
this._group._items.forEach(drop => {
|
|
2866
|
+
if (siblings.indexOf(drop) === -1) {
|
|
2867
|
+
siblings.push(drop);
|
|
2868
|
+
}
|
|
2869
|
+
});
|
|
1888
2870
|
}
|
|
1889
|
-
|
|
1890
|
-
|
|
2871
|
+
ref.lockAxis = this.lockAxis;
|
|
2872
|
+
ref
|
|
2873
|
+
.connectedTo(siblings.filter(drop => drop && drop !== this).map(list => list._dropListRef))
|
|
2874
|
+
.withOrientation(this.orientation);
|
|
2875
|
+
});
|
|
1891
2876
|
}
|
|
1892
2877
|
/**
|
|
1893
|
-
*
|
|
2878
|
+
* Handles events from the underlying DropListRef.
|
|
1894
2879
|
* @private
|
|
2880
|
+
* @param {?} ref
|
|
1895
2881
|
* @return {?}
|
|
1896
2882
|
*/
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
return typeof drop === 'string' ? (/** @type {?} */ (this._dragDropRegistry.getDropContainer(drop))) : drop;
|
|
2883
|
+
_handleEvents(ref) {
|
|
2884
|
+
ref.beforeStarted.subscribe(() => {
|
|
2885
|
+
this._changeDetectorRef.markForCheck();
|
|
1901
2886
|
});
|
|
1902
|
-
|
|
1903
|
-
this.
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
}
|
|
2887
|
+
ref.entered.subscribe(event => {
|
|
2888
|
+
this.entered.emit({
|
|
2889
|
+
container: this,
|
|
2890
|
+
item: event.item.data
|
|
1907
2891
|
});
|
|
1908
|
-
}
|
|
1909
|
-
|
|
2892
|
+
});
|
|
2893
|
+
ref.exited.subscribe(event => {
|
|
2894
|
+
this.exited.emit({
|
|
2895
|
+
container: this,
|
|
2896
|
+
item: event.item.data
|
|
2897
|
+
});
|
|
2898
|
+
});
|
|
2899
|
+
ref.sorted.subscribe(event => {
|
|
2900
|
+
this.sorted.emit({
|
|
2901
|
+
previousIndex: event.previousIndex,
|
|
2902
|
+
currentIndex: event.currentIndex,
|
|
2903
|
+
container: this,
|
|
2904
|
+
item: event.item.data
|
|
2905
|
+
});
|
|
2906
|
+
});
|
|
2907
|
+
ref.dropped.subscribe(event => {
|
|
2908
|
+
this.dropped.emit({
|
|
2909
|
+
previousIndex: event.previousIndex,
|
|
2910
|
+
currentIndex: event.currentIndex,
|
|
2911
|
+
previousContainer: event.previousContainer.data,
|
|
2912
|
+
container: event.container.data,
|
|
2913
|
+
item: event.item.data,
|
|
2914
|
+
isPointerOverContainer: event.isPointerOverContainer
|
|
2915
|
+
});
|
|
2916
|
+
// Mark for check since all of these events run outside of change
|
|
2917
|
+
// detection and we're not guaranteed for something else to have triggered it.
|
|
2918
|
+
this._changeDetectorRef.markForCheck();
|
|
2919
|
+
});
|
|
1910
2920
|
}
|
|
1911
2921
|
}
|
|
2922
|
+
/**
|
|
2923
|
+
* Keeps track of the drop lists that are currently on the page.
|
|
2924
|
+
*/
|
|
2925
|
+
CdkDropList._dropLists = [];
|
|
1912
2926
|
CdkDropList.decorators = [
|
|
1913
2927
|
{ type: Directive, args: [{
|
|
1914
2928
|
selector: '[cdkDropList], cdk-drop-list',
|
|
@@ -1921,7 +2935,8 @@ CdkDropList.decorators = [
|
|
|
1921
2935
|
host: {
|
|
1922
2936
|
'class': 'cdk-drop-list',
|
|
1923
2937
|
'[id]': 'id',
|
|
1924
|
-
'[class.cdk-drop-list-dragging]': '
|
|
2938
|
+
'[class.cdk-drop-list-dragging]': '_dropListRef.isDragging()',
|
|
2939
|
+
'[class.cdk-drop-list-receiving]': '_dropListRef.isReceiving()',
|
|
1925
2940
|
}
|
|
1926
2941
|
},] },
|
|
1927
2942
|
];
|
|
@@ -1931,10 +2946,16 @@ CdkDropList.ctorParameters = () => [
|
|
|
1931
2946
|
{ type: DragDropRegistry },
|
|
1932
2947
|
{ type: ChangeDetectorRef },
|
|
1933
2948
|
{ type: Directionality, decorators: [{ type: Optional }] },
|
|
1934
|
-
{ type: CdkDropListGroup, decorators: [{ type: Optional }, { type: SkipSelf }] }
|
|
2949
|
+
{ type: CdkDropListGroup, decorators: [{ type: Optional }, { type: SkipSelf }] },
|
|
2950
|
+
{ type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [DOCUMENT,] }] },
|
|
2951
|
+
{ type: DragDrop }
|
|
1935
2952
|
];
|
|
1936
2953
|
CdkDropList.propDecorators = {
|
|
1937
|
-
_draggables: [{ type: ContentChildren, args: [forwardRef(() => CdkDrag),
|
|
2954
|
+
_draggables: [{ type: ContentChildren, args: [forwardRef(() => CdkDrag), {
|
|
2955
|
+
// Explicitly set to false since some of the logic below makes assumptions about it.
|
|
2956
|
+
// The `.withItems` call below should be updated if we ever need to switch this to `true`.
|
|
2957
|
+
descendants: false
|
|
2958
|
+
},] }],
|
|
1938
2959
|
connectedTo: [{ type: Input, args: ['cdkDropListConnectedTo',] }],
|
|
1939
2960
|
data: [{ type: Input, args: ['cdkDropListData',] }],
|
|
1940
2961
|
orientation: [{ type: Input, args: ['cdkDropListOrientation',] }],
|
|
@@ -1947,38 +2968,6 @@ CdkDropList.propDecorators = {
|
|
|
1947
2968
|
exited: [{ type: Output, args: ['cdkDropListExited',] }],
|
|
1948
2969
|
sorted: [{ type: Output, args: ['cdkDropListSorted',] }]
|
|
1949
2970
|
};
|
|
1950
|
-
/**
|
|
1951
|
-
* Finds the index of an item that matches a predicate function. Used as an equivalent
|
|
1952
|
-
* of `Array.prototype.find` which isn't part of the standard Google typings.
|
|
1953
|
-
* @template T
|
|
1954
|
-
* @param {?} array Array in which to look for matches.
|
|
1955
|
-
* @param {?} predicate Function used to determine whether an item is a match.
|
|
1956
|
-
* @return {?}
|
|
1957
|
-
*/
|
|
1958
|
-
function findIndex(array, predicate) {
|
|
1959
|
-
for (let i = 0; i < array.length; i++) {
|
|
1960
|
-
if (predicate(array[i], i, array)) {
|
|
1961
|
-
return i;
|
|
1962
|
-
}
|
|
1963
|
-
}
|
|
1964
|
-
return -1;
|
|
1965
|
-
}
|
|
1966
|
-
/**
|
|
1967
|
-
* Checks whether some coordinates are within a `ClientRect`.
|
|
1968
|
-
* @param {?} clientRect ClientRect that is being checked.
|
|
1969
|
-
* @param {?} x Coordinates along the X axis.
|
|
1970
|
-
* @param {?} y Coordinates along the Y axis.
|
|
1971
|
-
* @return {?}
|
|
1972
|
-
*/
|
|
1973
|
-
function isInsideClientRect(clientRect, x, y) {
|
|
1974
|
-
const { top, bottom, left, right } = clientRect;
|
|
1975
|
-
return y >= top && y <= bottom && x >= left && x <= right;
|
|
1976
|
-
}
|
|
1977
|
-
|
|
1978
|
-
/**
|
|
1979
|
-
* @fileoverview added by tsickle
|
|
1980
|
-
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
1981
|
-
*/
|
|
1982
2971
|
|
|
1983
2972
|
/**
|
|
1984
2973
|
* @fileoverview added by tsickle
|
|
@@ -2004,6 +2993,9 @@ DragDropModule.decorators = [
|
|
|
2004
2993
|
CdkDragPreview,
|
|
2005
2994
|
CdkDragPlaceholder,
|
|
2006
2995
|
],
|
|
2996
|
+
providers: [
|
|
2997
|
+
DragDrop,
|
|
2998
|
+
]
|
|
2007
2999
|
},] },
|
|
2008
3000
|
];
|
|
2009
3001
|
|
|
@@ -2017,5 +3009,5 @@ DragDropModule.decorators = [
|
|
|
2017
3009
|
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
2018
3010
|
*/
|
|
2019
3011
|
|
|
2020
|
-
export { CdkDropList,
|
|
3012
|
+
export { DragDrop, DragRef, DropListRef, CdkDropList, CDK_DROP_LIST, CDK_DROP_LIST_CONTAINER, moveItemInArray, transferArrayItem, copyArrayItem, DragDropModule, DragDropRegistry, CdkDropListGroup, CDK_DRAG_CONFIG_FACTORY, CDK_DRAG_CONFIG, CdkDrag, CdkDragHandle, CdkDragPreview, CdkDragPlaceholder, CDK_DRAG_PARENT as ɵb };
|
|
2021
3013
|
//# sourceMappingURL=drag-drop.js.map
|