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