UNPKG

204 kBJavaScriptView Raw
1(function (global, factory) {
2 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/common'), require('@angular/cdk/scrolling'), require('@angular/cdk/platform'), require('@angular/cdk/coercion'), require('@angular/cdk/a11y'), require('rxjs'), require('rxjs/operators'), require('@angular/cdk/bidi')) :
3 typeof define === 'function' && define.amd ? define('@angular/cdk/drag-drop', ['exports', '@angular/core', '@angular/common', '@angular/cdk/scrolling', '@angular/cdk/platform', '@angular/cdk/coercion', '@angular/cdk/a11y', 'rxjs', 'rxjs/operators', '@angular/cdk/bidi'], factory) :
4 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.ng = global.ng || {}, global.ng.cdk = global.ng.cdk || {}, global.ng.cdk.dragDrop = {}), global.ng.core, global.ng.common, global.ng.cdk.scrolling, global.ng.cdk.platform, global.ng.cdk.coercion, global.ng.cdk.a11y, global.rxjs, global.rxjs.operators, global.ng.cdk.bidi));
5}(this, (function (exports, i0, i1, i2, platform, coercion, a11y, rxjs, operators, bidi) { 'use strict';
6
7 function _interopNamespace(e) {
8 if (e && e.__esModule) return e;
9 var n = Object.create(null);
10 if (e) {
11 Object.keys(e).forEach(function (k) {
12 if (k !== 'default') {
13 var d = Object.getOwnPropertyDescriptor(e, k);
14 Object.defineProperty(n, k, d.get ? d : {
15 enumerable: true,
16 get: function () {
17 return e[k];
18 }
19 });
20 }
21 });
22 }
23 n['default'] = e;
24 return Object.freeze(n);
25 }
26
27 var i0__namespace = /*#__PURE__*/_interopNamespace(i0);
28 var i1__namespace = /*#__PURE__*/_interopNamespace(i1);
29 var i2__namespace = /*#__PURE__*/_interopNamespace(i2);
30
31 /**
32 * @license
33 * Copyright Google LLC All Rights Reserved.
34 *
35 * Use of this source code is governed by an MIT-style license that can be
36 * found in the LICENSE file at https://angular.io/license
37 */
38 /**
39 * Shallow-extends a stylesheet object with another stylesheet-like object.
40 * Note that the keys in `source` have to be dash-cased.
41 * @docs-private
42 */
43 function extendStyles(dest, source, importantProperties) {
44 for (var key in source) {
45 if (source.hasOwnProperty(key)) {
46 var value = source[key];
47 if (value) {
48 dest.setProperty(key, value, (importantProperties === null || importantProperties === void 0 ? void 0 : importantProperties.has(key)) ? 'important' : '');
49 }
50 else {
51 dest.removeProperty(key);
52 }
53 }
54 }
55 return dest;
56 }
57 /**
58 * Toggles whether the native drag interactions should be enabled for an element.
59 * @param element Element on which to toggle the drag interactions.
60 * @param enable Whether the drag interactions should be enabled.
61 * @docs-private
62 */
63 function toggleNativeDragInteractions(element, enable) {
64 var userSelect = enable ? '' : 'none';
65 extendStyles(element.style, {
66 'touch-action': enable ? '' : 'none',
67 '-webkit-user-drag': enable ? '' : 'none',
68 '-webkit-tap-highlight-color': enable ? '' : 'transparent',
69 'user-select': userSelect,
70 '-ms-user-select': userSelect,
71 '-webkit-user-select': userSelect,
72 '-moz-user-select': userSelect
73 });
74 }
75 /**
76 * Toggles whether an element is visible while preserving its dimensions.
77 * @param element Element whose visibility to toggle
78 * @param enable Whether the element should be visible.
79 * @param importantProperties Properties to be set as `!important`.
80 * @docs-private
81 */
82 function toggleVisibility(element, enable, importantProperties) {
83 extendStyles(element.style, {
84 position: enable ? '' : 'fixed',
85 top: enable ? '' : '0',
86 opacity: enable ? '' : '0',
87 left: enable ? '' : '-999em'
88 }, importantProperties);
89 }
90 /**
91 * Combines a transform string with an optional other transform
92 * that exited before the base transform was applied.
93 */
94 function combineTransforms(transform, initialTransform) {
95 return initialTransform && initialTransform != 'none' ?
96 (transform + ' ' + initialTransform) :
97 transform;
98 }
99
100 /**
101 * @license
102 * Copyright Google LLC All Rights Reserved.
103 *
104 * Use of this source code is governed by an MIT-style license that can be
105 * found in the LICENSE file at https://angular.io/license
106 */
107 /** Parses a CSS time value to milliseconds. */
108 function parseCssTimeUnitsToMs(value) {
109 // Some browsers will return it in seconds, whereas others will return milliseconds.
110 var multiplier = value.toLowerCase().indexOf('ms') > -1 ? 1 : 1000;
111 return parseFloat(value) * multiplier;
112 }
113 /** Gets the transform transition duration, including the delay, of an element in milliseconds. */
114 function getTransformTransitionDurationInMs(element) {
115 var computedStyle = getComputedStyle(element);
116 var transitionedProperties = parseCssPropertyValue(computedStyle, 'transition-property');
117 var property = transitionedProperties.find(function (prop) { return prop === 'transform' || prop === 'all'; });
118 // If there's no transition for `all` or `transform`, we shouldn't do anything.
119 if (!property) {
120 return 0;
121 }
122 // Get the index of the property that we're interested in and match
123 // it up to the same index in `transition-delay` and `transition-duration`.
124 var propertyIndex = transitionedProperties.indexOf(property);
125 var rawDurations = parseCssPropertyValue(computedStyle, 'transition-duration');
126 var rawDelays = parseCssPropertyValue(computedStyle, 'transition-delay');
127 return parseCssTimeUnitsToMs(rawDurations[propertyIndex]) +
128 parseCssTimeUnitsToMs(rawDelays[propertyIndex]);
129 }
130 /** Parses out multiple values from a computed style into an array. */
131 function parseCssPropertyValue(computedStyle, name) {
132 var value = computedStyle.getPropertyValue(name);
133 return value.split(',').map(function (part) { return part.trim(); });
134 }
135
136 /**
137 * @license
138 * Copyright Google LLC All Rights Reserved.
139 *
140 * Use of this source code is governed by an MIT-style license that can be
141 * found in the LICENSE file at https://angular.io/license
142 */
143 /** Gets a mutable version of an element's bounding `ClientRect`. */
144 function getMutableClientRect(element) {
145 var clientRect = element.getBoundingClientRect();
146 // We need to clone the `clientRect` here, because all the values on it are readonly
147 // and we need to be able to update them. Also we can't use a spread here, because
148 // the values on a `ClientRect` aren't own properties. See:
149 // https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect#Notes
150 return {
151 top: clientRect.top,
152 right: clientRect.right,
153 bottom: clientRect.bottom,
154 left: clientRect.left,
155 width: clientRect.width,
156 height: clientRect.height
157 };
158 }
159 /**
160 * Checks whether some coordinates are within a `ClientRect`.
161 * @param clientRect ClientRect that is being checked.
162 * @param x Coordinates along the X axis.
163 * @param y Coordinates along the Y axis.
164 */
165 function isInsideClientRect(clientRect, x, y) {
166 var top = clientRect.top, bottom = clientRect.bottom, left = clientRect.left, right = clientRect.right;
167 return y >= top && y <= bottom && x >= left && x <= right;
168 }
169 /**
170 * Updates the top/left positions of a `ClientRect`, as well as their bottom/right counterparts.
171 * @param clientRect `ClientRect` that should be updated.
172 * @param top Amount to add to the `top` position.
173 * @param left Amount to add to the `left` position.
174 */
175 function adjustClientRect(clientRect, top, left) {
176 clientRect.top += top;
177 clientRect.bottom = clientRect.top + clientRect.height;
178 clientRect.left += left;
179 clientRect.right = clientRect.left + clientRect.width;
180 }
181 /**
182 * Checks whether the pointer coordinates are close to a ClientRect.
183 * @param rect ClientRect to check against.
184 * @param threshold Threshold around the ClientRect.
185 * @param pointerX Coordinates along the X axis.
186 * @param pointerY Coordinates along the Y axis.
187 */
188 function isPointerNearClientRect(rect, threshold, pointerX, pointerY) {
189 var top = rect.top, right = rect.right, bottom = rect.bottom, left = rect.left, width = rect.width, height = rect.height;
190 var xThreshold = width * threshold;
191 var yThreshold = height * threshold;
192 return pointerY > top - yThreshold && pointerY < bottom + yThreshold &&
193 pointerX > left - xThreshold && pointerX < right + xThreshold;
194 }
195
196 /**
197 * @license
198 * Copyright Google LLC All Rights Reserved.
199 *
200 * Use of this source code is governed by an MIT-style license that can be
201 * found in the LICENSE file at https://angular.io/license
202 */
203 /** Keeps track of the scroll position and dimensions of the parents of an element. */
204 var ParentPositionTracker = /** @class */ (function () {
205 function ParentPositionTracker(_document, _viewportRuler) {
206 this._document = _document;
207 this._viewportRuler = _viewportRuler;
208 /** Cached positions of the scrollable parent elements. */
209 this.positions = new Map();
210 }
211 /** Clears the cached positions. */
212 ParentPositionTracker.prototype.clear = function () {
213 this.positions.clear();
214 };
215 /** Caches the positions. Should be called at the beginning of a drag sequence. */
216 ParentPositionTracker.prototype.cache = function (elements) {
217 var _this = this;
218 this.clear();
219 this.positions.set(this._document, {
220 scrollPosition: this._viewportRuler.getViewportScrollPosition(),
221 });
222 elements.forEach(function (element) {
223 _this.positions.set(element, {
224 scrollPosition: { top: element.scrollTop, left: element.scrollLeft },
225 clientRect: getMutableClientRect(element)
226 });
227 });
228 };
229 /** Handles scrolling while a drag is taking place. */
230 ParentPositionTracker.prototype.handleScroll = function (event) {
231 var target = platform._getEventTarget(event);
232 var cachedPosition = this.positions.get(target);
233 if (!cachedPosition) {
234 return null;
235 }
236 // Used when figuring out whether an element is inside the scroll parent. If the scrolled
237 // parent is the `document`, we use the `documentElement`, because IE doesn't support
238 // `contains` on the `document`.
239 var scrolledParentNode = target === this._document ? target.documentElement : target;
240 var scrollPosition = cachedPosition.scrollPosition;
241 var newTop;
242 var newLeft;
243 if (target === this._document) {
244 var viewportScrollPosition = this._viewportRuler.getViewportScrollPosition();
245 newTop = viewportScrollPosition.top;
246 newLeft = viewportScrollPosition.left;
247 }
248 else {
249 newTop = target.scrollTop;
250 newLeft = target.scrollLeft;
251 }
252 var topDifference = scrollPosition.top - newTop;
253 var leftDifference = scrollPosition.left - newLeft;
254 // Go through and update the cached positions of the scroll
255 // parents that are inside the element that was scrolled.
256 this.positions.forEach(function (position, node) {
257 if (position.clientRect && target !== node && scrolledParentNode.contains(node)) {
258 adjustClientRect(position.clientRect, topDifference, leftDifference);
259 }
260 });
261 scrollPosition.top = newTop;
262 scrollPosition.left = newLeft;
263 return { top: topDifference, left: leftDifference };
264 };
265 return ParentPositionTracker;
266 }());
267
268 /**
269 * @license
270 * Copyright Google LLC All Rights Reserved.
271 *
272 * Use of this source code is governed by an MIT-style license that can be
273 * found in the LICENSE file at https://angular.io/license
274 */
275 /** Creates a deep clone of an element. */
276 function deepCloneNode(node) {
277 var clone = node.cloneNode(true);
278 var descendantsWithId = clone.querySelectorAll('[id]');
279 var nodeName = node.nodeName.toLowerCase();
280 // Remove the `id` to avoid having multiple elements with the same id on the page.
281 clone.removeAttribute('id');
282 for (var i = 0; i < descendantsWithId.length; i++) {
283 descendantsWithId[i].removeAttribute('id');
284 }
285 if (nodeName === 'canvas') {
286 transferCanvasData(node, clone);
287 }
288 else if (nodeName === 'input' || nodeName === 'select' || nodeName === 'textarea') {
289 transferInputData(node, clone);
290 }
291 transferData('canvas', node, clone, transferCanvasData);
292 transferData('input, textarea, select', node, clone, transferInputData);
293 return clone;
294 }
295 /** Matches elements between an element and its clone and allows for their data to be cloned. */
296 function transferData(selector, node, clone, callback) {
297 var descendantElements = node.querySelectorAll(selector);
298 if (descendantElements.length) {
299 var cloneElements = clone.querySelectorAll(selector);
300 for (var i = 0; i < descendantElements.length; i++) {
301 callback(descendantElements[i], cloneElements[i]);
302 }
303 }
304 }
305 // Counter for unique cloned radio button names.
306 var cloneUniqueId = 0;
307 /** Transfers the data of one input element to another. */
308 function transferInputData(source, clone) {
309 // Browsers throw an error when assigning the value of a file input programmatically.
310 if (clone.type !== 'file') {
311 clone.value = source.value;
312 }
313 // Radio button `name` attributes must be unique for radio button groups
314 // otherwise original radio buttons can lose their checked state
315 // once the clone is inserted in the DOM.
316 if (clone.type === 'radio' && clone.name) {
317 clone.name = "mat-clone-" + clone.name + "-" + cloneUniqueId++;
318 }
319 }
320 /** Transfers the data of one canvas element to another. */
321 function transferCanvasData(source, clone) {
322 var context = clone.getContext('2d');
323 if (context) {
324 // In some cases `drawImage` can throw (e.g. if the canvas size is 0x0).
325 // We can't do much about it so just ignore the error.
326 try {
327 context.drawImage(source, 0, 0);
328 }
329 catch (_a) { }
330 }
331 }
332
333 /**
334 * @license
335 * Copyright Google LLC All Rights Reserved.
336 *
337 * Use of this source code is governed by an MIT-style license that can be
338 * found in the LICENSE file at https://angular.io/license
339 */
340 /** Options that can be used to bind a passive event listener. */
341 var passiveEventListenerOptions = platform.normalizePassiveListenerOptions({ passive: true });
342 /** Options that can be used to bind an active event listener. */
343 var activeEventListenerOptions = platform.normalizePassiveListenerOptions({ passive: false });
344 /**
345 * Time in milliseconds for which to ignore mouse events, after
346 * receiving a touch event. Used to avoid doing double work for
347 * touch devices where the browser fires fake mouse events, in
348 * addition to touch events.
349 */
350 var MOUSE_EVENT_IGNORE_TIME = 800;
351 /** Inline styles to be set as `!important` while dragging. */
352 var dragImportantProperties = new Set([
353 // Needs to be important, because some `mat-table` sets `position: sticky !important`. See #22781.
354 'position'
355 ]);
356 /**
357 * Reference to a draggable item. Used to manipulate or dispose of the item.
358 */
359 var DragRef = /** @class */ (function () {
360 function DragRef(element, _config, _document, _ngZone, _viewportRuler, _dragDropRegistry) {
361 var _this = this;
362 this._config = _config;
363 this._document = _document;
364 this._ngZone = _ngZone;
365 this._viewportRuler = _viewportRuler;
366 this._dragDropRegistry = _dragDropRegistry;
367 /**
368 * CSS `transform` applied to the element when it isn't being dragged. We need a
369 * passive transform in order for the dragged element to retain its new position
370 * after the user has stopped dragging and because we need to know the relative
371 * position in case they start dragging again. This corresponds to `element.style.transform`.
372 */
373 this._passiveTransform = { x: 0, y: 0 };
374 /** CSS `transform` that is applied to the element while it's being dragged. */
375 this._activeTransform = { x: 0, y: 0 };
376 /**
377 * Whether the dragging sequence has been started. Doesn't
378 * necessarily mean that the element has been moved.
379 */
380 this._hasStartedDragging = false;
381 /** Emits when the item is being moved. */
382 this._moveEvents = new rxjs.Subject();
383 /** Subscription to pointer movement events. */
384 this._pointerMoveSubscription = rxjs.Subscription.EMPTY;
385 /** Subscription to the event that is dispatched when the user lifts their pointer. */
386 this._pointerUpSubscription = rxjs.Subscription.EMPTY;
387 /** Subscription to the viewport being scrolled. */
388 this._scrollSubscription = rxjs.Subscription.EMPTY;
389 /** Subscription to the viewport being resized. */
390 this._resizeSubscription = rxjs.Subscription.EMPTY;
391 /** Cached reference to the boundary element. */
392 this._boundaryElement = null;
393 /** Whether the native dragging interactions have been enabled on the root element. */
394 this._nativeInteractionsEnabled = true;
395 /** Elements that can be used to drag the draggable item. */
396 this._handles = [];
397 /** Registered handles that are currently disabled. */
398 this._disabledHandles = new Set();
399 /** Layout direction of the item. */
400 this._direction = 'ltr';
401 /**
402 * Amount of milliseconds to wait after the user has put their
403 * pointer down before starting to drag the element.
404 */
405 this.dragStartDelay = 0;
406 this._disabled = false;
407 /** Emits as the drag sequence is being prepared. */
408 this.beforeStarted = new rxjs.Subject();
409 /** Emits when the user starts dragging the item. */
410 this.started = new rxjs.Subject();
411 /** Emits when the user has released a drag item, before any animations have started. */
412 this.released = new rxjs.Subject();
413 /** Emits when the user stops dragging an item in the container. */
414 this.ended = new rxjs.Subject();
415 /** Emits when the user has moved the item into a new container. */
416 this.entered = new rxjs.Subject();
417 /** Emits when the user removes the item its container by dragging it into another container. */
418 this.exited = new rxjs.Subject();
419 /** Emits when the user drops the item inside a container. */
420 this.dropped = new rxjs.Subject();
421 /**
422 * Emits as the user is dragging the item. Use with caution,
423 * because this event will fire for every pixel that the user has dragged.
424 */
425 this.moved = this._moveEvents;
426 /** Handler for the `mousedown`/`touchstart` events. */
427 this._pointerDown = function (event) {
428 _this.beforeStarted.next();
429 // Delegate the event based on whether it started from a handle or the element itself.
430 if (_this._handles.length) {
431 var targetHandle = _this._handles.find(function (handle) {
432 var target = platform._getEventTarget(event);
433 return !!target && (target === handle || handle.contains(target));
434 });
435 if (targetHandle && !_this._disabledHandles.has(targetHandle) && !_this.disabled) {
436 _this._initializeDragSequence(targetHandle, event);
437 }
438 }
439 else if (!_this.disabled) {
440 _this._initializeDragSequence(_this._rootElement, event);
441 }
442 };
443 /** Handler that is invoked when the user moves their pointer after they've initiated a drag. */
444 this._pointerMove = function (event) {
445 var pointerPosition = _this._getPointerPositionOnPage(event);
446 if (!_this._hasStartedDragging) {
447 var distanceX = Math.abs(pointerPosition.x - _this._pickupPositionOnPage.x);
448 var distanceY = Math.abs(pointerPosition.y - _this._pickupPositionOnPage.y);
449 var isOverThreshold = distanceX + distanceY >= _this._config.dragStartThreshold;
450 // Only start dragging after the user has moved more than the minimum distance in either
451 // direction. Note that this is preferrable over doing something like `skip(minimumDistance)`
452 // in the `pointerMove` subscription, because we're not guaranteed to have one move event
453 // per pixel of movement (e.g. if the user moves their pointer quickly).
454 if (isOverThreshold) {
455 var isDelayElapsed = Date.now() >= _this._dragStartTime + _this._getDragStartDelay(event);
456 var container = _this._dropContainer;
457 if (!isDelayElapsed) {
458 _this._endDragSequence(event);
459 return;
460 }
461 // Prevent other drag sequences from starting while something in the container is still
462 // being dragged. This can happen while we're waiting for the drop animation to finish
463 // and can cause errors, because some elements might still be moving around.
464 if (!container || (!container.isDragging() && !container.isReceiving())) {
465 // Prevent the default action as soon as the dragging sequence is considered as
466 // "started" since waiting for the next event can allow the device to begin scrolling.
467 event.preventDefault();
468 _this._hasStartedDragging = true;
469 _this._ngZone.run(function () { return _this._startDragSequence(event); });
470 }
471 }
472 return;
473 }
474 // We only need the preview dimensions if we have a boundary element.
475 if (_this._boundaryElement) {
476 // Cache the preview element rect if we haven't cached it already or if
477 // we cached it too early before the element dimensions were computed.
478 if (!_this._previewRect || (!_this._previewRect.width && !_this._previewRect.height)) {
479 _this._previewRect = (_this._preview || _this._rootElement).getBoundingClientRect();
480 }
481 }
482 // We prevent the default action down here so that we know that dragging has started. This is
483 // important for touch devices where doing this too early can unnecessarily block scrolling,
484 // if there's a dragging delay.
485 event.preventDefault();
486 var constrainedPointerPosition = _this._getConstrainedPointerPosition(pointerPosition);
487 _this._hasMoved = true;
488 _this._lastKnownPointerPosition = pointerPosition;
489 _this._updatePointerDirectionDelta(constrainedPointerPosition);
490 if (_this._dropContainer) {
491 _this._updateActiveDropContainer(constrainedPointerPosition, pointerPosition);
492 }
493 else {
494 var activeTransform = _this._activeTransform;
495 activeTransform.x =
496 constrainedPointerPosition.x - _this._pickupPositionOnPage.x + _this._passiveTransform.x;
497 activeTransform.y =
498 constrainedPointerPosition.y - _this._pickupPositionOnPage.y + _this._passiveTransform.y;
499 _this._applyRootElementTransform(activeTransform.x, activeTransform.y);
500 // Apply transform as attribute if dragging and svg element to work for IE
501 if (typeof SVGElement !== 'undefined' && _this._rootElement instanceof SVGElement) {
502 var appliedTransform = "translate(" + activeTransform.x + " " + activeTransform.y + ")";
503 _this._rootElement.setAttribute('transform', appliedTransform);
504 }
505 }
506 // Since this event gets fired for every pixel while dragging, we only
507 // want to fire it if the consumer opted into it. Also we have to
508 // re-enter the zone because we run all of the events on the outside.
509 if (_this._moveEvents.observers.length) {
510 _this._ngZone.run(function () {
511 _this._moveEvents.next({
512 source: _this,
513 pointerPosition: constrainedPointerPosition,
514 event: event,
515 distance: _this._getDragDistance(constrainedPointerPosition),
516 delta: _this._pointerDirectionDelta
517 });
518 });
519 }
520 };
521 /** Handler that is invoked when the user lifts their pointer up, after initiating a drag. */
522 this._pointerUp = function (event) {
523 _this._endDragSequence(event);
524 };
525 this.withRootElement(element).withParent(_config.parentDragRef || null);
526 this._parentPositions = new ParentPositionTracker(_document, _viewportRuler);
527 _dragDropRegistry.registerDragItem(this);
528 }
529 Object.defineProperty(DragRef.prototype, "disabled", {
530 /** Whether starting to drag this element is disabled. */
531 get: function () {
532 return this._disabled || !!(this._dropContainer && this._dropContainer.disabled);
533 },
534 set: function (value) {
535 var newValue = coercion.coerceBooleanProperty(value);
536 if (newValue !== this._disabled) {
537 this._disabled = newValue;
538 this._toggleNativeDragInteractions();
539 this._handles.forEach(function (handle) { return toggleNativeDragInteractions(handle, newValue); });
540 }
541 },
542 enumerable: false,
543 configurable: true
544 });
545 /**
546 * Returns the element that is being used as a placeholder
547 * while the current element is being dragged.
548 */
549 DragRef.prototype.getPlaceholderElement = function () {
550 return this._placeholder;
551 };
552 /** Returns the root draggable element. */
553 DragRef.prototype.getRootElement = function () {
554 return this._rootElement;
555 };
556 /**
557 * Gets the currently-visible element that represents the drag item.
558 * While dragging this is the placeholder, otherwise it's the root element.
559 */
560 DragRef.prototype.getVisibleElement = function () {
561 return this.isDragging() ? this.getPlaceholderElement() : this.getRootElement();
562 };
563 /** Registers the handles that can be used to drag the element. */
564 DragRef.prototype.withHandles = function (handles) {
565 var _this = this;
566 this._handles = handles.map(function (handle) { return coercion.coerceElement(handle); });
567 this._handles.forEach(function (handle) { return toggleNativeDragInteractions(handle, _this.disabled); });
568 this._toggleNativeDragInteractions();
569 // Delete any lingering disabled handles that may have been destroyed. Note that we re-create
570 // the set, rather than iterate over it and filter out the destroyed handles, because while
571 // the ES spec allows for sets to be modified while they're being iterated over, some polyfills
572 // use an array internally which may throw an error.
573 var disabledHandles = new Set();
574 this._disabledHandles.forEach(function (handle) {
575 if (_this._handles.indexOf(handle) > -1) {
576 disabledHandles.add(handle);
577 }
578 });
579 this._disabledHandles = disabledHandles;
580 return this;
581 };
582 /**
583 * Registers the template that should be used for the drag preview.
584 * @param template Template that from which to stamp out the preview.
585 */
586 DragRef.prototype.withPreviewTemplate = function (template) {
587 this._previewTemplate = template;
588 return this;
589 };
590 /**
591 * Registers the template that should be used for the drag placeholder.
592 * @param template Template that from which to stamp out the placeholder.
593 */
594 DragRef.prototype.withPlaceholderTemplate = function (template) {
595 this._placeholderTemplate = template;
596 return this;
597 };
598 /**
599 * Sets an alternate drag root element. The root element is the element that will be moved as
600 * the user is dragging. Passing an alternate root element is useful when trying to enable
601 * dragging on an element that you might not have access to.
602 */
603 DragRef.prototype.withRootElement = function (rootElement) {
604 var _this = this;
605 var element = coercion.coerceElement(rootElement);
606 if (element !== this._rootElement) {
607 if (this._rootElement) {
608 this._removeRootElementListeners(this._rootElement);
609 }
610 this._ngZone.runOutsideAngular(function () {
611 element.addEventListener('mousedown', _this._pointerDown, activeEventListenerOptions);
612 element.addEventListener('touchstart', _this._pointerDown, passiveEventListenerOptions);
613 });
614 this._initialTransform = undefined;
615 this._rootElement = element;
616 }
617 if (typeof SVGElement !== 'undefined' && this._rootElement instanceof SVGElement) {
618 this._ownerSVGElement = this._rootElement.ownerSVGElement;
619 }
620 return this;
621 };
622 /**
623 * Element to which the draggable's position will be constrained.
624 */
625 DragRef.prototype.withBoundaryElement = function (boundaryElement) {
626 var _this = this;
627 this._boundaryElement = boundaryElement ? coercion.coerceElement(boundaryElement) : null;
628 this._resizeSubscription.unsubscribe();
629 if (boundaryElement) {
630 this._resizeSubscription = this._viewportRuler
631 .change(10)
632 .subscribe(function () { return _this._containInsideBoundaryOnResize(); });
633 }
634 return this;
635 };
636 /** Sets the parent ref that the ref is nested in. */
637 DragRef.prototype.withParent = function (parent) {
638 this._parentDragRef = parent;
639 return this;
640 };
641 /** Removes the dragging functionality from the DOM element. */
642 DragRef.prototype.dispose = function () {
643 this._removeRootElementListeners(this._rootElement);
644 // Do this check before removing from the registry since it'll
645 // stop being considered as dragged once it is removed.
646 if (this.isDragging()) {
647 // Since we move out the element to the end of the body while it's being
648 // dragged, we have to make sure that it's removed if it gets destroyed.
649 removeNode(this._rootElement);
650 }
651 removeNode(this._anchor);
652 this._destroyPreview();
653 this._destroyPlaceholder();
654 this._dragDropRegistry.removeDragItem(this);
655 this._removeSubscriptions();
656 this.beforeStarted.complete();
657 this.started.complete();
658 this.released.complete();
659 this.ended.complete();
660 this.entered.complete();
661 this.exited.complete();
662 this.dropped.complete();
663 this._moveEvents.complete();
664 this._handles = [];
665 this._disabledHandles.clear();
666 this._dropContainer = undefined;
667 this._resizeSubscription.unsubscribe();
668 this._parentPositions.clear();
669 this._boundaryElement = this._rootElement = this._ownerSVGElement = this._placeholderTemplate =
670 this._previewTemplate = this._anchor = this._parentDragRef = null;
671 };
672 /** Checks whether the element is currently being dragged. */
673 DragRef.prototype.isDragging = function () {
674 return this._hasStartedDragging && this._dragDropRegistry.isDragging(this);
675 };
676 /** Resets a standalone drag item to its initial position. */
677 DragRef.prototype.reset = function () {
678 this._rootElement.style.transform = this._initialTransform || '';
679 this._activeTransform = { x: 0, y: 0 };
680 this._passiveTransform = { x: 0, y: 0 };
681 };
682 /**
683 * Sets a handle as disabled. While a handle is disabled, it'll capture and interrupt dragging.
684 * @param handle Handle element that should be disabled.
685 */
686 DragRef.prototype.disableHandle = function (handle) {
687 if (!this._disabledHandles.has(handle) && this._handles.indexOf(handle) > -1) {
688 this._disabledHandles.add(handle);
689 toggleNativeDragInteractions(handle, true);
690 }
691 };
692 /**
693 * Enables a handle, if it has been disabled.
694 * @param handle Handle element to be enabled.
695 */
696 DragRef.prototype.enableHandle = function (handle) {
697 if (this._disabledHandles.has(handle)) {
698 this._disabledHandles.delete(handle);
699 toggleNativeDragInteractions(handle, this.disabled);
700 }
701 };
702 /** Sets the layout direction of the draggable item. */
703 DragRef.prototype.withDirection = function (direction) {
704 this._direction = direction;
705 return this;
706 };
707 /** Sets the container that the item is part of. */
708 DragRef.prototype._withDropContainer = function (container) {
709 this._dropContainer = container;
710 };
711 /**
712 * Gets the current position in pixels the draggable outside of a drop container.
713 */
714 DragRef.prototype.getFreeDragPosition = function () {
715 var position = this.isDragging() ? this._activeTransform : this._passiveTransform;
716 return { x: position.x, y: position.y };
717 };
718 /**
719 * Sets the current position in pixels the draggable outside of a drop container.
720 * @param value New position to be set.
721 */
722 DragRef.prototype.setFreeDragPosition = function (value) {
723 this._activeTransform = { x: 0, y: 0 };
724 this._passiveTransform.x = value.x;
725 this._passiveTransform.y = value.y;
726 if (!this._dropContainer) {
727 this._applyRootElementTransform(value.x, value.y);
728 }
729 return this;
730 };
731 /**
732 * Sets the container into which to insert the preview element.
733 * @param value Container into which to insert the preview.
734 */
735 DragRef.prototype.withPreviewContainer = function (value) {
736 this._previewContainer = value;
737 return this;
738 };
739 /** Updates the item's sort order based on the last-known pointer position. */
740 DragRef.prototype._sortFromLastPointerPosition = function () {
741 var position = this._lastKnownPointerPosition;
742 if (position && this._dropContainer) {
743 this._updateActiveDropContainer(this._getConstrainedPointerPosition(position), position);
744 }
745 };
746 /** Unsubscribes from the global subscriptions. */
747 DragRef.prototype._removeSubscriptions = function () {
748 this._pointerMoveSubscription.unsubscribe();
749 this._pointerUpSubscription.unsubscribe();
750 this._scrollSubscription.unsubscribe();
751 };
752 /** Destroys the preview element and its ViewRef. */
753 DragRef.prototype._destroyPreview = function () {
754 if (this._preview) {
755 removeNode(this._preview);
756 }
757 if (this._previewRef) {
758 this._previewRef.destroy();
759 }
760 this._preview = this._previewRef = null;
761 };
762 /** Destroys the placeholder element and its ViewRef. */
763 DragRef.prototype._destroyPlaceholder = function () {
764 if (this._placeholder) {
765 removeNode(this._placeholder);
766 }
767 if (this._placeholderRef) {
768 this._placeholderRef.destroy();
769 }
770 this._placeholder = this._placeholderRef = null;
771 };
772 /**
773 * Clears subscriptions and stops the dragging sequence.
774 * @param event Browser event object that ended the sequence.
775 */
776 DragRef.prototype._endDragSequence = function (event) {
777 var _this = this;
778 // Note that here we use `isDragging` from the service, rather than from `this`.
779 // The difference is that the one from the service reflects whether a dragging sequence
780 // has been initiated, whereas the one on `this` includes whether the user has passed
781 // the minimum dragging threshold.
782 if (!this._dragDropRegistry.isDragging(this)) {
783 return;
784 }
785 this._removeSubscriptions();
786 this._dragDropRegistry.stopDragging(this);
787 this._toggleNativeDragInteractions();
788 if (this._handles) {
789 this._rootElement.style.webkitTapHighlightColor = this._rootElementTapHighlight;
790 }
791 if (!this._hasStartedDragging) {
792 return;
793 }
794 this.released.next({ source: this });
795 if (this._dropContainer) {
796 // Stop scrolling immediately, instead of waiting for the animation to finish.
797 this._dropContainer._stopScrolling();
798 this._animatePreviewToPlaceholder().then(function () {
799 _this._cleanupDragArtifacts(event);
800 _this._cleanupCachedDimensions();
801 _this._dragDropRegistry.stopDragging(_this);
802 });
803 }
804 else {
805 // Convert the active transform into a passive one. This means that next time
806 // the user starts dragging the item, its position will be calculated relatively
807 // to the new passive transform.
808 this._passiveTransform.x = this._activeTransform.x;
809 var pointerPosition_1 = this._getPointerPositionOnPage(event);
810 this._passiveTransform.y = this._activeTransform.y;
811 this._ngZone.run(function () {
812 _this.ended.next({
813 source: _this,
814 distance: _this._getDragDistance(pointerPosition_1),
815 dropPoint: pointerPosition_1
816 });
817 });
818 this._cleanupCachedDimensions();
819 this._dragDropRegistry.stopDragging(this);
820 }
821 };
822 /** Starts the dragging sequence. */
823 DragRef.prototype._startDragSequence = function (event) {
824 if (isTouchEvent(event)) {
825 this._lastTouchEventTime = Date.now();
826 }
827 this._toggleNativeDragInteractions();
828 var dropContainer = this._dropContainer;
829 if (dropContainer) {
830 var element = this._rootElement;
831 var parent = element.parentNode;
832 var placeholder = this._placeholder = this._createPlaceholderElement();
833 var anchor = this._anchor = this._anchor || this._document.createComment('');
834 // Needs to happen before the root element is moved.
835 var shadowRoot = this._getShadowRoot();
836 // Insert an anchor node so that we can restore the element's position in the DOM.
837 parent.insertBefore(anchor, element);
838 // There's no risk of transforms stacking when inside a drop container so
839 // we can keep the initial transform up to date any time dragging starts.
840 this._initialTransform = element.style.transform || '';
841 // Create the preview after the initial transform has
842 // been cached, because it can be affected by the transform.
843 this._preview = this._createPreviewElement();
844 // We move the element out at the end of the body and we make it hidden, because keeping it in
845 // place will throw off the consumer's `:last-child` selectors. We can't remove the element
846 // from the DOM completely, because iOS will stop firing all subsequent events in the chain.
847 toggleVisibility(element, false, dragImportantProperties);
848 this._document.body.appendChild(parent.replaceChild(placeholder, element));
849 this._getPreviewInsertionPoint(parent, shadowRoot).appendChild(this._preview);
850 this.started.next({ source: this }); // Emit before notifying the container.
851 dropContainer.start();
852 this._initialContainer = dropContainer;
853 this._initialIndex = dropContainer.getItemIndex(this);
854 }
855 else {
856 this.started.next({ source: this });
857 this._initialContainer = this._initialIndex = undefined;
858 }
859 // Important to run after we've called `start` on the parent container
860 // so that it has had time to resolve its scrollable parents.
861 this._parentPositions.cache(dropContainer ? dropContainer.getScrollableParents() : []);
862 };
863 /**
864 * Sets up the different variables and subscriptions
865 * that will be necessary for the dragging sequence.
866 * @param referenceElement Element that started the drag sequence.
867 * @param event Browser event object that started the sequence.
868 */
869 DragRef.prototype._initializeDragSequence = function (referenceElement, event) {
870 var _this = this;
871 // Stop propagation if the item is inside another
872 // draggable so we don't start multiple drag sequences.
873 if (this._parentDragRef) {
874 event.stopPropagation();
875 }
876 var isDragging = this.isDragging();
877 var isTouchSequence = isTouchEvent(event);
878 var isAuxiliaryMouseButton = !isTouchSequence && event.button !== 0;
879 var rootElement = this._rootElement;
880 var target = platform._getEventTarget(event);
881 var isSyntheticEvent = !isTouchSequence && this._lastTouchEventTime &&
882 this._lastTouchEventTime + MOUSE_EVENT_IGNORE_TIME > Date.now();
883 var isFakeEvent = isTouchSequence ? a11y.isFakeTouchstartFromScreenReader(event) :
884 a11y.isFakeMousedownFromScreenReader(event);
885 // If the event started from an element with the native HTML drag&drop, it'll interfere
886 // with our own dragging (e.g. `img` tags do it by default). Prevent the default action
887 // to stop it from happening. Note that preventing on `dragstart` also seems to work, but
888 // it's flaky and it fails if the user drags it away quickly. Also note that we only want
889 // to do this for `mousedown` since doing the same for `touchstart` will stop any `click`
890 // events from firing on touch devices.
891 if (target && target.draggable && event.type === 'mousedown') {
892 event.preventDefault();
893 }
894 // Abort if the user is already dragging or is using a mouse button other than the primary one.
895 if (isDragging || isAuxiliaryMouseButton || isSyntheticEvent || isFakeEvent) {
896 return;
897 }
898 // If we've got handles, we need to disable the tap highlight on the entire root element,
899 // otherwise iOS will still add it, even though all the drag interactions on the handle
900 // are disabled.
901 if (this._handles.length) {
902 this._rootElementTapHighlight = rootElement.style.webkitTapHighlightColor || '';
903 rootElement.style.webkitTapHighlightColor = 'transparent';
904 }
905 this._hasStartedDragging = this._hasMoved = false;
906 // Avoid multiple subscriptions and memory leaks when multi touch
907 // (isDragging check above isn't enough because of possible temporal and/or dimensional delays)
908 this._removeSubscriptions();
909 this._pointerMoveSubscription = this._dragDropRegistry.pointerMove.subscribe(this._pointerMove);
910 this._pointerUpSubscription = this._dragDropRegistry.pointerUp.subscribe(this._pointerUp);
911 this._scrollSubscription = this._dragDropRegistry
912 .scrolled(this._getShadowRoot())
913 .subscribe(function (scrollEvent) { return _this._updateOnScroll(scrollEvent); });
914 if (this._boundaryElement) {
915 this._boundaryRect = getMutableClientRect(this._boundaryElement);
916 }
917 // If we have a custom preview we can't know ahead of time how large it'll be so we position
918 // it next to the cursor. The exception is when the consumer has opted into making the preview
919 // the same size as the root element, in which case we do know the size.
920 var previewTemplate = this._previewTemplate;
921 this._pickupPositionInElement = previewTemplate && previewTemplate.template &&
922 !previewTemplate.matchSize ? { x: 0, y: 0 } :
923 this._getPointerPositionInElement(referenceElement, event);
924 var pointerPosition = this._pickupPositionOnPage = this._lastKnownPointerPosition =
925 this._getPointerPositionOnPage(event);
926 this._pointerDirectionDelta = { x: 0, y: 0 };
927 this._pointerPositionAtLastDirectionChange = { x: pointerPosition.x, y: pointerPosition.y };
928 this._dragStartTime = Date.now();
929 this._dragDropRegistry.startDragging(this, event);
930 };
931 /** Cleans up the DOM artifacts that were added to facilitate the element being dragged. */
932 DragRef.prototype._cleanupDragArtifacts = function (event) {
933 var _this = this;
934 // Restore the element's visibility and insert it at its old position in the DOM.
935 // It's important that we maintain the position, because moving the element around in the DOM
936 // can throw off `NgFor` which does smart diffing and re-creates elements only when necessary,
937 // while moving the existing elements in all other cases.
938 toggleVisibility(this._rootElement, true, dragImportantProperties);
939 this._anchor.parentNode.replaceChild(this._rootElement, this._anchor);
940 this._destroyPreview();
941 this._destroyPlaceholder();
942 this._boundaryRect = this._previewRect = this._initialTransform = undefined;
943 // Re-enter the NgZone since we bound `document` events on the outside.
944 this._ngZone.run(function () {
945 var container = _this._dropContainer;
946 var currentIndex = container.getItemIndex(_this);
947 var pointerPosition = _this._getPointerPositionOnPage(event);
948 var distance = _this._getDragDistance(pointerPosition);
949 var isPointerOverContainer = container._isOverContainer(pointerPosition.x, pointerPosition.y);
950 _this.ended.next({ source: _this, distance: distance, dropPoint: pointerPosition });
951 _this.dropped.next({
952 item: _this,
953 currentIndex: currentIndex,
954 previousIndex: _this._initialIndex,
955 container: container,
956 previousContainer: _this._initialContainer,
957 isPointerOverContainer: isPointerOverContainer,
958 distance: distance,
959 dropPoint: pointerPosition
960 });
961 container.drop(_this, currentIndex, _this._initialIndex, _this._initialContainer, isPointerOverContainer, distance, pointerPosition);
962 _this._dropContainer = _this._initialContainer;
963 });
964 };
965 /**
966 * Updates the item's position in its drop container, or moves it
967 * into a new one, depending on its current drag position.
968 */
969 DragRef.prototype._updateActiveDropContainer = function (_b, _c) {
970 var _this = this;
971 var x = _b.x, y = _b.y;
972 var rawX = _c.x, rawY = _c.y;
973 // Drop container that draggable has been moved into.
974 var newContainer = this._initialContainer._getSiblingContainerFromPosition(this, x, y);
975 // If we couldn't find a new container to move the item into, and the item has left its
976 // initial container, check whether the it's over the initial container. This handles the
977 // case where two containers are connected one way and the user tries to undo dragging an
978 // item into a new container.
979 if (!newContainer && this._dropContainer !== this._initialContainer &&
980 this._initialContainer._isOverContainer(x, y)) {
981 newContainer = this._initialContainer;
982 }
983 if (newContainer && newContainer !== this._dropContainer) {
984 this._ngZone.run(function () {
985 // Notify the old container that the item has left.
986 _this.exited.next({ item: _this, container: _this._dropContainer });
987 _this._dropContainer.exit(_this);
988 // Notify the new container that the item has entered.
989 _this._dropContainer = newContainer;
990 _this._dropContainer.enter(_this, x, y, newContainer === _this._initialContainer &&
991 // If we're re-entering the initial container and sorting is disabled,
992 // put item the into its starting index to begin with.
993 newContainer.sortingDisabled ? _this._initialIndex : undefined);
994 _this.entered.next({
995 item: _this,
996 container: newContainer,
997 currentIndex: newContainer.getItemIndex(_this)
998 });
999 });
1000 }
1001 // Dragging may have been interrupted as a result of the events above.
1002 if (this.isDragging()) {
1003 this._dropContainer._startScrollingIfNecessary(rawX, rawY);
1004 this._dropContainer._sortItem(this, x, y, this._pointerDirectionDelta);
1005 this._applyPreviewTransform(x - this._pickupPositionInElement.x, y - this._pickupPositionInElement.y);
1006 }
1007 };
1008 /**
1009 * Creates the element that will be rendered next to the user's pointer
1010 * and will be used as a preview of the element that is being dragged.
1011 */
1012 DragRef.prototype._createPreviewElement = function () {
1013 var previewConfig = this._previewTemplate;
1014 var previewClass = this.previewClass;
1015 var previewTemplate = previewConfig ? previewConfig.template : null;
1016 var preview;
1017 if (previewTemplate && previewConfig) {
1018 // Measure the element before we've inserted the preview
1019 // since the insertion could throw off the measurement.
1020 var rootRect = previewConfig.matchSize ? this._rootElement.getBoundingClientRect() : null;
1021 var viewRef = previewConfig.viewContainer.createEmbeddedView(previewTemplate, previewConfig.context);
1022 viewRef.detectChanges();
1023 preview = getRootNode(viewRef, this._document);
1024 this._previewRef = viewRef;
1025 if (previewConfig.matchSize) {
1026 matchElementSize(preview, rootRect);
1027 }
1028 else {
1029 preview.style.transform =
1030 getTransform(this._pickupPositionOnPage.x, this._pickupPositionOnPage.y);
1031 }
1032 }
1033 else {
1034 var element = this._rootElement;
1035 preview = deepCloneNode(element);
1036 matchElementSize(preview, element.getBoundingClientRect());
1037 if (this._initialTransform) {
1038 preview.style.transform = this._initialTransform;
1039 }
1040 }
1041 extendStyles(preview.style, {
1042 // It's important that we disable the pointer events on the preview, because
1043 // it can throw off the `document.elementFromPoint` calls in the `CdkDropList`.
1044 'pointer-events': 'none',
1045 // We have to reset the margin, because it can throw off positioning relative to the viewport.
1046 'margin': '0',
1047 'position': 'fixed',
1048 'top': '0',
1049 'left': '0',
1050 'z-index': "" + (this._config.zIndex || 1000)
1051 }, dragImportantProperties);
1052 toggleNativeDragInteractions(preview, false);
1053 preview.classList.add('cdk-drag-preview');
1054 preview.setAttribute('dir', this._direction);
1055 if (previewClass) {
1056 if (Array.isArray(previewClass)) {
1057 previewClass.forEach(function (className) { return preview.classList.add(className); });
1058 }
1059 else {
1060 preview.classList.add(previewClass);
1061 }
1062 }
1063 return preview;
1064 };
1065 /**
1066 * Animates the preview element from its current position to the location of the drop placeholder.
1067 * @returns Promise that resolves when the animation completes.
1068 */
1069 DragRef.prototype._animatePreviewToPlaceholder = function () {
1070 var _this = this;
1071 // If the user hasn't moved yet, the transitionend event won't fire.
1072 if (!this._hasMoved) {
1073 return Promise.resolve();
1074 }
1075 var placeholderRect = this._placeholder.getBoundingClientRect();
1076 // Apply the class that adds a transition to the preview.
1077 this._preview.classList.add('cdk-drag-animating');
1078 // Move the preview to the placeholder position.
1079 this._applyPreviewTransform(placeholderRect.left, placeholderRect.top);
1080 // If the element doesn't have a `transition`, the `transitionend` event won't fire. Since
1081 // we need to trigger a style recalculation in order for the `cdk-drag-animating` class to
1082 // apply its style, we take advantage of the available info to figure out whether we need to
1083 // bind the event in the first place.
1084 var duration = getTransformTransitionDurationInMs(this._preview);
1085 if (duration === 0) {
1086 return Promise.resolve();
1087 }
1088 return this._ngZone.runOutsideAngular(function () {
1089 return new Promise(function (resolve) {
1090 var handler = (function (event) {
1091 if (!event || (platform._getEventTarget(event) === _this._preview &&
1092 event.propertyName === 'transform')) {
1093 _this._preview.removeEventListener('transitionend', handler);
1094 resolve();
1095 clearTimeout(timeout);
1096 }
1097 });
1098 // If a transition is short enough, the browser might not fire the `transitionend` event.
1099 // Since we know how long it's supposed to take, add a timeout with a 50% buffer that'll
1100 // fire if the transition hasn't completed when it was supposed to.
1101 var timeout = setTimeout(handler, duration * 1.5);
1102 _this._preview.addEventListener('transitionend', handler);
1103 });
1104 });
1105 };
1106 /** Creates an element that will be shown instead of the current element while dragging. */
1107 DragRef.prototype._createPlaceholderElement = function () {
1108 var placeholderConfig = this._placeholderTemplate;
1109 var placeholderTemplate = placeholderConfig ? placeholderConfig.template : null;
1110 var placeholder;
1111 if (placeholderTemplate) {
1112 this._placeholderRef = placeholderConfig.viewContainer.createEmbeddedView(placeholderTemplate, placeholderConfig.context);
1113 this._placeholderRef.detectChanges();
1114 placeholder = getRootNode(this._placeholderRef, this._document);
1115 }
1116 else {
1117 placeholder = deepCloneNode(this._rootElement);
1118 }
1119 placeholder.classList.add('cdk-drag-placeholder');
1120 return placeholder;
1121 };
1122 /**
1123 * Figures out the coordinates at which an element was picked up.
1124 * @param referenceElement Element that initiated the dragging.
1125 * @param event Event that initiated the dragging.
1126 */
1127 DragRef.prototype._getPointerPositionInElement = function (referenceElement, event) {
1128 var elementRect = this._rootElement.getBoundingClientRect();
1129 var handleElement = referenceElement === this._rootElement ? null : referenceElement;
1130 var referenceRect = handleElement ? handleElement.getBoundingClientRect() : elementRect;
1131 var point = isTouchEvent(event) ? event.targetTouches[0] : event;
1132 var scrollPosition = this._getViewportScrollPosition();
1133 var x = point.pageX - referenceRect.left - scrollPosition.left;
1134 var y = point.pageY - referenceRect.top - scrollPosition.top;
1135 return {
1136 x: referenceRect.left - elementRect.left + x,
1137 y: referenceRect.top - elementRect.top + y
1138 };
1139 };
1140 /** Determines the point of the page that was touched by the user. */
1141 DragRef.prototype._getPointerPositionOnPage = function (event) {
1142 var scrollPosition = this._getViewportScrollPosition();
1143 var point = isTouchEvent(event) ?
1144 // `touches` will be empty for start/end events so we have to fall back to `changedTouches`.
1145 // Also note that on real devices we're guaranteed for either `touches` or `changedTouches`
1146 // to have a value, but Firefox in device emulation mode has a bug where both can be empty
1147 // for `touchstart` and `touchend` so we fall back to a dummy object in order to avoid
1148 // throwing an error. The value returned here will be incorrect, but since this only
1149 // breaks inside a developer tool and the value is only used for secondary information,
1150 // we can get away with it. See https://bugzilla.mozilla.org/show_bug.cgi?id=1615824.
1151 (event.touches[0] || event.changedTouches[0] || { pageX: 0, pageY: 0 }) : event;
1152 var x = point.pageX - scrollPosition.left;
1153 var y = point.pageY - scrollPosition.top;
1154 // if dragging SVG element, try to convert from the screen coordinate system to the SVG
1155 // coordinate system
1156 if (this._ownerSVGElement) {
1157 var svgMatrix = this._ownerSVGElement.getScreenCTM();
1158 if (svgMatrix) {
1159 var svgPoint = this._ownerSVGElement.createSVGPoint();
1160 svgPoint.x = x;
1161 svgPoint.y = y;
1162 return svgPoint.matrixTransform(svgMatrix.inverse());
1163 }
1164 }
1165 return { x: x, y: y };
1166 };
1167 /** Gets the pointer position on the page, accounting for any position constraints. */
1168 DragRef.prototype._getConstrainedPointerPosition = function (point) {
1169 var dropContainerLock = this._dropContainer ? this._dropContainer.lockAxis : null;
1170 var _b = this.constrainPosition ? this.constrainPosition(point, this) : point, x = _b.x, y = _b.y;
1171 if (this.lockAxis === 'x' || dropContainerLock === 'x') {
1172 y = this._pickupPositionOnPage.y;
1173 }
1174 else if (this.lockAxis === 'y' || dropContainerLock === 'y') {
1175 x = this._pickupPositionOnPage.x;
1176 }
1177 if (this._boundaryRect) {
1178 var _c = this._pickupPositionInElement, pickupX = _c.x, pickupY = _c.y;
1179 var boundaryRect = this._boundaryRect;
1180 var previewRect = this._previewRect;
1181 var minY = boundaryRect.top + pickupY;
1182 var maxY = boundaryRect.bottom - (previewRect.height - pickupY);
1183 var minX = boundaryRect.left + pickupX;
1184 var maxX = boundaryRect.right - (previewRect.width - pickupX);
1185 x = clamp$1(x, minX, maxX);
1186 y = clamp$1(y, minY, maxY);
1187 }
1188 return { x: x, y: y };
1189 };
1190 /** Updates the current drag delta, based on the user's current pointer position on the page. */
1191 DragRef.prototype._updatePointerDirectionDelta = function (pointerPositionOnPage) {
1192 var x = pointerPositionOnPage.x, y = pointerPositionOnPage.y;
1193 var delta = this._pointerDirectionDelta;
1194 var positionSinceLastChange = this._pointerPositionAtLastDirectionChange;
1195 // Amount of pixels the user has dragged since the last time the direction changed.
1196 var changeX = Math.abs(x - positionSinceLastChange.x);
1197 var changeY = Math.abs(y - positionSinceLastChange.y);
1198 // Because we handle pointer events on a per-pixel basis, we don't want the delta
1199 // to change for every pixel, otherwise anything that depends on it can look erratic.
1200 // To make the delta more consistent, we track how much the user has moved since the last
1201 // delta change and we only update it after it has reached a certain threshold.
1202 if (changeX > this._config.pointerDirectionChangeThreshold) {
1203 delta.x = x > positionSinceLastChange.x ? 1 : -1;
1204 positionSinceLastChange.x = x;
1205 }
1206 if (changeY > this._config.pointerDirectionChangeThreshold) {
1207 delta.y = y > positionSinceLastChange.y ? 1 : -1;
1208 positionSinceLastChange.y = y;
1209 }
1210 return delta;
1211 };
1212 /** Toggles the native drag interactions, based on how many handles are registered. */
1213 DragRef.prototype._toggleNativeDragInteractions = function () {
1214 if (!this._rootElement || !this._handles) {
1215 return;
1216 }
1217 var shouldEnable = this._handles.length > 0 || !this.isDragging();
1218 if (shouldEnable !== this._nativeInteractionsEnabled) {
1219 this._nativeInteractionsEnabled = shouldEnable;
1220 toggleNativeDragInteractions(this._rootElement, shouldEnable);
1221 }
1222 };
1223 /** Removes the manually-added event listeners from the root element. */
1224 DragRef.prototype._removeRootElementListeners = function (element) {
1225 element.removeEventListener('mousedown', this._pointerDown, activeEventListenerOptions);
1226 element.removeEventListener('touchstart', this._pointerDown, passiveEventListenerOptions);
1227 };
1228 /**
1229 * Applies a `transform` to the root element, taking into account any existing transforms on it.
1230 * @param x New transform value along the X axis.
1231 * @param y New transform value along the Y axis.
1232 */
1233 DragRef.prototype._applyRootElementTransform = function (x, y) {
1234 var transform = getTransform(x, y);
1235 // Cache the previous transform amount only after the first drag sequence, because
1236 // we don't want our own transforms to stack on top of each other.
1237 // Should be excluded none because none + translate3d(x, y, x) is invalid css
1238 if (this._initialTransform == null) {
1239 this._initialTransform = this._rootElement.style.transform
1240 && this._rootElement.style.transform != 'none'
1241 ? this._rootElement.style.transform
1242 : '';
1243 }
1244 // Preserve the previous `transform` value, if there was one. Note that we apply our own
1245 // transform before the user's, because things like rotation can affect which direction
1246 // the element will be translated towards.
1247 this._rootElement.style.transform = combineTransforms(transform, this._initialTransform);
1248 };
1249 /**
1250 * Applies a `transform` to the preview, taking into account any existing transforms on it.
1251 * @param x New transform value along the X axis.
1252 * @param y New transform value along the Y axis.
1253 */
1254 DragRef.prototype._applyPreviewTransform = function (x, y) {
1255 var _a;
1256 // Only apply the initial transform if the preview is a clone of the original element, otherwise
1257 // it could be completely different and the transform might not make sense anymore.
1258 var initialTransform = ((_a = this._previewTemplate) === null || _a === void 0 ? void 0 : _a.template) ? undefined : this._initialTransform;
1259 var transform = getTransform(x, y);
1260 this._preview.style.transform = combineTransforms(transform, initialTransform);
1261 };
1262 /**
1263 * Gets the distance that the user has dragged during the current drag sequence.
1264 * @param currentPosition Current position of the user's pointer.
1265 */
1266 DragRef.prototype._getDragDistance = function (currentPosition) {
1267 var pickupPosition = this._pickupPositionOnPage;
1268 if (pickupPosition) {
1269 return { x: currentPosition.x - pickupPosition.x, y: currentPosition.y - pickupPosition.y };
1270 }
1271 return { x: 0, y: 0 };
1272 };
1273 /** Cleans up any cached element dimensions that we don't need after dragging has stopped. */
1274 DragRef.prototype._cleanupCachedDimensions = function () {
1275 this._boundaryRect = this._previewRect = undefined;
1276 this._parentPositions.clear();
1277 };
1278 /**
1279 * Checks whether the element is still inside its boundary after the viewport has been resized.
1280 * If not, the position is adjusted so that the element fits again.
1281 */
1282 DragRef.prototype._containInsideBoundaryOnResize = function () {
1283 var _b = this._passiveTransform, x = _b.x, y = _b.y;
1284 if ((x === 0 && y === 0) || this.isDragging() || !this._boundaryElement) {
1285 return;
1286 }
1287 var boundaryRect = this._boundaryElement.getBoundingClientRect();
1288 var elementRect = this._rootElement.getBoundingClientRect();
1289 // It's possible that the element got hidden away after dragging (e.g. by switching to a
1290 // different tab). Don't do anything in this case so we don't clear the user's position.
1291 if ((boundaryRect.width === 0 && boundaryRect.height === 0) ||
1292 (elementRect.width === 0 && elementRect.height === 0)) {
1293 return;
1294 }
1295 var leftOverflow = boundaryRect.left - elementRect.left;
1296 var rightOverflow = elementRect.right - boundaryRect.right;
1297 var topOverflow = boundaryRect.top - elementRect.top;
1298 var bottomOverflow = elementRect.bottom - boundaryRect.bottom;
1299 // If the element has become wider than the boundary, we can't
1300 // do much to make it fit so we just anchor it to the left.
1301 if (boundaryRect.width > elementRect.width) {
1302 if (leftOverflow > 0) {
1303 x += leftOverflow;
1304 }
1305 if (rightOverflow > 0) {
1306 x -= rightOverflow;
1307 }
1308 }
1309 else {
1310 x = 0;
1311 }
1312 // If the element has become taller than the boundary, we can't
1313 // do much to make it fit so we just anchor it to the top.
1314 if (boundaryRect.height > elementRect.height) {
1315 if (topOverflow > 0) {
1316 y += topOverflow;
1317 }
1318 if (bottomOverflow > 0) {
1319 y -= bottomOverflow;
1320 }
1321 }
1322 else {
1323 y = 0;
1324 }
1325 if (x !== this._passiveTransform.x || y !== this._passiveTransform.y) {
1326 this.setFreeDragPosition({ y: y, x: x });
1327 }
1328 };
1329 /** Gets the drag start delay, based on the event type. */
1330 DragRef.prototype._getDragStartDelay = function (event) {
1331 var value = this.dragStartDelay;
1332 if (typeof value === 'number') {
1333 return value;
1334 }
1335 else if (isTouchEvent(event)) {
1336 return value.touch;
1337 }
1338 return value ? value.mouse : 0;
1339 };
1340 /** Updates the internal state of the draggable element when scrolling has occurred. */
1341 DragRef.prototype._updateOnScroll = function (event) {
1342 var scrollDifference = this._parentPositions.handleScroll(event);
1343 if (scrollDifference) {
1344 var target = platform._getEventTarget(event);
1345 // ClientRect dimensions are based on the scroll position of the page and its parent node so
1346 // we have to update the cached boundary ClientRect if the user has scrolled. Check for
1347 // the `document` specifically since IE doesn't support `contains` on it.
1348 if (this._boundaryRect && (target === this._document ||
1349 (target !== this._boundaryElement && target.contains(this._boundaryElement)))) {
1350 adjustClientRect(this._boundaryRect, scrollDifference.top, scrollDifference.left);
1351 }
1352 this._pickupPositionOnPage.x += scrollDifference.left;
1353 this._pickupPositionOnPage.y += scrollDifference.top;
1354 // If we're in free drag mode, we have to update the active transform, because
1355 // it isn't relative to the viewport like the preview inside a drop list.
1356 if (!this._dropContainer) {
1357 this._activeTransform.x -= scrollDifference.left;
1358 this._activeTransform.y -= scrollDifference.top;
1359 this._applyRootElementTransform(this._activeTransform.x, this._activeTransform.y);
1360 }
1361 }
1362 };
1363 /** Gets the scroll position of the viewport. */
1364 DragRef.prototype._getViewportScrollPosition = function () {
1365 var cachedPosition = this._parentPositions.positions.get(this._document);
1366 return cachedPosition ? cachedPosition.scrollPosition :
1367 this._viewportRuler.getViewportScrollPosition();
1368 };
1369 /**
1370 * Lazily resolves and returns the shadow root of the element. We do this in a function, rather
1371 * than saving it in property directly on init, because we want to resolve it as late as possible
1372 * in order to ensure that the element has been moved into the shadow DOM. Doing it inside the
1373 * constructor might be too early if the element is inside of something like `ngFor` or `ngIf`.
1374 */
1375 DragRef.prototype._getShadowRoot = function () {
1376 if (this._cachedShadowRoot === undefined) {
1377 this._cachedShadowRoot = platform._getShadowRoot(this._rootElement);
1378 }
1379 return this._cachedShadowRoot;
1380 };
1381 /** Gets the element into which the drag preview should be inserted. */
1382 DragRef.prototype._getPreviewInsertionPoint = function (initialParent, shadowRoot) {
1383 var previewContainer = this._previewContainer || 'global';
1384 if (previewContainer === 'parent') {
1385 return initialParent;
1386 }
1387 if (previewContainer === 'global') {
1388 var documentRef = this._document;
1389 // We can't use the body if the user is in fullscreen mode,
1390 // because the preview will render under the fullscreen element.
1391 // TODO(crisbeto): dedupe this with the `FullscreenOverlayContainer` eventually.
1392 return shadowRoot ||
1393 documentRef.fullscreenElement ||
1394 documentRef.webkitFullscreenElement ||
1395 documentRef.mozFullScreenElement ||
1396 documentRef.msFullscreenElement ||
1397 documentRef.body;
1398 }
1399 return coercion.coerceElement(previewContainer);
1400 };
1401 return DragRef;
1402 }());
1403 /**
1404 * Gets a 3d `transform` that can be applied to an element.
1405 * @param x Desired position of the element along the X axis.
1406 * @param y Desired position of the element along the Y axis.
1407 */
1408 function getTransform(x, y) {
1409 // Round the transforms since some browsers will
1410 // blur the elements for sub-pixel transforms.
1411 return "translate3d(" + Math.round(x) + "px, " + Math.round(y) + "px, 0)";
1412 }
1413 /** Clamps a value between a minimum and a maximum. */
1414 function clamp$1(value, min, max) {
1415 return Math.max(min, Math.min(max, value));
1416 }
1417 /**
1418 * Helper to remove a node from the DOM and to do all the necessary null checks.
1419 * @param node Node to be removed.
1420 */
1421 function removeNode(node) {
1422 if (node && node.parentNode) {
1423 node.parentNode.removeChild(node);
1424 }
1425 }
1426 /** Determines whether an event is a touch event. */
1427 function isTouchEvent(event) {
1428 // This function is called for every pixel that the user has dragged so we need it to be
1429 // as fast as possible. Since we only bind mouse events and touch events, we can assume
1430 // that if the event's name starts with `t`, it's a touch event.
1431 return event.type[0] === 't';
1432 }
1433 /**
1434 * Gets the root HTML element of an embedded view.
1435 * If the root is not an HTML element it gets wrapped in one.
1436 */
1437 function getRootNode(viewRef, _document) {
1438 var rootNodes = viewRef.rootNodes;
1439 if (rootNodes.length === 1 && rootNodes[0].nodeType === _document.ELEMENT_NODE) {
1440 return rootNodes[0];
1441 }
1442 var wrapper = _document.createElement('div');
1443 rootNodes.forEach(function (node) { return wrapper.appendChild(node); });
1444 return wrapper;
1445 }
1446 /**
1447 * Matches the target element's size to the source's size.
1448 * @param target Element that needs to be resized.
1449 * @param sourceRect Dimensions of the source element.
1450 */
1451 function matchElementSize(target, sourceRect) {
1452 target.style.width = sourceRect.width + "px";
1453 target.style.height = sourceRect.height + "px";
1454 target.style.transform = getTransform(sourceRect.left, sourceRect.top);
1455 }
1456
1457 /*! *****************************************************************************
1458 Copyright (c) Microsoft Corporation.
1459
1460 Permission to use, copy, modify, and/or distribute this software for any
1461 purpose with or without fee is hereby granted.
1462
1463 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
1464 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1465 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
1466 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
1467 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
1468 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
1469 PERFORMANCE OF THIS SOFTWARE.
1470 ***************************************************************************** */
1471 /* global Reflect, Promise */
1472 var extendStatics = function (d, b) {
1473 extendStatics = Object.setPrototypeOf ||
1474 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
1475 function (d, b) { for (var p in b)
1476 if (Object.prototype.hasOwnProperty.call(b, p))
1477 d[p] = b[p]; };
1478 return extendStatics(d, b);
1479 };
1480 function __extends(d, b) {
1481 if (typeof b !== "function" && b !== null)
1482 throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
1483 extendStatics(d, b);
1484 function __() { this.constructor = d; }
1485 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
1486 }
1487 var __assign = function () {
1488 __assign = Object.assign || function __assign(t) {
1489 for (var s, i = 1, n = arguments.length; i < n; i++) {
1490 s = arguments[i];
1491 for (var p in s)
1492 if (Object.prototype.hasOwnProperty.call(s, p))
1493 t[p] = s[p];
1494 }
1495 return t;
1496 };
1497 return __assign.apply(this, arguments);
1498 };
1499 function __rest(s, e) {
1500 var t = {};
1501 for (var p in s)
1502 if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
1503 t[p] = s[p];
1504 if (s != null && typeof Object.getOwnPropertySymbols === "function")
1505 for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
1506 if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
1507 t[p[i]] = s[p[i]];
1508 }
1509 return t;
1510 }
1511 function __decorate(decorators, target, key, desc) {
1512 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1513 if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
1514 r = Reflect.decorate(decorators, target, key, desc);
1515 else
1516 for (var i = decorators.length - 1; i >= 0; i--)
1517 if (d = decorators[i])
1518 r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1519 return c > 3 && r && Object.defineProperty(target, key, r), r;
1520 }
1521 function __param(paramIndex, decorator) {
1522 return function (target, key) { decorator(target, key, paramIndex); };
1523 }
1524 function __metadata(metadataKey, metadataValue) {
1525 if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
1526 return Reflect.metadata(metadataKey, metadataValue);
1527 }
1528 function __awaiter(thisArg, _arguments, P, generator) {
1529 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
1530 return new (P || (P = Promise))(function (resolve, reject) {
1531 function fulfilled(value) { try {
1532 step(generator.next(value));
1533 }
1534 catch (e) {
1535 reject(e);
1536 } }
1537 function rejected(value) { try {
1538 step(generator["throw"](value));
1539 }
1540 catch (e) {
1541 reject(e);
1542 } }
1543 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
1544 step((generator = generator.apply(thisArg, _arguments || [])).next());
1545 });
1546 }
1547 function __generator(thisArg, body) {
1548 var _ = { label: 0, sent: function () { if (t[0] & 1)
1549 throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
1550 return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function () { return this; }), g;
1551 function verb(n) { return function (v) { return step([n, v]); }; }
1552 function step(op) {
1553 if (f)
1554 throw new TypeError("Generator is already executing.");
1555 while (_)
1556 try {
1557 if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done)
1558 return t;
1559 if (y = 0, t)
1560 op = [op[0] & 2, t.value];
1561 switch (op[0]) {
1562 case 0:
1563 case 1:
1564 t = op;
1565 break;
1566 case 4:
1567 _.label++;
1568 return { value: op[1], done: false };
1569 case 5:
1570 _.label++;
1571 y = op[1];
1572 op = [0];
1573 continue;
1574 case 7:
1575 op = _.ops.pop();
1576 _.trys.pop();
1577 continue;
1578 default:
1579 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
1580 _ = 0;
1581 continue;
1582 }
1583 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) {
1584 _.label = op[1];
1585 break;
1586 }
1587 if (op[0] === 6 && _.label < t[1]) {
1588 _.label = t[1];
1589 t = op;
1590 break;
1591 }
1592 if (t && _.label < t[2]) {
1593 _.label = t[2];
1594 _.ops.push(op);
1595 break;
1596 }
1597 if (t[2])
1598 _.ops.pop();
1599 _.trys.pop();
1600 continue;
1601 }
1602 op = body.call(thisArg, _);
1603 }
1604 catch (e) {
1605 op = [6, e];
1606 y = 0;
1607 }
1608 finally {
1609 f = t = 0;
1610 }
1611 if (op[0] & 5)
1612 throw op[1];
1613 return { value: op[0] ? op[1] : void 0, done: true };
1614 }
1615 }
1616 var __createBinding = Object.create ? (function (o, m, k, k2) {
1617 if (k2 === undefined)
1618 k2 = k;
1619 Object.defineProperty(o, k2, { enumerable: true, get: function () { return m[k]; } });
1620 }) : (function (o, m, k, k2) {
1621 if (k2 === undefined)
1622 k2 = k;
1623 o[k2] = m[k];
1624 });
1625 function __exportStar(m, o) {
1626 for (var p in m)
1627 if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p))
1628 __createBinding(o, m, p);
1629 }
1630 function __values(o) {
1631 var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
1632 if (m)
1633 return m.call(o);
1634 if (o && typeof o.length === "number")
1635 return {
1636 next: function () {
1637 if (o && i >= o.length)
1638 o = void 0;
1639 return { value: o && o[i++], done: !o };
1640 }
1641 };
1642 throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
1643 }
1644 function __read(o, n) {
1645 var m = typeof Symbol === "function" && o[Symbol.iterator];
1646 if (!m)
1647 return o;
1648 var i = m.call(o), r, ar = [], e;
1649 try {
1650 while ((n === void 0 || n-- > 0) && !(r = i.next()).done)
1651 ar.push(r.value);
1652 }
1653 catch (error) {
1654 e = { error: error };
1655 }
1656 finally {
1657 try {
1658 if (r && !r.done && (m = i["return"]))
1659 m.call(i);
1660 }
1661 finally {
1662 if (e)
1663 throw e.error;
1664 }
1665 }
1666 return ar;
1667 }
1668 /** @deprecated */
1669 function __spread() {
1670 for (var ar = [], i = 0; i < arguments.length; i++)
1671 ar = ar.concat(__read(arguments[i]));
1672 return ar;
1673 }
1674 /** @deprecated */
1675 function __spreadArrays() {
1676 for (var s = 0, i = 0, il = arguments.length; i < il; i++)
1677 s += arguments[i].length;
1678 for (var r = Array(s), k = 0, i = 0; i < il; i++)
1679 for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
1680 r[k] = a[j];
1681 return r;
1682 }
1683 function __spreadArray(to, from, pack) {
1684 if (pack || arguments.length === 2)
1685 for (var i = 0, l = from.length, ar; i < l; i++) {
1686 if (ar || !(i in from)) {
1687 if (!ar)
1688 ar = Array.prototype.slice.call(from, 0, i);
1689 ar[i] = from[i];
1690 }
1691 }
1692 return to.concat(ar || from);
1693 }
1694 function __await(v) {
1695 return this instanceof __await ? (this.v = v, this) : new __await(v);
1696 }
1697 function __asyncGenerator(thisArg, _arguments, generator) {
1698 if (!Symbol.asyncIterator)
1699 throw new TypeError("Symbol.asyncIterator is not defined.");
1700 var g = generator.apply(thisArg, _arguments || []), i, q = [];
1701 return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
1702 function verb(n) { if (g[n])
1703 i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
1704 function resume(n, v) { try {
1705 step(g[n](v));
1706 }
1707 catch (e) {
1708 settle(q[0][3], e);
1709 } }
1710 function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
1711 function fulfill(value) { resume("next", value); }
1712 function reject(value) { resume("throw", value); }
1713 function settle(f, v) { if (f(v), q.shift(), q.length)
1714 resume(q[0][0], q[0][1]); }
1715 }
1716 function __asyncDelegator(o) {
1717 var i, p;
1718 return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
1719 function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; }
1720 }
1721 function __asyncValues(o) {
1722 if (!Symbol.asyncIterator)
1723 throw new TypeError("Symbol.asyncIterator is not defined.");
1724 var m = o[Symbol.asyncIterator], i;
1725 return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
1726 function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
1727 function settle(resolve, reject, d, v) { Promise.resolve(v).then(function (v) { resolve({ value: v, done: d }); }, reject); }
1728 }
1729 function __makeTemplateObject(cooked, raw) {
1730 if (Object.defineProperty) {
1731 Object.defineProperty(cooked, "raw", { value: raw });
1732 }
1733 else {
1734 cooked.raw = raw;
1735 }
1736 return cooked;
1737 }
1738 ;
1739 var __setModuleDefault = Object.create ? (function (o, v) {
1740 Object.defineProperty(o, "default", { enumerable: true, value: v });
1741 }) : function (o, v) {
1742 o["default"] = v;
1743 };
1744 function __importStar(mod) {
1745 if (mod && mod.__esModule)
1746 return mod;
1747 var result = {};
1748 if (mod != null)
1749 for (var k in mod)
1750 if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k))
1751 __createBinding(result, mod, k);
1752 __setModuleDefault(result, mod);
1753 return result;
1754 }
1755 function __importDefault(mod) {
1756 return (mod && mod.__esModule) ? mod : { default: mod };
1757 }
1758 function __classPrivateFieldGet(receiver, state, kind, f) {
1759 if (kind === "a" && !f)
1760 throw new TypeError("Private accessor was defined without a getter");
1761 if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver))
1762 throw new TypeError("Cannot read private member from an object whose class did not declare it");
1763 return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
1764 }
1765 function __classPrivateFieldSet(receiver, state, value, kind, f) {
1766 if (kind === "m")
1767 throw new TypeError("Private method is not writable");
1768 if (kind === "a" && !f)
1769 throw new TypeError("Private accessor was defined without a setter");
1770 if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver))
1771 throw new TypeError("Cannot write private member to an object whose class did not declare it");
1772 return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
1773 }
1774
1775 /**
1776 * @license
1777 * Copyright Google LLC All Rights Reserved.
1778 *
1779 * Use of this source code is governed by an MIT-style license that can be
1780 * found in the LICENSE file at https://angular.io/license
1781 */
1782 /**
1783 * Moves an item one index in an array to another.
1784 * @param array Array in which to move the item.
1785 * @param fromIndex Starting index of the item.
1786 * @param toIndex Index to which the item should be moved.
1787 */
1788 function moveItemInArray(array, fromIndex, toIndex) {
1789 var from = clamp(fromIndex, array.length - 1);
1790 var to = clamp(toIndex, array.length - 1);
1791 if (from === to) {
1792 return;
1793 }
1794 var target = array[from];
1795 var delta = to < from ? -1 : 1;
1796 for (var i = from; i !== to; i += delta) {
1797 array[i] = array[i + delta];
1798 }
1799 array[to] = target;
1800 }
1801 /**
1802 * Moves an item from one array to another.
1803 * @param currentArray Array from which to transfer the item.
1804 * @param targetArray Array into which to put the item.
1805 * @param currentIndex Index of the item in its current array.
1806 * @param targetIndex Index at which to insert the item.
1807 */
1808 function transferArrayItem(currentArray, targetArray, currentIndex, targetIndex) {
1809 var from = clamp(currentIndex, currentArray.length - 1);
1810 var to = clamp(targetIndex, targetArray.length);
1811 if (currentArray.length) {
1812 targetArray.splice(to, 0, currentArray.splice(from, 1)[0]);
1813 }
1814 }
1815 /**
1816 * Copies an item from one array to another, leaving it in its
1817 * original position in current array.
1818 * @param currentArray Array from which to copy the item.
1819 * @param targetArray Array into which is copy the item.
1820 * @param currentIndex Index of the item in its current array.
1821 * @param targetIndex Index at which to insert the item.
1822 *
1823 */
1824 function copyArrayItem(currentArray, targetArray, currentIndex, targetIndex) {
1825 var to = clamp(targetIndex, targetArray.length);
1826 if (currentArray.length) {
1827 targetArray.splice(to, 0, currentArray[currentIndex]);
1828 }
1829 }
1830 /** Clamps a number between zero and a maximum. */
1831 function clamp(value, max) {
1832 return Math.max(0, Math.min(max, value));
1833 }
1834
1835 /**
1836 * Proximity, as a ratio to width/height, at which a
1837 * dragged item will affect the drop container.
1838 */
1839 var DROP_PROXIMITY_THRESHOLD = 0.05;
1840 /**
1841 * Proximity, as a ratio to width/height at which to start auto-scrolling the drop list or the
1842 * viewport. The value comes from trying it out manually until it feels right.
1843 */
1844 var SCROLL_PROXIMITY_THRESHOLD = 0.05;
1845 /**
1846 * Reference to a drop list. Used to manipulate or dispose of the container.
1847 */
1848 var DropListRef = /** @class */ (function () {
1849 function DropListRef(element, _dragDropRegistry, _document, _ngZone, _viewportRuler) {
1850 var _this = this;
1851 this._dragDropRegistry = _dragDropRegistry;
1852 this._ngZone = _ngZone;
1853 this._viewportRuler = _viewportRuler;
1854 /** Whether starting a dragging sequence from this container is disabled. */
1855 this.disabled = false;
1856 /** Whether sorting items within the list is disabled. */
1857 this.sortingDisabled = false;
1858 /**
1859 * Whether auto-scrolling the view when the user
1860 * moves their pointer close to the edges is disabled.
1861 */
1862 this.autoScrollDisabled = false;
1863 /** Number of pixels to scroll for each frame when auto-scrolling an element. */
1864 this.autoScrollStep = 2;
1865 /**
1866 * Function that is used to determine whether an item
1867 * is allowed to be moved into a drop container.
1868 */
1869 this.enterPredicate = function () { return true; };
1870 /** Functions that is used to determine whether an item can be sorted into a particular index. */
1871 this.sortPredicate = function () { return true; };
1872 /** Emits right before dragging has started. */
1873 this.beforeStarted = new rxjs.Subject();
1874 /**
1875 * Emits when the user has moved a new drag item into this container.
1876 */
1877 this.entered = new rxjs.Subject();
1878 /**
1879 * Emits when the user removes an item from the container
1880 * by dragging it into another container.
1881 */
1882 this.exited = new rxjs.Subject();
1883 /** Emits when the user drops an item inside the container. */
1884 this.dropped = new rxjs.Subject();
1885 /** Emits as the user is swapping items while actively dragging. */
1886 this.sorted = new rxjs.Subject();
1887 /** Whether an item in the list is being dragged. */
1888 this._isDragging = false;
1889 /** Cache of the dimensions of all the items inside the container. */
1890 this._itemPositions = [];
1891 /**
1892 * Keeps track of the item that was last swapped with the dragged item, as well as what direction
1893 * the pointer was moving in when the swap occured and whether the user's pointer continued to
1894 * overlap with the swapped item after the swapping occurred.
1895 */
1896 this._previousSwap = { drag: null, delta: 0, overlaps: false };
1897 /** Draggable items in the container. */
1898 this._draggables = [];
1899 /** Drop lists that are connected to the current one. */
1900 this._siblings = [];
1901 /** Direction in which the list is oriented. */
1902 this._orientation = 'vertical';
1903 /** Connected siblings that currently have a dragged item. */
1904 this._activeSiblings = new Set();
1905 /** Layout direction of the drop list. */
1906 this._direction = 'ltr';
1907 /** Subscription to the window being scrolled. */
1908 this._viewportScrollSubscription = rxjs.Subscription.EMPTY;
1909 /** Vertical direction in which the list is currently scrolling. */
1910 this._verticalScrollDirection = 0 /* NONE */;
1911 /** Horizontal direction in which the list is currently scrolling. */
1912 this._horizontalScrollDirection = 0 /* NONE */;
1913 /** Used to signal to the current auto-scroll sequence when to stop. */
1914 this._stopScrollTimers = new rxjs.Subject();
1915 /** Shadow root of the current element. Necessary for `elementFromPoint` to resolve correctly. */
1916 this._cachedShadowRoot = null;
1917 /** Starts the interval that'll auto-scroll the element. */
1918 this._startScrollInterval = function () {
1919 _this._stopScrolling();
1920 rxjs.interval(0, rxjs.animationFrameScheduler)
1921 .pipe(operators.takeUntil(_this._stopScrollTimers))
1922 .subscribe(function () {
1923 var node = _this._scrollNode;
1924 var scrollStep = _this.autoScrollStep;
1925 if (_this._verticalScrollDirection === 1 /* UP */) {
1926 incrementVerticalScroll(node, -scrollStep);
1927 }
1928 else if (_this._verticalScrollDirection === 2 /* DOWN */) {
1929 incrementVerticalScroll(node, scrollStep);
1930 }
1931 if (_this._horizontalScrollDirection === 1 /* LEFT */) {
1932 incrementHorizontalScroll(node, -scrollStep);
1933 }
1934 else if (_this._horizontalScrollDirection === 2 /* RIGHT */) {
1935 incrementHorizontalScroll(node, scrollStep);
1936 }
1937 });
1938 };
1939 this.element = coercion.coerceElement(element);
1940 this._document = _document;
1941 this.withScrollableParents([this.element]);
1942 _dragDropRegistry.registerDropContainer(this);
1943 this._parentPositions = new ParentPositionTracker(_document, _viewportRuler);
1944 }
1945 /** Removes the drop list functionality from the DOM element. */
1946 DropListRef.prototype.dispose = function () {
1947 this._stopScrolling();
1948 this._stopScrollTimers.complete();
1949 this._viewportScrollSubscription.unsubscribe();
1950 this.beforeStarted.complete();
1951 this.entered.complete();
1952 this.exited.complete();
1953 this.dropped.complete();
1954 this.sorted.complete();
1955 this._activeSiblings.clear();
1956 this._scrollNode = null;
1957 this._parentPositions.clear();
1958 this._dragDropRegistry.removeDropContainer(this);
1959 };
1960 /** Whether an item from this list is currently being dragged. */
1961 DropListRef.prototype.isDragging = function () {
1962 return this._isDragging;
1963 };
1964 /** Starts dragging an item. */
1965 DropListRef.prototype.start = function () {
1966 this._draggingStarted();
1967 this._notifyReceivingSiblings();
1968 };
1969 /**
1970 * Emits an event to indicate that the user moved an item into the container.
1971 * @param item Item that was moved into the container.
1972 * @param pointerX Position of the item along the X axis.
1973 * @param pointerY Position of the item along the Y axis.
1974 * @param index Index at which the item entered. If omitted, the container will try to figure it
1975 * out automatically.
1976 */
1977 DropListRef.prototype.enter = function (item, pointerX, pointerY, index) {
1978 this._draggingStarted();
1979 // If sorting is disabled, we want the item to return to its starting
1980 // position if the user is returning it to its initial container.
1981 var newIndex;
1982 if (index == null) {
1983 newIndex = this.sortingDisabled ? this._draggables.indexOf(item) : -1;
1984 if (newIndex === -1) {
1985 // We use the coordinates of where the item entered the drop
1986 // zone to figure out at which index it should be inserted.
1987 newIndex = this._getItemIndexFromPointerPosition(item, pointerX, pointerY);
1988 }
1989 }
1990 else {
1991 newIndex = index;
1992 }
1993 var activeDraggables = this._activeDraggables;
1994 var currentIndex = activeDraggables.indexOf(item);
1995 var placeholder = item.getPlaceholderElement();
1996 var newPositionReference = activeDraggables[newIndex];
1997 // If the item at the new position is the same as the item that is being dragged,
1998 // it means that we're trying to restore the item to its initial position. In this
1999 // case we should use the next item from the list as the reference.
2000 if (newPositionReference === item) {
2001 newPositionReference = activeDraggables[newIndex + 1];
2002 }
2003 // Since the item may be in the `activeDraggables` already (e.g. if the user dragged it
2004 // into another container and back again), we have to ensure that it isn't duplicated.
2005 if (currentIndex > -1) {
2006 activeDraggables.splice(currentIndex, 1);
2007 }
2008 // Don't use items that are being dragged as a reference, because
2009 // their element has been moved down to the bottom of the body.
2010 if (newPositionReference && !this._dragDropRegistry.isDragging(newPositionReference)) {
2011 var element = newPositionReference.getRootElement();
2012 element.parentElement.insertBefore(placeholder, element);
2013 activeDraggables.splice(newIndex, 0, item);
2014 }
2015 else if (this._shouldEnterAsFirstChild(pointerX, pointerY)) {
2016 var reference = activeDraggables[0].getRootElement();
2017 reference.parentNode.insertBefore(placeholder, reference);
2018 activeDraggables.unshift(item);
2019 }
2020 else {
2021 coercion.coerceElement(this.element).appendChild(placeholder);
2022 activeDraggables.push(item);
2023 }
2024 // The transform needs to be cleared so it doesn't throw off the measurements.
2025 placeholder.style.transform = '';
2026 // Note that the positions were already cached when we called `start` above,
2027 // but we need to refresh them since the amount of items has changed and also parent rects.
2028 this._cacheItemPositions();
2029 this._cacheParentPositions();
2030 // Notify siblings at the end so that the item has been inserted into the `activeDraggables`.
2031 this._notifyReceivingSiblings();
2032 this.entered.next({ item: item, container: this, currentIndex: this.getItemIndex(item) });
2033 };
2034 /**
2035 * Removes an item from the container after it was dragged into another container by the user.
2036 * @param item Item that was dragged out.
2037 */
2038 DropListRef.prototype.exit = function (item) {
2039 this._reset();
2040 this.exited.next({ item: item, container: this });
2041 };
2042 /**
2043 * Drops an item into this container.
2044 * @param item Item being dropped into the container.
2045 * @param currentIndex Index at which the item should be inserted.
2046 * @param previousIndex Index of the item when dragging started.
2047 * @param previousContainer Container from which the item got dragged in.
2048 * @param isPointerOverContainer Whether the user's pointer was over the
2049 * container when the item was dropped.
2050 * @param distance Distance the user has dragged since the start of the dragging sequence.
2051 */
2052 DropListRef.prototype.drop = function (item, currentIndex, previousIndex, previousContainer, isPointerOverContainer, distance, dropPoint) {
2053 this._reset();
2054 this.dropped.next({
2055 item: item,
2056 currentIndex: currentIndex,
2057 previousIndex: previousIndex,
2058 container: this,
2059 previousContainer: previousContainer,
2060 isPointerOverContainer: isPointerOverContainer,
2061 distance: distance,
2062 dropPoint: dropPoint
2063 });
2064 };
2065 /**
2066 * Sets the draggable items that are a part of this list.
2067 * @param items Items that are a part of this list.
2068 */
2069 DropListRef.prototype.withItems = function (items) {
2070 var _this = this;
2071 var previousItems = this._draggables;
2072 this._draggables = items;
2073 items.forEach(function (item) { return item._withDropContainer(_this); });
2074 if (this.isDragging()) {
2075 var draggedItems = previousItems.filter(function (item) { return item.isDragging(); });
2076 // If all of the items being dragged were removed
2077 // from the list, abort the current drag sequence.
2078 if (draggedItems.every(function (item) { return items.indexOf(item) === -1; })) {
2079 this._reset();
2080 }
2081 else {
2082 this._cacheItems();
2083 }
2084 }
2085 return this;
2086 };
2087 /** Sets the layout direction of the drop list. */
2088 DropListRef.prototype.withDirection = function (direction) {
2089 this._direction = direction;
2090 return this;
2091 };
2092 /**
2093 * Sets the containers that are connected to this one. When two or more containers are
2094 * connected, the user will be allowed to transfer items between them.
2095 * @param connectedTo Other containers that the current containers should be connected to.
2096 */
2097 DropListRef.prototype.connectedTo = function (connectedTo) {
2098 this._siblings = connectedTo.slice();
2099 return this;
2100 };
2101 /**
2102 * Sets the orientation of the container.
2103 * @param orientation New orientation for the container.
2104 */
2105 DropListRef.prototype.withOrientation = function (orientation) {
2106 this._orientation = orientation;
2107 return this;
2108 };
2109 /**
2110 * Sets which parent elements are can be scrolled while the user is dragging.
2111 * @param elements Elements that can be scrolled.
2112 */
2113 DropListRef.prototype.withScrollableParents = function (elements) {
2114 var element = coercion.coerceElement(this.element);
2115 // We always allow the current element to be scrollable
2116 // so we need to ensure that it's in the array.
2117 this._scrollableElements =
2118 elements.indexOf(element) === -1 ? __spreadArray([element], __read(elements)) : elements.slice();
2119 return this;
2120 };
2121 /** Gets the scrollable parents that are registered with this drop container. */
2122 DropListRef.prototype.getScrollableParents = function () {
2123 return this._scrollableElements;
2124 };
2125 /**
2126 * Figures out the index of an item in the container.
2127 * @param item Item whose index should be determined.
2128 */
2129 DropListRef.prototype.getItemIndex = function (item) {
2130 if (!this._isDragging) {
2131 return this._draggables.indexOf(item);
2132 }
2133 // Items are sorted always by top/left in the cache, however they flow differently in RTL.
2134 // The rest of the logic still stands no matter what orientation we're in, however
2135 // we need to invert the array when determining the index.
2136 var items = this._orientation === 'horizontal' && this._direction === 'rtl' ?
2137 this._itemPositions.slice().reverse() : this._itemPositions;
2138 return findIndex(items, function (currentItem) { return currentItem.drag === item; });
2139 };
2140 /**
2141 * Whether the list is able to receive the item that
2142 * is currently being dragged inside a connected drop list.
2143 */
2144 DropListRef.prototype.isReceiving = function () {
2145 return this._activeSiblings.size > 0;
2146 };
2147 /**
2148 * Sorts an item inside the container based on its position.
2149 * @param item Item to be sorted.
2150 * @param pointerX Position of the item along the X axis.
2151 * @param pointerY Position of the item along the Y axis.
2152 * @param pointerDelta Direction in which the pointer is moving along each axis.
2153 */
2154 DropListRef.prototype._sortItem = function (item, pointerX, pointerY, pointerDelta) {
2155 // Don't sort the item if sorting is disabled or it's out of range.
2156 if (this.sortingDisabled || !this._clientRect ||
2157 !isPointerNearClientRect(this._clientRect, DROP_PROXIMITY_THRESHOLD, pointerX, pointerY)) {
2158 return;
2159 }
2160 var siblings = this._itemPositions;
2161 var newIndex = this._getItemIndexFromPointerPosition(item, pointerX, pointerY, pointerDelta);
2162 if (newIndex === -1 && siblings.length > 0) {
2163 return;
2164 }
2165 var isHorizontal = this._orientation === 'horizontal';
2166 var currentIndex = findIndex(siblings, function (currentItem) { return currentItem.drag === item; });
2167 var siblingAtNewPosition = siblings[newIndex];
2168 var currentPosition = siblings[currentIndex].clientRect;
2169 var newPosition = siblingAtNewPosition.clientRect;
2170 var delta = currentIndex > newIndex ? 1 : -1;
2171 // How many pixels the item's placeholder should be offset.
2172 var itemOffset = this._getItemOffsetPx(currentPosition, newPosition, delta);
2173 // How many pixels all the other items should be offset.
2174 var siblingOffset = this._getSiblingOffsetPx(currentIndex, siblings, delta);
2175 // Save the previous order of the items before moving the item to its new index.
2176 // We use this to check whether an item has been moved as a result of the sorting.
2177 var oldOrder = siblings.slice();
2178 // Shuffle the array in place.
2179 moveItemInArray(siblings, currentIndex, newIndex);
2180 this.sorted.next({
2181 previousIndex: currentIndex,
2182 currentIndex: newIndex,
2183 container: this,
2184 item: item
2185 });
2186 siblings.forEach(function (sibling, index) {
2187 // Don't do anything if the position hasn't changed.
2188 if (oldOrder[index] === sibling) {
2189 return;
2190 }
2191 var isDraggedItem = sibling.drag === item;
2192 var offset = isDraggedItem ? itemOffset : siblingOffset;
2193 var elementToOffset = isDraggedItem ? item.getPlaceholderElement() :
2194 sibling.drag.getRootElement();
2195 // Update the offset to reflect the new position.
2196 sibling.offset += offset;
2197 // Since we're moving the items with a `transform`, we need to adjust their cached
2198 // client rects to reflect their new position, as well as swap their positions in the cache.
2199 // Note that we shouldn't use `getBoundingClientRect` here to update the cache, because the
2200 // elements may be mid-animation which will give us a wrong result.
2201 if (isHorizontal) {
2202 // Round the transforms since some browsers will
2203 // blur the elements, for sub-pixel transforms.
2204 elementToOffset.style.transform = combineTransforms("translate3d(" + Math.round(sibling.offset) + "px, 0, 0)", sibling.initialTransform);
2205 adjustClientRect(sibling.clientRect, 0, offset);
2206 }
2207 else {
2208 elementToOffset.style.transform = combineTransforms("translate3d(0, " + Math.round(sibling.offset) + "px, 0)", sibling.initialTransform);
2209 adjustClientRect(sibling.clientRect, offset, 0);
2210 }
2211 });
2212 // Note that it's important that we do this after the client rects have been adjusted.
2213 this._previousSwap.overlaps = isInsideClientRect(newPosition, pointerX, pointerY);
2214 this._previousSwap.drag = siblingAtNewPosition.drag;
2215 this._previousSwap.delta = isHorizontal ? pointerDelta.x : pointerDelta.y;
2216 };
2217 /**
2218 * Checks whether the user's pointer is close to the edges of either the
2219 * viewport or the drop list and starts the auto-scroll sequence.
2220 * @param pointerX User's pointer position along the x axis.
2221 * @param pointerY User's pointer position along the y axis.
2222 */
2223 DropListRef.prototype._startScrollingIfNecessary = function (pointerX, pointerY) {
2224 var _this = this;
2225 if (this.autoScrollDisabled) {
2226 return;
2227 }
2228 var scrollNode;
2229 var verticalScrollDirection = 0 /* NONE */;
2230 var horizontalScrollDirection = 0 /* NONE */;
2231 // Check whether we should start scrolling any of the parent containers.
2232 this._parentPositions.positions.forEach(function (position, element) {
2233 var _b;
2234 // We have special handling for the `document` below. Also this would be
2235 // nicer with a for...of loop, but it requires changing a compiler flag.
2236 if (element === _this._document || !position.clientRect || scrollNode) {
2237 return;
2238 }
2239 if (isPointerNearClientRect(position.clientRect, DROP_PROXIMITY_THRESHOLD, pointerX, pointerY)) {
2240 _b = __read(getElementScrollDirections(element, position.clientRect, pointerX, pointerY), 2), verticalScrollDirection = _b[0], horizontalScrollDirection = _b[1];
2241 if (verticalScrollDirection || horizontalScrollDirection) {
2242 scrollNode = element;
2243 }
2244 }
2245 });
2246 // Otherwise check if we can start scrolling the viewport.
2247 if (!verticalScrollDirection && !horizontalScrollDirection) {
2248 var _b = this._viewportRuler.getViewportSize(), width = _b.width, height = _b.height;
2249 var clientRect = { width: width, height: height, top: 0, right: width, bottom: height, left: 0 };
2250 verticalScrollDirection = getVerticalScrollDirection(clientRect, pointerY);
2251 horizontalScrollDirection = getHorizontalScrollDirection(clientRect, pointerX);
2252 scrollNode = window;
2253 }
2254 if (scrollNode && (verticalScrollDirection !== this._verticalScrollDirection ||
2255 horizontalScrollDirection !== this._horizontalScrollDirection ||
2256 scrollNode !== this._scrollNode)) {
2257 this._verticalScrollDirection = verticalScrollDirection;
2258 this._horizontalScrollDirection = horizontalScrollDirection;
2259 this._scrollNode = scrollNode;
2260 if ((verticalScrollDirection || horizontalScrollDirection) && scrollNode) {
2261 this._ngZone.runOutsideAngular(this._startScrollInterval);
2262 }
2263 else {
2264 this._stopScrolling();
2265 }
2266 }
2267 };
2268 /** Stops any currently-running auto-scroll sequences. */
2269 DropListRef.prototype._stopScrolling = function () {
2270 this._stopScrollTimers.next();
2271 };
2272 /** Starts the dragging sequence within the list. */
2273 DropListRef.prototype._draggingStarted = function () {
2274 var styles = coercion.coerceElement(this.element).style;
2275 this.beforeStarted.next();
2276 this._isDragging = true;
2277 // We need to disable scroll snapping while the user is dragging, because it breaks automatic
2278 // scrolling. The browser seems to round the value based on the snapping points which means
2279 // that we can't increment/decrement the scroll position.
2280 this._initialScrollSnap = styles.msScrollSnapType || styles.scrollSnapType || '';
2281 styles.scrollSnapType = styles.msScrollSnapType = 'none';
2282 this._cacheItems();
2283 this._viewportScrollSubscription.unsubscribe();
2284 this._listenToScrollEvents();
2285 };
2286 /** Caches the positions of the configured scrollable parents. */
2287 DropListRef.prototype._cacheParentPositions = function () {
2288 var element = coercion.coerceElement(this.element);
2289 this._parentPositions.cache(this._scrollableElements);
2290 // The list element is always in the `scrollableElements`
2291 // so we can take advantage of the cached `ClientRect`.
2292 this._clientRect = this._parentPositions.positions.get(element).clientRect;
2293 };
2294 /** Refreshes the position cache of the items and sibling containers. */
2295 DropListRef.prototype._cacheItemPositions = function () {
2296 var isHorizontal = this._orientation === 'horizontal';
2297 this._itemPositions = this._activeDraggables.map(function (drag) {
2298 var elementToMeasure = drag.getVisibleElement();
2299 return {
2300 drag: drag,
2301 offset: 0,
2302 initialTransform: elementToMeasure.style.transform || '',
2303 clientRect: getMutableClientRect(elementToMeasure),
2304 };
2305 }).sort(function (a, b) {
2306 return isHorizontal ? a.clientRect.left - b.clientRect.left :
2307 a.clientRect.top - b.clientRect.top;
2308 });
2309 };
2310 /** Resets the container to its initial state. */
2311 DropListRef.prototype._reset = function () {
2312 var _this = this;
2313 this._isDragging = false;
2314 var styles = coercion.coerceElement(this.element).style;
2315 styles.scrollSnapType = styles.msScrollSnapType = this._initialScrollSnap;
2316 // TODO(crisbeto): may have to wait for the animations to finish.
2317 this._activeDraggables.forEach(function (item) {
2318 var _a;
2319 var rootElement = item.getRootElement();
2320 if (rootElement) {
2321 var initialTransform = (_a = _this._itemPositions
2322 .find(function (current) { return current.drag === item; })) === null || _a === void 0 ? void 0 : _a.initialTransform;
2323 rootElement.style.transform = initialTransform || '';
2324 }
2325 });
2326 this._siblings.forEach(function (sibling) { return sibling._stopReceiving(_this); });
2327 this._activeDraggables = [];
2328 this._itemPositions = [];
2329 this._previousSwap.drag = null;
2330 this._previousSwap.delta = 0;
2331 this._previousSwap.overlaps = false;
2332 this._stopScrolling();
2333 this._viewportScrollSubscription.unsubscribe();
2334 this._parentPositions.clear();
2335 };
2336 /**
2337 * Gets the offset in pixels by which the items that aren't being dragged should be moved.
2338 * @param currentIndex Index of the item currently being dragged.
2339 * @param siblings All of the items in the list.
2340 * @param delta Direction in which the user is moving.
2341 */
2342 DropListRef.prototype._getSiblingOffsetPx = function (currentIndex, siblings, delta) {
2343 var isHorizontal = this._orientation === 'horizontal';
2344 var currentPosition = siblings[currentIndex].clientRect;
2345 var immediateSibling = siblings[currentIndex + delta * -1];
2346 var siblingOffset = currentPosition[isHorizontal ? 'width' : 'height'] * delta;
2347 if (immediateSibling) {
2348 var start = isHorizontal ? 'left' : 'top';
2349 var end = isHorizontal ? 'right' : 'bottom';
2350 // Get the spacing between the start of the current item and the end of the one immediately
2351 // after it in the direction in which the user is dragging, or vice versa. We add it to the
2352 // offset in order to push the element to where it will be when it's inline and is influenced
2353 // by the `margin` of its siblings.
2354 if (delta === -1) {
2355 siblingOffset -= immediateSibling.clientRect[start] - currentPosition[end];
2356 }
2357 else {
2358 siblingOffset += currentPosition[start] - immediateSibling.clientRect[end];
2359 }
2360 }
2361 return siblingOffset;
2362 };
2363 /**
2364 * Gets the offset in pixels by which the item that is being dragged should be moved.
2365 * @param currentPosition Current position of the item.
2366 * @param newPosition Position of the item where the current item should be moved.
2367 * @param delta Direction in which the user is moving.
2368 */
2369 DropListRef.prototype._getItemOffsetPx = function (currentPosition, newPosition, delta) {
2370 var isHorizontal = this._orientation === 'horizontal';
2371 var itemOffset = isHorizontal ? newPosition.left - currentPosition.left :
2372 newPosition.top - currentPosition.top;
2373 // Account for differences in the item width/height.
2374 if (delta === -1) {
2375 itemOffset += isHorizontal ? newPosition.width - currentPosition.width :
2376 newPosition.height - currentPosition.height;
2377 }
2378 return itemOffset;
2379 };
2380 /**
2381 * Checks if pointer is entering in the first position
2382 * @param pointerX Position of the user's pointer along the X axis.
2383 * @param pointerY Position of the user's pointer along the Y axis.
2384 */
2385 DropListRef.prototype._shouldEnterAsFirstChild = function (pointerX, pointerY) {
2386 if (!this._activeDraggables.length) {
2387 return false;
2388 }
2389 var itemPositions = this._itemPositions;
2390 var isHorizontal = this._orientation === 'horizontal';
2391 // `itemPositions` are sorted by position while `activeDraggables` are sorted by child index
2392 // check if container is using some sort of "reverse" ordering (eg: flex-direction: row-reverse)
2393 var reversed = itemPositions[0].drag !== this._activeDraggables[0];
2394 if (reversed) {
2395 var lastItemRect = itemPositions[itemPositions.length - 1].clientRect;
2396 return isHorizontal ? pointerX >= lastItemRect.right : pointerY >= lastItemRect.bottom;
2397 }
2398 else {
2399 var firstItemRect = itemPositions[0].clientRect;
2400 return isHorizontal ? pointerX <= firstItemRect.left : pointerY <= firstItemRect.top;
2401 }
2402 };
2403 /**
2404 * Gets the index of an item in the drop container, based on the position of the user's pointer.
2405 * @param item Item that is being sorted.
2406 * @param pointerX Position of the user's pointer along the X axis.
2407 * @param pointerY Position of the user's pointer along the Y axis.
2408 * @param delta Direction in which the user is moving their pointer.
2409 */
2410 DropListRef.prototype._getItemIndexFromPointerPosition = function (item, pointerX, pointerY, delta) {
2411 var _this = this;
2412 var isHorizontal = this._orientation === 'horizontal';
2413 var index = findIndex(this._itemPositions, function (_b, _, array) {
2414 var drag = _b.drag, clientRect = _b.clientRect;
2415 if (drag === item) {
2416 // If there's only one item left in the container, it must be
2417 // the dragged item itself so we use it as a reference.
2418 return array.length < 2;
2419 }
2420 if (delta) {
2421 var direction = isHorizontal ? delta.x : delta.y;
2422 // If the user is still hovering over the same item as last time, their cursor hasn't left
2423 // the item after we made the swap, and they didn't change the direction in which they're
2424 // dragging, we don't consider it a direction swap.
2425 if (drag === _this._previousSwap.drag && _this._previousSwap.overlaps &&
2426 direction === _this._previousSwap.delta) {
2427 return false;
2428 }
2429 }
2430 return isHorizontal ?
2431 // Round these down since most browsers report client rects with
2432 // sub-pixel precision, whereas the pointer coordinates are rounded to pixels.
2433 pointerX >= Math.floor(clientRect.left) && pointerX < Math.floor(clientRect.right) :
2434 pointerY >= Math.floor(clientRect.top) && pointerY < Math.floor(clientRect.bottom);
2435 });
2436 return (index === -1 || !this.sortPredicate(index, item, this)) ? -1 : index;
2437 };
2438 /** Caches the current items in the list and their positions. */
2439 DropListRef.prototype._cacheItems = function () {
2440 this._activeDraggables = this._draggables.slice();
2441 this._cacheItemPositions();
2442 this._cacheParentPositions();
2443 };
2444 /**
2445 * Checks whether the user's pointer is positioned over the container.
2446 * @param x Pointer position along the X axis.
2447 * @param y Pointer position along the Y axis.
2448 */
2449 DropListRef.prototype._isOverContainer = function (x, y) {
2450 return this._clientRect != null && isInsideClientRect(this._clientRect, x, y);
2451 };
2452 /**
2453 * Figures out whether an item should be moved into a sibling
2454 * drop container, based on its current position.
2455 * @param item Drag item that is being moved.
2456 * @param x Position of the item along the X axis.
2457 * @param y Position of the item along the Y axis.
2458 */
2459 DropListRef.prototype._getSiblingContainerFromPosition = function (item, x, y) {
2460 return this._siblings.find(function (sibling) { return sibling._canReceive(item, x, y); });
2461 };
2462 /**
2463 * Checks whether the drop list can receive the passed-in item.
2464 * @param item Item that is being dragged into the list.
2465 * @param x Position of the item along the X axis.
2466 * @param y Position of the item along the Y axis.
2467 */
2468 DropListRef.prototype._canReceive = function (item, x, y) {
2469 if (!this._clientRect || !isInsideClientRect(this._clientRect, x, y) ||
2470 !this.enterPredicate(item, this)) {
2471 return false;
2472 }
2473 var elementFromPoint = this._getShadowRoot().elementFromPoint(x, y);
2474 // If there's no element at the pointer position, then
2475 // the client rect is probably scrolled out of the view.
2476 if (!elementFromPoint) {
2477 return false;
2478 }
2479 var nativeElement = coercion.coerceElement(this.element);
2480 // The `ClientRect`, that we're using to find the container over which the user is
2481 // hovering, doesn't give us any information on whether the element has been scrolled
2482 // out of the view or whether it's overlapping with other containers. This means that
2483 // we could end up transferring the item into a container that's invisible or is positioned
2484 // below another one. We use the result from `elementFromPoint` to get the top-most element
2485 // at the pointer position and to find whether it's one of the intersecting drop containers.
2486 return elementFromPoint === nativeElement || nativeElement.contains(elementFromPoint);
2487 };
2488 /**
2489 * Called by one of the connected drop lists when a dragging sequence has started.
2490 * @param sibling Sibling in which dragging has started.
2491 */
2492 DropListRef.prototype._startReceiving = function (sibling, items) {
2493 var _this = this;
2494 var activeSiblings = this._activeSiblings;
2495 if (!activeSiblings.has(sibling) && items.every(function (item) {
2496 // Note that we have to add an exception to the `enterPredicate` for items that started off
2497 // in this drop list. The drag ref has logic that allows an item to return to its initial
2498 // container, if it has left the initial container and none of the connected containers
2499 // allow it to enter. See `DragRef._updateActiveDropContainer` for more context.
2500 return _this.enterPredicate(item, _this) || _this._draggables.indexOf(item) > -1;
2501 })) {
2502 activeSiblings.add(sibling);
2503 this._cacheParentPositions();
2504 this._listenToScrollEvents();
2505 }
2506 };
2507 /**
2508 * Called by a connected drop list when dragging has stopped.
2509 * @param sibling Sibling whose dragging has stopped.
2510 */
2511 DropListRef.prototype._stopReceiving = function (sibling) {
2512 this._activeSiblings.delete(sibling);
2513 this._viewportScrollSubscription.unsubscribe();
2514 };
2515 /**
2516 * Starts listening to scroll events on the viewport.
2517 * Used for updating the internal state of the list.
2518 */
2519 DropListRef.prototype._listenToScrollEvents = function () {
2520 var _this = this;
2521 this._viewportScrollSubscription = this._dragDropRegistry
2522 .scrolled(this._getShadowRoot())
2523 .subscribe(function (event) {
2524 if (_this.isDragging()) {
2525 var scrollDifference_1 = _this._parentPositions.handleScroll(event);
2526 if (scrollDifference_1) {
2527 // Since we know the amount that the user has scrolled we can shift all of the
2528 // client rectangles ourselves. This is cheaper than re-measuring everything and
2529 // we can avoid inconsistent behavior where we might be measuring the element before
2530 // its position has changed.
2531 _this._itemPositions.forEach(function (_b) {
2532 var clientRect = _b.clientRect;
2533 adjustClientRect(clientRect, scrollDifference_1.top, scrollDifference_1.left);
2534 });
2535 // We need two loops for this, because we want all of the cached
2536 // positions to be up-to-date before we re-sort the item.
2537 _this._itemPositions.forEach(function (_b) {
2538 var drag = _b.drag;
2539 if (_this._dragDropRegistry.isDragging(drag)) {
2540 // We need to re-sort the item manually, because the pointer move
2541 // events won't be dispatched while the user is scrolling.
2542 drag._sortFromLastPointerPosition();
2543 }
2544 });
2545 }
2546 }
2547 else if (_this.isReceiving()) {
2548 _this._cacheParentPositions();
2549 }
2550 });
2551 };
2552 /**
2553 * Lazily resolves and returns the shadow root of the element. We do this in a function, rather
2554 * than saving it in property directly on init, because we want to resolve it as late as possible
2555 * in order to ensure that the element has been moved into the shadow DOM. Doing it inside the
2556 * constructor might be too early if the element is inside of something like `ngFor` or `ngIf`.
2557 */
2558 DropListRef.prototype._getShadowRoot = function () {
2559 if (!this._cachedShadowRoot) {
2560 var shadowRoot = platform._getShadowRoot(coercion.coerceElement(this.element));
2561 this._cachedShadowRoot = shadowRoot || this._document;
2562 }
2563 return this._cachedShadowRoot;
2564 };
2565 /** Notifies any siblings that may potentially receive the item. */
2566 DropListRef.prototype._notifyReceivingSiblings = function () {
2567 var _this = this;
2568 var draggedItems = this._activeDraggables.filter(function (item) { return item.isDragging(); });
2569 this._siblings.forEach(function (sibling) { return sibling._startReceiving(_this, draggedItems); });
2570 };
2571 return DropListRef;
2572 }());
2573 /**
2574 * Finds the index of an item that matches a predicate function. Used as an equivalent
2575 * of `Array.prototype.findIndex` which isn't part of the standard Google typings.
2576 * @param array Array in which to look for matches.
2577 * @param predicate Function used to determine whether an item is a match.
2578 */
2579 function findIndex(array, predicate) {
2580 for (var i = 0; i < array.length; i++) {
2581 if (predicate(array[i], i, array)) {
2582 return i;
2583 }
2584 }
2585 return -1;
2586 }
2587 /**
2588 * Increments the vertical scroll position of a node.
2589 * @param node Node whose scroll position should change.
2590 * @param amount Amount of pixels that the `node` should be scrolled.
2591 */
2592 function incrementVerticalScroll(node, amount) {
2593 if (node === window) {
2594 node.scrollBy(0, amount);
2595 }
2596 else {
2597 // Ideally we could use `Element.scrollBy` here as well, but IE and Edge don't support it.
2598 node.scrollTop += amount;
2599 }
2600 }
2601 /**
2602 * Increments the horizontal scroll position of a node.
2603 * @param node Node whose scroll position should change.
2604 * @param amount Amount of pixels that the `node` should be scrolled.
2605 */
2606 function incrementHorizontalScroll(node, amount) {
2607 if (node === window) {
2608 node.scrollBy(amount, 0);
2609 }
2610 else {
2611 // Ideally we could use `Element.scrollBy` here as well, but IE and Edge don't support it.
2612 node.scrollLeft += amount;
2613 }
2614 }
2615 /**
2616 * Gets whether the vertical auto-scroll direction of a node.
2617 * @param clientRect Dimensions of the node.
2618 * @param pointerY Position of the user's pointer along the y axis.
2619 */
2620 function getVerticalScrollDirection(clientRect, pointerY) {
2621 var top = clientRect.top, bottom = clientRect.bottom, height = clientRect.height;
2622 var yThreshold = height * SCROLL_PROXIMITY_THRESHOLD;
2623 if (pointerY >= top - yThreshold && pointerY <= top + yThreshold) {
2624 return 1 /* UP */;
2625 }
2626 else if (pointerY >= bottom - yThreshold && pointerY <= bottom + yThreshold) {
2627 return 2 /* DOWN */;
2628 }
2629 return 0 /* NONE */;
2630 }
2631 /**
2632 * Gets whether the horizontal auto-scroll direction of a node.
2633 * @param clientRect Dimensions of the node.
2634 * @param pointerX Position of the user's pointer along the x axis.
2635 */
2636 function getHorizontalScrollDirection(clientRect, pointerX) {
2637 var left = clientRect.left, right = clientRect.right, width = clientRect.width;
2638 var xThreshold = width * SCROLL_PROXIMITY_THRESHOLD;
2639 if (pointerX >= left - xThreshold && pointerX <= left + xThreshold) {
2640 return 1 /* LEFT */;
2641 }
2642 else if (pointerX >= right - xThreshold && pointerX <= right + xThreshold) {
2643 return 2 /* RIGHT */;
2644 }
2645 return 0 /* NONE */;
2646 }
2647 /**
2648 * Gets the directions in which an element node should be scrolled,
2649 * assuming that the user's pointer is already within it scrollable region.
2650 * @param element Element for which we should calculate the scroll direction.
2651 * @param clientRect Bounding client rectangle of the element.
2652 * @param pointerX Position of the user's pointer along the x axis.
2653 * @param pointerY Position of the user's pointer along the y axis.
2654 */
2655 function getElementScrollDirections(element, clientRect, pointerX, pointerY) {
2656 var computedVertical = getVerticalScrollDirection(clientRect, pointerY);
2657 var computedHorizontal = getHorizontalScrollDirection(clientRect, pointerX);
2658 var verticalScrollDirection = 0 /* NONE */;
2659 var horizontalScrollDirection = 0 /* NONE */;
2660 // Note that we here we do some extra checks for whether the element is actually scrollable in
2661 // a certain direction and we only assign the scroll direction if it is. We do this so that we
2662 // can allow other elements to be scrolled, if the current element can't be scrolled anymore.
2663 // This allows us to handle cases where the scroll regions of two scrollable elements overlap.
2664 if (computedVertical) {
2665 var scrollTop = element.scrollTop;
2666 if (computedVertical === 1 /* UP */) {
2667 if (scrollTop > 0) {
2668 verticalScrollDirection = 1 /* UP */;
2669 }
2670 }
2671 else if (element.scrollHeight - scrollTop > element.clientHeight) {
2672 verticalScrollDirection = 2 /* DOWN */;
2673 }
2674 }
2675 if (computedHorizontal) {
2676 var scrollLeft = element.scrollLeft;
2677 if (computedHorizontal === 1 /* LEFT */) {
2678 if (scrollLeft > 0) {
2679 horizontalScrollDirection = 1 /* LEFT */;
2680 }
2681 }
2682 else if (element.scrollWidth - scrollLeft > element.clientWidth) {
2683 horizontalScrollDirection = 2 /* RIGHT */;
2684 }
2685 }
2686 return [verticalScrollDirection, horizontalScrollDirection];
2687 }
2688
2689 /** Event options that can be used to bind an active, capturing event. */
2690 var activeCapturingEventOptions = platform.normalizePassiveListenerOptions({
2691 passive: false,
2692 capture: true
2693 });
2694 /**
2695 * Service that keeps track of all the drag item and drop container
2696 * instances, and manages global event listeners on the `document`.
2697 * @docs-private
2698 */
2699 // Note: this class is generic, rather than referencing CdkDrag and CdkDropList directly, in order
2700 // to avoid circular imports. If we were to reference them here, importing the registry into the
2701 // classes that are registering themselves will introduce a circular import.
2702 var DragDropRegistry = /** @class */ (function () {
2703 function DragDropRegistry(_ngZone, _document) {
2704 var _this = this;
2705 this._ngZone = _ngZone;
2706 /** Registered drop container instances. */
2707 this._dropInstances = new Set();
2708 /** Registered drag item instances. */
2709 this._dragInstances = new Set();
2710 /** Drag item instances that are currently being dragged. */
2711 this._activeDragInstances = [];
2712 /** Keeps track of the event listeners that we've bound to the `document`. */
2713 this._globalListeners = new Map();
2714 /**
2715 * Predicate function to check if an item is being dragged. Moved out into a property,
2716 * because it'll be called a lot and we don't want to create a new function every time.
2717 */
2718 this._draggingPredicate = function (item) { return item.isDragging(); };
2719 /**
2720 * Emits the `touchmove` or `mousemove` events that are dispatched
2721 * while the user is dragging a drag item instance.
2722 */
2723 this.pointerMove = new rxjs.Subject();
2724 /**
2725 * Emits the `touchend` or `mouseup` events that are dispatched
2726 * while the user is dragging a drag item instance.
2727 */
2728 this.pointerUp = new rxjs.Subject();
2729 /**
2730 * Emits when the viewport has been scrolled while the user is dragging an item.
2731 * @deprecated To be turned into a private member. Use the `scrolled` method instead.
2732 * @breaking-change 13.0.0
2733 */
2734 this.scroll = new rxjs.Subject();
2735 /**
2736 * Event listener that will prevent the default browser action while the user is dragging.
2737 * @param event Event whose default action should be prevented.
2738 */
2739 this._preventDefaultWhileDragging = function (event) {
2740 if (_this._activeDragInstances.length > 0) {
2741 event.preventDefault();
2742 }
2743 };
2744 /** Event listener for `touchmove` that is bound even if no dragging is happening. */
2745 this._persistentTouchmoveListener = function (event) {
2746 if (_this._activeDragInstances.length > 0) {
2747 // Note that we only want to prevent the default action after dragging has actually started.
2748 // Usually this is the same time at which the item is added to the `_activeDragInstances`,
2749 // but it could be pushed back if the user has set up a drag delay or threshold.
2750 if (_this._activeDragInstances.some(_this._draggingPredicate)) {
2751 event.preventDefault();
2752 }
2753 _this.pointerMove.next(event);
2754 }
2755 };
2756 this._document = _document;
2757 }
2758 /** Adds a drop container to the registry. */
2759 DragDropRegistry.prototype.registerDropContainer = function (drop) {
2760 if (!this._dropInstances.has(drop)) {
2761 this._dropInstances.add(drop);
2762 }
2763 };
2764 /** Adds a drag item instance to the registry. */
2765 DragDropRegistry.prototype.registerDragItem = function (drag) {
2766 var _this = this;
2767 this._dragInstances.add(drag);
2768 // The `touchmove` event gets bound once, ahead of time, because WebKit
2769 // won't preventDefault on a dynamically-added `touchmove` listener.
2770 // See https://bugs.webkit.org/show_bug.cgi?id=184250.
2771 if (this._dragInstances.size === 1) {
2772 this._ngZone.runOutsideAngular(function () {
2773 // The event handler has to be explicitly active,
2774 // because newer browsers make it passive by default.
2775 _this._document.addEventListener('touchmove', _this._persistentTouchmoveListener, activeCapturingEventOptions);
2776 });
2777 }
2778 };
2779 /** Removes a drop container from the registry. */
2780 DragDropRegistry.prototype.removeDropContainer = function (drop) {
2781 this._dropInstances.delete(drop);
2782 };
2783 /** Removes a drag item instance from the registry. */
2784 DragDropRegistry.prototype.removeDragItem = function (drag) {
2785 this._dragInstances.delete(drag);
2786 this.stopDragging(drag);
2787 if (this._dragInstances.size === 0) {
2788 this._document.removeEventListener('touchmove', this._persistentTouchmoveListener, activeCapturingEventOptions);
2789 }
2790 };
2791 /**
2792 * Starts the dragging sequence for a drag instance.
2793 * @param drag Drag instance which is being dragged.
2794 * @param event Event that initiated the dragging.
2795 */
2796 DragDropRegistry.prototype.startDragging = function (drag, event) {
2797 var _this = this;
2798 // Do not process the same drag twice to avoid memory leaks and redundant listeners
2799 if (this._activeDragInstances.indexOf(drag) > -1) {
2800 return;
2801 }
2802 this._activeDragInstances.push(drag);
2803 if (this._activeDragInstances.length === 1) {
2804 var isTouchEvent = event.type.startsWith('touch');
2805 // We explicitly bind __active__ listeners here, because newer browsers will default to
2806 // passive ones for `mousemove` and `touchmove`. The events need to be active, because we
2807 // use `preventDefault` to prevent the page from scrolling while the user is dragging.
2808 this._globalListeners
2809 .set(isTouchEvent ? 'touchend' : 'mouseup', {
2810 handler: function (e) { return _this.pointerUp.next(e); },
2811 options: true
2812 })
2813 .set('scroll', {
2814 handler: function (e) { return _this.scroll.next(e); },
2815 // Use capturing so that we pick up scroll changes in any scrollable nodes that aren't
2816 // the document. See https://github.com/angular/components/issues/17144.
2817 options: true
2818 })
2819 // Preventing the default action on `mousemove` isn't enough to disable text selection
2820 // on Safari so we need to prevent the selection event as well. Alternatively this can
2821 // be done by setting `user-select: none` on the `body`, however it has causes a style
2822 // recalculation which can be expensive on pages with a lot of elements.
2823 .set('selectstart', {
2824 handler: this._preventDefaultWhileDragging,
2825 options: activeCapturingEventOptions
2826 });
2827 // We don't have to bind a move event for touch drag sequences, because
2828 // we already have a persistent global one bound from `registerDragItem`.
2829 if (!isTouchEvent) {
2830 this._globalListeners.set('mousemove', {
2831 handler: function (e) { return _this.pointerMove.next(e); },
2832 options: activeCapturingEventOptions
2833 });
2834 }
2835 this._ngZone.runOutsideAngular(function () {
2836 _this._globalListeners.forEach(function (config, name) {
2837 _this._document.addEventListener(name, config.handler, config.options);
2838 });
2839 });
2840 }
2841 };
2842 /** Stops dragging a drag item instance. */
2843 DragDropRegistry.prototype.stopDragging = function (drag) {
2844 var index = this._activeDragInstances.indexOf(drag);
2845 if (index > -1) {
2846 this._activeDragInstances.splice(index, 1);
2847 if (this._activeDragInstances.length === 0) {
2848 this._clearGlobalListeners();
2849 }
2850 }
2851 };
2852 /** Gets whether a drag item instance is currently being dragged. */
2853 DragDropRegistry.prototype.isDragging = function (drag) {
2854 return this._activeDragInstances.indexOf(drag) > -1;
2855 };
2856 /**
2857 * Gets a stream that will emit when any element on the page is scrolled while an item is being
2858 * dragged.
2859 * @param shadowRoot Optional shadow root that the current dragging sequence started from.
2860 * Top-level listeners won't pick up events coming from the shadow DOM so this parameter can
2861 * be used to include an additional top-level listener at the shadow root level.
2862 */
2863 DragDropRegistry.prototype.scrolled = function (shadowRoot) {
2864 var _this = this;
2865 var streams = [this.scroll];
2866 if (shadowRoot && shadowRoot !== this._document) {
2867 // Note that this is basically the same as `fromEvent` from rjxs, but we do it ourselves,
2868 // because we want to guarantee that the event is bound outside of the `NgZone`. With
2869 // `fromEvent` it'll only happen if the subscription is outside the `NgZone`.
2870 streams.push(new rxjs.Observable(function (observer) {
2871 return _this._ngZone.runOutsideAngular(function () {
2872 var eventOptions = true;
2873 var callback = function (event) {
2874 if (_this._activeDragInstances.length) {
2875 observer.next(event);
2876 }
2877 };
2878 shadowRoot.addEventListener('scroll', callback, eventOptions);
2879 return function () {
2880 shadowRoot.removeEventListener('scroll', callback, eventOptions);
2881 };
2882 });
2883 }));
2884 }
2885 return rxjs.merge.apply(void 0, __spreadArray([], __read(streams)));
2886 };
2887 DragDropRegistry.prototype.ngOnDestroy = function () {
2888 var _this = this;
2889 this._dragInstances.forEach(function (instance) { return _this.removeDragItem(instance); });
2890 this._dropInstances.forEach(function (instance) { return _this.removeDropContainer(instance); });
2891 this._clearGlobalListeners();
2892 this.pointerMove.complete();
2893 this.pointerUp.complete();
2894 };
2895 /** Clears out the global event listeners from the `document`. */
2896 DragDropRegistry.prototype._clearGlobalListeners = function () {
2897 var _this = this;
2898 this._globalListeners.forEach(function (config, name) {
2899 _this._document.removeEventListener(name, config.handler, config.options);
2900 });
2901 this._globalListeners.clear();
2902 };
2903 return DragDropRegistry;
2904 }());
2905 DragDropRegistry.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function DragDropRegistry_Factory() { return new DragDropRegistry(i0__namespace.ɵɵinject(i0__namespace.NgZone), i0__namespace.ɵɵinject(i1__namespace.DOCUMENT)); }, token: DragDropRegistry, providedIn: "root" });
2906 DragDropRegistry.decorators = [
2907 { type: i0.Injectable, args: [{ providedIn: 'root' },] }
2908 ];
2909 DragDropRegistry.ctorParameters = function () { return [
2910 { type: i0.NgZone },
2911 { type: undefined, decorators: [{ type: i0.Inject, args: [i1.DOCUMENT,] }] }
2912 ]; };
2913
2914 /**
2915 * @license
2916 * Copyright Google LLC All Rights Reserved.
2917 *
2918 * Use of this source code is governed by an MIT-style license that can be
2919 * found in the LICENSE file at https://angular.io/license
2920 */
2921 /** Default configuration to be used when creating a `DragRef`. */
2922 var DEFAULT_CONFIG = {
2923 dragStartThreshold: 5,
2924 pointerDirectionChangeThreshold: 5
2925 };
2926 /**
2927 * Service that allows for drag-and-drop functionality to be attached to DOM elements.
2928 */
2929 var DragDrop = /** @class */ (function () {
2930 function DragDrop(_document, _ngZone, _viewportRuler, _dragDropRegistry) {
2931 this._document = _document;
2932 this._ngZone = _ngZone;
2933 this._viewportRuler = _viewportRuler;
2934 this._dragDropRegistry = _dragDropRegistry;
2935 }
2936 /**
2937 * Turns an element into a draggable item.
2938 * @param element Element to which to attach the dragging functionality.
2939 * @param config Object used to configure the dragging behavior.
2940 */
2941 DragDrop.prototype.createDrag = function (element, config) {
2942 if (config === void 0) { config = DEFAULT_CONFIG; }
2943 return new DragRef(element, config, this._document, this._ngZone, this._viewportRuler, this._dragDropRegistry);
2944 };
2945 /**
2946 * Turns an element into a drop list.
2947 * @param element Element to which to attach the drop list functionality.
2948 */
2949 DragDrop.prototype.createDropList = function (element) {
2950 return new DropListRef(element, this._dragDropRegistry, this._document, this._ngZone, this._viewportRuler);
2951 };
2952 return DragDrop;
2953 }());
2954 DragDrop.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function DragDrop_Factory() { return new DragDrop(i0__namespace.ɵɵinject(i1__namespace.DOCUMENT), i0__namespace.ɵɵinject(i0__namespace.NgZone), i0__namespace.ɵɵinject(i2__namespace.ViewportRuler), i0__namespace.ɵɵinject(DragDropRegistry)); }, token: DragDrop, providedIn: "root" });
2955 DragDrop.decorators = [
2956 { type: i0.Injectable, args: [{ providedIn: 'root' },] }
2957 ];
2958 DragDrop.ctorParameters = function () { return [
2959 { type: undefined, decorators: [{ type: i0.Inject, args: [i1.DOCUMENT,] }] },
2960 { type: i0.NgZone },
2961 { type: i2.ViewportRuler },
2962 { type: DragDropRegistry }
2963 ]; };
2964
2965 /**
2966 * @license
2967 * Copyright Google LLC All Rights Reserved.
2968 *
2969 * Use of this source code is governed by an MIT-style license that can be
2970 * found in the LICENSE file at https://angular.io/license
2971 */
2972 /**
2973 * Injection token that can be used for a `CdkDrag` to provide itself as a parent to the
2974 * drag-specific child directive (`CdkDragHandle`, `CdkDragPreview` etc.). Used primarily
2975 * to avoid circular imports.
2976 * @docs-private
2977 */
2978 var CDK_DRAG_PARENT = new i0.InjectionToken('CDK_DRAG_PARENT');
2979
2980 /**
2981 * @license
2982 * Copyright Google LLC All Rights Reserved.
2983 *
2984 * Use of this source code is governed by an MIT-style license that can be
2985 * found in the LICENSE file at https://angular.io/license
2986 */
2987 /**
2988 * Injection token that can be used to reference instances of `CdkDropListGroup`. It serves as
2989 * alternative token to the actual `CdkDropListGroup` class which could cause unnecessary
2990 * retention of the class and its directive metadata.
2991 */
2992 var CDK_DROP_LIST_GROUP = new i0.InjectionToken('CdkDropListGroup');
2993 /**
2994 * Declaratively connects sibling `cdkDropList` instances together. All of the `cdkDropList`
2995 * elements that are placed inside a `cdkDropListGroup` will be connected to each other
2996 * automatically. Can be used as an alternative to the `cdkDropListConnectedTo` input
2997 * from `cdkDropList`.
2998 */
2999 var CdkDropListGroup = /** @class */ (function () {
3000 function CdkDropListGroup() {
3001 /** Drop lists registered inside the group. */
3002 this._items = new Set();
3003 this._disabled = false;
3004 }
3005 Object.defineProperty(CdkDropListGroup.prototype, "disabled", {
3006 /** Whether starting a dragging sequence from inside this group is disabled. */
3007 get: function () { return this._disabled; },
3008 set: function (value) {
3009 this._disabled = coercion.coerceBooleanProperty(value);
3010 },
3011 enumerable: false,
3012 configurable: true
3013 });
3014 CdkDropListGroup.prototype.ngOnDestroy = function () {
3015 this._items.clear();
3016 };
3017 return CdkDropListGroup;
3018 }());
3019 CdkDropListGroup.decorators = [
3020 { type: i0.Directive, args: [{
3021 selector: '[cdkDropListGroup]',
3022 exportAs: 'cdkDropListGroup',
3023 providers: [{ provide: CDK_DROP_LIST_GROUP, useExisting: CdkDropListGroup }],
3024 },] }
3025 ];
3026 CdkDropListGroup.propDecorators = {
3027 disabled: [{ type: i0.Input, args: ['cdkDropListGroupDisabled',] }]
3028 };
3029
3030 /**
3031 * @license
3032 * Copyright Google LLC All Rights Reserved.
3033 *
3034 * Use of this source code is governed by an MIT-style license that can be
3035 * found in the LICENSE file at https://angular.io/license
3036 */
3037 /**
3038 * Injection token that can be used to configure the
3039 * behavior of the drag&drop-related components.
3040 */
3041 var CDK_DRAG_CONFIG = new i0.InjectionToken('CDK_DRAG_CONFIG');
3042
3043 /**
3044 * @license
3045 * Copyright Google LLC All Rights Reserved.
3046 *
3047 * Use of this source code is governed by an MIT-style license that can be
3048 * found in the LICENSE file at https://angular.io/license
3049 */
3050 /**
3051 * Asserts that a particular node is an element.
3052 * @param node Node to be checked.
3053 * @param name Name to attach to the error message.
3054 */
3055 function assertElementNode(node, name) {
3056 if (node.nodeType !== 1) {
3057 throw Error(name + " must be attached to an element node. " +
3058 ("Currently attached to \"" + node.nodeName + "\"."));
3059 }
3060 }
3061
3062 /**
3063 * @license
3064 * Copyright Google LLC All Rights Reserved.
3065 *
3066 * Use of this source code is governed by an MIT-style license that can be
3067 * found in the LICENSE file at https://angular.io/license
3068 */
3069 /** Counter used to generate unique ids for drop zones. */
3070 var _uniqueIdCounter = 0;
3071 /**
3072 * Injection token that can be used to reference instances of `CdkDropList`. It serves as
3073 * alternative token to the actual `CdkDropList` class which could cause unnecessary
3074 * retention of the class and its directive metadata.
3075 */
3076 var CDK_DROP_LIST = new i0.InjectionToken('CdkDropList');
3077 var ɵ0 = undefined;
3078 /** Container that wraps a set of draggable items. */
3079 var CdkDropList = /** @class */ (function () {
3080 function CdkDropList(
3081 /** Element that the drop list is attached to. */
3082 element, dragDrop, _changeDetectorRef, _scrollDispatcher, _dir, _group, config) {
3083 var _this = this;
3084 this.element = element;
3085 this._changeDetectorRef = _changeDetectorRef;
3086 this._scrollDispatcher = _scrollDispatcher;
3087 this._dir = _dir;
3088 this._group = _group;
3089 /** Emits when the list has been destroyed. */
3090 this._destroyed = new rxjs.Subject();
3091 /**
3092 * Other draggable containers that this container is connected to and into which the
3093 * container's items can be transferred. Can either be references to other drop containers,
3094 * or their unique IDs.
3095 */
3096 this.connectedTo = [];
3097 /**
3098 * Unique ID for the drop zone. Can be used as a reference
3099 * in the `connectedTo` of another `CdkDropList`.
3100 */
3101 this.id = "cdk-drop-list-" + _uniqueIdCounter++;
3102 /**
3103 * Function that is used to determine whether an item
3104 * is allowed to be moved into a drop container.
3105 */
3106 this.enterPredicate = function () { return true; };
3107 /** Functions that is used to determine whether an item can be sorted into a particular index. */
3108 this.sortPredicate = function () { return true; };
3109 /** Emits when the user drops an item inside the container. */
3110 this.dropped = new i0.EventEmitter();
3111 /**
3112 * Emits when the user has moved a new drag item into this container.
3113 */
3114 this.entered = new i0.EventEmitter();
3115 /**
3116 * Emits when the user removes an item from the container
3117 * by dragging it into another container.
3118 */
3119 this.exited = new i0.EventEmitter();
3120 /** Emits as the user is swapping items while actively dragging. */
3121 this.sorted = new i0.EventEmitter();
3122 /**
3123 * Keeps track of the items that are registered with this container. Historically we used to
3124 * do this with a `ContentChildren` query, however queries don't handle transplanted views very
3125 * well which means that we can't handle cases like dragging the headers of a `mat-table`
3126 * correctly. What we do instead is to have the items register themselves with the container
3127 * and then we sort them based on their position in the DOM.
3128 */
3129 this._unsortedItems = new Set();
3130 if (typeof ngDevMode === 'undefined' || ngDevMode) {
3131 assertElementNode(element.nativeElement, 'cdkDropList');
3132 }
3133 this._dropListRef = dragDrop.createDropList(element);
3134 this._dropListRef.data = this;
3135 if (config) {
3136 this._assignDefaults(config);
3137 }
3138 this._dropListRef.enterPredicate = function (drag, drop) {
3139 return _this.enterPredicate(drag.data, drop.data);
3140 };
3141 this._dropListRef.sortPredicate =
3142 function (index, drag, drop) {
3143 return _this.sortPredicate(index, drag.data, drop.data);
3144 };
3145 this._setupInputSyncSubscription(this._dropListRef);
3146 this._handleEvents(this._dropListRef);
3147 CdkDropList._dropLists.push(this);
3148 if (_group) {
3149 _group._items.add(this);
3150 }
3151 }
3152 Object.defineProperty(CdkDropList.prototype, "disabled", {
3153 /** Whether starting a dragging sequence from this container is disabled. */
3154 get: function () {
3155 return this._disabled || (!!this._group && this._group.disabled);
3156 },
3157 set: function (value) {
3158 // Usually we sync the directive and ref state right before dragging starts, in order to have
3159 // a single point of failure and to avoid having to use setters for everything. `disabled` is
3160 // a special case, because it can prevent the `beforeStarted` event from firing, which can lock
3161 // the user in a disabled state, so we also need to sync it as it's being set.
3162 this._dropListRef.disabled = this._disabled = coercion.coerceBooleanProperty(value);
3163 },
3164 enumerable: false,
3165 configurable: true
3166 });
3167 /** Registers an items with the drop list. */
3168 CdkDropList.prototype.addItem = function (item) {
3169 this._unsortedItems.add(item);
3170 if (this._dropListRef.isDragging()) {
3171 this._syncItemsWithRef();
3172 }
3173 };
3174 /** Removes an item from the drop list. */
3175 CdkDropList.prototype.removeItem = function (item) {
3176 this._unsortedItems.delete(item);
3177 if (this._dropListRef.isDragging()) {
3178 this._syncItemsWithRef();
3179 }
3180 };
3181 /** Gets the registered items in the list, sorted by their position in the DOM. */
3182 CdkDropList.prototype.getSortedItems = function () {
3183 return Array.from(this._unsortedItems).sort(function (a, b) {
3184 var documentPosition = a._dragRef.getVisibleElement().compareDocumentPosition(b._dragRef.getVisibleElement());
3185 // `compareDocumentPosition` returns a bitmask so we have to use a bitwise operator.
3186 // https://developer.mozilla.org/en-US/docs/Web/API/Node/compareDocumentPosition
3187 // tslint:disable-next-line:no-bitwise
3188 return documentPosition & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1;
3189 });
3190 };
3191 CdkDropList.prototype.ngOnDestroy = function () {
3192 var index = CdkDropList._dropLists.indexOf(this);
3193 if (index > -1) {
3194 CdkDropList._dropLists.splice(index, 1);
3195 }
3196 if (this._group) {
3197 this._group._items.delete(this);
3198 }
3199 this._unsortedItems.clear();
3200 this._dropListRef.dispose();
3201 this._destroyed.next();
3202 this._destroyed.complete();
3203 };
3204 /** Syncs the inputs of the CdkDropList with the options of the underlying DropListRef. */
3205 CdkDropList.prototype._setupInputSyncSubscription = function (ref) {
3206 var _this = this;
3207 if (this._dir) {
3208 this._dir.change
3209 .pipe(operators.startWith(this._dir.value), operators.takeUntil(this._destroyed))
3210 .subscribe(function (value) { return ref.withDirection(value); });
3211 }
3212 ref.beforeStarted.subscribe(function () {
3213 var siblings = coercion.coerceArray(_this.connectedTo).map(function (drop) {
3214 if (typeof drop === 'string') {
3215 var correspondingDropList = CdkDropList._dropLists.find(function (list) { return list.id === drop; });
3216 if (!correspondingDropList && (typeof ngDevMode === 'undefined' || ngDevMode)) {
3217 console.warn("CdkDropList could not find connected drop list with id \"" + drop + "\"");
3218 }
3219 return correspondingDropList;
3220 }
3221 return drop;
3222 });
3223 if (_this._group) {
3224 _this._group._items.forEach(function (drop) {
3225 if (siblings.indexOf(drop) === -1) {
3226 siblings.push(drop);
3227 }
3228 });
3229 }
3230 // Note that we resolve the scrollable parents here so that we delay the resolution
3231 // as long as possible, ensuring that the element is in its final place in the DOM.
3232 if (!_this._scrollableParentsResolved) {
3233 var scrollableParents = _this._scrollDispatcher
3234 .getAncestorScrollContainers(_this.element)
3235 .map(function (scrollable) { return scrollable.getElementRef().nativeElement; });
3236 _this._dropListRef.withScrollableParents(scrollableParents);
3237 // Only do this once since it involves traversing the DOM and the parents
3238 // shouldn't be able to change without the drop list being destroyed.
3239 _this._scrollableParentsResolved = true;
3240 }
3241 ref.disabled = _this.disabled;
3242 ref.lockAxis = _this.lockAxis;
3243 ref.sortingDisabled = coercion.coerceBooleanProperty(_this.sortingDisabled);
3244 ref.autoScrollDisabled = coercion.coerceBooleanProperty(_this.autoScrollDisabled);
3245 ref.autoScrollStep = coercion.coerceNumberProperty(_this.autoScrollStep, 2);
3246 ref
3247 .connectedTo(siblings.filter(function (drop) { return drop && drop !== _this; }).map(function (list) { return list._dropListRef; }))
3248 .withOrientation(_this.orientation);
3249 });
3250 };
3251 /** Handles events from the underlying DropListRef. */
3252 CdkDropList.prototype._handleEvents = function (ref) {
3253 var _this = this;
3254 ref.beforeStarted.subscribe(function () {
3255 _this._syncItemsWithRef();
3256 _this._changeDetectorRef.markForCheck();
3257 });
3258 ref.entered.subscribe(function (event) {
3259 _this.entered.emit({
3260 container: _this,
3261 item: event.item.data,
3262 currentIndex: event.currentIndex
3263 });
3264 });
3265 ref.exited.subscribe(function (event) {
3266 _this.exited.emit({
3267 container: _this,
3268 item: event.item.data
3269 });
3270 _this._changeDetectorRef.markForCheck();
3271 });
3272 ref.sorted.subscribe(function (event) {
3273 _this.sorted.emit({
3274 previousIndex: event.previousIndex,
3275 currentIndex: event.currentIndex,
3276 container: _this,
3277 item: event.item.data
3278 });
3279 });
3280 ref.dropped.subscribe(function (event) {
3281 _this.dropped.emit({
3282 previousIndex: event.previousIndex,
3283 currentIndex: event.currentIndex,
3284 previousContainer: event.previousContainer.data,
3285 container: event.container.data,
3286 item: event.item.data,
3287 isPointerOverContainer: event.isPointerOverContainer,
3288 distance: event.distance,
3289 dropPoint: event.dropPoint
3290 });
3291 // Mark for check since all of these events run outside of change
3292 // detection and we're not guaranteed for something else to have triggered it.
3293 _this._changeDetectorRef.markForCheck();
3294 });
3295 };
3296 /** Assigns the default input values based on a provided config object. */
3297 CdkDropList.prototype._assignDefaults = function (config) {
3298 var lockAxis = config.lockAxis, draggingDisabled = config.draggingDisabled, sortingDisabled = config.sortingDisabled, listAutoScrollDisabled = config.listAutoScrollDisabled, listOrientation = config.listOrientation;
3299 this.disabled = draggingDisabled == null ? false : draggingDisabled;
3300 this.sortingDisabled = sortingDisabled == null ? false : sortingDisabled;
3301 this.autoScrollDisabled = listAutoScrollDisabled == null ? false : listAutoScrollDisabled;
3302 this.orientation = listOrientation || 'vertical';
3303 if (lockAxis) {
3304 this.lockAxis = lockAxis;
3305 }
3306 };
3307 /** Syncs up the registered drag items with underlying drop list ref. */
3308 CdkDropList.prototype._syncItemsWithRef = function () {
3309 this._dropListRef.withItems(this.getSortedItems().map(function (item) { return item._dragRef; }));
3310 };
3311 return CdkDropList;
3312 }());
3313 /** Keeps track of the drop lists that are currently on the page. */
3314 CdkDropList._dropLists = [];
3315 CdkDropList.decorators = [
3316 { type: i0.Directive, args: [{
3317 selector: '[cdkDropList], cdk-drop-list',
3318 exportAs: 'cdkDropList',
3319 providers: [
3320 // Prevent child drop lists from picking up the same group as their parent.
3321 { provide: CDK_DROP_LIST_GROUP, useValue: ɵ0 },
3322 { provide: CDK_DROP_LIST, useExisting: CdkDropList },
3323 ],
3324 host: {
3325 'class': 'cdk-drop-list',
3326 '[attr.id]': 'id',
3327 '[class.cdk-drop-list-disabled]': 'disabled',
3328 '[class.cdk-drop-list-dragging]': '_dropListRef.isDragging()',
3329 '[class.cdk-drop-list-receiving]': '_dropListRef.isReceiving()',
3330 }
3331 },] }
3332 ];
3333 CdkDropList.ctorParameters = function () { return [
3334 { type: i0.ElementRef },
3335 { type: DragDrop },
3336 { type: i0.ChangeDetectorRef },
3337 { type: i2.ScrollDispatcher },
3338 { type: bidi.Directionality, decorators: [{ type: i0.Optional }] },
3339 { type: CdkDropListGroup, decorators: [{ type: i0.Optional }, { type: i0.Inject, args: [CDK_DROP_LIST_GROUP,] }, { type: i0.SkipSelf }] },
3340 { type: undefined, decorators: [{ type: i0.Optional }, { type: i0.Inject, args: [CDK_DRAG_CONFIG,] }] }
3341 ]; };
3342 CdkDropList.propDecorators = {
3343 connectedTo: [{ type: i0.Input, args: ['cdkDropListConnectedTo',] }],
3344 data: [{ type: i0.Input, args: ['cdkDropListData',] }],
3345 orientation: [{ type: i0.Input, args: ['cdkDropListOrientation',] }],
3346 id: [{ type: i0.Input }],
3347 lockAxis: [{ type: i0.Input, args: ['cdkDropListLockAxis',] }],
3348 disabled: [{ type: i0.Input, args: ['cdkDropListDisabled',] }],
3349 sortingDisabled: [{ type: i0.Input, args: ['cdkDropListSortingDisabled',] }],
3350 enterPredicate: [{ type: i0.Input, args: ['cdkDropListEnterPredicate',] }],
3351 sortPredicate: [{ type: i0.Input, args: ['cdkDropListSortPredicate',] }],
3352 autoScrollDisabled: [{ type: i0.Input, args: ['cdkDropListAutoScrollDisabled',] }],
3353 autoScrollStep: [{ type: i0.Input, args: ['cdkDropListAutoScrollStep',] }],
3354 dropped: [{ type: i0.Output, args: ['cdkDropListDropped',] }],
3355 entered: [{ type: i0.Output, args: ['cdkDropListEntered',] }],
3356 exited: [{ type: i0.Output, args: ['cdkDropListExited',] }],
3357 sorted: [{ type: i0.Output, args: ['cdkDropListSorted',] }]
3358 };
3359
3360 /**
3361 * @license
3362 * Copyright Google LLC All Rights Reserved.
3363 *
3364 * Use of this source code is governed by an MIT-style license that can be
3365 * found in the LICENSE file at https://angular.io/license
3366 */
3367 /**
3368 * Injection token that can be used to reference instances of `CdkDragHandle`. It serves as
3369 * alternative token to the actual `CdkDragHandle` class which could cause unnecessary
3370 * retention of the class and its directive metadata.
3371 */
3372 var CDK_DRAG_HANDLE = new i0.InjectionToken('CdkDragHandle');
3373 /** Handle that can be used to drag a CdkDrag instance. */
3374 var CdkDragHandle = /** @class */ (function () {
3375 function CdkDragHandle(element, parentDrag) {
3376 this.element = element;
3377 /** Emits when the state of the handle has changed. */
3378 this._stateChanges = new rxjs.Subject();
3379 this._disabled = false;
3380 if (typeof ngDevMode === 'undefined' || ngDevMode) {
3381 assertElementNode(element.nativeElement, 'cdkDragHandle');
3382 }
3383 this._parentDrag = parentDrag;
3384 }
3385 Object.defineProperty(CdkDragHandle.prototype, "disabled", {
3386 /** Whether starting to drag through this handle is disabled. */
3387 get: function () { return this._disabled; },
3388 set: function (value) {
3389 this._disabled = coercion.coerceBooleanProperty(value);
3390 this._stateChanges.next(this);
3391 },
3392 enumerable: false,
3393 configurable: true
3394 });
3395 CdkDragHandle.prototype.ngOnDestroy = function () {
3396 this._stateChanges.complete();
3397 };
3398 return CdkDragHandle;
3399 }());
3400 CdkDragHandle.decorators = [
3401 { type: i0.Directive, args: [{
3402 selector: '[cdkDragHandle]',
3403 host: {
3404 'class': 'cdk-drag-handle'
3405 },
3406 providers: [{ provide: CDK_DRAG_HANDLE, useExisting: CdkDragHandle }],
3407 },] }
3408 ];
3409 CdkDragHandle.ctorParameters = function () { return [
3410 { type: i0.ElementRef },
3411 { type: undefined, decorators: [{ type: i0.Inject, args: [CDK_DRAG_PARENT,] }, { type: i0.Optional }, { type: i0.SkipSelf }] }
3412 ]; };
3413 CdkDragHandle.propDecorators = {
3414 disabled: [{ type: i0.Input, args: ['cdkDragHandleDisabled',] }]
3415 };
3416
3417 /**
3418 * @license
3419 * Copyright Google LLC All Rights Reserved.
3420 *
3421 * Use of this source code is governed by an MIT-style license that can be
3422 * found in the LICENSE file at https://angular.io/license
3423 */
3424 /**
3425 * Injection token that can be used to reference instances of `CdkDragPlaceholder`. It serves as
3426 * alternative token to the actual `CdkDragPlaceholder` class which could cause unnecessary
3427 * retention of the class and its directive metadata.
3428 */
3429 var CDK_DRAG_PLACEHOLDER = new i0.InjectionToken('CdkDragPlaceholder');
3430 /**
3431 * Element that will be used as a template for the placeholder of a CdkDrag when
3432 * it is being dragged. The placeholder is displayed in place of the element being dragged.
3433 */
3434 var CdkDragPlaceholder = /** @class */ (function () {
3435 function CdkDragPlaceholder(templateRef) {
3436 this.templateRef = templateRef;
3437 }
3438 return CdkDragPlaceholder;
3439 }());
3440 CdkDragPlaceholder.decorators = [
3441 { type: i0.Directive, args: [{
3442 selector: 'ng-template[cdkDragPlaceholder]',
3443 providers: [{ provide: CDK_DRAG_PLACEHOLDER, useExisting: CdkDragPlaceholder }],
3444 },] }
3445 ];
3446 CdkDragPlaceholder.ctorParameters = function () { return [
3447 { type: i0.TemplateRef }
3448 ]; };
3449 CdkDragPlaceholder.propDecorators = {
3450 data: [{ type: i0.Input }]
3451 };
3452
3453 /**
3454 * @license
3455 * Copyright Google LLC All Rights Reserved.
3456 *
3457 * Use of this source code is governed by an MIT-style license that can be
3458 * found in the LICENSE file at https://angular.io/license
3459 */
3460 /**
3461 * Injection token that can be used to reference instances of `CdkDragPreview`. It serves as
3462 * alternative token to the actual `CdkDragPreview` class which could cause unnecessary
3463 * retention of the class and its directive metadata.
3464 */
3465 var CDK_DRAG_PREVIEW = new i0.InjectionToken('CdkDragPreview');
3466 /**
3467 * Element that will be used as a template for the preview
3468 * of a CdkDrag when it is being dragged.
3469 */
3470 var CdkDragPreview = /** @class */ (function () {
3471 function CdkDragPreview(templateRef) {
3472 this.templateRef = templateRef;
3473 this._matchSize = false;
3474 }
3475 Object.defineProperty(CdkDragPreview.prototype, "matchSize", {
3476 /** Whether the preview should preserve the same size as the item that is being dragged. */
3477 get: function () { return this._matchSize; },
3478 set: function (value) { this._matchSize = coercion.coerceBooleanProperty(value); },
3479 enumerable: false,
3480 configurable: true
3481 });
3482 return CdkDragPreview;
3483 }());
3484 CdkDragPreview.decorators = [
3485 { type: i0.Directive, args: [{
3486 selector: 'ng-template[cdkDragPreview]',
3487 providers: [{ provide: CDK_DRAG_PREVIEW, useExisting: CdkDragPreview }],
3488 },] }
3489 ];
3490 CdkDragPreview.ctorParameters = function () { return [
3491 { type: i0.TemplateRef }
3492 ]; };
3493 CdkDragPreview.propDecorators = {
3494 data: [{ type: i0.Input }],
3495 matchSize: [{ type: i0.Input }]
3496 };
3497
3498 var DRAG_HOST_CLASS = 'cdk-drag';
3499 /** Element that can be moved inside a CdkDropList container. */
3500 var CdkDrag = /** @class */ (function () {
3501 function CdkDrag(
3502 /** Element that the draggable is attached to. */
3503 element,
3504 /** Droppable container that the draggable is a part of. */
3505 dropContainer,
3506 /**
3507 * @deprecated `_document` parameter no longer being used and will be removed.
3508 * @breaking-change 12.0.0
3509 */
3510 _document, _ngZone, _viewContainerRef, config, _dir, dragDrop, _changeDetectorRef, _selfHandle, _parentDrag) {
3511 var _this = this;
3512 this.element = element;
3513 this.dropContainer = dropContainer;
3514 this._ngZone = _ngZone;
3515 this._viewContainerRef = _viewContainerRef;
3516 this._dir = _dir;
3517 this._changeDetectorRef = _changeDetectorRef;
3518 this._selfHandle = _selfHandle;
3519 this._parentDrag = _parentDrag;
3520 this._destroyed = new rxjs.Subject();
3521 /** Emits when the user starts dragging the item. */
3522 this.started = new i0.EventEmitter();
3523 /** Emits when the user has released a drag item, before any animations have started. */
3524 this.released = new i0.EventEmitter();
3525 /** Emits when the user stops dragging an item in the container. */
3526 this.ended = new i0.EventEmitter();
3527 /** Emits when the user has moved the item into a new container. */
3528 this.entered = new i0.EventEmitter();
3529 /** Emits when the user removes the item its container by dragging it into another container. */
3530 this.exited = new i0.EventEmitter();
3531 /** Emits when the user drops the item inside a container. */
3532 this.dropped = new i0.EventEmitter();
3533 /**
3534 * Emits as the user is dragging the item. Use with caution,
3535 * because this event will fire for every pixel that the user has dragged.
3536 */
3537 this.moved = new rxjs.Observable(function (observer) {
3538 var subscription = _this._dragRef.moved.pipe(operators.map(function (movedEvent) { return ({
3539 source: _this,
3540 pointerPosition: movedEvent.pointerPosition,
3541 event: movedEvent.event,
3542 delta: movedEvent.delta,
3543 distance: movedEvent.distance
3544 }); })).subscribe(observer);
3545 return function () {
3546 subscription.unsubscribe();
3547 };
3548 });
3549 this._dragRef = dragDrop.createDrag(element, {
3550 dragStartThreshold: config && config.dragStartThreshold != null ?
3551 config.dragStartThreshold : 5,
3552 pointerDirectionChangeThreshold: config && config.pointerDirectionChangeThreshold != null ?
3553 config.pointerDirectionChangeThreshold : 5,
3554 zIndex: config === null || config === void 0 ? void 0 : config.zIndex,
3555 });
3556 this._dragRef.data = this;
3557 // We have to keep track of the drag instances in order to be able to match an element to
3558 // a drag instance. We can't go through the global registry of `DragRef`, because the root
3559 // element could be different.
3560 CdkDrag._dragInstances.push(this);
3561 if (config) {
3562 this._assignDefaults(config);
3563 }
3564 // Note that usually the container is assigned when the drop list is picks up the item, but in
3565 // some cases (mainly transplanted views with OnPush, see #18341) we may end up in a situation
3566 // where there are no items on the first change detection pass, but the items get picked up as
3567 // soon as the user triggers another pass by dragging. This is a problem, because the item would
3568 // have to switch from standalone mode to drag mode in the middle of the dragging sequence which
3569 // is too late since the two modes save different kinds of information. We work around it by
3570 // assigning the drop container both from here and the list.
3571 if (dropContainer) {
3572 this._dragRef._withDropContainer(dropContainer._dropListRef);
3573 dropContainer.addItem(this);
3574 }
3575 this._syncInputs(this._dragRef);
3576 this._handleEvents(this._dragRef);
3577 }
3578 Object.defineProperty(CdkDrag.prototype, "disabled", {
3579 /** Whether starting to drag this element is disabled. */
3580 get: function () {
3581 return this._disabled || (this.dropContainer && this.dropContainer.disabled);
3582 },
3583 set: function (value) {
3584 this._disabled = coercion.coerceBooleanProperty(value);
3585 this._dragRef.disabled = this._disabled;
3586 },
3587 enumerable: false,
3588 configurable: true
3589 });
3590 /**
3591 * Returns the element that is being used as a placeholder
3592 * while the current element is being dragged.
3593 */
3594 CdkDrag.prototype.getPlaceholderElement = function () {
3595 return this._dragRef.getPlaceholderElement();
3596 };
3597 /** Returns the root draggable element. */
3598 CdkDrag.prototype.getRootElement = function () {
3599 return this._dragRef.getRootElement();
3600 };
3601 /** Resets a standalone drag item to its initial position. */
3602 CdkDrag.prototype.reset = function () {
3603 this._dragRef.reset();
3604 };
3605 /**
3606 * Gets the pixel coordinates of the draggable outside of a drop container.
3607 */
3608 CdkDrag.prototype.getFreeDragPosition = function () {
3609 return this._dragRef.getFreeDragPosition();
3610 };
3611 CdkDrag.prototype.ngAfterViewInit = function () {
3612 var _this = this;
3613 // Normally this isn't in the zone, but it can cause major performance regressions for apps
3614 // using `zone-patch-rxjs` because it'll trigger a change detection when it unsubscribes.
3615 this._ngZone.runOutsideAngular(function () {
3616 // We need to wait for the zone to stabilize, in order for the reference
3617 // element to be in the proper place in the DOM. This is mostly relevant
3618 // for draggable elements inside portals since they get stamped out in
3619 // their original DOM position and then they get transferred to the portal.
3620 _this._ngZone.onStable
3621 .pipe(operators.take(1), operators.takeUntil(_this._destroyed))
3622 .subscribe(function () {
3623 _this._updateRootElement();
3624 _this._setupHandlesListener();
3625 if (_this.freeDragPosition) {
3626 _this._dragRef.setFreeDragPosition(_this.freeDragPosition);
3627 }
3628 });
3629 });
3630 };
3631 CdkDrag.prototype.ngOnChanges = function (changes) {
3632 var rootSelectorChange = changes['rootElementSelector'];
3633 var positionChange = changes['freeDragPosition'];
3634 // We don't have to react to the first change since it's being
3635 // handled in `ngAfterViewInit` where it needs to be deferred.
3636 if (rootSelectorChange && !rootSelectorChange.firstChange) {
3637 this._updateRootElement();
3638 }
3639 // Skip the first change since it's being handled in `ngAfterViewInit`.
3640 if (positionChange && !positionChange.firstChange && this.freeDragPosition) {
3641 this._dragRef.setFreeDragPosition(this.freeDragPosition);
3642 }
3643 };
3644 CdkDrag.prototype.ngOnDestroy = function () {
3645 var _this = this;
3646 if (this.dropContainer) {
3647 this.dropContainer.removeItem(this);
3648 }
3649 var index = CdkDrag._dragInstances.indexOf(this);
3650 if (index > -1) {
3651 CdkDrag._dragInstances.splice(index, 1);
3652 }
3653 // Unnecessary in most cases, but used to avoid extra change detections with `zone-paths-rxjs`.
3654 this._ngZone.runOutsideAngular(function () {
3655 _this._destroyed.next();
3656 _this._destroyed.complete();
3657 _this._dragRef.dispose();
3658 });
3659 };
3660 /** Syncs the root element with the `DragRef`. */
3661 CdkDrag.prototype._updateRootElement = function () {
3662 var element = this.element.nativeElement;
3663 var rootElement = this.rootElementSelector ?
3664 getClosestMatchingAncestor(element, this.rootElementSelector) : element;
3665 if (rootElement && (typeof ngDevMode === 'undefined' || ngDevMode)) {
3666 assertElementNode(rootElement, 'cdkDrag');
3667 }
3668 this._dragRef.withRootElement(rootElement || element);
3669 };
3670 /** Gets the boundary element, based on the `boundaryElement` value. */
3671 CdkDrag.prototype._getBoundaryElement = function () {
3672 var boundary = this.boundaryElement;
3673 if (!boundary) {
3674 return null;
3675 }
3676 if (typeof boundary === 'string') {
3677 return getClosestMatchingAncestor(this.element.nativeElement, boundary);
3678 }
3679 var element = coercion.coerceElement(boundary);
3680 if ((typeof ngDevMode === 'undefined' || ngDevMode) &&
3681 !element.contains(this.element.nativeElement)) {
3682 throw Error('Draggable element is not inside of the node passed into cdkDragBoundary.');
3683 }
3684 return element;
3685 };
3686 /** Syncs the inputs of the CdkDrag with the options of the underlying DragRef. */
3687 CdkDrag.prototype._syncInputs = function (ref) {
3688 var _this = this;
3689 ref.beforeStarted.subscribe(function () {
3690 if (!ref.isDragging()) {
3691 var dir = _this._dir;
3692 var dragStartDelay = _this.dragStartDelay;
3693 var placeholder = _this._placeholderTemplate ? {
3694 template: _this._placeholderTemplate.templateRef,
3695 context: _this._placeholderTemplate.data,
3696 viewContainer: _this._viewContainerRef
3697 } : null;
3698 var preview = _this._previewTemplate ? {
3699 template: _this._previewTemplate.templateRef,
3700 context: _this._previewTemplate.data,
3701 matchSize: _this._previewTemplate.matchSize,
3702 viewContainer: _this._viewContainerRef
3703 } : null;
3704 ref.disabled = _this.disabled;
3705 ref.lockAxis = _this.lockAxis;
3706 ref.dragStartDelay = (typeof dragStartDelay === 'object' && dragStartDelay) ?
3707 dragStartDelay : coercion.coerceNumberProperty(dragStartDelay);
3708 ref.constrainPosition = _this.constrainPosition;
3709 ref.previewClass = _this.previewClass;
3710 ref
3711 .withBoundaryElement(_this._getBoundaryElement())
3712 .withPlaceholderTemplate(placeholder)
3713 .withPreviewTemplate(preview)
3714 .withPreviewContainer(_this.previewContainer || 'global');
3715 if (dir) {
3716 ref.withDirection(dir.value);
3717 }
3718 }
3719 });
3720 // This only needs to be resolved once.
3721 ref.beforeStarted.pipe(operators.take(1)).subscribe(function () {
3722 var _a, _b;
3723 // If we managed to resolve a parent through DI, use it.
3724 if (_this._parentDrag) {
3725 ref.withParent(_this._parentDrag._dragRef);
3726 return;
3727 }
3728 // Otherwise fall back to resolving the parent by looking up the DOM. This can happen if
3729 // the item was projected into another item by something like `ngTemplateOutlet`.
3730 var parent = _this.element.nativeElement.parentElement;
3731 while (parent) {
3732 // `classList` needs to be null checked, because IE doesn't have it on some elements.
3733 if ((_a = parent.classList) === null || _a === void 0 ? void 0 : _a.contains(DRAG_HOST_CLASS)) {
3734 ref.withParent(((_b = CdkDrag._dragInstances.find(function (drag) {
3735 return drag.element.nativeElement === parent;
3736 })) === null || _b === void 0 ? void 0 : _b._dragRef) || null);
3737 break;
3738 }
3739 parent = parent.parentElement;
3740 }
3741 });
3742 };
3743 /** Handles the events from the underlying `DragRef`. */
3744 CdkDrag.prototype._handleEvents = function (ref) {
3745 var _this = this;
3746 ref.started.subscribe(function () {
3747 _this.started.emit({ source: _this });
3748 // Since all of these events run outside of change detection,
3749 // we need to ensure that everything is marked correctly.
3750 _this._changeDetectorRef.markForCheck();
3751 });
3752 ref.released.subscribe(function () {
3753 _this.released.emit({ source: _this });
3754 });
3755 ref.ended.subscribe(function (event) {
3756 _this.ended.emit({
3757 source: _this,
3758 distance: event.distance,
3759 dropPoint: event.dropPoint
3760 });
3761 // Since all of these events run outside of change detection,
3762 // we need to ensure that everything is marked correctly.
3763 _this._changeDetectorRef.markForCheck();
3764 });
3765 ref.entered.subscribe(function (event) {
3766 _this.entered.emit({
3767 container: event.container.data,
3768 item: _this,
3769 currentIndex: event.currentIndex
3770 });
3771 });
3772 ref.exited.subscribe(function (event) {
3773 _this.exited.emit({
3774 container: event.container.data,
3775 item: _this
3776 });
3777 });
3778 ref.dropped.subscribe(function (event) {
3779 _this.dropped.emit({
3780 previousIndex: event.previousIndex,
3781 currentIndex: event.currentIndex,
3782 previousContainer: event.previousContainer.data,
3783 container: event.container.data,
3784 isPointerOverContainer: event.isPointerOverContainer,
3785 item: _this,
3786 distance: event.distance,
3787 dropPoint: event.dropPoint
3788 });
3789 });
3790 };
3791 /** Assigns the default input values based on a provided config object. */
3792 CdkDrag.prototype._assignDefaults = function (config) {
3793 var lockAxis = config.lockAxis, dragStartDelay = config.dragStartDelay, constrainPosition = config.constrainPosition, previewClass = config.previewClass, boundaryElement = config.boundaryElement, draggingDisabled = config.draggingDisabled, rootElementSelector = config.rootElementSelector, previewContainer = config.previewContainer;
3794 this.disabled = draggingDisabled == null ? false : draggingDisabled;
3795 this.dragStartDelay = dragStartDelay || 0;
3796 if (lockAxis) {
3797 this.lockAxis = lockAxis;
3798 }
3799 if (constrainPosition) {
3800 this.constrainPosition = constrainPosition;
3801 }
3802 if (previewClass) {
3803 this.previewClass = previewClass;
3804 }
3805 if (boundaryElement) {
3806 this.boundaryElement = boundaryElement;
3807 }
3808 if (rootElementSelector) {
3809 this.rootElementSelector = rootElementSelector;
3810 }
3811 if (previewContainer) {
3812 this.previewContainer = previewContainer;
3813 }
3814 };
3815 /** Sets up the listener that syncs the handles with the drag ref. */
3816 CdkDrag.prototype._setupHandlesListener = function () {
3817 var _this = this;
3818 // Listen for any newly-added handles.
3819 this._handles.changes.pipe(operators.startWith(this._handles),
3820 // Sync the new handles with the DragRef.
3821 operators.tap(function (handles) {
3822 var childHandleElements = handles
3823 .filter(function (handle) { return handle._parentDrag === _this; })
3824 .map(function (handle) { return handle.element; });
3825 // Usually handles are only allowed to be a descendant of the drag element, but if
3826 // the consumer defined a different drag root, we should allow the drag element
3827 // itself to be a handle too.
3828 if (_this._selfHandle && _this.rootElementSelector) {
3829 childHandleElements.push(_this.element);
3830 }
3831 _this._dragRef.withHandles(childHandleElements);
3832 }),
3833 // Listen if the state of any of the handles changes.
3834 operators.switchMap(function (handles) {
3835 return rxjs.merge.apply(void 0, __spreadArray([], __read(handles.map(function (item) {
3836 return item._stateChanges.pipe(operators.startWith(item));
3837 }))));
3838 }), operators.takeUntil(this._destroyed)).subscribe(function (handleInstance) {
3839 // Enabled/disable the handle that changed in the DragRef.
3840 var dragRef = _this._dragRef;
3841 var handle = handleInstance.element.nativeElement;
3842 handleInstance.disabled ? dragRef.disableHandle(handle) : dragRef.enableHandle(handle);
3843 });
3844 };
3845 return CdkDrag;
3846 }());
3847 CdkDrag._dragInstances = [];
3848 CdkDrag.decorators = [
3849 { type: i0.Directive, args: [{
3850 selector: '[cdkDrag]',
3851 exportAs: 'cdkDrag',
3852 host: {
3853 'class': DRAG_HOST_CLASS,
3854 '[class.cdk-drag-disabled]': 'disabled',
3855 '[class.cdk-drag-dragging]': '_dragRef.isDragging()',
3856 },
3857 providers: [{ provide: CDK_DRAG_PARENT, useExisting: CdkDrag }]
3858 },] }
3859 ];
3860 CdkDrag.ctorParameters = function () { return [
3861 { type: i0.ElementRef },
3862 { type: undefined, decorators: [{ type: i0.Inject, args: [CDK_DROP_LIST,] }, { type: i0.Optional }, { type: i0.SkipSelf }] },
3863 { type: undefined, decorators: [{ type: i0.Inject, args: [i1.DOCUMENT,] }] },
3864 { type: i0.NgZone },
3865 { type: i0.ViewContainerRef },
3866 { type: undefined, decorators: [{ type: i0.Optional }, { type: i0.Inject, args: [CDK_DRAG_CONFIG,] }] },
3867 { type: bidi.Directionality, decorators: [{ type: i0.Optional }] },
3868 { type: DragDrop },
3869 { type: i0.ChangeDetectorRef },
3870 { type: CdkDragHandle, decorators: [{ type: i0.Optional }, { type: i0.Self }, { type: i0.Inject, args: [CDK_DRAG_HANDLE,] }] },
3871 { type: CdkDrag, decorators: [{ type: i0.Optional }, { type: i0.SkipSelf }, { type: i0.Inject, args: [CDK_DRAG_PARENT,] }] }
3872 ]; };
3873 CdkDrag.propDecorators = {
3874 _handles: [{ type: i0.ContentChildren, args: [CDK_DRAG_HANDLE, { descendants: true },] }],
3875 _previewTemplate: [{ type: i0.ContentChild, args: [CDK_DRAG_PREVIEW,] }],
3876 _placeholderTemplate: [{ type: i0.ContentChild, args: [CDK_DRAG_PLACEHOLDER,] }],
3877 data: [{ type: i0.Input, args: ['cdkDragData',] }],
3878 lockAxis: [{ type: i0.Input, args: ['cdkDragLockAxis',] }],
3879 rootElementSelector: [{ type: i0.Input, args: ['cdkDragRootElement',] }],
3880 boundaryElement: [{ type: i0.Input, args: ['cdkDragBoundary',] }],
3881 dragStartDelay: [{ type: i0.Input, args: ['cdkDragStartDelay',] }],
3882 freeDragPosition: [{ type: i0.Input, args: ['cdkDragFreeDragPosition',] }],
3883 disabled: [{ type: i0.Input, args: ['cdkDragDisabled',] }],
3884 constrainPosition: [{ type: i0.Input, args: ['cdkDragConstrainPosition',] }],
3885 previewClass: [{ type: i0.Input, args: ['cdkDragPreviewClass',] }],
3886 previewContainer: [{ type: i0.Input, args: ['cdkDragPreviewContainer',] }],
3887 started: [{ type: i0.Output, args: ['cdkDragStarted',] }],
3888 released: [{ type: i0.Output, args: ['cdkDragReleased',] }],
3889 ended: [{ type: i0.Output, args: ['cdkDragEnded',] }],
3890 entered: [{ type: i0.Output, args: ['cdkDragEntered',] }],
3891 exited: [{ type: i0.Output, args: ['cdkDragExited',] }],
3892 dropped: [{ type: i0.Output, args: ['cdkDragDropped',] }],
3893 moved: [{ type: i0.Output, args: ['cdkDragMoved',] }]
3894 };
3895 /** Gets the closest ancestor of an element that matches a selector. */
3896 function getClosestMatchingAncestor(element, selector) {
3897 var currentElement = element.parentElement;
3898 while (currentElement) {
3899 // IE doesn't support `matches` so we have to fall back to `msMatchesSelector`.
3900 if (currentElement.matches ? currentElement.matches(selector) :
3901 currentElement.msMatchesSelector(selector)) {
3902 return currentElement;
3903 }
3904 currentElement = currentElement.parentElement;
3905 }
3906 return null;
3907 }
3908
3909 /**
3910 * @license
3911 * Copyright Google LLC All Rights Reserved.
3912 *
3913 * Use of this source code is governed by an MIT-style license that can be
3914 * found in the LICENSE file at https://angular.io/license
3915 */
3916 var DragDropModule = /** @class */ (function () {
3917 function DragDropModule() {
3918 }
3919 return DragDropModule;
3920 }());
3921 DragDropModule.decorators = [
3922 { type: i0.NgModule, args: [{
3923 declarations: [
3924 CdkDropList,
3925 CdkDropListGroup,
3926 CdkDrag,
3927 CdkDragHandle,
3928 CdkDragPreview,
3929 CdkDragPlaceholder,
3930 ],
3931 exports: [
3932 i2.CdkScrollableModule,
3933 CdkDropList,
3934 CdkDropListGroup,
3935 CdkDrag,
3936 CdkDragHandle,
3937 CdkDragPreview,
3938 CdkDragPlaceholder,
3939 ],
3940 providers: [
3941 DragDrop,
3942 ]
3943 },] }
3944 ];
3945
3946 /**
3947 * @license
3948 * Copyright Google LLC All Rights Reserved.
3949 *
3950 * Use of this source code is governed by an MIT-style license that can be
3951 * found in the LICENSE file at https://angular.io/license
3952 */
3953
3954 /**
3955 * Generated bundle index. Do not edit.
3956 */
3957
3958 exports.CDK_DRAG_CONFIG = CDK_DRAG_CONFIG;
3959 exports.CDK_DRAG_HANDLE = CDK_DRAG_HANDLE;
3960 exports.CDK_DRAG_PARENT = CDK_DRAG_PARENT;
3961 exports.CDK_DRAG_PLACEHOLDER = CDK_DRAG_PLACEHOLDER;
3962 exports.CDK_DRAG_PREVIEW = CDK_DRAG_PREVIEW;
3963 exports.CDK_DROP_LIST = CDK_DROP_LIST;
3964 exports.CDK_DROP_LIST_GROUP = CDK_DROP_LIST_GROUP;
3965 exports.CdkDrag = CdkDrag;
3966 exports.CdkDragHandle = CdkDragHandle;
3967 exports.CdkDragPlaceholder = CdkDragPlaceholder;
3968 exports.CdkDragPreview = CdkDragPreview;
3969 exports.CdkDropList = CdkDropList;
3970 exports.CdkDropListGroup = CdkDropListGroup;
3971 exports.DragDrop = DragDrop;
3972 exports.DragDropModule = DragDropModule;
3973 exports.DragDropRegistry = DragDropRegistry;
3974 exports.DragRef = DragRef;
3975 exports.DropListRef = DropListRef;
3976 exports.copyArrayItem = copyArrayItem;
3977 exports.moveItemInArray = moveItemInArray;
3978 exports.transferArrayItem = transferArrayItem;
3979
3980 Object.defineProperty(exports, '__esModule', { value: true });
3981
3982})));
3983//# sourceMappingURL=cdk-drag-drop.umd.js.map