@angular/cdk 7.2.1 → 7.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/a11y/typings/index.metadata.json +1 -1
  2. package/bundles/cdk-a11y.umd.js +2 -1
  3. package/bundles/cdk-a11y.umd.js.map +1 -1
  4. package/bundles/cdk-a11y.umd.min.js +1 -1
  5. package/bundles/cdk-a11y.umd.min.js.map +1 -1
  6. package/bundles/cdk-drag-drop.umd.js +274 -126
  7. package/bundles/cdk-drag-drop.umd.js.map +1 -1
  8. package/bundles/cdk-drag-drop.umd.min.js +2 -2
  9. package/bundles/cdk-drag-drop.umd.min.js.map +1 -1
  10. package/bundles/cdk-observers.umd.js +1 -1
  11. package/bundles/cdk-observers.umd.js.map +1 -1
  12. package/bundles/cdk-observers.umd.min.js +1 -1
  13. package/bundles/cdk-observers.umd.min.js.map +1 -1
  14. package/bundles/cdk-overlay.umd.js +13 -12
  15. package/bundles/cdk-overlay.umd.js.map +1 -1
  16. package/bundles/cdk-overlay.umd.min.js +2 -2
  17. package/bundles/cdk-overlay.umd.min.js.map +1 -1
  18. package/bundles/cdk-portal.umd.js +3 -3
  19. package/bundles/cdk-portal.umd.js.map +1 -1
  20. package/bundles/cdk-portal.umd.min.js.map +1 -1
  21. package/bundles/cdk-scrolling.umd.js +9 -6
  22. package/bundles/cdk-scrolling.umd.js.map +1 -1
  23. package/bundles/cdk-scrolling.umd.min.js +1 -1
  24. package/bundles/cdk-scrolling.umd.min.js.map +1 -1
  25. package/bundles/cdk-stepper.umd.js +23 -11
  26. package/bundles/cdk-stepper.umd.js.map +1 -1
  27. package/bundles/cdk-stepper.umd.min.js +1 -1
  28. package/bundles/cdk-stepper.umd.min.js.map +1 -1
  29. package/bundles/cdk-table.umd.js +8 -4
  30. package/bundles/cdk-table.umd.js.map +1 -1
  31. package/bundles/cdk-table.umd.min.js +1 -1
  32. package/bundles/cdk-table.umd.min.js.map +1 -1
  33. package/bundles/cdk-text-field.umd.js +1 -1
  34. package/bundles/cdk-text-field.umd.min.js +1 -1
  35. package/bundles/cdk-text-field.umd.min.js.map +1 -1
  36. package/bundles/cdk.umd.js +1 -1
  37. package/bundles/cdk.umd.js.map +1 -1
  38. package/bundles/cdk.umd.min.js +1 -1
  39. package/bundles/cdk.umd.min.js.map +1 -1
  40. package/drag-drop/typings/directives/drag-handle.d.ts +6 -2
  41. package/drag-drop/typings/directives/drag.d.ts +3 -2
  42. package/drag-drop/typings/directives/drop-list.d.ts +2 -5
  43. package/drag-drop/typings/drag-ref.d.ts +27 -19
  44. package/drag-drop/typings/drop-list-ref.d.ts +28 -14
  45. package/drag-drop/typings/index.metadata.json +1 -1
  46. package/esm2015/a11y.js +2 -1
  47. package/esm2015/a11y.js.map +1 -1
  48. package/esm2015/cdk.js +1 -1
  49. package/esm2015/cdk.js.map +1 -1
  50. package/esm2015/drag-drop.js +192 -108
  51. package/esm2015/drag-drop.js.map +1 -1
  52. package/esm2015/observers.js +1 -1
  53. package/esm2015/observers.js.map +1 -1
  54. package/esm2015/overlay.js +11 -10
  55. package/esm2015/overlay.js.map +1 -1
  56. package/esm2015/portal.js +1 -1
  57. package/esm2015/portal.js.map +1 -1
  58. package/esm2015/scrolling.js +9 -6
  59. package/esm2015/scrolling.js.map +1 -1
  60. package/esm2015/stepper.js +18 -11
  61. package/esm2015/stepper.js.map +1 -1
  62. package/esm2015/table.js +8 -4
  63. package/esm2015/table.js.map +1 -1
  64. package/esm5/a11y.es5.js +2 -1
  65. package/esm5/a11y.es5.js.map +1 -1
  66. package/esm5/cdk.es5.js +1 -1
  67. package/esm5/cdk.es5.js.map +1 -1
  68. package/esm5/drag-drop.es5.js +276 -128
  69. package/esm5/drag-drop.es5.js.map +1 -1
  70. package/esm5/observers.es5.js +1 -1
  71. package/esm5/observers.es5.js.map +1 -1
  72. package/esm5/overlay.es5.js +13 -12
  73. package/esm5/overlay.es5.js.map +1 -1
  74. package/esm5/portal.es5.js +3 -3
  75. package/esm5/portal.es5.js.map +1 -1
  76. package/esm5/scrolling.es5.js +9 -6
  77. package/esm5/scrolling.es5.js.map +1 -1
  78. package/esm5/stepper.es5.js +23 -11
  79. package/esm5/stepper.es5.js.map +1 -1
  80. package/esm5/table.es5.js +8 -4
  81. package/esm5/table.es5.js.map +1 -1
  82. package/overlay/typings/index.metadata.json +1 -1
  83. package/overlay/typings/overlay-ref.d.ts +1 -1
  84. package/package.json +3 -3
  85. package/portal/typings/portal.d.ts +1 -1
  86. package/schematics/migration.json +5 -0
  87. package/schematics/ng-update/index.d.ts +2 -0
  88. package/schematics/ng-update/index.js +5 -0
  89. package/schematics/ng-update/index.js.map +1 -1
  90. package/schematics/ng-update/target-version.d.ts +7 -1
  91. package/schematics/ng-update/target-version.js +10 -0
  92. package/schematics/ng-update/target-version.js.map +1 -1
  93. package/stepper/typings/index.metadata.json +1 -1
  94. package/stepper/typings/stepper.d.ts +7 -1
  95. package/typings/a11y/index.metadata.json +1 -1
  96. package/typings/drag-drop/directives/drag-handle.d.ts +6 -2
  97. package/typings/drag-drop/directives/drag.d.ts +3 -2
  98. package/typings/drag-drop/directives/drop-list.d.ts +2 -5
  99. package/typings/drag-drop/drag-ref.d.ts +27 -19
  100. package/typings/drag-drop/drop-list-ref.d.ts +28 -14
  101. package/typings/drag-drop/index.metadata.json +1 -1
  102. package/typings/esm5/a11y/index.metadata.json +1 -1
  103. package/typings/esm5/drag-drop/directives/drag-handle.d.ts +6 -2
  104. package/typings/esm5/drag-drop/directives/drag.d.ts +3 -2
  105. package/typings/esm5/drag-drop/directives/drop-list.d.ts +2 -5
  106. package/typings/esm5/drag-drop/drag-ref.d.ts +27 -19
  107. package/typings/esm5/drag-drop/drop-list-ref.d.ts +28 -14
  108. package/typings/esm5/drag-drop/index.metadata.json +1 -1
  109. package/typings/esm5/index.metadata.json +1 -1
  110. package/typings/esm5/overlay/index.metadata.json +1 -1
  111. package/typings/esm5/overlay/overlay-ref.d.ts +1 -1
  112. package/typings/esm5/portal/portal.d.ts +1 -1
  113. package/typings/esm5/stepper/index.metadata.json +1 -1
  114. package/typings/esm5/stepper/stepper.d.ts +7 -1
  115. package/typings/index.metadata.json +1 -1
  116. package/typings/overlay/index.metadata.json +1 -1
  117. package/typings/overlay/overlay-ref.d.ts +1 -1
  118. package/typings/portal/portal.d.ts +1 -1
  119. package/typings/schematics/ng-update/index.d.ts +2 -0
  120. package/typings/schematics/ng-update/target-version.d.ts +7 -1
  121. package/typings/stepper/index.metadata.json +1 -1
  122. package/typings/stepper/stepper.d.ts +7 -1
@@ -1 +1 @@
1
- {"version":3,"file":"cdk.js","sources":["../../src/cdk/version.ts"],"sourcesContent":["/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Version} from '@angular/core';\n\n/** Current version of the Angular Component Development Kit. */\nexport const VERSION = new Version('7.2.1');\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAWA,AAAA,MAAa,OAAO,GAAG,IAAI,OAAO,CAAC,mBAAmB,CAAC;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"cdk.js","sources":["../../src/cdk/version.ts"],"sourcesContent":["/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Version} from '@angular/core';\n\n/** Current version of the Angular Component Development Kit. */\nexport const VERSION = new Version('7.2.2');\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAWA,AAAA,MAAa,OAAO,GAAG,IAAI,OAAO,CAAC,mBAAmB,CAAC;;;;;;;;;;;;;;"}
@@ -8,11 +8,11 @@
8
8
  import { InjectionToken, Injectable, NgZone, Inject, NgModule, ContentChildren, ElementRef, EventEmitter, forwardRef, Input, Output, Optional, Directive, ChangeDetectorRef, SkipSelf, ContentChild, ViewContainerRef, TemplateRef, defineInjectable, inject } from '@angular/core';
9
9
  import { DOCUMENT } from '@angular/common';
10
10
  import { normalizePassiveListenerOptions } from '@angular/cdk/platform';
11
- import { Subject, Subscription, Observable } from 'rxjs';
12
- import { coerceBooleanProperty, coerceArray } from '@angular/cdk/coercion';
11
+ import { Subject, Subscription, Observable, merge } from 'rxjs';
12
+ import { coerceBooleanProperty, coerceElement, coerceArray } from '@angular/cdk/coercion';
13
13
  import { Directionality } from '@angular/cdk/bidi';
14
14
  import { ViewportRuler } from '@angular/cdk/scrolling';
15
- import { startWith, take, map } from 'rxjs/operators';
15
+ import { startWith, take, map, takeUntil, switchMap, tap } from 'rxjs/operators';
16
16
 
17
17
  /**
18
18
  * @fileoverview added by tsickle
@@ -408,6 +408,10 @@ class CdkDragHandle {
408
408
  */
409
409
  constructor(element, parentDrag) {
410
410
  this.element = element;
411
+ /**
412
+ * Emits when the state of the handle has changed.
413
+ */
414
+ this._stateChanges = new Subject();
411
415
  this._disabled = false;
412
416
  this._parentDrag = parentDrag;
413
417
  toggleNativeDragInteractions(element.nativeElement, false);
@@ -423,6 +427,13 @@ class CdkDragHandle {
423
427
  */
424
428
  set disabled(value) {
425
429
  this._disabled = coerceBooleanProperty(value);
430
+ this._stateChanges.next(this);
431
+ }
432
+ /**
433
+ * @return {?}
434
+ */
435
+ ngOnDestroy() {
436
+ this._stateChanges.complete();
426
437
  }
427
438
  }
428
439
  CdkDragHandle.decorators = [
@@ -645,6 +656,10 @@ class DragRef {
645
656
  * Elements that can be used to drag the draggable item.
646
657
  */
647
658
  this._handles = [];
659
+ /**
660
+ * Registered handles that are currently disabled.
661
+ */
662
+ this._disabledHandles = new Set();
648
663
  this._disabled = false;
649
664
  /**
650
665
  * Emits as the drag sequence is being prepared.
@@ -678,7 +693,7 @@ class DragRef {
678
693
  * Emits as the user is dragging the item. Use with caution,
679
694
  * because this event will fire for every pixel that the user has dragged.
680
695
  */
681
- this.moved = Observable.create((observer) => {
696
+ this.moved = new Observable((observer) => {
682
697
  /** @type {?} */
683
698
  const subscription = this._moveEvents.subscribe(observer);
684
699
  this._moveEventSubscriptions++;
@@ -696,14 +711,12 @@ class DragRef {
696
711
  if (this._handles.length) {
697
712
  /** @type {?} */
698
713
  const targetHandle = this._handles.find(handle => {
699
- /** @type {?} */
700
- const element = handle.element.nativeElement;
701
714
  /** @type {?} */
702
715
  const target = event.target;
703
- return !!target && (target === element || element.contains((/** @type {?} */ (target))));
716
+ return !!target && (target === handle || handle.contains((/** @type {?} */ (target))));
704
717
  });
705
- if (targetHandle && !targetHandle.disabled && !this.disabled) {
706
- this._initializeDragSequence(targetHandle.element.nativeElement, event);
718
+ if (targetHandle && !this._disabledHandles.has(targetHandle) && !this.disabled) {
719
+ this._initializeDragSequence(targetHandle, event);
707
720
  }
708
721
  }
709
722
  else if (!this.disabled) {
@@ -756,9 +769,11 @@ class DragRef {
756
769
  constrainedPointerPosition.y - this._pickupPositionOnPage.y + this._passiveTransform.y;
757
770
  /** @type {?} */
758
771
  const transform = getTransform(activeTransform.x, activeTransform.y);
759
- // Preserve the previous `transform` value, if there was one.
772
+ // Preserve the previous `transform` value, if there was one. Note that we apply our own
773
+ // transform before the user's, because things like rotation can affect which direction
774
+ // the element will be translated towards.
760
775
  this._rootElement.style.transform = this._initialTransform ?
761
- this._initialTransform + ' ' + transform : transform;
776
+ transform + ' ' + this._initialTransform : transform;
762
777
  // Apply transform as attribute if dragging and svg element to work for IE
763
778
  if (typeof SVGElement !== 'undefined' && this._rootElement instanceof SVGElement) {
764
779
  /** @type {?} */
@@ -860,9 +875,8 @@ class DragRef {
860
875
  * @return {THIS}
861
876
  */
862
877
  withHandles(handles) {
863
- // TODO(crisbeto): have this accept HTMLElement[] | ElementRef<HTMLElement>[]
864
- (/** @type {?} */ (this))._handles = handles;
865
- handles.forEach(handle => toggleNativeDragInteractions(handle.element.nativeElement, false));
878
+ (/** @type {?} */ (this))._handles = handles.map(handle => coerceElement(handle));
879
+ (/** @type {?} */ (this))._handles.forEach(handle => toggleNativeDragInteractions(handle, false));
866
880
  (/** @type {?} */ (this))._toggleNativeDragInteractions();
867
881
  return (/** @type {?} */ (this));
868
882
  }
@@ -870,24 +884,24 @@ class DragRef {
870
884
  * Registers the template that should be used for the drag preview.
871
885
  * @template THIS
872
886
  * @this {THIS}
873
- * @param {?} template
887
+ * @param {?} template Template that from which to stamp out the preview.
888
+ * @param {?=} context Variables to add to the template's context.
874
889
  * @return {THIS}
875
890
  */
876
- withPreviewTemplate(template) {
877
- // TODO(crisbeto): have this accept a TemplateRef
878
- (/** @type {?} */ (this))._previewTemplate = template;
891
+ withPreviewTemplate(template, context) {
892
+ (/** @type {?} */ (this))._previewTemplate = { template, context };
879
893
  return (/** @type {?} */ (this));
880
894
  }
881
895
  /**
882
896
  * Registers the template that should be used for the drag placeholder.
883
897
  * @template THIS
884
898
  * @this {THIS}
885
- * @param {?} template
899
+ * @param {?} template Template that from which to stamp out the placeholder.
900
+ * @param {?=} context Variables to add to the template's context.
886
901
  * @return {THIS}
887
902
  */
888
- withPlaceholderTemplate(template) {
889
- // TODO(crisbeto): have this accept a TemplateRef
890
- (/** @type {?} */ (this))._placeholderTemplate = template;
903
+ withPlaceholderTemplate(template, context) {
904
+ (/** @type {?} */ (this))._placeholderTemplate = { template, context };
891
905
  return (/** @type {?} */ (this));
892
906
  }
893
907
  /**
@@ -901,13 +915,14 @@ class DragRef {
901
915
  */
902
916
  withRootElement(rootElement) {
903
917
  /** @type {?} */
904
- const element = rootElement instanceof ElementRef ? rootElement.nativeElement : rootElement;
918
+ const element = coerceElement(rootElement);
905
919
  if (element !== (/** @type {?} */ (this))._rootElement) {
906
920
  if ((/** @type {?} */ (this))._rootElement) {
907
921
  (/** @type {?} */ (this))._removeRootElementListeners((/** @type {?} */ (this))._rootElement);
908
922
  }
909
923
  element.addEventListener('mousedown', (/** @type {?} */ (this))._pointerDown, activeEventListenerOptions);
910
924
  element.addEventListener('touchstart', (/** @type {?} */ (this))._pointerDown, passiveEventListenerOptions);
925
+ (/** @type {?} */ (this))._initialTransform = undefined;
911
926
  (/** @type {?} */ (this))._rootElement = element;
912
927
  }
913
928
  return (/** @type {?} */ (this));
@@ -920,8 +935,7 @@ class DragRef {
920
935
  * @return {THIS}
921
936
  */
922
937
  withBoundaryElement(boundaryElement) {
923
- (/** @type {?} */ (this))._boundaryElement = boundaryElement instanceof ElementRef ?
924
- boundaryElement.nativeElement : boundaryElement;
938
+ (/** @type {?} */ (this))._boundaryElement = boundaryElement ? coerceElement(boundaryElement) : null;
925
939
  return (/** @type {?} */ (this));
926
940
  }
927
941
  /**
@@ -950,6 +964,7 @@ class DragRef {
950
964
  this.dropped.complete();
951
965
  this._moveEvents.complete();
952
966
  this._handles = [];
967
+ this._disabledHandles.clear();
953
968
  this._boundaryElement = this._rootElement = this._placeholderTemplate =
954
969
  this._previewTemplate = this._nextSibling = (/** @type {?} */ (null));
955
970
  }
@@ -965,10 +980,28 @@ class DragRef {
965
980
  * @return {?}
966
981
  */
967
982
  reset() {
968
- this._rootElement.style.transform = '';
983
+ this._rootElement.style.transform = this._initialTransform || '';
969
984
  this._activeTransform = { x: 0, y: 0 };
970
985
  this._passiveTransform = { x: 0, y: 0 };
971
986
  }
987
+ /**
988
+ * Sets a handle as disabled. While a handle is disabled, it'll capture and interrupt dragging.
989
+ * @param {?} handle Handle element that should be disabled.
990
+ * @return {?}
991
+ */
992
+ disableHandle(handle) {
993
+ if (this._handles.indexOf(handle) > -1) {
994
+ this._disabledHandles.add(handle);
995
+ }
996
+ }
997
+ /**
998
+ * Enables a handle, if it has been disabled.
999
+ * @param {?} handle Handle element to be enabled.
1000
+ * @return {?}
1001
+ */
1002
+ enableHandle(handle) {
1003
+ this._disabledHandles.delete(handle);
1004
+ }
972
1005
  /**
973
1006
  * Unsubscribes from the global subscriptions.
974
1007
  * @private
@@ -1097,7 +1130,8 @@ class DragRef {
1097
1130
  }
1098
1131
  // If we have a custom preview template, the element won't be visible anyway so we avoid the
1099
1132
  // extra `getBoundingClientRect` calls and just move the preview next to the cursor.
1100
- this._pickupPositionInElement = this._previewTemplate ? { x: 0, y: 0 } :
1133
+ this._pickupPositionInElement = this._previewTemplate && this._previewTemplate.template ?
1134
+ { x: 0, y: 0 } :
1101
1135
  this._getPointerPositionInElement(referenceElement, event);
1102
1136
  /** @type {?} */
1103
1137
  const pointerPosition = this._pickupPositionOnPage = this._getPointerPositionOnPage(event);
@@ -1158,7 +1192,8 @@ class DragRef {
1158
1192
  _updateActiveDropContainer({ x, y }) {
1159
1193
  // Drop container that draggable has been moved into.
1160
1194
  /** @type {?} */
1161
- let newContainer = (/** @type {?} */ (this.dropContainer))._getSiblingContainerFromPosition(this, x, y);
1195
+ let newContainer = (/** @type {?} */ (this.dropContainer))._getSiblingContainerFromPosition(this, x, y) ||
1196
+ this._initialContainer._getSiblingContainerFromPosition(this, x, y);
1162
1197
  // If we couldn't find a new container to move the item into, and the item has left it's
1163
1198
  // initial container, check whether the it's over the initial container. This handles the
1164
1199
  // case where two containers are connected one way and the user tries to undo dragging an
@@ -1167,7 +1202,7 @@ class DragRef {
1167
1202
  this._initialContainer._isOverContainer(x, y)) {
1168
1203
  newContainer = this._initialContainer;
1169
1204
  }
1170
- if (newContainer) {
1205
+ if (newContainer && newContainer !== this.dropContainer) {
1171
1206
  this._ngZone.run(() => {
1172
1207
  // Notify the old container that the item has left.
1173
1208
  this.exited.next({ item: this, container: (/** @type {?} */ (this.dropContainer)) });
@@ -1189,11 +1224,13 @@ class DragRef {
1189
1224
  * @return {?}
1190
1225
  */
1191
1226
  _createPreviewElement() {
1227
+ /** @type {?} */
1228
+ const previewTemplate = this._previewTemplate;
1192
1229
  /** @type {?} */
1193
1230
  let preview;
1194
- if (this._previewTemplate) {
1231
+ if (previewTemplate && previewTemplate.template) {
1195
1232
  /** @type {?} */
1196
- const viewRef = this._viewContainerRef.createEmbeddedView(this._previewTemplate.templateRef, this._previewTemplate.data);
1233
+ const viewRef = this._viewContainerRef.createEmbeddedView(previewTemplate.template, previewTemplate.context);
1197
1234
  preview = viewRef.rootNodes[0];
1198
1235
  this._previewRef = viewRef;
1199
1236
  preview.style.transform =
@@ -1273,10 +1310,12 @@ class DragRef {
1273
1310
  * @return {?}
1274
1311
  */
1275
1312
  _createPlaceholderElement() {
1313
+ /** @type {?} */
1314
+ const placeholderTemplate = this._placeholderTemplate;
1276
1315
  /** @type {?} */
1277
1316
  let placeholder;
1278
- if (this._placeholderTemplate) {
1279
- this._placeholderRef = this._viewContainerRef.createEmbeddedView(this._placeholderTemplate.templateRef, this._placeholderTemplate.data);
1317
+ if (placeholderTemplate && placeholderTemplate.template) {
1318
+ this._placeholderRef = this._viewContainerRef.createEmbeddedView(placeholderTemplate.template, placeholderTemplate.context);
1280
1319
  placeholder = this._placeholderRef.rootNodes[0];
1281
1320
  }
1282
1321
  else {
@@ -1516,10 +1555,7 @@ class CdkDrag {
1516
1555
  this._dragDropRegistry = _dragDropRegistry;
1517
1556
  this._config = _config;
1518
1557
  this._dir = _dir;
1519
- /**
1520
- * Subscription to the stream that initializes the root element.
1521
- */
1522
- this._rootElementInitSubscription = Subscription.EMPTY;
1558
+ this._destroyed = new Subject();
1523
1559
  this._disabled = false;
1524
1560
  /**
1525
1561
  * Emits when the user starts dragging the item.
@@ -1549,7 +1585,7 @@ class CdkDrag {
1549
1585
  * Emits as the user is dragging the item. Use with caution,
1550
1586
  * because this event will fire for every pixel that the user has dragged.
1551
1587
  */
1552
- this.moved = Observable.create((observer) => {
1588
+ this.moved = new Observable((observer) => {
1553
1589
  /** @type {?} */
1554
1590
  const subscription = this._dragRef.moved.pipe(map(movedEvent => ({
1555
1591
  source: this,
@@ -1564,16 +1600,7 @@ class CdkDrag {
1564
1600
  /** @type {?} */
1565
1601
  const ref = this._dragRef = new DragRef(element, this._document, this._ngZone, this._viewContainerRef, this._viewportRuler, this._dragDropRegistry, this._config, this.dropContainer ? this.dropContainer._dropListRef : undefined, this._dir);
1566
1602
  ref.data = this;
1567
- ref.beforeStarted.subscribe(() => {
1568
- if (!ref.isDragging()) {
1569
- ref.disabled = this.disabled;
1570
- ref.lockAxis = this.lockAxis;
1571
- ref
1572
- .withBoundaryElement(this._getBoundaryElement())
1573
- .withPlaceholderTemplate(this._placeholderTemplate)
1574
- .withPreviewTemplate(this._previewTemplate);
1575
- }
1576
- });
1603
+ this._syncInputs(ref);
1577
1604
  this._proxyEvents(ref);
1578
1605
  }
1579
1606
  /**
@@ -1621,14 +1648,30 @@ class CdkDrag {
1621
1648
  // element to be in the proper place in the DOM. This is mostly relevant
1622
1649
  // for draggable elements inside portals since they get stamped out in
1623
1650
  // their original DOM position and then they get transferred to the portal.
1624
- this._rootElementInitSubscription = this._ngZone.onStable.asObservable()
1625
- .pipe(take(1))
1651
+ this._ngZone.onStable.asObservable()
1652
+ .pipe(take(1), takeUntil(this._destroyed))
1626
1653
  .subscribe(() => {
1627
1654
  this._updateRootElement();
1628
- this._handles.changes
1629
- .pipe(startWith(this._handles))
1630
- .subscribe((handleList) => {
1631
- this._dragRef.withHandles(handleList.filter(handle => handle._parentDrag === this));
1655
+ // Listen for any newly-added handles.
1656
+ this._handles.changes.pipe(startWith(this._handles),
1657
+ // Sync the new handles with the DragRef.
1658
+ tap((handles) => {
1659
+ /** @type {?} */
1660
+ const childHandleElements = handles
1661
+ .filter(handle => handle._parentDrag === this)
1662
+ .map(handle => handle.element);
1663
+ this._dragRef.withHandles(childHandleElements);
1664
+ }),
1665
+ // Listen if the state of any of the handles changes.
1666
+ switchMap((handles) => {
1667
+ return merge(...handles.map(item => item._stateChanges));
1668
+ }), takeUntil(this._destroyed)).subscribe(handleInstance => {
1669
+ // Enabled/disable the handle that changed in the DragRef.
1670
+ /** @type {?} */
1671
+ const dragRef = this._dragRef;
1672
+ /** @type {?} */
1673
+ const handle = handleInstance.element.nativeElement;
1674
+ handleInstance.disabled ? dragRef.disableHandle(handle) : dragRef.enableHandle(handle);
1632
1675
  });
1633
1676
  });
1634
1677
  }
@@ -1649,7 +1692,8 @@ class CdkDrag {
1649
1692
  * @return {?}
1650
1693
  */
1651
1694
  ngOnDestroy() {
1652
- this._rootElementInitSubscription.unsubscribe();
1695
+ this._destroyed.next();
1696
+ this._destroyed.complete();
1653
1697
  this._dragRef.dispose();
1654
1698
  }
1655
1699
  /**
@@ -1679,6 +1723,26 @@ class CdkDrag {
1679
1723
  const selector = this.boundaryElementSelector;
1680
1724
  return selector ? getClosestMatchingAncestor(this.element.nativeElement, selector) : null;
1681
1725
  }
1726
+ /**
1727
+ * Syncs the inputs of the CdkDrag with the options of the underlying DragRef.
1728
+ * @private
1729
+ * @param {?} ref
1730
+ * @return {?}
1731
+ */
1732
+ _syncInputs(ref) {
1733
+ ref.beforeStarted.subscribe(() => {
1734
+ if (!ref.isDragging()) {
1735
+ const { _placeholderTemplate: placeholder, _previewTemplate: preview } = this;
1736
+ ref.disabled = this.disabled;
1737
+ ref.lockAxis = this.lockAxis;
1738
+ ref.withBoundaryElement(this._getBoundaryElement());
1739
+ placeholder ? ref.withPlaceholderTemplate(placeholder.templateRef, placeholder.data) :
1740
+ ref.withPlaceholderTemplate(null);
1741
+ preview ? ref.withPreviewTemplate(preview.templateRef, preview.data) :
1742
+ ref.withPreviewTemplate(null);
1743
+ }
1744
+ });
1745
+ }
1682
1746
  /**
1683
1747
  * Proxies the events from a DragRef to events that
1684
1748
  * match the interfaces of the CdkDrag outputs.
@@ -1900,23 +1964,26 @@ class DropListRef {
1900
1964
  */
1901
1965
  this._isDragging = false;
1902
1966
  /**
1903
- * Cache of the dimensions of all the items and the sibling containers.
1967
+ * Cache of the dimensions of all the items inside the container.
1904
1968
  */
1905
- this._positionCache = { items: [], siblings: [], self: (/** @type {?} */ ({})) };
1969
+ this._itemPositions = [];
1906
1970
  /**
1907
1971
  * Keeps track of the item that was last swapped with the dragged item, as
1908
1972
  * well as what direction the pointer was moving in when the swap occured.
1909
1973
  */
1910
1974
  this._previousSwap = { drag: (/** @type {?} */ (null)), delta: 0 };
1975
+ /**
1976
+ * Drop lists that are connected to the current one.
1977
+ */
1911
1978
  this._siblings = [];
1912
1979
  /**
1913
1980
  * Direction in which the list is oriented.
1914
1981
  */
1915
1982
  this._orientation = 'vertical';
1916
1983
  /**
1917
- * Amount of connected siblings that currently have a dragged item.
1984
+ * Connected siblings that currently have a dragged item.
1918
1985
  */
1919
- this._activeSiblings = 0;
1986
+ this._activeSiblings = new Set();
1920
1987
  _dragDropRegistry.registerDropContainer(this);
1921
1988
  this._document = _document;
1922
1989
  }
@@ -1930,6 +1997,7 @@ class DropListRef {
1930
1997
  this.exited.complete();
1931
1998
  this.dropped.complete();
1932
1999
  this.sorted.complete();
2000
+ this._activeSiblings.clear();
1933
2001
  this._dragDropRegistry.removeDropContainer(this);
1934
2002
  }
1935
2003
  /**
@@ -1947,8 +2015,9 @@ class DropListRef {
1947
2015
  this.beforeStarted.next();
1948
2016
  this._isDragging = true;
1949
2017
  this._activeDraggables = this._draggables.slice();
1950
- this._cachePositions();
1951
- this._positionCache.siblings.forEach(sibling => sibling.drop._toggleIsReceiving(true));
2018
+ this._cacheOwnPosition();
2019
+ this._cacheItemPositions();
2020
+ this._siblings.forEach(sibling => sibling._startReceiving(this));
1952
2021
  }
1953
2022
  /**
1954
2023
  * Emits an event to indicate that the user moved an item into the container.
@@ -1991,7 +2060,7 @@ class DropListRef {
1991
2060
  placeholder.style.transform = '';
1992
2061
  // Note that the positions were already cached when we called `start` above,
1993
2062
  // but we need to refresh them since the amount of items has changed.
1994
- this._cachePositions();
2063
+ this._cacheItemPositions();
1995
2064
  }
1996
2065
  /**
1997
2066
  * Removes an item from the container after it was dragged into another container by the user.
@@ -2070,7 +2139,7 @@ class DropListRef {
2070
2139
  // we need to invert the array when determining the index.
2071
2140
  /** @type {?} */
2072
2141
  const items = this._orientation === 'horizontal' && this._dir && this._dir.value === 'rtl' ?
2073
- this._positionCache.items.slice().reverse() : this._positionCache.items;
2142
+ this._itemPositions.slice().reverse() : this._itemPositions;
2074
2143
  return findIndex(items, currentItem => currentItem.drag === item);
2075
2144
  }
2076
2145
  /**
@@ -2079,7 +2148,7 @@ class DropListRef {
2079
2148
  * @return {?}
2080
2149
  */
2081
2150
  isReceiving() {
2082
- return this._activeSiblings > 0;
2151
+ return this._activeSiblings.size > 0;
2083
2152
  }
2084
2153
  /**
2085
2154
  * Sorts an item inside the container based on its position.
@@ -2095,7 +2164,7 @@ class DropListRef {
2095
2164
  return;
2096
2165
  }
2097
2166
  /** @type {?} */
2098
- const siblings = this._positionCache.items;
2167
+ const siblings = this._itemPositions;
2099
2168
  /** @type {?} */
2100
2169
  const newIndex = this._getItemIndexFromPointerPosition(item, pointerX, pointerY, pointerDelta);
2101
2170
  if (newIndex === -1 && siblings.length > 0) {
@@ -2163,17 +2232,23 @@ class DropListRef {
2163
2232
  }
2164
2233
  });
2165
2234
  }
2235
+ /**
2236
+ * Caches the position of the drop list.
2237
+ * @private
2238
+ * @return {?}
2239
+ */
2240
+ _cacheOwnPosition() {
2241
+ this._clientRect = this.element.nativeElement.getBoundingClientRect();
2242
+ }
2166
2243
  /**
2167
2244
  * Refreshes the position cache of the items and sibling containers.
2168
2245
  * @private
2169
2246
  * @return {?}
2170
2247
  */
2171
- _cachePositions() {
2248
+ _cacheItemPositions() {
2172
2249
  /** @type {?} */
2173
2250
  const isHorizontal = this._orientation === 'horizontal';
2174
- this._positionCache.self = this.element.nativeElement.getBoundingClientRect();
2175
- this._positionCache.items = this._activeDraggables
2176
- .map(drag => {
2251
+ this._itemPositions = this._activeDraggables.map(drag => {
2177
2252
  /** @type {?} */
2178
2253
  const elementToMeasure = this._dragDropRegistry.isDragging(drag) ?
2179
2254
  // If the element is being dragged, we have to measure the
@@ -2198,24 +2273,10 @@ class DropListRef {
2198
2273
  height: clientRect.height
2199
2274
  }
2200
2275
  };
2201
- })
2202
- .sort((a, b) => {
2276
+ }).sort((a, b) => {
2203
2277
  return isHorizontal ? a.clientRect.left - b.clientRect.left :
2204
2278
  a.clientRect.top - b.clientRect.top;
2205
2279
  });
2206
- this._positionCache.siblings = this._siblings.map(drop => ({
2207
- drop,
2208
- clientRect: drop.element.nativeElement.getBoundingClientRect()
2209
- }));
2210
- }
2211
- /**
2212
- * Toggles whether the list can receive the item that is currently being dragged.
2213
- * Usually called by a sibling that initiated the dragging.
2214
- * @param {?} isDragging
2215
- * @return {?}
2216
- */
2217
- _toggleIsReceiving(isDragging) {
2218
- this._activeSiblings = Math.max(0, this._activeSiblings + (isDragging ? 1 : -1));
2219
2280
  }
2220
2281
  /**
2221
2282
  * Resets the container to its initial state.
@@ -2226,10 +2287,9 @@ class DropListRef {
2226
2287
  this._isDragging = false;
2227
2288
  // TODO(crisbeto): may have to wait for the animations to finish.
2228
2289
  this._activeDraggables.forEach(item => item.getRootElement().style.transform = '');
2229
- this._positionCache.siblings.forEach(sibling => sibling.drop._toggleIsReceiving(false));
2290
+ this._siblings.forEach(sibling => sibling._stopReceiving(this));
2230
2291
  this._activeDraggables = [];
2231
- this._positionCache.items = [];
2232
- this._positionCache.siblings = [];
2292
+ this._itemPositions = [];
2233
2293
  this._previousSwap.drag = null;
2234
2294
  this._previousSwap.delta = 0;
2235
2295
  }
@@ -2276,7 +2336,7 @@ class DropListRef {
2276
2336
  * @return {?}
2277
2337
  */
2278
2338
  _isPointerNearDropContainer(pointerX, pointerY) {
2279
- const { top, right, bottom, left, width, height } = this._positionCache.self;
2339
+ const { top, right, bottom, left, width, height } = this._clientRect;
2280
2340
  /** @type {?} */
2281
2341
  const xThreshold = width * DROP_PROXIMITY_THRESHOLD;
2282
2342
  /** @type {?} */
@@ -2317,7 +2377,7 @@ class DropListRef {
2317
2377
  _getItemIndexFromPointerPosition(item, pointerX, pointerY, delta) {
2318
2378
  /** @type {?} */
2319
2379
  const isHorizontal = this._orientation === 'horizontal';
2320
- return findIndex(this._positionCache.items, ({ drag, clientRect }, _, array) => {
2380
+ return findIndex(this._itemPositions, ({ drag, clientRect }, _, array) => {
2321
2381
  if (drag === item) {
2322
2382
  // If there's only one item left in the container, it must be
2323
2383
  // the dragged item itself so we use it as a reference.
@@ -2346,7 +2406,7 @@ class DropListRef {
2346
2406
  * @return {?}
2347
2407
  */
2348
2408
  _isOverContainer(x, y) {
2349
- return isInsideClientRect(this._positionCache.self, x, y);
2409
+ return isInsideClientRect(this._clientRect, x, y);
2350
2410
  }
2351
2411
  /**
2352
2412
  * Figures out whether an item should be moved into a sibling
@@ -2357,34 +2417,56 @@ class DropListRef {
2357
2417
  * @return {?}
2358
2418
  */
2359
2419
  _getSiblingContainerFromPosition(item, x, y) {
2360
- /** @type {?} */
2361
- const results = this._positionCache.siblings.filter(sibling => {
2362
- return isInsideClientRect(sibling.clientRect, x, y);
2363
- });
2364
- // No drop containers are intersecting with the pointer.
2365
- if (!results.length) {
2366
- return null;
2420
+ return this._siblings.find(sibling => sibling._canReceive(item, x, y));
2421
+ }
2422
+ /**
2423
+ * Checks whether the drop list can receive the passed-in item.
2424
+ * @param {?} item Item that is being dragged into the list.
2425
+ * @param {?} x Position of the item along the X axis.
2426
+ * @param {?} y Position of the item along the Y axis.
2427
+ * @return {?}
2428
+ */
2429
+ _canReceive(item, x, y) {
2430
+ if (!this.enterPredicate(item, this) || !isInsideClientRect(this._clientRect, x, y)) {
2431
+ return false;
2367
2432
  }
2368
2433
  /** @type {?} */
2369
2434
  const elementFromPoint = this._document.elementFromPoint(x, y);
2370
2435
  // If there's no element at the pointer position, then
2371
2436
  // the client rect is probably scrolled out of the view.
2372
2437
  if (!elementFromPoint) {
2373
- return null;
2438
+ return false;
2374
2439
  }
2440
+ /** @type {?} */
2441
+ const element = this.element.nativeElement;
2375
2442
  // The `ClientRect`, that we're using to find the container over which the user is
2376
2443
  // hovering, doesn't give us any information on whether the element has been scrolled
2377
2444
  // out of the view or whether it's overlapping with other containers. This means that
2378
2445
  // we could end up transferring the item into a container that's invisible or is positioned
2379
2446
  // below another one. We use the result from `elementFromPoint` to get the top-most element
2380
2447
  // at the pointer position and to find whether it's one of the intersecting drop containers.
2448
+ return elementFromPoint === element || element.contains(elementFromPoint);
2449
+ }
2450
+ /**
2451
+ * Called by one of the connected drop lists when a dragging sequence has started.
2452
+ * @param {?} sibling Sibling in which dragging has started.
2453
+ * @return {?}
2454
+ */
2455
+ _startReceiving(sibling) {
2381
2456
  /** @type {?} */
2382
- const result = results.find(sibling => {
2383
- /** @type {?} */
2384
- const element = sibling.drop.element.nativeElement;
2385
- return element === elementFromPoint || element.contains(elementFromPoint);
2386
- });
2387
- return result && result.drop.enterPredicate(item, result.drop) ? result.drop : null;
2457
+ const activeSiblings = this._activeSiblings;
2458
+ if (!activeSiblings.has(sibling)) {
2459
+ activeSiblings.add(sibling);
2460
+ this._cacheOwnPosition();
2461
+ }
2462
+ }
2463
+ /**
2464
+ * Called by a connected drop list when dragging has stopped.
2465
+ * @param {?} sibling Sibling whose dragging has stopped.
2466
+ * @return {?}
2467
+ */
2468
+ _stopReceiving(sibling) {
2469
+ this._activeSiblings.delete(sibling);
2388
2470
  }
2389
2471
  }
2390
2472
  /**
@@ -2506,7 +2588,7 @@ class CdkDropList {
2506
2588
  return this.enterPredicate(drag.data, drop.data);
2507
2589
  };
2508
2590
  this._syncInputs(ref);
2509
- this._proxyEvents(ref);
2591
+ this._handleEvents(ref);
2510
2592
  CdkDropList._dropLists.push(this);
2511
2593
  if (_group) {
2512
2594
  _group._items.add(this);
@@ -2646,13 +2728,12 @@ class CdkDropList {
2646
2728
  });
2647
2729
  }
2648
2730
  /**
2649
- * Proxies the events from a DropListRef to events that
2650
- * match the interfaces of the CdkDropList outputs.
2731
+ * Handles events from the underlying DropListRef.
2651
2732
  * @private
2652
2733
  * @param {?} ref
2653
2734
  * @return {?}
2654
2735
  */
2655
- _proxyEvents(ref) {
2736
+ _handleEvents(ref) {
2656
2737
  ref.beforeStarted.subscribe(() => {
2657
2738
  this._changeDetectorRef.markForCheck();
2658
2739
  });
@@ -2685,6 +2766,9 @@ class CdkDropList {
2685
2766
  item: event.item.data,
2686
2767
  isPointerOverContainer: event.isPointerOverContainer
2687
2768
  });
2769
+ // Mark for check since all of these events run outside of change
2770
+ // detection and we're not guaranteed for something else to have triggered it.
2771
+ this._changeDetectorRef.markForCheck();
2688
2772
  });
2689
2773
  }
2690
2774
  }