@angular/cdk 10.0.2 → 10.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/a11y/aria-describer/aria-describer.d.ts +10 -1
  2. package/a11y/index.metadata.json +1 -1
  3. package/a11y/interactivity-checker/interactivity-checker.d.ts +11 -1
  4. package/a11y/key-manager/list-key-manager.d.ts +6 -0
  5. package/accordion/accordion.d.ts +7 -1
  6. package/accordion/index.d.ts +1 -0
  7. package/accordion/index.metadata.json +1 -1
  8. package/bundles/cdk-a11y.umd.js +63 -11
  9. package/bundles/cdk-a11y.umd.js.map +1 -1
  10. package/bundles/cdk-a11y.umd.min.js +11 -11
  11. package/bundles/cdk-a11y.umd.min.js.map +1 -1
  12. package/bundles/cdk-accordion.umd.js +12 -4
  13. package/bundles/cdk-accordion.umd.js.map +1 -1
  14. package/bundles/cdk-accordion.umd.min.js +2 -2
  15. package/bundles/cdk-accordion.umd.min.js.map +1 -1
  16. package/bundles/cdk-drag-drop.umd.js +640 -599
  17. package/bundles/cdk-drag-drop.umd.js.map +1 -1
  18. package/bundles/cdk-drag-drop.umd.min.js +8 -16
  19. package/bundles/cdk-drag-drop.umd.min.js.map +1 -1
  20. package/bundles/cdk-overlay.umd.js +199 -42
  21. package/bundles/cdk-overlay.umd.js.map +1 -1
  22. package/bundles/cdk-overlay.umd.min.js +11 -18
  23. package/bundles/cdk-overlay.umd.min.js.map +1 -1
  24. package/bundles/cdk-platform.umd.min.js +1 -1
  25. package/bundles/cdk-platform.umd.min.js.map +1 -1
  26. package/bundles/cdk-scrolling.umd.js +9 -1
  27. package/bundles/cdk-scrolling.umd.js.map +1 -1
  28. package/bundles/cdk-scrolling.umd.min.js +7 -0
  29. package/bundles/cdk-scrolling.umd.min.js.map +1 -1
  30. package/bundles/cdk-testing-protractor.umd.min.js +1 -1
  31. package/bundles/cdk-testing-protractor.umd.min.js.map +1 -1
  32. package/bundles/cdk-testing-testbed.umd.min.js +8 -8
  33. package/bundles/cdk-testing-testbed.umd.min.js.map +1 -1
  34. package/bundles/cdk-testing.umd.js +32 -0
  35. package/bundles/cdk-testing.umd.js.map +1 -1
  36. package/bundles/cdk-testing.umd.min.js +5 -5
  37. package/bundles/cdk-testing.umd.min.js.map +1 -1
  38. package/bundles/cdk-tree.umd.js +6 -2
  39. package/bundles/cdk-tree.umd.js.map +1 -1
  40. package/bundles/cdk-tree.umd.min.js +3 -3
  41. package/bundles/cdk-tree.umd.min.js.map +1 -1
  42. package/bundles/cdk.umd.js +1 -1
  43. package/bundles/cdk.umd.js.map +1 -1
  44. package/bundles/cdk.umd.min.js +1 -1
  45. package/bundles/cdk.umd.min.js.map +1 -1
  46. package/drag-drop/directives/drag-handle.d.ts +7 -1
  47. package/drag-drop/directives/drag-placeholder.d.ts +7 -1
  48. package/drag-drop/directives/drag-preview.d.ts +7 -1
  49. package/drag-drop/directives/drag.d.ts +3 -7
  50. package/drag-drop/directives/drop-list-group.d.ts +7 -1
  51. package/drag-drop/directives/drop-list.d.ts +7 -1
  52. package/drag-drop/index.d.ts +2 -2
  53. package/drag-drop/index.metadata.json +1 -1
  54. package/esm2015/a11y/aria-describer/aria-describer.js +20 -6
  55. package/esm2015/a11y/interactivity-checker/interactivity-checker.js +16 -3
  56. package/esm2015/a11y/key-manager/list-key-manager.js +27 -2
  57. package/esm2015/accordion/accordion-item.js +7 -7
  58. package/esm2015/accordion/accordion.js +9 -2
  59. package/esm2015/accordion/index.js +2 -1
  60. package/esm2015/drag-drop/directives/drag-handle.js +11 -4
  61. package/esm2015/drag-drop/directives/drag-placeholder.js +10 -3
  62. package/esm2015/drag-drop/directives/drag-preview.js +10 -3
  63. package/esm2015/drag-drop/directives/drag.js +19 -15
  64. package/esm2015/drag-drop/directives/drop-list-group.js +9 -2
  65. package/esm2015/drag-drop/directives/drop-list.js +11 -6
  66. package/esm2015/drag-drop/index.js +3 -2
  67. package/esm2015/layout/breakpoints-observer.js +1 -1
  68. package/esm2015/overlay/dispatchers/base-overlay-dispatcher.js +51 -0
  69. package/esm2015/overlay/dispatchers/index.js +10 -0
  70. package/esm2015/overlay/dispatchers/overlay-keyboard-dispatcher.js +79 -0
  71. package/esm2015/overlay/dispatchers/overlay-outside-click-dispatcher.js +94 -0
  72. package/esm2015/overlay/index.js +5 -4
  73. package/esm2015/overlay/overlay-config.js +5 -1
  74. package/esm2015/overlay/overlay-directives.js +17 -7
  75. package/esm2015/overlay/overlay-module.js +2 -2
  76. package/esm2015/overlay/overlay-ref.js +24 -2
  77. package/esm2015/overlay/overlay-reference.js +1 -1
  78. package/esm2015/overlay/overlay.js +10 -5
  79. package/esm2015/overlay/position/overlay-position-builder.js +1 -1
  80. package/esm2015/overlay/public-api.js +2 -2
  81. package/esm2015/scrolling/public-api.js +2 -1
  82. package/esm2015/scrolling/virtual-for-of.js +1 -1
  83. package/esm2015/scrolling/virtual-scroll-repeater.js +8 -0
  84. package/esm2015/scrolling/virtual-scroll-viewport.js +2 -2
  85. package/esm2015/testing/component-harness.js +19 -1
  86. package/esm2015/testing/harness-environment.js +7 -1
  87. package/esm2015/tree/control/nested-tree-control.js +7 -3
  88. package/esm2015/version.js +1 -1
  89. package/fesm2015/a11y.js +60 -10
  90. package/fesm2015/a11y.js.map +1 -1
  91. package/fesm2015/accordion.js +13 -6
  92. package/fesm2015/accordion.js.map +1 -1
  93. package/fesm2015/cdk.js +1 -1
  94. package/fesm2015/cdk.js.map +1 -1
  95. package/fesm2015/drag-drop.js +607 -570
  96. package/fesm2015/drag-drop.js.map +1 -1
  97. package/fesm2015/overlay.js +196 -32
  98. package/fesm2015/overlay.js.map +1 -1
  99. package/fesm2015/scrolling.js +9 -1
  100. package/fesm2015/scrolling.js.map +1 -1
  101. package/fesm2015/testing.js +25 -1
  102. package/fesm2015/testing.js.map +1 -1
  103. package/fesm2015/tree.js +6 -2
  104. package/fesm2015/tree.js.map +1 -1
  105. package/overlay/dispatchers/base-overlay-dispatcher.d.ts +28 -0
  106. package/overlay/dispatchers/index.d.ts +9 -0
  107. package/overlay/{keyboard → dispatchers}/overlay-keyboard-dispatcher.d.ts +4 -10
  108. package/overlay/dispatchers/overlay-outside-click-dispatcher.d.ts +27 -0
  109. package/overlay/index.d.ts +4 -3
  110. package/overlay/index.metadata.json +1 -1
  111. package/overlay/overlay-config.d.ts +4 -0
  112. package/overlay/overlay-directives.d.ts +4 -0
  113. package/overlay/overlay-ref.d.ts +8 -2
  114. package/overlay/overlay-reference.d.ts +1 -0
  115. package/overlay/overlay.d.ts +4 -2
  116. package/overlay/public-api.d.ts +1 -1
  117. package/package.json +1 -1
  118. package/schematics/ng-add/index.js +1 -1
  119. package/scrolling/index.metadata.json +1 -1
  120. package/scrolling/public-api.d.ts +1 -0
  121. package/scrolling/virtual-for-of.d.ts +2 -1
  122. package/scrolling/virtual-scroll-repeater.d.ts +16 -0
  123. package/scrolling/virtual-scroll-viewport.d.ts +4 -4
  124. package/testing/component-harness.d.ts +12 -0
  125. package/testing/harness-environment.d.ts +1 -0
  126. package/tree/control/nested-tree-control.d.ts +7 -2
  127. package/tree/index.metadata.json +1 -1
  128. package/esm2015/overlay/keyboard/overlay-keyboard-dispatcher.js +0 -96
@@ -351,6 +351,10 @@ class OverlayConfig {
351
351
  * the `HashLocationStrategy`).
352
352
  */
353
353
  this.disposeOnNavigation = false;
354
+ /**
355
+ * Array of HTML elements clicking on which should not be considered as outside click
356
+ */
357
+ this.excludeFromOutsideClick = [];
354
358
  if (config) {
355
359
  // Use `Iterable` instead of `Array` because TypeScript, as of 3.6.3,
356
360
  // loses the array generic type in the `for of`. But we *also* have to use `Array` because
@@ -471,14 +475,60 @@ function validateHorizontalPosition(property, value) {
471
475
  * found in the LICENSE file at https://angular.io/license
472
476
  */
473
477
  /**
474
- * Service for dispatching keyboard events that land on the body to appropriate overlay ref,
478
+ * Service for dispatching events that land on the body to appropriate overlay ref,
475
479
  * if any. It maintains a list of attached overlays to determine best suited overlay based
476
480
  * on event target and order of overlay opens.
477
481
  */
478
- class OverlayKeyboardDispatcher {
482
+ class BaseOverlayDispatcher {
479
483
  constructor(document) {
480
484
  /** Currently attached overlays in the order they were attached. */
481
485
  this._attachedOverlays = [];
486
+ this._document = document;
487
+ }
488
+ ngOnDestroy() {
489
+ this.detach();
490
+ }
491
+ /** Add a new overlay to the list of attached overlay refs. */
492
+ add(overlayRef) {
493
+ // Ensure that we don't get the same overlay multiple times.
494
+ this.remove(overlayRef);
495
+ this._attachedOverlays.push(overlayRef);
496
+ }
497
+ /** Remove an overlay from the list of attached overlay refs. */
498
+ remove(overlayRef) {
499
+ const index = this._attachedOverlays.indexOf(overlayRef);
500
+ if (index > -1) {
501
+ this._attachedOverlays.splice(index, 1);
502
+ }
503
+ // Remove the global listener once there are no more overlays.
504
+ if (this._attachedOverlays.length === 0) {
505
+ this.detach();
506
+ }
507
+ }
508
+ }
509
+ BaseOverlayDispatcher.ɵprov = ɵɵdefineInjectable({ factory: function BaseOverlayDispatcher_Factory() { return new BaseOverlayDispatcher(ɵɵinject(DOCUMENT)); }, token: BaseOverlayDispatcher, providedIn: "root" });
510
+ BaseOverlayDispatcher.decorators = [
511
+ { type: Injectable, args: [{ providedIn: 'root' },] }
512
+ ];
513
+ BaseOverlayDispatcher.ctorParameters = () => [
514
+ { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] }
515
+ ];
516
+
517
+ /**
518
+ * @license
519
+ * Copyright Google LLC All Rights Reserved.
520
+ *
521
+ * Use of this source code is governed by an MIT-style license that can be
522
+ * found in the LICENSE file at https://angular.io/license
523
+ */
524
+ /**
525
+ * Service for dispatching keyboard events that land on the body to appropriate overlay ref,
526
+ * if any. It maintains a list of attached overlays to determine best suited overlay based
527
+ * on event target and order of overlay opens.
528
+ */
529
+ class OverlayKeyboardDispatcher extends BaseOverlayDispatcher {
530
+ constructor(document) {
531
+ super(document);
482
532
  /** Keyboard event listener that will be attached to the body. */
483
533
  this._keydownListener = (event) => {
484
534
  const overlays = this._attachedOverlays;
@@ -495,35 +545,18 @@ class OverlayKeyboardDispatcher {
495
545
  }
496
546
  }
497
547
  };
498
- this._document = document;
499
- }
500
- ngOnDestroy() {
501
- this._detach();
502
548
  }
503
549
  /** Add a new overlay to the list of attached overlay refs. */
504
550
  add(overlayRef) {
505
- // Ensure that we don't get the same overlay multiple times.
506
- this.remove(overlayRef);
551
+ super.add(overlayRef);
507
552
  // Lazily start dispatcher once first overlay is added
508
553
  if (!this._isAttached) {
509
554
  this._document.body.addEventListener('keydown', this._keydownListener);
510
555
  this._isAttached = true;
511
556
  }
512
- this._attachedOverlays.push(overlayRef);
513
- }
514
- /** Remove an overlay from the list of attached overlay refs. */
515
- remove(overlayRef) {
516
- const index = this._attachedOverlays.indexOf(overlayRef);
517
- if (index > -1) {
518
- this._attachedOverlays.splice(index, 1);
519
- }
520
- // Remove the global listener once there are no more overlays.
521
- if (this._attachedOverlays.length === 0) {
522
- this._detach();
523
- }
524
557
  }
525
558
  /** Detaches the global keyboard event listener. */
526
- _detach() {
559
+ detach() {
527
560
  if (this._isAttached) {
528
561
  this._document.body.removeEventListener('keydown', this._keydownListener);
529
562
  this._isAttached = false;
@@ -555,6 +588,93 @@ const OVERLAY_KEYBOARD_DISPATCHER_PROVIDER = {
555
588
  useFactory: OVERLAY_KEYBOARD_DISPATCHER_PROVIDER_FACTORY
556
589
  };
557
590
 
591
+ /**
592
+ * @license
593
+ * Copyright Google LLC All Rights Reserved.
594
+ *
595
+ * Use of this source code is governed by an MIT-style license that can be
596
+ * found in the LICENSE file at https://angular.io/license
597
+ */
598
+ /**
599
+ * Service for dispatching mouse click events that land on the body to appropriate overlay ref,
600
+ * if any. It maintains a list of attached overlays to determine best suited overlay based
601
+ * on event target and order of overlay opens.
602
+ */
603
+ class OverlayOutsideClickDispatcher extends BaseOverlayDispatcher {
604
+ constructor(document, _platform) {
605
+ super(document);
606
+ this._platform = _platform;
607
+ this._cursorStyleIsSet = false;
608
+ /** Click event listener that will be attached to the body propagate phase. */
609
+ this._clickListener = (event) => {
610
+ // Get the target through the `composedPath` if possible to account for shadow DOM.
611
+ const target = event.composedPath ? event.composedPath()[0] : event.target;
612
+ const overlays = this._attachedOverlays;
613
+ // Dispatch the mouse event to the top overlay which has subscribers to its mouse events.
614
+ // We want to target all overlays for which the click could be considered as outside click.
615
+ // As soon as we reach an overlay for which the click is not outside click we break off
616
+ // the loop.
617
+ for (let i = overlays.length - 1; i > -1; i--) {
618
+ const overlayRef = overlays[i];
619
+ if (overlayRef._outsidePointerEvents.observers.length < 1) {
620
+ continue;
621
+ }
622
+ const config = overlayRef.getConfig();
623
+ const excludeElements = [...config.excludeFromOutsideClick, overlayRef.overlayElement];
624
+ const isInsideClick = excludeElements.some(e => e.contains(target));
625
+ // If it is inside click just break - we should do nothing
626
+ // If it is outside click dispatch the mouse event, and proceed with the next overlay
627
+ if (isInsideClick) {
628
+ break;
629
+ }
630
+ overlayRef._outsidePointerEvents.next(event);
631
+ }
632
+ };
633
+ }
634
+ /** Add a new overlay to the list of attached overlay refs. */
635
+ add(overlayRef) {
636
+ super.add(overlayRef);
637
+ // tslint:disable: max-line-length
638
+ // Safari on iOS does not generate click events for non-interactive
639
+ // elements. However, we want to receive a click for any element outside
640
+ // the overlay. We can force a "clickable" state by setting
641
+ // `cursor: pointer` on the document body.
642
+ // See https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event#Safari_Mobile
643
+ // and https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html
644
+ // tslint:enable: max-line-length
645
+ if (!this._isAttached) {
646
+ this._document.body.addEventListener('click', this._clickListener, true);
647
+ // click event is not fired on iOS. To make element "clickable" we are
648
+ // setting the cursor to pointer
649
+ if (this._platform.IOS && !this._cursorStyleIsSet) {
650
+ this._cursorOriginalValue = this._document.body.style.cursor;
651
+ this._document.body.style.cursor = 'pointer';
652
+ this._cursorStyleIsSet = true;
653
+ }
654
+ this._isAttached = true;
655
+ }
656
+ }
657
+ /** Detaches the global keyboard event listener. */
658
+ detach() {
659
+ if (this._isAttached) {
660
+ this._document.body.removeEventListener('click', this._clickListener, true);
661
+ if (this._platform.IOS && this._cursorStyleIsSet) {
662
+ this._document.body.style.cursor = this._cursorOriginalValue;
663
+ this._cursorStyleIsSet = false;
664
+ }
665
+ this._isAttached = false;
666
+ }
667
+ }
668
+ }
669
+ OverlayOutsideClickDispatcher.ɵprov = ɵɵdefineInjectable({ factory: function OverlayOutsideClickDispatcher_Factory() { return new OverlayOutsideClickDispatcher(ɵɵinject(DOCUMENT), ɵɵinject(Platform)); }, token: OverlayOutsideClickDispatcher, providedIn: "root" });
670
+ OverlayOutsideClickDispatcher.decorators = [
671
+ { type: Injectable, args: [{ providedIn: 'root' },] }
672
+ ];
673
+ OverlayOutsideClickDispatcher.ctorParameters = () => [
674
+ { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] },
675
+ { type: Platform }
676
+ ];
677
+
558
678
  /**
559
679
  * @license
560
680
  * Copyright Google LLC All Rights Reserved.
@@ -672,7 +792,9 @@ const OVERLAY_CONTAINER_PROVIDER = {
672
792
  class OverlayRef {
673
793
  constructor(_portalOutlet, _host, _pane, _config, _ngZone, _keyboardDispatcher, _document,
674
794
  // @breaking-change 8.0.0 `_location` parameter to be made required.
675
- _location) {
795
+ _location,
796
+ // @breaking-change 9.0.0 `_mouseClickDispatcher` parameter to be made required.
797
+ _outsideClickDispatcher) {
676
798
  this._portalOutlet = _portalOutlet;
677
799
  this._host = _host;
678
800
  this._pane = _pane;
@@ -681,6 +803,7 @@ class OverlayRef {
681
803
  this._keyboardDispatcher = _keyboardDispatcher;
682
804
  this._document = _document;
683
805
  this._location = _location;
806
+ this._outsideClickDispatcher = _outsideClickDispatcher;
684
807
  this._backdropElement = null;
685
808
  this._backdropClick = new Subject();
686
809
  this._attachments = new Subject();
@@ -689,6 +812,8 @@ class OverlayRef {
689
812
  this._backdropClickHandler = (event) => this._backdropClick.next(event);
690
813
  /** Stream of keydown events dispatched to this overlay. */
691
814
  this._keydownEvents = new Subject();
815
+ /** Stream of mouse outside events dispatched to this overlay. */
816
+ this._outsidePointerEvents = new Subject();
692
817
  if (_config.scrollStrategy) {
693
818
  this._scrollStrategy = _config.scrollStrategy;
694
819
  this._scrollStrategy.attach(this);
@@ -762,6 +887,10 @@ class OverlayRef {
762
887
  if (this._config.disposeOnNavigation && this._location) {
763
888
  this._locationChanges = this._location.subscribe(() => this.dispose());
764
889
  }
890
+ // @breaking-change 9.0.0 remove the null check for `_mouseClickDispatcher`
891
+ if (this._outsideClickDispatcher) {
892
+ this._outsideClickDispatcher.add(this);
893
+ }
765
894
  return attachResult;
766
895
  }
767
896
  /**
@@ -793,6 +922,10 @@ class OverlayRef {
793
922
  this._detachContentWhenStable();
794
923
  // Stop listening for location changes.
795
924
  this._locationChanges.unsubscribe();
925
+ // @breaking-change 9.0.0 remove the null check for `_outsideClickDispatcher`
926
+ if (this._outsideClickDispatcher) {
927
+ this._outsideClickDispatcher.remove(this);
928
+ }
796
929
  return detachmentResult;
797
930
  }
798
931
  /** Cleans up the overlay from the DOM. */
@@ -809,6 +942,11 @@ class OverlayRef {
809
942
  this._attachments.complete();
810
943
  this._backdropClick.complete();
811
944
  this._keydownEvents.complete();
945
+ this._outsidePointerEvents.complete();
946
+ // @breaking-change 9.0.0 remove the null check for `_outsideClickDispatcher`
947
+ if (this._outsideClickDispatcher) {
948
+ this._outsideClickDispatcher.remove(this);
949
+ }
812
950
  if (this._host && this._host.parentNode) {
813
951
  this._host.parentNode.removeChild(this._host);
814
952
  this._host = null;
@@ -839,6 +977,10 @@ class OverlayRef {
839
977
  keydownEvents() {
840
978
  return this._keydownEvents.asObservable();
841
979
  }
980
+ /** Gets an observable of pointer events targeted outside this overlay. */
981
+ outsidePointerEvents() {
982
+ return this._outsidePointerEvents.asObservable();
983
+ }
842
984
  /** Gets the current overlay configuration, which is immutable. */
843
985
  getConfig() {
844
986
  return this._config;
@@ -2415,7 +2557,9 @@ class Overlay {
2415
2557
  /** Scrolling strategies that can be used when creating an overlay. */
2416
2558
  scrollStrategies, _overlayContainer, _componentFactoryResolver, _positionBuilder, _keyboardDispatcher, _injector, _ngZone, _document, _directionality,
2417
2559
  // @breaking-change 8.0.0 `_location` parameter to be made required.
2418
- _location) {
2560
+ _location,
2561
+ // @breaking-change 9.0.0 `_outsideClickDispatcher` parameter to be made required.
2562
+ _outsideClickDispatcher) {
2419
2563
  this.scrollStrategies = scrollStrategies;
2420
2564
  this._overlayContainer = _overlayContainer;
2421
2565
  this._componentFactoryResolver = _componentFactoryResolver;
@@ -2426,6 +2570,7 @@ class Overlay {
2426
2570
  this._document = _document;
2427
2571
  this._directionality = _directionality;
2428
2572
  this._location = _location;
2573
+ this._outsideClickDispatcher = _outsideClickDispatcher;
2429
2574
  }
2430
2575
  /**
2431
2576
  * Creates an overlay.
@@ -2438,7 +2583,7 @@ class Overlay {
2438
2583
  const portalOutlet = this._createPortalOutlet(pane);
2439
2584
  const overlayConfig = new OverlayConfig(config);
2440
2585
  overlayConfig.direction = overlayConfig.direction || this._directionality.value;
2441
- return new OverlayRef(portalOutlet, host, pane, overlayConfig, this._ngZone, this._keyboardDispatcher, this._document, this._location);
2586
+ return new OverlayRef(portalOutlet, host, pane, overlayConfig, this._ngZone, this._keyboardDispatcher, this._document, this._location, this._outsideClickDispatcher);
2442
2587
  }
2443
2588
  /**
2444
2589
  * Gets a position builder that can be used, via fluent API,
@@ -2496,7 +2641,8 @@ Overlay.ctorParameters = () => [
2496
2641
  { type: NgZone },
2497
2642
  { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] },
2498
2643
  { type: Directionality },
2499
- { type: Location, decorators: [{ type: Optional }] }
2644
+ { type: Location, decorators: [{ type: Optional }] },
2645
+ { type: OverlayOutsideClickDispatcher, decorators: [{ type: Optional }] }
2500
2646
  ];
2501
2647
 
2502
2648
  /**
@@ -2574,6 +2720,8 @@ class CdkConnectedOverlay {
2574
2720
  this._flexibleDimensions = false;
2575
2721
  this._push = false;
2576
2722
  this._backdropSubscription = Subscription.EMPTY;
2723
+ this._attachSubscription = Subscription.EMPTY;
2724
+ this._detachSubscription = Subscription.EMPTY;
2577
2725
  /** Margin between the overlay and the viewport edges. */
2578
2726
  this.viewportMargin = 0;
2579
2727
  /** Whether the overlay is open. */
@@ -2588,6 +2736,8 @@ class CdkConnectedOverlay {
2588
2736
  this.detach = new EventEmitter();
2589
2737
  /** Emits when there are keyboard events that are targeted at the overlay. */
2590
2738
  this.overlayKeydown = new EventEmitter();
2739
+ /** Emits when there are mouse outside click events that are targeted at the overlay. */
2740
+ this.overlayOutsideClick = new EventEmitter();
2591
2741
  this._templatePortal = new TemplatePortal(templateRef, viewContainerRef);
2592
2742
  this._scrollStrategyFactory = scrollStrategyFactory;
2593
2743
  this.scrollStrategy = this._scrollStrategyFactory();
@@ -2634,10 +2784,12 @@ class CdkConnectedOverlay {
2634
2784
  return this._dir ? this._dir.value : 'ltr';
2635
2785
  }
2636
2786
  ngOnDestroy() {
2787
+ this._attachSubscription.unsubscribe();
2788
+ this._detachSubscription.unsubscribe();
2789
+ this._backdropSubscription.unsubscribe();
2637
2790
  if (this._overlayRef) {
2638
2791
  this._overlayRef.dispose();
2639
2792
  }
2640
- this._backdropSubscription.unsubscribe();
2641
2793
  }
2642
2794
  ngOnChanges(changes) {
2643
2795
  if (this._position) {
@@ -2661,14 +2813,19 @@ class CdkConnectedOverlay {
2661
2813
  if (!this.positions || !this.positions.length) {
2662
2814
  this.positions = defaultPositionList;
2663
2815
  }
2664
- this._overlayRef = this._overlay.create(this._buildConfig());
2665
- this._overlayRef.keydownEvents().subscribe((event) => {
2816
+ const overlayRef = this._overlayRef = this._overlay.create(this._buildConfig());
2817
+ this._attachSubscription = overlayRef.attachments().subscribe(() => this.attach.emit());
2818
+ this._detachSubscription = overlayRef.detachments().subscribe(() => this.detach.emit());
2819
+ overlayRef.keydownEvents().subscribe((event) => {
2666
2820
  this.overlayKeydown.next(event);
2667
2821
  if (event.keyCode === ESCAPE && !hasModifierKey(event)) {
2668
2822
  event.preventDefault();
2669
2823
  this._detachOverlay();
2670
2824
  }
2671
2825
  });
2826
+ this._overlayRef.outsidePointerEvents().subscribe((event) => {
2827
+ this.overlayOutsideClick.next(event);
2828
+ });
2672
2829
  }
2673
2830
  /** Builds the overlay config based on the directive's inputs */
2674
2831
  _buildConfig() {
@@ -2739,7 +2896,6 @@ class CdkConnectedOverlay {
2739
2896
  }
2740
2897
  if (!this._overlayRef.hasAttached()) {
2741
2898
  this._overlayRef.attach(this._templatePortal);
2742
- this.attach.emit();
2743
2899
  }
2744
2900
  if (this.hasBackdrop) {
2745
2901
  this._backdropSubscription = this._overlayRef.backdropClick().subscribe(event => {
@@ -2754,7 +2910,6 @@ class CdkConnectedOverlay {
2754
2910
  _detachOverlay() {
2755
2911
  if (this._overlayRef) {
2756
2912
  this._overlayRef.detach();
2757
- this.detach.emit();
2758
2913
  }
2759
2914
  this._backdropSubscription.unsubscribe();
2760
2915
  }
@@ -2797,7 +2952,8 @@ CdkConnectedOverlay.propDecorators = {
2797
2952
  positionChange: [{ type: Output }],
2798
2953
  attach: [{ type: Output }],
2799
2954
  detach: [{ type: Output }],
2800
- overlayKeydown: [{ type: Output }]
2955
+ overlayKeydown: [{ type: Output }],
2956
+ overlayOutsideClick: [{ type: Output }]
2801
2957
  };
2802
2958
  /** @docs-private */
2803
2959
  function CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER_FACTORY(overlay) {
@@ -2843,6 +2999,14 @@ const OVERLAY_PROVIDERS = [
2843
2999
  CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER,
2844
3000
  ];
2845
3001
 
3002
+ /**
3003
+ * @license
3004
+ * Copyright Google LLC All Rights Reserved.
3005
+ *
3006
+ * Use of this source code is governed by an MIT-style license that can be
3007
+ * found in the LICENSE file at https://angular.io/license
3008
+ */
3009
+
2846
3010
  /**
2847
3011
  * @license
2848
3012
  * Copyright Google LLC All Rights Reserved.
@@ -2947,5 +3111,5 @@ FullscreenOverlayContainer.ctorParameters = () => [
2947
3111
  * Generated bundle index. Do not edit.
2948
3112
  */
2949
3113
 
2950
- export { BlockScrollStrategy, CdkConnectedOverlay, CdkOverlayOrigin, CloseScrollStrategy, ConnectedOverlayPositionChange, ConnectedPositionStrategy, ConnectionPositionPair, FlexibleConnectedPositionStrategy, FullscreenOverlayContainer, GlobalPositionStrategy, NoopScrollStrategy, OVERLAY_PROVIDERS, Overlay, OverlayConfig, OverlayContainer, OverlayKeyboardDispatcher, OverlayModule, OverlayPositionBuilder, OverlayRef, RepositionScrollStrategy, ScrollStrategyOptions, ScrollingVisibility, validateHorizontalPosition, validateVerticalPosition, OVERLAY_CONTAINER_PROVIDER_FACTORY as ɵangular_material_src_cdk_overlay_overlay_a, OVERLAY_CONTAINER_PROVIDER as ɵangular_material_src_cdk_overlay_overlay_b, CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY as ɵangular_material_src_cdk_overlay_overlay_c, CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER_FACTORY as ɵangular_material_src_cdk_overlay_overlay_d, CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER as ɵangular_material_src_cdk_overlay_overlay_e, OVERLAY_KEYBOARD_DISPATCHER_PROVIDER_FACTORY as ɵangular_material_src_cdk_overlay_overlay_f, OVERLAY_KEYBOARD_DISPATCHER_PROVIDER as ɵangular_material_src_cdk_overlay_overlay_g };
3114
+ export { BlockScrollStrategy, CdkConnectedOverlay, CdkOverlayOrigin, CloseScrollStrategy, ConnectedOverlayPositionChange, ConnectedPositionStrategy, ConnectionPositionPair, FlexibleConnectedPositionStrategy, FullscreenOverlayContainer, GlobalPositionStrategy, NoopScrollStrategy, OVERLAY_PROVIDERS, Overlay, OverlayConfig, OverlayContainer, OverlayKeyboardDispatcher, OverlayModule, OverlayOutsideClickDispatcher, OverlayPositionBuilder, OverlayRef, RepositionScrollStrategy, ScrollStrategyOptions, ScrollingVisibility, validateHorizontalPosition, validateVerticalPosition, OVERLAY_KEYBOARD_DISPATCHER_PROVIDER_FACTORY as ɵangular_material_src_cdk_overlay_overlay_a, OVERLAY_KEYBOARD_DISPATCHER_PROVIDER as ɵangular_material_src_cdk_overlay_overlay_b, OVERLAY_CONTAINER_PROVIDER_FACTORY as ɵangular_material_src_cdk_overlay_overlay_c, OVERLAY_CONTAINER_PROVIDER as ɵangular_material_src_cdk_overlay_overlay_d, CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY as ɵangular_material_src_cdk_overlay_overlay_e, CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER_FACTORY as ɵangular_material_src_cdk_overlay_overlay_f, CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER as ɵangular_material_src_cdk_overlay_overlay_g, BaseOverlayDispatcher as ɵangular_material_src_cdk_overlay_overlay_h };
2951
3115
  //# sourceMappingURL=overlay.js.map