@angular/cdk 2.0.0-beta.10 → 2.0.0-beta.11

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 (170) hide show
  1. package/a11y/package.json +2 -2
  2. package/a11y/typings/aria-describer.d.ts +51 -0
  3. package/a11y/typings/aria-reference.d.ts +15 -0
  4. package/a11y/typings/focus-monitor.d.ts +106 -0
  5. package/a11y/typings/index.metadata.json +1 -1
  6. package/a11y/typings/public_api.d.ts +5 -3
  7. package/bidi/package.json +2 -2
  8. package/bundles/cdk-a11y.umd.js +639 -25
  9. package/bundles/cdk-a11y.umd.js.map +1 -1
  10. package/bundles/cdk-a11y.umd.min.js +9 -0
  11. package/bundles/cdk-a11y.umd.min.js.map +1 -0
  12. package/bundles/cdk-bidi.umd.min.js +9 -0
  13. package/bundles/cdk-bidi.umd.min.js.map +1 -0
  14. package/bundles/cdk-coercion.umd.min.js +9 -0
  15. package/bundles/cdk-coercion.umd.min.js.map +1 -0
  16. package/bundles/cdk-collections.umd.min.js +9 -0
  17. package/bundles/cdk-collections.umd.min.js.map +1 -0
  18. package/bundles/cdk-keycodes.umd.min.js +9 -0
  19. package/bundles/cdk-keycodes.umd.min.js.map +1 -0
  20. package/bundles/cdk-observers.umd.min.js +9 -0
  21. package/bundles/cdk-observers.umd.min.js.map +1 -0
  22. package/bundles/cdk-overlay.umd.js +49 -75
  23. package/bundles/cdk-overlay.umd.js.map +1 -1
  24. package/bundles/cdk-overlay.umd.min.js +9 -0
  25. package/bundles/cdk-overlay.umd.min.js.map +1 -0
  26. package/bundles/cdk-platform.umd.min.js +9 -0
  27. package/bundles/cdk-platform.umd.min.js.map +1 -0
  28. package/bundles/cdk-portal.umd.min.js +9 -0
  29. package/bundles/cdk-portal.umd.min.js.map +1 -0
  30. package/bundles/cdk-rxjs.umd.js.map +1 -1
  31. package/bundles/cdk-rxjs.umd.min.js +9 -0
  32. package/bundles/cdk-rxjs.umd.min.js.map +1 -0
  33. package/bundles/cdk-scrolling.umd.min.js +9 -0
  34. package/bundles/cdk-scrolling.umd.min.js.map +1 -0
  35. package/bundles/cdk-stepper.umd.js +460 -0
  36. package/bundles/cdk-stepper.umd.js.map +1 -0
  37. package/bundles/cdk-stepper.umd.min.js +9 -0
  38. package/bundles/cdk-stepper.umd.min.js.map +1 -0
  39. package/bundles/cdk-table.umd.js +8 -8
  40. package/bundles/cdk-table.umd.js.map +1 -1
  41. package/bundles/cdk-table.umd.min.js +9 -0
  42. package/bundles/cdk-table.umd.min.js.map +1 -0
  43. package/bundles/cdk.umd.js +1 -1
  44. package/bundles/cdk.umd.js.map +1 -1
  45. package/bundles/cdk.umd.min.js +9 -0
  46. package/bundles/cdk.umd.min.js.map +1 -0
  47. package/coercion/package.json +2 -2
  48. package/collections/package.json +2 -2
  49. package/collections/typings/selection.d.ts +3 -3
  50. package/{@angular/cdk → esm2015}/a11y.js +617 -17
  51. package/esm2015/a11y.js.map +1 -0
  52. package/{@angular/cdk → esm2015}/bidi.js +0 -0
  53. package/{@angular/cdk → esm2015}/bidi.js.map +0 -0
  54. package/{@angular → esm2015}/cdk.js +1 -1
  55. package/{@angular → esm2015}/cdk.js.map +1 -1
  56. package/{@angular/cdk → esm2015}/coercion.js +0 -0
  57. package/{@angular/cdk → esm2015}/coercion.js.map +0 -0
  58. package/{@angular/cdk → esm2015}/collections.js +0 -0
  59. package/{@angular/cdk → esm2015}/collections.js.map +0 -0
  60. package/{@angular/cdk → esm2015}/keycodes.js +0 -0
  61. package/{@angular/cdk → esm2015}/keycodes.js.map +0 -0
  62. package/{@angular/cdk → esm2015}/observers.js +0 -0
  63. package/{@angular/cdk → esm2015}/observers.js.map +0 -0
  64. package/{@angular/cdk → esm2015}/overlay.js +44 -66
  65. package/esm2015/overlay.js.map +1 -0
  66. package/{@angular/cdk → esm2015}/platform.js +0 -0
  67. package/{@angular/cdk → esm2015}/platform.js.map +0 -0
  68. package/{@angular/cdk → esm2015}/portal.js +0 -0
  69. package/{@angular/cdk → esm2015}/portal.js.map +0 -0
  70. package/{@angular/cdk → esm2015}/rxjs.js +0 -0
  71. package/esm2015/rxjs.js.map +1 -0
  72. package/{@angular/cdk → esm2015}/scrolling.js +0 -0
  73. package/{@angular/cdk → esm2015}/scrolling.js.map +0 -0
  74. package/esm2015/stepper.js +418 -0
  75. package/esm2015/stepper.js.map +1 -0
  76. package/{@angular/cdk → esm2015}/table.js +8 -8
  77. package/esm2015/table.js.map +1 -0
  78. package/{@angular/cdk → esm5}/a11y.es5.js +622 -17
  79. package/esm5/a11y.es5.js.map +1 -0
  80. package/{@angular/cdk → esm5}/bidi.es5.js +0 -0
  81. package/{@angular/cdk → esm5}/bidi.es5.js.map +0 -0
  82. package/{@angular → esm5}/cdk.es5.js +1 -1
  83. package/{@angular → esm5}/cdk.es5.js.map +1 -1
  84. package/{@angular/cdk → esm5}/coercion.es5.js +0 -0
  85. package/{@angular/cdk → esm5}/coercion.es5.js.map +0 -0
  86. package/{@angular/cdk → esm5}/collections.es5.js +0 -0
  87. package/{@angular/cdk → esm5}/collections.es5.js.map +0 -0
  88. package/{@angular/cdk → esm5}/keycodes.es5.js +0 -0
  89. package/{@angular/cdk → esm5}/keycodes.es5.js.map +0 -0
  90. package/{@angular/cdk → esm5}/observers.es5.js +0 -0
  91. package/{@angular/cdk → esm5}/observers.es5.js.map +0 -0
  92. package/{@angular/cdk → esm5}/overlay.es5.js +46 -71
  93. package/esm5/overlay.es5.js.map +1 -0
  94. package/{@angular/cdk → esm5}/platform.es5.js +0 -0
  95. package/{@angular/cdk → esm5}/platform.es5.js.map +0 -0
  96. package/{@angular/cdk → esm5}/portal.es5.js +0 -0
  97. package/{@angular/cdk → esm5}/portal.es5.js.map +0 -0
  98. package/{@angular/cdk → esm5}/rxjs.es5.js +0 -0
  99. package/esm5/rxjs.es5.js.map +1 -0
  100. package/{@angular/cdk → esm5}/scrolling.es5.js +0 -0
  101. package/{@angular/cdk → esm5}/scrolling.es5.js.map +0 -0
  102. package/esm5/stepper.es5.js +451 -0
  103. package/esm5/stepper.es5.js.map +1 -0
  104. package/{@angular/cdk → esm5}/table.es5.js +8 -8
  105. package/esm5/table.es5.js.map +1 -0
  106. package/keycodes/package.json +2 -2
  107. package/observers/package.json +2 -2
  108. package/overlay/package.json +2 -2
  109. package/overlay/typings/index.metadata.json +1 -1
  110. package/overlay/typings/{overlay-state.d.ts → overlay-config.d.ts} +5 -7
  111. package/overlay/typings/overlay-container.d.ts +1 -6
  112. package/overlay/typings/overlay-ref.d.ts +3 -3
  113. package/overlay/typings/overlay.d.ts +2 -2
  114. package/overlay/typings/position/connected-position-strategy.d.ts +1 -3
  115. package/overlay/typings/public_api.d.ts +1 -1
  116. package/overlay/typings/scroll/reposition-scroll-strategy.d.ts +1 -1
  117. package/package.json +5 -5
  118. package/platform/package.json +2 -2
  119. package/portal/package.json +2 -2
  120. package/portal/typings/portal-injector.d.ts +19 -0
  121. package/rxjs/package.json +2 -2
  122. package/rxjs/typings/rx-chain.d.ts +1 -1
  123. package/rxjs/typings/rx-operators.d.ts +1 -1
  124. package/scrolling/package.json +2 -2
  125. package/stepper/index.d.ts +8 -0
  126. package/stepper/index.metadata.json +11 -0
  127. package/stepper/package.json +7 -0
  128. package/stepper/typings/index.d.ts +4 -0
  129. package/stepper/typings/index.metadata.json +1 -0
  130. package/stepper/typings/public_api.d.ts +5 -0
  131. package/stepper/typings/step-label.d.ts +12 -0
  132. package/stepper/typings/stepper-button.d.ts +11 -0
  133. package/stepper/typings/stepper.d.ts +93 -0
  134. package/stepper.d.ts +8 -0
  135. package/stepper.metadata.json +11 -0
  136. package/table/package.json +2 -2
  137. package/table/typings/index.metadata.json +1 -1
  138. package/typings/a11y/aria-describer.d.ts +51 -0
  139. package/typings/a11y/aria-reference.d.ts +15 -0
  140. package/typings/a11y/focus-monitor.d.ts +106 -0
  141. package/typings/a11y/index.metadata.json +1 -1
  142. package/typings/a11y/public_api.d.ts +5 -3
  143. package/typings/collections/selection.d.ts +3 -3
  144. package/typings/index.metadata.json +1 -1
  145. package/typings/overlay/index.metadata.json +1 -1
  146. package/typings/overlay/{overlay-state.d.ts → overlay-config.d.ts} +5 -7
  147. package/typings/overlay/overlay-container.d.ts +1 -6
  148. package/typings/overlay/overlay-ref.d.ts +3 -3
  149. package/typings/overlay/overlay.d.ts +2 -2
  150. package/typings/overlay/position/connected-position-strategy.d.ts +1 -3
  151. package/typings/overlay/public_api.d.ts +1 -1
  152. package/typings/overlay/scroll/reposition-scroll-strategy.d.ts +1 -1
  153. package/typings/portal/portal-injector.d.ts +19 -0
  154. package/typings/rxjs/rx-chain.d.ts +1 -1
  155. package/typings/rxjs/rx-operators.d.ts +1 -1
  156. package/typings/stepper/index.d.ts +4 -0
  157. package/typings/stepper/index.metadata.json +1 -0
  158. package/typings/stepper/public_api.d.ts +5 -0
  159. package/typings/stepper/step-label.d.ts +12 -0
  160. package/typings/stepper/stepper-button.d.ts +11 -0
  161. package/typings/stepper/stepper.d.ts +93 -0
  162. package/typings/table/index.metadata.json +1 -1
  163. package/@angular/cdk/a11y.es5.js.map +0 -1
  164. package/@angular/cdk/a11y.js.map +0 -1
  165. package/@angular/cdk/overlay.es5.js.map +0 -1
  166. package/@angular/cdk/overlay.js.map +0 -1
  167. package/@angular/cdk/rxjs.es5.js.map +0 -1
  168. package/@angular/cdk/rxjs.js.map +0 -1
  169. package/@angular/cdk/table.es5.js.map +0 -1
  170. package/@angular/cdk/table.js.map +0 -1
@@ -6,12 +6,14 @@ import * as tslib_1 from "tslib";
6
6
  * Use of this source code is governed by an MIT-style license that can be
7
7
  * found in the LICENSE file at https://angular.io/license
8
8
  */
9
- import { Directive, ElementRef, Inject, Injectable, InjectionToken, Input, NgModule, NgZone, Optional, SkipSelf } from '@angular/core';
9
+ import { Directive, ElementRef, EventEmitter, Inject, Injectable, InjectionToken, Input, NgModule, NgZone, Optional, Output, Renderer2, SkipSelf } from '@angular/core';
10
10
  import { coerceBooleanProperty } from '@angular/cdk/coercion';
11
11
  import { Platform, PlatformModule } from '@angular/cdk/platform';
12
12
  import { RxChain, debounceTime, doOperator, filter, first, map } from '@angular/cdk/rxjs';
13
13
  import { CommonModule } from '@angular/common';
14
14
  import { Subject } from 'rxjs/Subject';
15
+ import { of } from 'rxjs/observable/of';
16
+ import { Subscription } from 'rxjs/Subscription';
15
17
  import { A, DOWN_ARROW, NINE, TAB, UP_ARROW, Z, ZERO } from '@angular/cdk/keycodes';
16
18
  /**
17
19
  * Utility for checking the interactivity of an element, such as whether is is focusable or
@@ -502,7 +504,7 @@ var FocusTrap = (function () {
502
504
  fn();
503
505
  }
504
506
  else {
505
- first.call(this._ngZone.onStable).subscribe(fn);
507
+ first.call(this._ngZone.onStable.asObservable()).subscribe(fn);
506
508
  }
507
509
  };
508
510
  return FocusTrap;
@@ -748,17 +750,602 @@ var LIVE_ANNOUNCER_PROVIDER = {
748
750
  useFactory: LIVE_ANNOUNCER_PROVIDER_FACTORY
749
751
  };
750
752
  /**
751
- * Screenreaders will often fire fake mousedown events when a focusable element
752
- * is activated using the keyboard. We can typically distinguish between these faked
753
- * mousedown events and real mousedown events using the "buttons" property. While
754
- * real mousedowns will indicate the mouse button that was pressed (e.g. "1" for
755
- * the left mouse button), faked mousedowns will usually set the property value to 0.
756
- * @param {?} event
753
+ * IDs are deliminated by an empty space, as per the spec.
754
+ */
755
+ var ID_DELIMINATOR = ' ';
756
+ /**
757
+ * Adds the given ID to the specified ARIA attribute on an element.
758
+ * Used for attributes such as aria-labelledby, aria-owns, etc.
759
+ * @param {?} el
760
+ * @param {?} attr
761
+ * @param {?} id
757
762
  * @return {?}
758
763
  */
759
- function isFakeMousedownFromScreenReader(event) {
760
- return event.buttons === 0;
764
+ function addAriaReferencedId(el, attr, id) {
765
+ var /** @type {?} */ ids = getAriaReferenceIds(el, attr);
766
+ if (ids.some(function (existingId) { return existingId.trim() == id.trim(); })) {
767
+ return;
768
+ }
769
+ ids.push(id.trim());
770
+ el.setAttribute(attr, ids.join(ID_DELIMINATOR));
771
+ }
772
+ /**
773
+ * Removes the given ID from the specified ARIA attribute on an element.
774
+ * Used for attributes such as aria-labelledby, aria-owns, etc.
775
+ * @param {?} el
776
+ * @param {?} attr
777
+ * @param {?} id
778
+ * @return {?}
779
+ */
780
+ function removeAriaReferencedId(el, attr, id) {
781
+ var /** @type {?} */ ids = getAriaReferenceIds(el, attr);
782
+ var /** @type {?} */ filteredIds = ids.filter(function (val) { return val != id.trim(); });
783
+ el.setAttribute(attr, filteredIds.join(ID_DELIMINATOR));
784
+ }
785
+ /**
786
+ * Gets the list of IDs referenced by the given ARIA attribute on an element.
787
+ * Used for attributes such as aria-labelledby, aria-owns, etc.
788
+ * @param {?} el
789
+ * @param {?} attr
790
+ * @return {?}
791
+ */
792
+ function getAriaReferenceIds(el, attr) {
793
+ // Get string array of all individual ids (whitespace deliminated) in the attribute value
794
+ return (el.getAttribute(attr) || '').match(/\S+/g) || [];
761
795
  }
796
+ /**
797
+ * ID used for the body container where all messages are appended.
798
+ */
799
+ var MESSAGES_CONTAINER_ID = 'cdk-describedby-message-container';
800
+ /**
801
+ * ID prefix used for each created message element.
802
+ */
803
+ var CDK_DESCRIBEDBY_ID_PREFIX = 'cdk-describedby-message';
804
+ /**
805
+ * Attribute given to each host element that is described by a message element.
806
+ */
807
+ var CDK_DESCRIBEDBY_HOST_ATTRIBUTE = 'cdk-describedby-host';
808
+ /**
809
+ * Global incremental identifier for each registered message element.
810
+ */
811
+ var nextId = 0;
812
+ /**
813
+ * Global map of all registered message elements that have been placed into the document.
814
+ */
815
+ var messageRegistry = new Map();
816
+ /**
817
+ * Container for all registered messages.
818
+ */
819
+ var messagesContainer = null;
820
+ /**
821
+ * Utility that creates visually hidden elements with a message content. Useful for elements that
822
+ * want to use aria-describedby to further describe themselves without adding additional visual
823
+ * content.
824
+ * \@docs-private
825
+ */
826
+ var AriaDescriber = (function () {
827
+ /**
828
+ * @param {?} _platform
829
+ */
830
+ function AriaDescriber(_platform) {
831
+ this._platform = _platform;
832
+ }
833
+ /**
834
+ * Adds to the host element an aria-describedby reference to a hidden element that contains
835
+ * the message. If the same message has already been registered, then it will reuse the created
836
+ * message element.
837
+ * @param {?} hostElement
838
+ * @param {?} message
839
+ * @return {?}
840
+ */
841
+ AriaDescriber.prototype.describe = function (hostElement, message) {
842
+ if (!this._platform.isBrowser || !message.trim()) {
843
+ return;
844
+ }
845
+ if (!messageRegistry.has(message)) {
846
+ createMessageElement(message);
847
+ }
848
+ if (!isElementDescribedByMessage(hostElement, message)) {
849
+ addMessageReference(hostElement, message);
850
+ }
851
+ };
852
+ /**
853
+ * Removes the host element's aria-describedby reference to the message element.
854
+ * @param {?} hostElement
855
+ * @param {?} message
856
+ * @return {?}
857
+ */
858
+ AriaDescriber.prototype.removeDescription = function (hostElement, message) {
859
+ if (!this._platform.isBrowser || !message.trim()) {
860
+ return;
861
+ }
862
+ if (isElementDescribedByMessage(hostElement, message)) {
863
+ removeMessageReference(hostElement, message);
864
+ }
865
+ var /** @type {?} */ registeredMessage = messageRegistry.get(message);
866
+ if (registeredMessage && registeredMessage.referenceCount === 0) {
867
+ deleteMessageElement(message);
868
+ }
869
+ if (messagesContainer && messagesContainer.childNodes.length === 0) {
870
+ deleteMessagesContainer();
871
+ }
872
+ };
873
+ /**
874
+ * Unregisters all created message elements and removes the message container.
875
+ * @return {?}
876
+ */
877
+ AriaDescriber.prototype.ngOnDestroy = function () {
878
+ if (!this._platform.isBrowser) {
879
+ return;
880
+ }
881
+ var /** @type {?} */ describedElements = document.querySelectorAll("[" + CDK_DESCRIBEDBY_HOST_ATTRIBUTE + "]");
882
+ for (var /** @type {?} */ i = 0; i < describedElements.length; i++) {
883
+ removeCdkDescribedByReferenceIds(describedElements[i]);
884
+ describedElements[i].removeAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE);
885
+ }
886
+ if (messagesContainer) {
887
+ deleteMessagesContainer();
888
+ }
889
+ messageRegistry.clear();
890
+ };
891
+ return AriaDescriber;
892
+ }());
893
+ AriaDescriber.decorators = [
894
+ { type: Injectable },
895
+ ];
896
+ /**
897
+ * @nocollapse
898
+ */
899
+ AriaDescriber.ctorParameters = function () { return [
900
+ { type: Platform, },
901
+ ]; };
902
+ /**
903
+ * Creates a new element in the visually hidden message container element with the message
904
+ * as its content and adds it to the message registry.
905
+ * @param {?} message
906
+ * @return {?}
907
+ */
908
+ function createMessageElement(message) {
909
+ var /** @type {?} */ messageElement = document.createElement('div');
910
+ messageElement.setAttribute('id', CDK_DESCRIBEDBY_ID_PREFIX + "-" + nextId++);
911
+ messageElement.appendChild(/** @type {?} */ ((document.createTextNode(message))));
912
+ if (!messagesContainer) {
913
+ createMessagesContainer();
914
+ } /** @type {?} */
915
+ ((messagesContainer)).appendChild(messageElement);
916
+ messageRegistry.set(message, { messageElement: messageElement, referenceCount: 0 });
917
+ }
918
+ /**
919
+ * Deletes the message element from the global messages container.
920
+ * @param {?} message
921
+ * @return {?}
922
+ */
923
+ function deleteMessageElement(message) {
924
+ var /** @type {?} */ registeredMessage = messageRegistry.get(message);
925
+ var /** @type {?} */ messageElement = registeredMessage && registeredMessage.messageElement;
926
+ if (messagesContainer && messageElement) {
927
+ messagesContainer.removeChild(messageElement);
928
+ }
929
+ messageRegistry.delete(message);
930
+ }
931
+ /**
932
+ * Creates the global container for all aria-describedby messages.
933
+ * @return {?}
934
+ */
935
+ function createMessagesContainer() {
936
+ messagesContainer = document.createElement('div');
937
+ messagesContainer.setAttribute('id', MESSAGES_CONTAINER_ID);
938
+ messagesContainer.setAttribute('aria-hidden', 'true');
939
+ messagesContainer.style.display = 'none';
940
+ document.body.appendChild(messagesContainer);
941
+ }
942
+ /**
943
+ * Deletes the global messages container.
944
+ * @return {?}
945
+ */
946
+ function deleteMessagesContainer() {
947
+ document.body.removeChild(/** @type {?} */ ((messagesContainer)));
948
+ messagesContainer = null;
949
+ }
950
+ /**
951
+ * Removes all cdk-describedby messages that are hosted through the element.
952
+ * @param {?} element
953
+ * @return {?}
954
+ */
955
+ function removeCdkDescribedByReferenceIds(element) {
956
+ // Remove all aria-describedby reference IDs that are prefixed by CDK_DESCRIBEDBY_ID_PREFIX
957
+ var /** @type {?} */ originalReferenceIds = getAriaReferenceIds(element, 'aria-describedby')
958
+ .filter(function (id) { return id.indexOf(CDK_DESCRIBEDBY_ID_PREFIX) != 0; });
959
+ element.setAttribute('aria-describedby', originalReferenceIds.join(' '));
960
+ }
961
+ /**
962
+ * Adds a message reference to the element using aria-describedby and increments the registered
963
+ * message's reference count.
964
+ * @param {?} element
965
+ * @param {?} message
966
+ * @return {?}
967
+ */
968
+ function addMessageReference(element, message) {
969
+ var /** @type {?} */ registeredMessage = ((messageRegistry.get(message)));
970
+ // Add the aria-describedby reference and set the describedby_host attribute to mark the element.
971
+ addAriaReferencedId(element, 'aria-describedby', registeredMessage.messageElement.id);
972
+ element.setAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE, '');
973
+ registeredMessage.referenceCount++;
974
+ }
975
+ /**
976
+ * Removes a message reference from the element using aria-describedby and decrements the registered
977
+ * message's reference count.
978
+ * @param {?} element
979
+ * @param {?} message
980
+ * @return {?}
981
+ */
982
+ function removeMessageReference(element, message) {
983
+ var /** @type {?} */ registeredMessage = ((messageRegistry.get(message)));
984
+ registeredMessage.referenceCount--;
985
+ removeAriaReferencedId(element, 'aria-describedby', registeredMessage.messageElement.id);
986
+ element.removeAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE);
987
+ }
988
+ /**
989
+ * Returns true if the element has been described by the provided message ID.
990
+ * @param {?} element
991
+ * @param {?} message
992
+ * @return {?}
993
+ */
994
+ function isElementDescribedByMessage(element, message) {
995
+ var /** @type {?} */ referenceIds = getAriaReferenceIds(element, 'aria-describedby');
996
+ var /** @type {?} */ registeredMessage = messageRegistry.get(message);
997
+ var /** @type {?} */ messageId = registeredMessage && registeredMessage.messageElement.id;
998
+ return !!messageId && referenceIds.indexOf(messageId) != -1;
999
+ }
1000
+ /**
1001
+ * \@docs-private
1002
+ * @param {?} parentDispatcher
1003
+ * @param {?} platform
1004
+ * @return {?}
1005
+ */
1006
+ function ARIA_DESCRIBER_PROVIDER_FACTORY(parentDispatcher, platform) {
1007
+ return parentDispatcher || new AriaDescriber(platform);
1008
+ }
1009
+ /**
1010
+ * \@docs-private
1011
+ */
1012
+ var ARIA_DESCRIBER_PROVIDER = {
1013
+ // If there is already an AriaDescriber available, use that. Otherwise, provide a new one.
1014
+ provide: AriaDescriber,
1015
+ deps: [
1016
+ [new Optional(), new SkipSelf(), AriaDescriber],
1017
+ Platform
1018
+ ],
1019
+ useFactory: ARIA_DESCRIBER_PROVIDER_FACTORY
1020
+ };
1021
+ // This is the value used by AngularJS Material. Through trial and error (on iPhone 6S) they found
1022
+ // that a value of around 650ms seems appropriate.
1023
+ var TOUCH_BUFFER_MS = 650;
1024
+ /**
1025
+ * Monitors mouse and keyboard events to determine the cause of focus events.
1026
+ */
1027
+ var FocusMonitor = (function () {
1028
+ /**
1029
+ * @param {?} _ngZone
1030
+ * @param {?} _platform
1031
+ */
1032
+ function FocusMonitor(_ngZone, _platform) {
1033
+ var _this = this;
1034
+ this._ngZone = _ngZone;
1035
+ this._platform = _platform;
1036
+ /**
1037
+ * The focus origin that the next focus event is a result of.
1038
+ */
1039
+ this._origin = null;
1040
+ /**
1041
+ * Whether the window has just been focused.
1042
+ */
1043
+ this._windowFocused = false;
1044
+ /**
1045
+ * Weak map of elements being monitored to their info.
1046
+ */
1047
+ this._elementInfo = new WeakMap();
1048
+ this._ngZone.runOutsideAngular(function () { return _this._registerDocumentEvents(); });
1049
+ }
1050
+ /**
1051
+ * Monitors focus on an element and applies appropriate CSS classes.
1052
+ * @param {?} element The element to monitor
1053
+ * @param {?} renderer The renderer to use to apply CSS classes to the element.
1054
+ * @param {?} checkChildren Whether to count the element as focused when its children are focused.
1055
+ * @return {?} An observable that emits when the focus state of the element changes.
1056
+ * When the element is blurred, null will be emitted.
1057
+ */
1058
+ FocusMonitor.prototype.monitor = function (element, renderer, checkChildren) {
1059
+ var _this = this;
1060
+ // Do nothing if we're not on the browser platform.
1061
+ if (!this._platform.isBrowser) {
1062
+ return of(null);
1063
+ }
1064
+ // Check if we're already monitoring this element.
1065
+ if (this._elementInfo.has(element)) {
1066
+ var /** @type {?} */ cachedInfo = this._elementInfo.get(element); /** @type {?} */
1067
+ ((cachedInfo)).checkChildren = checkChildren;
1068
+ return ((cachedInfo)).subject.asObservable();
1069
+ }
1070
+ // Create monitored element info.
1071
+ var /** @type {?} */ info = {
1072
+ unlisten: function () { },
1073
+ checkChildren: checkChildren,
1074
+ renderer: renderer,
1075
+ subject: new Subject()
1076
+ };
1077
+ this._elementInfo.set(element, info);
1078
+ // Start listening. We need to listen in capture phase since focus events don't bubble.
1079
+ var /** @type {?} */ focusListener = function (event) { return _this._onFocus(event, element); };
1080
+ var /** @type {?} */ blurListener = function (event) { return _this._onBlur(event, element); };
1081
+ this._ngZone.runOutsideAngular(function () {
1082
+ element.addEventListener('focus', focusListener, true);
1083
+ element.addEventListener('blur', blurListener, true);
1084
+ });
1085
+ // Create an unlisten function for later.
1086
+ info.unlisten = function () {
1087
+ element.removeEventListener('focus', focusListener, true);
1088
+ element.removeEventListener('blur', blurListener, true);
1089
+ };
1090
+ return info.subject.asObservable();
1091
+ };
1092
+ /**
1093
+ * Stops monitoring an element and removes all focus classes.
1094
+ * @param {?} element The element to stop monitoring.
1095
+ * @return {?}
1096
+ */
1097
+ FocusMonitor.prototype.stopMonitoring = function (element) {
1098
+ var /** @type {?} */ elementInfo = this._elementInfo.get(element);
1099
+ if (elementInfo) {
1100
+ elementInfo.unlisten();
1101
+ elementInfo.subject.complete();
1102
+ this._setClasses(element);
1103
+ this._elementInfo.delete(element);
1104
+ }
1105
+ };
1106
+ /**
1107
+ * Focuses the element via the specified focus origin.
1108
+ * @param {?} element The element to focus.
1109
+ * @param {?} origin The focus origin.
1110
+ * @return {?}
1111
+ */
1112
+ FocusMonitor.prototype.focusVia = function (element, origin) {
1113
+ this._setOriginForCurrentEventQueue(origin);
1114
+ element.focus();
1115
+ };
1116
+ /**
1117
+ * Register necessary event listeners on the document and window.
1118
+ * @return {?}
1119
+ */
1120
+ FocusMonitor.prototype._registerDocumentEvents = function () {
1121
+ var _this = this;
1122
+ // Do nothing if we're not on the browser platform.
1123
+ if (!this._platform.isBrowser) {
1124
+ return;
1125
+ }
1126
+ // Note: we listen to events in the capture phase so we can detect them even if the user stops
1127
+ // propagation.
1128
+ // On keydown record the origin and clear any touch event that may be in progress.
1129
+ document.addEventListener('keydown', function () {
1130
+ _this._lastTouchTarget = null;
1131
+ _this._setOriginForCurrentEventQueue('keyboard');
1132
+ }, true);
1133
+ // On mousedown record the origin only if there is not touch target, since a mousedown can
1134
+ // happen as a result of a touch event.
1135
+ document.addEventListener('mousedown', function () {
1136
+ if (!_this._lastTouchTarget) {
1137
+ _this._setOriginForCurrentEventQueue('mouse');
1138
+ }
1139
+ }, true);
1140
+ // When the touchstart event fires the focus event is not yet in the event queue. This means
1141
+ // we can't rely on the trick used above (setting timeout of 0ms). Instead we wait 650ms to
1142
+ // see if a focus happens.
1143
+ document.addEventListener('touchstart', function (event) {
1144
+ if (_this._touchTimeout != null) {
1145
+ clearTimeout(_this._touchTimeout);
1146
+ }
1147
+ _this._lastTouchTarget = event.target;
1148
+ _this._touchTimeout = setTimeout(function () { return _this._lastTouchTarget = null; }, TOUCH_BUFFER_MS);
1149
+ }, true);
1150
+ // Make a note of when the window regains focus, so we can restore the origin info for the
1151
+ // focused element.
1152
+ window.addEventListener('focus', function () {
1153
+ _this._windowFocused = true;
1154
+ setTimeout(function () { return _this._windowFocused = false; }, 0);
1155
+ });
1156
+ };
1157
+ /**
1158
+ * Sets the focus classes on the element based on the given focus origin.
1159
+ * @param {?} element The element to update the classes on.
1160
+ * @param {?=} origin The focus origin.
1161
+ * @return {?}
1162
+ */
1163
+ FocusMonitor.prototype._setClasses = function (element, origin) {
1164
+ var /** @type {?} */ elementInfo = this._elementInfo.get(element);
1165
+ if (elementInfo) {
1166
+ var /** @type {?} */ toggleClass = function (className, shouldSet) {
1167
+ shouldSet ? elementInfo.renderer.addClass(element, className) :
1168
+ elementInfo.renderer.removeClass(element, className);
1169
+ };
1170
+ toggleClass('cdk-focused', !!origin);
1171
+ toggleClass('cdk-touch-focused', origin === 'touch');
1172
+ toggleClass('cdk-keyboard-focused', origin === 'keyboard');
1173
+ toggleClass('cdk-mouse-focused', origin === 'mouse');
1174
+ toggleClass('cdk-program-focused', origin === 'program');
1175
+ }
1176
+ };
1177
+ /**
1178
+ * Sets the origin and schedules an async function to clear it at the end of the event queue.
1179
+ * @param {?} origin The origin to set.
1180
+ * @return {?}
1181
+ */
1182
+ FocusMonitor.prototype._setOriginForCurrentEventQueue = function (origin) {
1183
+ var _this = this;
1184
+ this._origin = origin;
1185
+ setTimeout(function () { return _this._origin = null; }, 0);
1186
+ };
1187
+ /**
1188
+ * Checks whether the given focus event was caused by a touchstart event.
1189
+ * @param {?} event The focus event to check.
1190
+ * @return {?} Whether the event was caused by a touch.
1191
+ */
1192
+ FocusMonitor.prototype._wasCausedByTouch = function (event) {
1193
+ // Note(mmalerba): This implementation is not quite perfect, there is a small edge case.
1194
+ // Consider the following dom structure:
1195
+ //
1196
+ // <div #parent tabindex="0" cdkFocusClasses>
1197
+ // <div #child (click)="#parent.focus()"></div>
1198
+ // </div>
1199
+ //
1200
+ // If the user touches the #child element and the #parent is programmatically focused as a
1201
+ // result, this code will still consider it to have been caused by the touch event and will
1202
+ // apply the cdk-touch-focused class rather than the cdk-program-focused class. This is a
1203
+ // relatively small edge-case that can be worked around by using
1204
+ // focusVia(parentEl, renderer, 'program') to focus the parent element.
1205
+ //
1206
+ // If we decide that we absolutely must handle this case correctly, we can do so by listening
1207
+ // for the first focus event after the touchstart, and then the first blur event after that
1208
+ // focus event. When that blur event fires we know that whatever follows is not a result of the
1209
+ // touchstart.
1210
+ var /** @type {?} */ focusTarget = event.target;
1211
+ return this._lastTouchTarget instanceof Node && focusTarget instanceof Node &&
1212
+ (focusTarget === this._lastTouchTarget || focusTarget.contains(this._lastTouchTarget));
1213
+ };
1214
+ /**
1215
+ * Handles focus events on a registered element.
1216
+ * @param {?} event The focus event.
1217
+ * @param {?} element The monitored element.
1218
+ * @return {?}
1219
+ */
1220
+ FocusMonitor.prototype._onFocus = function (event, element) {
1221
+ // NOTE(mmalerba): We currently set the classes based on the focus origin of the most recent
1222
+ // focus event affecting the monitored element. If we want to use the origin of the first event
1223
+ // instead we should check for the cdk-focused class here and return if the element already has
1224
+ // it. (This only matters for elements that have includesChildren = true).
1225
+ // If we are not counting child-element-focus as focused, make sure that the event target is the
1226
+ // monitored element itself.
1227
+ var /** @type {?} */ elementInfo = this._elementInfo.get(element);
1228
+ if (!elementInfo || (!elementInfo.checkChildren && element !== event.target)) {
1229
+ return;
1230
+ }
1231
+ // If we couldn't detect a cause for the focus event, it's due to one of three reasons:
1232
+ // 1) The window has just regained focus, in which case we want to restore the focused state of
1233
+ // the element from before the window blurred.
1234
+ // 2) It was caused by a touch event, in which case we mark the origin as 'touch'.
1235
+ // 3) The element was programmatically focused, in which case we should mark the origin as
1236
+ // 'program'.
1237
+ if (!this._origin) {
1238
+ if (this._windowFocused && this._lastFocusOrigin) {
1239
+ this._origin = this._lastFocusOrigin;
1240
+ }
1241
+ else if (this._wasCausedByTouch(event)) {
1242
+ this._origin = 'touch';
1243
+ }
1244
+ else {
1245
+ this._origin = 'program';
1246
+ }
1247
+ }
1248
+ this._setClasses(element, this._origin);
1249
+ elementInfo.subject.next(this._origin);
1250
+ this._lastFocusOrigin = this._origin;
1251
+ this._origin = null;
1252
+ };
1253
+ /**
1254
+ * Handles blur events on a registered element.
1255
+ * @param {?} event The blur event.
1256
+ * @param {?} element The monitored element.
1257
+ * @return {?}
1258
+ */
1259
+ FocusMonitor.prototype._onBlur = function (event, element) {
1260
+ // If we are counting child-element-focus as focused, make sure that we aren't just blurring in
1261
+ // order to focus another child of the monitored element.
1262
+ var /** @type {?} */ elementInfo = this._elementInfo.get(element);
1263
+ if (!elementInfo || (elementInfo.checkChildren && event.relatedTarget instanceof Node &&
1264
+ element.contains(event.relatedTarget))) {
1265
+ return;
1266
+ }
1267
+ this._setClasses(element);
1268
+ elementInfo.subject.next(null);
1269
+ };
1270
+ return FocusMonitor;
1271
+ }());
1272
+ FocusMonitor.decorators = [
1273
+ { type: Injectable },
1274
+ ];
1275
+ /**
1276
+ * @nocollapse
1277
+ */
1278
+ FocusMonitor.ctorParameters = function () { return [
1279
+ { type: NgZone, },
1280
+ { type: Platform, },
1281
+ ]; };
1282
+ /**
1283
+ * Directive that determines how a particular element was focused (via keyboard, mouse, touch, or
1284
+ * programmatically) and adds corresponding classes to the element.
1285
+ *
1286
+ * There are two variants of this directive:
1287
+ * 1) cdkMonitorElementFocus: does not consider an element to be focused if one of its children is
1288
+ * focused.
1289
+ * 2) cdkMonitorSubtreeFocus: considers an element focused if it or any of its children are focused.
1290
+ */
1291
+ var CdkMonitorFocus = (function () {
1292
+ /**
1293
+ * @param {?} _elementRef
1294
+ * @param {?} _focusMonitor
1295
+ * @param {?} renderer
1296
+ */
1297
+ function CdkMonitorFocus(_elementRef, _focusMonitor, renderer) {
1298
+ var _this = this;
1299
+ this._elementRef = _elementRef;
1300
+ this._focusMonitor = _focusMonitor;
1301
+ this.cdkFocusChange = new EventEmitter();
1302
+ this._monitorSubscription = this._focusMonitor.monitor(this._elementRef.nativeElement, renderer, this._elementRef.nativeElement.hasAttribute('cdkMonitorSubtreeFocus'))
1303
+ .subscribe(function (origin) { return _this.cdkFocusChange.emit(origin); });
1304
+ }
1305
+ /**
1306
+ * @return {?}
1307
+ */
1308
+ CdkMonitorFocus.prototype.ngOnDestroy = function () {
1309
+ this._focusMonitor.stopMonitoring(this._elementRef.nativeElement);
1310
+ this._monitorSubscription.unsubscribe();
1311
+ };
1312
+ return CdkMonitorFocus;
1313
+ }());
1314
+ CdkMonitorFocus.decorators = [
1315
+ { type: Directive, args: [{
1316
+ selector: '[cdkMonitorElementFocus], [cdkMonitorSubtreeFocus]',
1317
+ },] },
1318
+ ];
1319
+ /**
1320
+ * @nocollapse
1321
+ */
1322
+ CdkMonitorFocus.ctorParameters = function () { return [
1323
+ { type: ElementRef, },
1324
+ { type: FocusMonitor, },
1325
+ { type: Renderer2, },
1326
+ ]; };
1327
+ CdkMonitorFocus.propDecorators = {
1328
+ 'cdkFocusChange': [{ type: Output },],
1329
+ };
1330
+ /**
1331
+ * \@docs-private
1332
+ * @param {?} parentDispatcher
1333
+ * @param {?} ngZone
1334
+ * @param {?} platform
1335
+ * @return {?}
1336
+ */
1337
+ function FOCUS_MONITOR_PROVIDER_FACTORY(parentDispatcher, ngZone, platform) {
1338
+ return parentDispatcher || new FocusMonitor(ngZone, platform);
1339
+ }
1340
+ /**
1341
+ * \@docs-private
1342
+ */
1343
+ var FOCUS_MONITOR_PROVIDER = {
1344
+ // If there is already a FocusMonitor available, use that. Otherwise, provide a new one.
1345
+ provide: FocusMonitor,
1346
+ deps: [[new Optional(), new SkipSelf(), FocusMonitor], NgZone, Platform],
1347
+ useFactory: FOCUS_MONITOR_PROVIDER_FACTORY
1348
+ };
762
1349
  /**
763
1350
  * This class manages keyboard events for selectable lists. If you pass it a query list
764
1351
  * of items, it will set the active item correctly when arrow events occur.
@@ -772,6 +1359,7 @@ var ListKeyManager = (function () {
772
1359
  this._activeItemIndex = -1;
773
1360
  this._wrap = false;
774
1361
  this._letterKeyStream = new Subject();
1362
+ this._typeaheadSubscription = Subscription.EMPTY;
775
1363
  this._pressedLetters = [];
776
1364
  /**
777
1365
  * Stream that emits any time the TAB key is pressed, so components can react
@@ -799,9 +1387,7 @@ var ListKeyManager = (function () {
799
1387
  if (this._items.length && this._items.some(function (item) { return typeof item.getLabel !== 'function'; })) {
800
1388
  throw Error('ListKeyManager items in typeahead mode must implement the `getLabel` method.');
801
1389
  }
802
- if (this._typeaheadSubscription) {
803
- this._typeaheadSubscription.unsubscribe();
804
- }
1390
+ this._typeaheadSubscription.unsubscribe();
805
1391
  // Debounce the presses of non-navigational keys, collect the ones that correspond to letters
806
1392
  // and convert those letters back into a string. Afterwards find the first item that starts
807
1393
  // with that string and select it.
@@ -1017,6 +1603,18 @@ var ActiveDescendantKeyManager = (function (_super) {
1017
1603
  };
1018
1604
  return ActiveDescendantKeyManager;
1019
1605
  }(ListKeyManager));
1606
+ /**
1607
+ * Screenreaders will often fire fake mousedown events when a focusable element
1608
+ * is activated using the keyboard. We can typically distinguish between these faked
1609
+ * mousedown events and real mousedown events using the "buttons" property. While
1610
+ * real mousedowns will indicate the mouse button that was pressed (e.g. "1" for
1611
+ * the left mouse button), faked mousedowns will usually set the property value to 0.
1612
+ * @param {?} event
1613
+ * @return {?}
1614
+ */
1615
+ function isFakeMousedownFromScreenReader(event) {
1616
+ return event.buttons === 0;
1617
+ }
1020
1618
  var FocusKeyManager = (function (_super) {
1021
1619
  tslib_1.__extends(FocusKeyManager, _super);
1022
1620
  function FocusKeyManager() {
@@ -1044,9 +1642,16 @@ var A11yModule = (function () {
1044
1642
  A11yModule.decorators = [
1045
1643
  { type: NgModule, args: [{
1046
1644
  imports: [CommonModule, PlatformModule],
1047
- declarations: [FocusTrapDirective, FocusTrapDeprecatedDirective],
1048
- exports: [FocusTrapDirective, FocusTrapDeprecatedDirective],
1049
- providers: [InteractivityChecker, FocusTrapFactory, LIVE_ANNOUNCER_PROVIDER]
1645
+ declarations: [FocusTrapDirective, FocusTrapDeprecatedDirective, CdkMonitorFocus],
1646
+ exports: [FocusTrapDirective, FocusTrapDeprecatedDirective, CdkMonitorFocus],
1647
+ providers: [
1648
+ InteractivityChecker,
1649
+ FocusTrapFactory,
1650
+ AriaDescriber,
1651
+ LIVE_ANNOUNCER_PROVIDER,
1652
+ ARIA_DESCRIBER_PROVIDER,
1653
+ FOCUS_MONITOR_PROVIDER,
1654
+ ]
1050
1655
  },] },
1051
1656
  ];
1052
1657
  /**
@@ -1056,5 +1661,5 @@ A11yModule.ctorParameters = function () { return []; };
1056
1661
  /**
1057
1662
  * Generated bundle index. Do not edit.
1058
1663
  */
1059
- export { A11yModule, LIVE_ANNOUNCER_ELEMENT_TOKEN, LiveAnnouncer, LIVE_ANNOUNCER_PROVIDER_FACTORY, LIVE_ANNOUNCER_PROVIDER, isFakeMousedownFromScreenReader, FocusTrap, FocusTrapFactory, FocusTrapDeprecatedDirective, FocusTrapDirective, InteractivityChecker, ListKeyManager, ActiveDescendantKeyManager, FocusKeyManager };
1664
+ export { A11yModule, ActiveDescendantKeyManager, MESSAGES_CONTAINER_ID, CDK_DESCRIBEDBY_ID_PREFIX, CDK_DESCRIBEDBY_HOST_ATTRIBUTE, AriaDescriber, ARIA_DESCRIBER_PROVIDER_FACTORY, ARIA_DESCRIBER_PROVIDER, isFakeMousedownFromScreenReader, FocusKeyManager, FocusTrap, FocusTrapFactory, FocusTrapDeprecatedDirective, FocusTrapDirective, InteractivityChecker, ListKeyManager, LIVE_ANNOUNCER_ELEMENT_TOKEN, LiveAnnouncer, LIVE_ANNOUNCER_PROVIDER_FACTORY, LIVE_ANNOUNCER_PROVIDER, TOUCH_BUFFER_MS, FocusMonitor, CdkMonitorFocus, FOCUS_MONITOR_PROVIDER_FACTORY, FOCUS_MONITOR_PROVIDER };
1060
1665
  //# sourceMappingURL=a11y.es5.js.map