@angular/cdk 7.0.3 → 7.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/a11y/typings/focus-monitor/focus-monitor.d.ts +20 -4
- package/a11y/typings/index.metadata.json +1 -1
- package/a11y/typings/key-manager/list-key-manager.d.ts +8 -0
- package/a11y/typings/live-announcer/live-announcer.d.ts +37 -4
- package/bidi/typings/dir.d.ts +4 -1
- package/bidi/typings/index.metadata.json +1 -1
- package/bundles/cdk-a11y.umd.js +503 -210
- package/bundles/cdk-a11y.umd.js.map +1 -1
- package/bundles/cdk-a11y.umd.min.js +1 -1
- package/bundles/cdk-a11y.umd.min.js.map +1 -1
- package/bundles/cdk-accordion.umd.js +16 -9
- package/bundles/cdk-accordion.umd.js.map +1 -1
- package/bundles/cdk-accordion.umd.min.js.map +1 -1
- package/bundles/cdk-bidi.umd.js +16 -7
- package/bundles/cdk-bidi.umd.js.map +1 -1
- package/bundles/cdk-bidi.umd.min.js +1 -1
- package/bundles/cdk-bidi.umd.min.js.map +1 -1
- package/bundles/cdk-coercion.umd.js +5 -5
- package/bundles/cdk-coercion.umd.js.map +1 -1
- package/bundles/cdk-collections.umd.js +28 -5
- package/bundles/cdk-collections.umd.js.map +1 -1
- package/bundles/cdk-collections.umd.min.js.map +1 -1
- package/bundles/cdk-drag-drop.umd.js +2251 -853
- package/bundles/cdk-drag-drop.umd.js.map +1 -1
- package/bundles/cdk-drag-drop.umd.min.js +2 -1
- package/bundles/cdk-drag-drop.umd.min.js.map +1 -1
- package/bundles/cdk-keycodes.umd.js +33 -1
- package/bundles/cdk-keycodes.umd.js.map +1 -1
- package/bundles/cdk-keycodes.umd.min.js +1 -1
- package/bundles/cdk-keycodes.umd.min.js.map +1 -1
- package/bundles/cdk-layout.umd.js +29 -22
- package/bundles/cdk-layout.umd.js.map +1 -1
- package/bundles/cdk-layout.umd.min.js +1 -1
- package/bundles/cdk-layout.umd.min.js.map +1 -1
- package/bundles/cdk-observers.umd.js +25 -6
- package/bundles/cdk-observers.umd.js.map +1 -1
- package/bundles/cdk-observers.umd.min.js.map +1 -1
- package/bundles/cdk-overlay.umd.js +600 -243
- package/bundles/cdk-overlay.umd.js.map +1 -1
- package/bundles/cdk-overlay.umd.min.js +2 -2
- package/bundles/cdk-overlay.umd.min.js.map +1 -1
- package/bundles/cdk-platform.umd.js +50 -28
- package/bundles/cdk-platform.umd.js.map +1 -1
- package/bundles/cdk-platform.umd.min.js.map +1 -1
- package/bundles/cdk-portal.umd.js +14 -7
- package/bundles/cdk-portal.umd.js.map +1 -1
- package/bundles/cdk-portal.umd.min.js.map +1 -1
- package/bundles/cdk-scrolling.umd.js +143 -48
- package/bundles/cdk-scrolling.umd.js.map +1 -1
- package/bundles/cdk-scrolling.umd.min.js +1 -1
- package/bundles/cdk-scrolling.umd.min.js.map +1 -1
- package/bundles/cdk-stepper.umd.js +103 -19
- package/bundles/cdk-stepper.umd.js.map +1 -1
- package/bundles/cdk-stepper.umd.min.js +1 -1
- package/bundles/cdk-stepper.umd.min.js.map +1 -1
- package/bundles/cdk-table.umd.js +182 -48
- package/bundles/cdk-table.umd.js.map +1 -1
- package/bundles/cdk-table.umd.min.js.map +1 -1
- package/bundles/cdk-text-field.umd.js +70 -32
- package/bundles/cdk-text-field.umd.js.map +1 -1
- package/bundles/cdk-text-field.umd.min.js +1 -1
- package/bundles/cdk-text-field.umd.min.js.map +1 -1
- package/bundles/cdk-tree.umd.js +71 -34
- package/bundles/cdk-tree.umd.js.map +1 -1
- package/bundles/cdk-tree.umd.min.js +1 -1
- package/bundles/cdk-tree.umd.min.js.map +1 -1
- package/bundles/cdk.umd.js +5 -4
- package/bundles/cdk.umd.js.map +1 -1
- package/bundles/cdk.umd.min.js +1 -1
- package/bundles/cdk.umd.min.js.map +1 -1
- package/drag-drop/typings/{drag-handle.d.ts → directives/drag-handle.d.ts} +3 -0
- package/drag-drop/typings/{drag-placeholder.d.ts → directives/drag-placeholder.d.ts} +0 -0
- package/drag-drop/typings/{drag-preview.d.ts → directives/drag-preview.d.ts} +0 -0
- package/drag-drop/typings/directives/drag.d.ts +108 -0
- package/drag-drop/typings/directives/drop-list-group.d.ts +22 -0
- package/drag-drop/typings/directives/drop-list.d.ts +135 -0
- package/drag-drop/typings/drag-drop-registry.d.ts +8 -5
- package/drag-drop/typings/drag-events.d.ts +24 -6
- package/{typings/esm5/drag-drop/drag.d.ts → drag-drop/typings/drag-ref.d.ts} +153 -77
- package/drag-drop/typings/drop-list-container.d.ts +21 -3
- package/drag-drop/typings/{drop-list.d.ts → drop-list-ref.d.ts} +133 -77
- package/drag-drop/typings/index.d.ts +1 -0
- package/drag-drop/typings/index.metadata.json +1 -1
- package/drag-drop/typings/public-api.d.ts +13 -5
- package/esm2015/a11y.js +353 -189
- package/esm2015/a11y.js.map +1 -1
- package/esm2015/accordion.js +16 -11
- package/esm2015/accordion.js.map +1 -1
- package/esm2015/bidi.js +18 -9
- package/esm2015/bidi.js.map +1 -1
- package/esm2015/cdk.js +7 -6
- package/esm2015/cdk.js.map +1 -1
- package/esm2015/coercion.js +7 -7
- package/esm2015/coercion.js.map +1 -1
- package/esm2015/collections.js +22 -7
- package/esm2015/collections.js.map +1 -1
- package/esm2015/drag-drop.js +1768 -751
- package/esm2015/drag-drop.js.map +1 -1
- package/esm2015/keycodes.js +31 -4
- package/esm2015/keycodes.js.map +1 -1
- package/esm2015/layout.js +29 -19
- package/esm2015/layout.js.map +1 -1
- package/esm2015/observers.js +13 -8
- package/esm2015/observers.js.map +1 -1
- package/esm2015/overlay.js +384 -219
- package/esm2015/overlay.js.map +1 -1
- package/esm2015/platform.js +53 -31
- package/esm2015/platform.js.map +1 -1
- package/esm2015/portal.js +13 -9
- package/esm2015/portal.js.map +1 -1
- package/esm2015/scrolling.js +106 -49
- package/esm2015/scrolling.js.map +1 -1
- package/esm2015/stepper.js +93 -24
- package/esm2015/stepper.js.map +1 -1
- package/esm2015/table.js +89 -45
- package/esm2015/table.js.map +1 -1
- package/esm2015/text-field.js +51 -34
- package/esm2015/text-field.js.map +1 -1
- package/esm2015/tree.js +55 -36
- package/esm2015/tree.js.map +1 -1
- package/esm5/a11y.es5.js +507 -214
- package/esm5/a11y.es5.js.map +1 -1
- package/esm5/accordion.es5.js +18 -11
- package/esm5/accordion.es5.js.map +1 -1
- package/esm5/bidi.es5.js +18 -9
- package/esm5/bidi.es5.js.map +1 -1
- package/esm5/cdk.es5.js +7 -6
- package/esm5/cdk.es5.js.map +1 -1
- package/esm5/coercion.es5.js +7 -7
- package/esm5/coercion.es5.js.map +1 -1
- package/esm5/collections.es5.js +35 -7
- package/esm5/collections.es5.js.map +1 -1
- package/esm5/drag-drop.es5.js +2125 -729
- package/esm5/drag-drop.es5.js.map +1 -1
- package/esm5/keycodes.es5.js +35 -4
- package/esm5/keycodes.es5.js.map +1 -1
- package/esm5/layout.es5.js +31 -24
- package/esm5/layout.es5.js.map +1 -1
- package/esm5/observers.es5.js +27 -8
- package/esm5/observers.es5.js.map +1 -1
- package/esm5/overlay.es5.js +602 -245
- package/esm5/overlay.es5.js.map +1 -1
- package/esm5/platform.es5.js +52 -30
- package/esm5/platform.es5.js.map +1 -1
- package/esm5/portal.es5.js +16 -9
- package/esm5/portal.es5.js.map +1 -1
- package/esm5/scrolling.es5.js +145 -50
- package/esm5/scrolling.es5.js.map +1 -1
- package/esm5/stepper.es5.js +106 -24
- package/esm5/stepper.es5.js.map +1 -1
- package/esm5/table.es5.js +184 -50
- package/esm5/table.es5.js.map +1 -1
- package/esm5/text-field.es5.js +72 -34
- package/esm5/text-field.es5.js.map +1 -1
- package/esm5/tree.es5.js +74 -37
- package/esm5/tree.es5.js.map +1 -1
- package/keycodes/typings/index.metadata.json +1 -1
- package/keycodes/typings/modifiers.d.ts +14 -0
- package/keycodes/typings/public-api.d.ts +1 -0
- package/overlay/typings/index.metadata.json +1 -1
- package/package.json +4 -4
- package/schematics/ng-generate/drag-drop/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.component.ts +2 -2
- package/schematics/ng-update/upgrade-data.js +2 -1
- package/schematics/ng-update/upgrade-data.js.map +1 -1
- package/schematics/ng-update/upgrade-rules/index.js +3 -2
- package/schematics/ng-update/upgrade-rules/index.js.map +1 -1
- package/schematics/utils/ast/ng-module-imports.d.ts +1 -1
- package/schematics/utils/ast/ng-module-imports.js +25 -13
- package/schematics/utils/ast/ng-module-imports.js.map +1 -1
- package/schematics/utils/get-project.js +2 -1
- package/schematics/utils/get-project.js.map +1 -1
- package/schematics/utils/parse5-element.js +3 -2
- package/schematics/utils/parse5-element.js.map +1 -1
- package/schematics/utils/project-targets.js +2 -1
- package/schematics/utils/project-targets.js.map +1 -1
- package/schematics/utils/version-agnostic-typescript.js +3 -2
- package/schematics/utils/version-agnostic-typescript.js.map +1 -1
- package/scrolling/typings/index.metadata.json +1 -1
- package/stepper/typings/index.metadata.json +1 -1
- package/stepper/typings/public-api.d.ts +1 -0
- package/stepper/typings/step-header.d.ts +15 -0
- package/stepper/typings/stepper.d.ts +11 -1
- package/text-field/typings/autosize.d.ts +6 -0
- package/text-field/typings/index.metadata.json +1 -1
- package/tree/typings/nested-node.d.ts +5 -5
- package/typings/a11y/focus-monitor/focus-monitor.d.ts +20 -4
- package/typings/a11y/index.metadata.json +1 -1
- package/typings/a11y/key-manager/list-key-manager.d.ts +8 -0
- package/typings/a11y/live-announcer/live-announcer.d.ts +37 -4
- package/typings/bidi/dir.d.ts +4 -1
- package/typings/bidi/index.metadata.json +1 -1
- package/typings/{esm5/drag-drop → drag-drop/directives}/drag-handle.d.ts +3 -0
- package/typings/drag-drop/{drag-placeholder.d.ts → directives/drag-placeholder.d.ts} +0 -0
- package/typings/drag-drop/{drag-preview.d.ts → directives/drag-preview.d.ts} +0 -0
- package/typings/drag-drop/directives/drag.d.ts +108 -0
- package/typings/drag-drop/directives/drop-list-group.d.ts +22 -0
- package/typings/drag-drop/directives/drop-list.d.ts +135 -0
- package/typings/drag-drop/drag-drop-registry.d.ts +8 -5
- package/typings/drag-drop/drag-events.d.ts +24 -6
- package/typings/drag-drop/{drag.d.ts → drag-ref.d.ts} +153 -77
- package/typings/drag-drop/drop-list-container.d.ts +21 -3
- package/typings/{esm5/drag-drop/drop-list.d.ts → drag-drop/drop-list-ref.d.ts} +133 -77
- package/typings/drag-drop/index.d.ts +1 -0
- package/typings/drag-drop/index.metadata.json +1 -1
- package/typings/drag-drop/public-api.d.ts +13 -5
- package/typings/esm5/a11y/focus-monitor/focus-monitor.d.ts +20 -4
- package/typings/esm5/a11y/index.metadata.json +1 -1
- package/typings/esm5/a11y/key-manager/list-key-manager.d.ts +8 -0
- package/typings/esm5/a11y/live-announcer/live-announcer.d.ts +37 -4
- package/typings/esm5/bidi/dir.d.ts +4 -1
- package/typings/esm5/bidi/index.metadata.json +1 -1
- package/typings/{drag-drop → esm5/drag-drop/directives}/drag-handle.d.ts +3 -0
- package/typings/esm5/drag-drop/{drag-placeholder.d.ts → directives/drag-placeholder.d.ts} +0 -0
- package/typings/esm5/drag-drop/{drag-preview.d.ts → directives/drag-preview.d.ts} +0 -0
- package/typings/esm5/drag-drop/directives/drag.d.ts +108 -0
- package/typings/esm5/drag-drop/directives/drop-list-group.d.ts +22 -0
- package/typings/esm5/drag-drop/directives/drop-list.d.ts +135 -0
- package/typings/esm5/drag-drop/drag-drop-registry.d.ts +8 -5
- package/typings/esm5/drag-drop/drag-events.d.ts +24 -6
- package/{drag-drop/typings/drag.d.ts → typings/esm5/drag-drop/drag-ref.d.ts} +153 -77
- package/typings/esm5/drag-drop/drop-list-container.d.ts +21 -3
- package/typings/{drag-drop/drop-list.d.ts → esm5/drag-drop/drop-list-ref.d.ts} +133 -77
- package/typings/esm5/drag-drop/index.d.ts +1 -0
- package/typings/esm5/drag-drop/index.metadata.json +1 -1
- package/typings/esm5/drag-drop/public-api.d.ts +13 -5
- package/typings/esm5/index.metadata.json +1 -1
- package/typings/esm5/keycodes/index.metadata.json +1 -1
- package/typings/esm5/keycodes/modifiers.d.ts +14 -0
- package/typings/esm5/keycodes/public-api.d.ts +1 -0
- package/typings/esm5/overlay/index.metadata.json +1 -1
- package/typings/esm5/scrolling/index.metadata.json +1 -1
- package/typings/esm5/stepper/index.metadata.json +1 -1
- package/typings/esm5/stepper/public-api.d.ts +1 -0
- package/typings/esm5/stepper/step-header.d.ts +15 -0
- package/typings/esm5/stepper/stepper.d.ts +11 -1
- package/typings/esm5/text-field/autosize.d.ts +6 -0
- package/typings/esm5/text-field/index.metadata.json +1 -1
- package/typings/esm5/tree/nested-node.d.ts +5 -5
- package/typings/index.metadata.json +1 -1
- package/typings/keycodes/index.metadata.json +1 -1
- package/typings/keycodes/modifiers.d.ts +14 -0
- package/typings/keycodes/public-api.d.ts +1 -0
- package/typings/overlay/index.metadata.json +1 -1
- package/typings/schematics/utils/ast/ng-module-imports.d.ts +1 -1
- package/typings/scrolling/index.metadata.json +1 -1
- package/typings/stepper/index.metadata.json +1 -1
- package/typings/stepper/public-api.d.ts +1 -0
- package/typings/stepper/step-header.d.ts +15 -0
- package/typings/stepper/stepper.d.ts +11 -1
- package/typings/text-field/autosize.d.ts +6 -0
- package/typings/text-field/index.metadata.json +1 -1
- package/typings/tree/nested-node.d.ts +5 -5
package/esm2015/a11y.js
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
* found in the LICENSE file at https://angular.io/license
|
|
7
7
|
*/
|
|
8
8
|
import { DOCUMENT, CommonModule } from '@angular/common';
|
|
9
|
-
import { Inject, Injectable, Optional, SkipSelf, QueryList, Directive, ElementRef, Input, NgZone, InjectionToken, EventEmitter, Output, NgModule, defineInjectable, inject } from '@angular/core';
|
|
9
|
+
import { Inject, Injectable, Optional, SkipSelf, QueryList, Directive, ElementRef, Input, NgZone, isDevMode, InjectionToken, EventEmitter, Output, NgModule, defineInjectable, inject } from '@angular/core';
|
|
10
10
|
import { Subject, Subscription, of } from 'rxjs';
|
|
11
|
-
import { UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW, TAB, A, Z, ZERO, NINE } from '@angular/cdk/keycodes';
|
|
11
|
+
import { UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW, TAB, A, Z, ZERO, NINE, hasModifierKey } from '@angular/cdk/keycodes';
|
|
12
12
|
import { debounceTime, filter, map, tap, take } from 'rxjs/operators';
|
|
13
13
|
import { Platform, normalizePassiveListenerOptions, PlatformModule } from '@angular/cdk/platform';
|
|
14
14
|
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
|
@@ -16,12 +16,13 @@ import { ContentObserver, ObserversModule } from '@angular/cdk/observers';
|
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* @fileoverview added by tsickle
|
|
19
|
-
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
|
|
19
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
/**
|
|
22
|
+
/**
|
|
23
23
|
* IDs are deliminated by an empty space, as per the spec.
|
|
24
|
-
|
|
24
|
+
* @type {?}
|
|
25
|
+
*/
|
|
25
26
|
const ID_DELIMINATOR = ' ';
|
|
26
27
|
/**
|
|
27
28
|
* Adds the given ID to the specified ARIA attribute on an element.
|
|
@@ -69,31 +70,37 @@ function getAriaReferenceIds(el, attr) {
|
|
|
69
70
|
|
|
70
71
|
/**
|
|
71
72
|
* @fileoverview added by tsickle
|
|
72
|
-
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
|
|
73
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
73
74
|
*/
|
|
74
|
-
/**
|
|
75
|
+
/**
|
|
75
76
|
* ID used for the body container where all messages are appended.
|
|
76
|
-
|
|
77
|
+
* @type {?}
|
|
78
|
+
*/
|
|
77
79
|
const MESSAGES_CONTAINER_ID = 'cdk-describedby-message-container';
|
|
78
|
-
/**
|
|
80
|
+
/**
|
|
79
81
|
* ID prefix used for each created message element.
|
|
80
|
-
|
|
82
|
+
* @type {?}
|
|
83
|
+
*/
|
|
81
84
|
const CDK_DESCRIBEDBY_ID_PREFIX = 'cdk-describedby-message';
|
|
82
|
-
/**
|
|
85
|
+
/**
|
|
83
86
|
* Attribute given to each host element that is described by a message element.
|
|
84
|
-
|
|
87
|
+
* @type {?}
|
|
88
|
+
*/
|
|
85
89
|
const CDK_DESCRIBEDBY_HOST_ATTRIBUTE = 'cdk-describedby-host';
|
|
86
|
-
/**
|
|
90
|
+
/**
|
|
87
91
|
* Global incremental identifier for each registered message element.
|
|
88
|
-
|
|
92
|
+
* @type {?}
|
|
93
|
+
*/
|
|
89
94
|
let nextId = 0;
|
|
90
|
-
/**
|
|
95
|
+
/**
|
|
91
96
|
* Global map of all registered message elements that have been placed into the document.
|
|
92
|
-
|
|
97
|
+
* @type {?}
|
|
98
|
+
*/
|
|
93
99
|
const messageRegistry = new Map();
|
|
94
|
-
/**
|
|
100
|
+
/**
|
|
95
101
|
* Container for all registered messages.
|
|
96
|
-
|
|
102
|
+
* @type {?}
|
|
103
|
+
*/
|
|
97
104
|
let messagesContainer = null;
|
|
98
105
|
/**
|
|
99
106
|
* Utility that creates visually hidden elements with a message content. Useful for elements that
|
|
@@ -168,6 +175,7 @@ class AriaDescriber {
|
|
|
168
175
|
/**
|
|
169
176
|
* Creates a new element in the visually hidden message container element with the message
|
|
170
177
|
* as its content and adds it to the message registry.
|
|
178
|
+
* @private
|
|
171
179
|
* @param {?} message
|
|
172
180
|
* @return {?}
|
|
173
181
|
*/
|
|
@@ -175,13 +183,14 @@ class AriaDescriber {
|
|
|
175
183
|
/** @type {?} */
|
|
176
184
|
const messageElement = this._document.createElement('div');
|
|
177
185
|
messageElement.setAttribute('id', `${CDK_DESCRIBEDBY_ID_PREFIX}-${nextId++}`);
|
|
178
|
-
messageElement.appendChild(/** @type {?} */ (
|
|
179
|
-
this._createMessagesContainer();
|
|
180
|
-
((messagesContainer)).appendChild(messageElement);
|
|
186
|
+
messageElement.appendChild((/** @type {?} */ (this._document.createTextNode(message))));
|
|
187
|
+
this._createMessagesContainer();
|
|
188
|
+
(/** @type {?} */ (messagesContainer)).appendChild(messageElement);
|
|
181
189
|
messageRegistry.set(message, { messageElement, referenceCount: 0 });
|
|
182
190
|
}
|
|
183
191
|
/**
|
|
184
192
|
* Deletes the message element from the global messages container.
|
|
193
|
+
* @private
|
|
185
194
|
* @param {?} message
|
|
186
195
|
* @return {?}
|
|
187
196
|
*/
|
|
@@ -197,6 +206,7 @@ class AriaDescriber {
|
|
|
197
206
|
}
|
|
198
207
|
/**
|
|
199
208
|
* Creates the global container for all aria-describedby messages.
|
|
209
|
+
* @private
|
|
200
210
|
* @return {?}
|
|
201
211
|
*/
|
|
202
212
|
_createMessagesContainer() {
|
|
@@ -208,7 +218,7 @@ class AriaDescriber {
|
|
|
208
218
|
// old container so we don't get duplicates. Doing this, instead of emptying the previous
|
|
209
219
|
// container, should be slightly faster.
|
|
210
220
|
if (preExistingContainer) {
|
|
211
|
-
/** @type {?} */ (
|
|
221
|
+
(/** @type {?} */ (preExistingContainer.parentNode)).removeChild(preExistingContainer);
|
|
212
222
|
}
|
|
213
223
|
messagesContainer = this._document.createElement('div');
|
|
214
224
|
messagesContainer.id = MESSAGES_CONTAINER_ID;
|
|
@@ -219,6 +229,7 @@ class AriaDescriber {
|
|
|
219
229
|
}
|
|
220
230
|
/**
|
|
221
231
|
* Deletes the global messages container.
|
|
232
|
+
* @private
|
|
222
233
|
* @return {?}
|
|
223
234
|
*/
|
|
224
235
|
_deleteMessagesContainer() {
|
|
@@ -229,10 +240,12 @@ class AriaDescriber {
|
|
|
229
240
|
}
|
|
230
241
|
/**
|
|
231
242
|
* Removes all cdk-describedby messages that are hosted through the element.
|
|
243
|
+
* @private
|
|
232
244
|
* @param {?} element
|
|
233
245
|
* @return {?}
|
|
234
246
|
*/
|
|
235
247
|
_removeCdkDescribedByReferenceIds(element) {
|
|
248
|
+
// Remove all aria-describedby reference IDs that are prefixed by CDK_DESCRIBEDBY_ID_PREFIX
|
|
236
249
|
/** @type {?} */
|
|
237
250
|
const originalReferenceIds = getAriaReferenceIds(element, 'aria-describedby')
|
|
238
251
|
.filter(id => id.indexOf(CDK_DESCRIBEDBY_ID_PREFIX) != 0);
|
|
@@ -241,13 +254,14 @@ class AriaDescriber {
|
|
|
241
254
|
/**
|
|
242
255
|
* Adds a message reference to the element using aria-describedby and increments the registered
|
|
243
256
|
* message's reference count.
|
|
257
|
+
* @private
|
|
244
258
|
* @param {?} element
|
|
245
259
|
* @param {?} message
|
|
246
260
|
* @return {?}
|
|
247
261
|
*/
|
|
248
262
|
_addMessageReference(element, message) {
|
|
249
263
|
/** @type {?} */
|
|
250
|
-
const registeredMessage = /** @type {?} */ (
|
|
264
|
+
const registeredMessage = (/** @type {?} */ (messageRegistry.get(message)));
|
|
251
265
|
// Add the aria-describedby reference and set the
|
|
252
266
|
// describedby_host attribute to mark the element.
|
|
253
267
|
addAriaReferencedId(element, 'aria-describedby', registeredMessage.messageElement.id);
|
|
@@ -257,19 +271,21 @@ class AriaDescriber {
|
|
|
257
271
|
/**
|
|
258
272
|
* Removes a message reference from the element using aria-describedby
|
|
259
273
|
* and decrements the registered message's reference count.
|
|
274
|
+
* @private
|
|
260
275
|
* @param {?} element
|
|
261
276
|
* @param {?} message
|
|
262
277
|
* @return {?}
|
|
263
278
|
*/
|
|
264
279
|
_removeMessageReference(element, message) {
|
|
265
280
|
/** @type {?} */
|
|
266
|
-
const registeredMessage = /** @type {?} */ (
|
|
281
|
+
const registeredMessage = (/** @type {?} */ (messageRegistry.get(message)));
|
|
267
282
|
registeredMessage.referenceCount--;
|
|
268
283
|
removeAriaReferencedId(element, 'aria-describedby', registeredMessage.messageElement.id);
|
|
269
284
|
element.removeAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE);
|
|
270
285
|
}
|
|
271
286
|
/**
|
|
272
287
|
* Returns true if the element has been described by the provided message ID.
|
|
288
|
+
* @private
|
|
273
289
|
* @param {?} element
|
|
274
290
|
* @param {?} message
|
|
275
291
|
* @return {?}
|
|
@@ -285,6 +301,7 @@ class AriaDescriber {
|
|
|
285
301
|
}
|
|
286
302
|
/**
|
|
287
303
|
* Determines whether a message can be described on a particular element.
|
|
304
|
+
* @private
|
|
288
305
|
* @param {?} element
|
|
289
306
|
* @param {?} message
|
|
290
307
|
* @return {?}
|
|
@@ -311,24 +328,24 @@ AriaDescriber.ctorParameters = () => [
|
|
|
311
328
|
function ARIA_DESCRIBER_PROVIDER_FACTORY(parentDispatcher, _document) {
|
|
312
329
|
return parentDispatcher || new AriaDescriber(_document);
|
|
313
330
|
}
|
|
314
|
-
/**
|
|
331
|
+
/**
|
|
315
332
|
* \@docs-private \@deprecated \@breaking-change 8.0.0
|
|
316
|
-
|
|
333
|
+
* @type {?}
|
|
334
|
+
*/
|
|
317
335
|
const ARIA_DESCRIBER_PROVIDER = {
|
|
318
336
|
// If there is already an AriaDescriber available, use that. Otherwise, provide a new one.
|
|
319
337
|
provide: AriaDescriber,
|
|
320
338
|
deps: [
|
|
321
339
|
[new Optional(), new SkipSelf(), AriaDescriber],
|
|
322
|
-
/** @type {?} */ (DOCUMENT)
|
|
340
|
+
(/** @type {?} */ (DOCUMENT))
|
|
323
341
|
],
|
|
324
342
|
useFactory: ARIA_DESCRIBER_PROVIDER_FACTORY
|
|
325
343
|
};
|
|
326
344
|
|
|
327
345
|
/**
|
|
328
346
|
* @fileoverview added by tsickle
|
|
329
|
-
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
|
|
347
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
330
348
|
*/
|
|
331
|
-
// unsupported: template constraints.
|
|
332
349
|
/**
|
|
333
350
|
* This class manages keyboard events for selectable lists. If you pass it a query list
|
|
334
351
|
* of items, it will set the active item correctly when arrow events occur.
|
|
@@ -341,15 +358,18 @@ class ListKeyManager {
|
|
|
341
358
|
constructor(_items) {
|
|
342
359
|
this._items = _items;
|
|
343
360
|
this._activeItemIndex = -1;
|
|
361
|
+
this._activeItem = null;
|
|
344
362
|
this._wrap = false;
|
|
345
363
|
this._letterKeyStream = new Subject();
|
|
346
364
|
this._typeaheadSubscription = Subscription.EMPTY;
|
|
347
365
|
this._vertical = true;
|
|
366
|
+
this._allowedModifierKeys = [];
|
|
348
367
|
/**
|
|
349
368
|
* Predicate function that can be used to check whether an item should be skipped
|
|
350
369
|
* by the key manager. By default, disabled items are skipped.
|
|
351
370
|
*/
|
|
352
371
|
this._skipPredicateFn = (item) => item.disabled;
|
|
372
|
+
// Buffer for the letters that the user has pressed when the typeahead option is turned on.
|
|
353
373
|
this._pressedLetters = [];
|
|
354
374
|
/**
|
|
355
375
|
* Stream that emits any time the TAB key is pressed, so components can react
|
|
@@ -380,73 +400,96 @@ class ListKeyManager {
|
|
|
380
400
|
/**
|
|
381
401
|
* Sets the predicate function that determines which items should be skipped by the
|
|
382
402
|
* list key manager.
|
|
403
|
+
* @template THIS
|
|
404
|
+
* @this {THIS}
|
|
383
405
|
* @param {?} predicate Function that determines whether the given item should be skipped.
|
|
384
|
-
* @return {
|
|
406
|
+
* @return {THIS}
|
|
385
407
|
*/
|
|
386
408
|
skipPredicate(predicate) {
|
|
387
|
-
this._skipPredicateFn = predicate;
|
|
388
|
-
return this;
|
|
409
|
+
(/** @type {?} */ (this))._skipPredicateFn = predicate;
|
|
410
|
+
return (/** @type {?} */ (this));
|
|
389
411
|
}
|
|
390
412
|
/**
|
|
391
413
|
* Configures wrapping mode, which determines whether the active item will wrap to
|
|
392
414
|
* the other end of list when there are no more items in the given direction.
|
|
415
|
+
* @template THIS
|
|
416
|
+
* @this {THIS}
|
|
393
417
|
* @param {?=} shouldWrap Whether the list should wrap when reaching the end.
|
|
394
|
-
* @return {
|
|
418
|
+
* @return {THIS}
|
|
395
419
|
*/
|
|
396
420
|
withWrap(shouldWrap = true) {
|
|
397
|
-
this._wrap = shouldWrap;
|
|
398
|
-
return this;
|
|
421
|
+
(/** @type {?} */ (this))._wrap = shouldWrap;
|
|
422
|
+
return (/** @type {?} */ (this));
|
|
399
423
|
}
|
|
400
424
|
/**
|
|
401
425
|
* Configures whether the key manager should be able to move the selection vertically.
|
|
426
|
+
* @template THIS
|
|
427
|
+
* @this {THIS}
|
|
402
428
|
* @param {?=} enabled Whether vertical selection should be enabled.
|
|
403
|
-
* @return {
|
|
429
|
+
* @return {THIS}
|
|
404
430
|
*/
|
|
405
431
|
withVerticalOrientation(enabled = true) {
|
|
406
|
-
this._vertical = enabled;
|
|
407
|
-
return this;
|
|
432
|
+
(/** @type {?} */ (this))._vertical = enabled;
|
|
433
|
+
return (/** @type {?} */ (this));
|
|
408
434
|
}
|
|
409
435
|
/**
|
|
410
436
|
* Configures the key manager to move the selection horizontally.
|
|
411
437
|
* Passing in `null` will disable horizontal movement.
|
|
438
|
+
* @template THIS
|
|
439
|
+
* @this {THIS}
|
|
412
440
|
* @param {?} direction Direction in which the selection can be moved.
|
|
413
|
-
* @return {
|
|
441
|
+
* @return {THIS}
|
|
414
442
|
*/
|
|
415
443
|
withHorizontalOrientation(direction) {
|
|
416
|
-
this._horizontal = direction;
|
|
417
|
-
return this;
|
|
444
|
+
(/** @type {?} */ (this))._horizontal = direction;
|
|
445
|
+
return (/** @type {?} */ (this));
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Modifier keys which are allowed to be held down and whose default actions will be prevented
|
|
449
|
+
* as the user is pressing the arrow keys. Defaults to not allowing any modifier keys.
|
|
450
|
+
* @template THIS
|
|
451
|
+
* @this {THIS}
|
|
452
|
+
* @param {?} keys
|
|
453
|
+
* @return {THIS}
|
|
454
|
+
*/
|
|
455
|
+
withAllowedModifierKeys(keys) {
|
|
456
|
+
(/** @type {?} */ (this))._allowedModifierKeys = keys;
|
|
457
|
+
return (/** @type {?} */ (this));
|
|
418
458
|
}
|
|
419
459
|
/**
|
|
420
460
|
* Turns on typeahead mode which allows users to set the active item by typing.
|
|
461
|
+
* @template THIS
|
|
462
|
+
* @this {THIS}
|
|
421
463
|
* @param {?=} debounceInterval Time to wait after the last keystroke before setting the active item.
|
|
422
|
-
* @return {
|
|
464
|
+
* @return {THIS}
|
|
423
465
|
*/
|
|
424
466
|
withTypeAhead(debounceInterval = 200) {
|
|
425
|
-
if (this._items.length && this._items.some(item => typeof item.getLabel !== 'function')) {
|
|
467
|
+
if ((/** @type {?} */ (this))._items.length && (/** @type {?} */ (this))._items.some(item => typeof item.getLabel !== 'function')) {
|
|
426
468
|
throw Error('ListKeyManager items in typeahead mode must implement the `getLabel` method.');
|
|
427
469
|
}
|
|
428
|
-
this._typeaheadSubscription.unsubscribe();
|
|
470
|
+
(/** @type {?} */ (this))._typeaheadSubscription.unsubscribe();
|
|
429
471
|
// Debounce the presses of non-navigational keys, collect the ones that correspond to letters
|
|
430
472
|
// and convert those letters back into a string. Afterwards find the first item that starts
|
|
431
473
|
// with that string and select it.
|
|
432
|
-
this._typeaheadSubscription = this._letterKeyStream.pipe(tap(keyCode => this._pressedLetters.push(keyCode)), debounceTime(debounceInterval), filter(() => this._pressedLetters.length > 0), map(() => this._pressedLetters.join(''))).subscribe(inputString => {
|
|
474
|
+
(/** @type {?} */ (this))._typeaheadSubscription = (/** @type {?} */ (this))._letterKeyStream.pipe(tap(keyCode => (/** @type {?} */ (this))._pressedLetters.push(keyCode)), debounceTime(debounceInterval), filter(() => (/** @type {?} */ (this))._pressedLetters.length > 0), map(() => (/** @type {?} */ (this))._pressedLetters.join(''))).subscribe(inputString => {
|
|
433
475
|
/** @type {?} */
|
|
434
|
-
const items = this._getItemsArray();
|
|
476
|
+
const items = (/** @type {?} */ (this))._getItemsArray();
|
|
435
477
|
// Start at 1 because we want to start searching at the item immediately
|
|
436
478
|
// following the current active item.
|
|
437
479
|
for (let i = 1; i < items.length + 1; i++) {
|
|
438
480
|
/** @type {?} */
|
|
439
|
-
const index = (this._activeItemIndex + i) % items.length;
|
|
481
|
+
const index = ((/** @type {?} */ (this))._activeItemIndex + i) % items.length;
|
|
440
482
|
/** @type {?} */
|
|
441
483
|
const item = items[index];
|
|
442
|
-
if (!
|
|
443
|
-
|
|
484
|
+
if (!(/** @type {?} */ (this))._skipPredicateFn(item) &&
|
|
485
|
+
(/** @type {?} */ (item.getLabel))().toUpperCase().trim().indexOf(inputString) === 0) {
|
|
486
|
+
(/** @type {?} */ (this)).setActiveItem(index);
|
|
444
487
|
break;
|
|
445
488
|
}
|
|
446
489
|
}
|
|
447
|
-
this._pressedLetters = [];
|
|
490
|
+
(/** @type {?} */ (this))._pressedLetters = [];
|
|
448
491
|
});
|
|
449
|
-
return this;
|
|
492
|
+
return (/** @type {?} */ (this));
|
|
450
493
|
}
|
|
451
494
|
/**
|
|
452
495
|
* @param {?} item
|
|
@@ -468,12 +511,18 @@ class ListKeyManager {
|
|
|
468
511
|
onKeydown(event) {
|
|
469
512
|
/** @type {?} */
|
|
470
513
|
const keyCode = event.keyCode;
|
|
514
|
+
/** @type {?} */
|
|
515
|
+
const modifiers = ['altKey', 'ctrlKey', 'metaKey', 'shiftKey'];
|
|
516
|
+
/** @type {?} */
|
|
517
|
+
const isModifierAllowed = modifiers.every(modifier => {
|
|
518
|
+
return !event[modifier] || this._allowedModifierKeys.indexOf(modifier) > -1;
|
|
519
|
+
});
|
|
471
520
|
switch (keyCode) {
|
|
472
521
|
case TAB:
|
|
473
522
|
this.tabOut.next();
|
|
474
523
|
return;
|
|
475
524
|
case DOWN_ARROW:
|
|
476
|
-
if (this._vertical) {
|
|
525
|
+
if (this._vertical && isModifierAllowed) {
|
|
477
526
|
this.setNextItemActive();
|
|
478
527
|
break;
|
|
479
528
|
}
|
|
@@ -481,7 +530,7 @@ class ListKeyManager {
|
|
|
481
530
|
return;
|
|
482
531
|
}
|
|
483
532
|
case UP_ARROW:
|
|
484
|
-
if (this._vertical) {
|
|
533
|
+
if (this._vertical && isModifierAllowed) {
|
|
485
534
|
this.setPreviousItemActive();
|
|
486
535
|
break;
|
|
487
536
|
}
|
|
@@ -489,37 +538,31 @@ class ListKeyManager {
|
|
|
489
538
|
return;
|
|
490
539
|
}
|
|
491
540
|
case RIGHT_ARROW:
|
|
492
|
-
if (this._horizontal
|
|
493
|
-
this.setNextItemActive();
|
|
494
|
-
break;
|
|
495
|
-
}
|
|
496
|
-
else if (this._horizontal === 'rtl') {
|
|
497
|
-
this.setPreviousItemActive();
|
|
541
|
+
if (this._horizontal && isModifierAllowed) {
|
|
542
|
+
this._horizontal === 'rtl' ? this.setPreviousItemActive() : this.setNextItemActive();
|
|
498
543
|
break;
|
|
499
544
|
}
|
|
500
545
|
else {
|
|
501
546
|
return;
|
|
502
547
|
}
|
|
503
548
|
case LEFT_ARROW:
|
|
504
|
-
if (this._horizontal
|
|
505
|
-
this.setPreviousItemActive();
|
|
506
|
-
break;
|
|
507
|
-
}
|
|
508
|
-
else if (this._horizontal === 'rtl') {
|
|
509
|
-
this.setNextItemActive();
|
|
549
|
+
if (this._horizontal && isModifierAllowed) {
|
|
550
|
+
this._horizontal === 'rtl' ? this.setNextItemActive() : this.setPreviousItemActive();
|
|
510
551
|
break;
|
|
511
552
|
}
|
|
512
553
|
else {
|
|
513
554
|
return;
|
|
514
555
|
}
|
|
515
556
|
default:
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
557
|
+
if (isModifierAllowed || hasModifierKey(event, 'shiftKey')) {
|
|
558
|
+
// Attempt to use the `event.key` which also maps it to the user's keyboard language,
|
|
559
|
+
// otherwise fall back to resolving alphanumeric characters via the keyCode.
|
|
560
|
+
if (event.key && event.key.length === 1) {
|
|
561
|
+
this._letterKeyStream.next(event.key.toLocaleUpperCase());
|
|
562
|
+
}
|
|
563
|
+
else if ((keyCode >= A && keyCode <= Z) || (keyCode >= ZERO && keyCode <= NINE)) {
|
|
564
|
+
this._letterKeyStream.next(String.fromCharCode(keyCode));
|
|
565
|
+
}
|
|
523
566
|
}
|
|
524
567
|
// Note that we return here, in order to avoid preventing
|
|
525
568
|
// the default action of non-navigational keys.
|
|
@@ -580,8 +623,11 @@ class ListKeyManager {
|
|
|
580
623
|
const itemArray = this._getItemsArray();
|
|
581
624
|
/** @type {?} */
|
|
582
625
|
const index = typeof item === 'number' ? item : itemArray.indexOf(item);
|
|
626
|
+
/** @type {?} */
|
|
627
|
+
const activeItem = itemArray[index];
|
|
628
|
+
// Explicitly check for `null` and `undefined` because other falsy values are valid.
|
|
629
|
+
this._activeItem = activeItem == null ? null : activeItem;
|
|
583
630
|
this._activeItemIndex = index;
|
|
584
|
-
this._activeItem = itemArray[index];
|
|
585
631
|
}
|
|
586
632
|
/**
|
|
587
633
|
* Allows setting of the activeItemIndex without any other effects.
|
|
@@ -597,6 +643,7 @@ class ListKeyManager {
|
|
|
597
643
|
* This method sets the active item, given a list of items and the delta between the
|
|
598
644
|
* currently active item and the new active item. It will calculate differently
|
|
599
645
|
* depending on whether wrap mode is turned on.
|
|
646
|
+
* @private
|
|
600
647
|
* @param {?} delta
|
|
601
648
|
* @return {?}
|
|
602
649
|
*/
|
|
@@ -607,6 +654,7 @@ class ListKeyManager {
|
|
|
607
654
|
* Sets the active item properly given "wrap" mode. In other words, it will continue to move
|
|
608
655
|
* down the list until it finds an item that is not disabled, and it will wrap if it
|
|
609
656
|
* encounters either end of the list.
|
|
657
|
+
* @private
|
|
610
658
|
* @param {?} delta
|
|
611
659
|
* @return {?}
|
|
612
660
|
*/
|
|
@@ -628,6 +676,7 @@ class ListKeyManager {
|
|
|
628
676
|
* Sets the active item properly given the default mode. In other words, it will
|
|
629
677
|
* continue to move down the list until it finds an item that is not disabled. If
|
|
630
678
|
* it encounters either end of the list, it will stop and not wrap.
|
|
679
|
+
* @private
|
|
631
680
|
* @param {?} delta
|
|
632
681
|
* @return {?}
|
|
633
682
|
*/
|
|
@@ -638,6 +687,7 @@ class ListKeyManager {
|
|
|
638
687
|
* Sets the active item to the first enabled item starting at the index specified. If the
|
|
639
688
|
* item is disabled, it will move in the fallbackDelta direction until it either
|
|
640
689
|
* finds an enabled item or encounters the end of the list.
|
|
690
|
+
* @private
|
|
641
691
|
* @param {?} index
|
|
642
692
|
* @param {?} fallbackDelta
|
|
643
693
|
* @return {?}
|
|
@@ -658,6 +708,7 @@ class ListKeyManager {
|
|
|
658
708
|
}
|
|
659
709
|
/**
|
|
660
710
|
* Returns the items as an array.
|
|
711
|
+
* @private
|
|
661
712
|
* @return {?}
|
|
662
713
|
*/
|
|
663
714
|
_getItemsArray() {
|
|
@@ -667,7 +718,7 @@ class ListKeyManager {
|
|
|
667
718
|
|
|
668
719
|
/**
|
|
669
720
|
* @fileoverview added by tsickle
|
|
670
|
-
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
|
|
721
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
671
722
|
*/
|
|
672
723
|
/**
|
|
673
724
|
* @template T
|
|
@@ -690,7 +741,7 @@ class ActiveDescendantKeyManager extends ListKeyManager {
|
|
|
690
741
|
|
|
691
742
|
/**
|
|
692
743
|
* @fileoverview added by tsickle
|
|
693
|
-
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
|
|
744
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
694
745
|
*/
|
|
695
746
|
/**
|
|
696
747
|
* @template T
|
|
@@ -702,12 +753,14 @@ class FocusKeyManager extends ListKeyManager {
|
|
|
702
753
|
}
|
|
703
754
|
/**
|
|
704
755
|
* Sets the focus origin that will be passed in to the items for any subsequent `focus` calls.
|
|
756
|
+
* @template THIS
|
|
757
|
+
* @this {THIS}
|
|
705
758
|
* @param {?} origin Focus origin to be used when focusing items.
|
|
706
|
-
* @return {
|
|
759
|
+
* @return {THIS}
|
|
707
760
|
*/
|
|
708
761
|
setFocusOrigin(origin) {
|
|
709
|
-
this._origin = origin;
|
|
710
|
-
return this;
|
|
762
|
+
(/** @type {?} */ (this))._origin = origin;
|
|
763
|
+
return (/** @type {?} */ (this));
|
|
711
764
|
}
|
|
712
765
|
/**
|
|
713
766
|
* @param {?} item
|
|
@@ -723,8 +776,11 @@ class FocusKeyManager extends ListKeyManager {
|
|
|
723
776
|
|
|
724
777
|
/**
|
|
725
778
|
* @fileoverview added by tsickle
|
|
726
|
-
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
|
|
779
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
727
780
|
*/
|
|
781
|
+
// The InteractivityChecker leans heavily on the ally.js accessibility utilities.
|
|
782
|
+
// Methods like `isTabbable` are only covering specific edge-cases for the browsers which are
|
|
783
|
+
// supported.
|
|
728
784
|
/**
|
|
729
785
|
* Utility for checking the interactivity of an element, such as whether is is focusable or
|
|
730
786
|
* tabbable.
|
|
@@ -860,7 +916,7 @@ InteractivityChecker.ctorParameters = () => [
|
|
|
860
916
|
*/
|
|
861
917
|
function getFrameElement(window) {
|
|
862
918
|
try {
|
|
863
|
-
return /** @type {?} */ (window.frameElement);
|
|
919
|
+
return (/** @type {?} */ (window.frameElement));
|
|
864
920
|
}
|
|
865
921
|
catch (_a) {
|
|
866
922
|
return null;
|
|
@@ -949,6 +1005,7 @@ function getTabIndexValue(element) {
|
|
|
949
1005
|
if (!hasValidTabIndex(element)) {
|
|
950
1006
|
return null;
|
|
951
1007
|
}
|
|
1008
|
+
// See browser issue in Gecko https://bugzilla.mozilla.org/show_bug.cgi?id=1128054
|
|
952
1009
|
/** @type {?} */
|
|
953
1010
|
const tabIndex = parseInt(element.getAttribute('tabindex') || '', 10);
|
|
954
1011
|
return isNaN(tabIndex) ? -1 : tabIndex;
|
|
@@ -962,7 +1019,7 @@ function isPotentiallyTabbableIOS(element) {
|
|
|
962
1019
|
/** @type {?} */
|
|
963
1020
|
let nodeName = element.nodeName.toLowerCase();
|
|
964
1021
|
/** @type {?} */
|
|
965
|
-
let inputType = nodeName === 'input' && (/** @type {?} */ (element)).type;
|
|
1022
|
+
let inputType = nodeName === 'input' && ((/** @type {?} */ (element))).type;
|
|
966
1023
|
return inputType === 'text'
|
|
967
1024
|
|| inputType === 'password'
|
|
968
1025
|
|| nodeName === 'select'
|
|
@@ -996,7 +1053,7 @@ function getWindow(node) {
|
|
|
996
1053
|
|
|
997
1054
|
/**
|
|
998
1055
|
* @fileoverview added by tsickle
|
|
999
|
-
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
|
|
1056
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
1000
1057
|
*/
|
|
1001
1058
|
/**
|
|
1002
1059
|
* Class that allows for trapping focus within a DOM element.
|
|
@@ -1066,17 +1123,17 @@ class FocusTrap {
|
|
|
1066
1123
|
}
|
|
1067
1124
|
this._ngZone.runOutsideAngular(() => {
|
|
1068
1125
|
if (!this._startAnchor) {
|
|
1069
|
-
this._startAnchor = this._createAnchor();
|
|
1070
|
-
((this._startAnchor)).addEventListener('focus', () => this.focusLastTabbableElement());
|
|
1126
|
+
this._startAnchor = this._createAnchor();
|
|
1127
|
+
(/** @type {?} */ (this._startAnchor)).addEventListener('focus', () => this.focusLastTabbableElement());
|
|
1071
1128
|
}
|
|
1072
1129
|
if (!this._endAnchor) {
|
|
1073
|
-
this._endAnchor = this._createAnchor();
|
|
1074
|
-
((this._endAnchor)).addEventListener('focus', () => this.focusFirstTabbableElement());
|
|
1130
|
+
this._endAnchor = this._createAnchor();
|
|
1131
|
+
(/** @type {?} */ (this._endAnchor)).addEventListener('focus', () => this.focusFirstTabbableElement());
|
|
1075
1132
|
}
|
|
1076
1133
|
});
|
|
1077
1134
|
if (this._element.parentNode) {
|
|
1078
|
-
this._element.parentNode.insertBefore(/** @type {?} */ (
|
|
1079
|
-
this._element.parentNode.insertBefore(/** @type {?} */ (
|
|
1135
|
+
this._element.parentNode.insertBefore((/** @type {?} */ (this._startAnchor)), this._element);
|
|
1136
|
+
this._element.parentNode.insertBefore((/** @type {?} */ (this._endAnchor)), this._element.nextSibling);
|
|
1080
1137
|
this._hasAttached = true;
|
|
1081
1138
|
}
|
|
1082
1139
|
return this._hasAttached;
|
|
@@ -1116,14 +1173,16 @@ class FocusTrap {
|
|
|
1116
1173
|
}
|
|
1117
1174
|
/**
|
|
1118
1175
|
* Get the specified boundary element of the trapped region.
|
|
1176
|
+
* @private
|
|
1119
1177
|
* @param {?} bound The boundary to get (start or end of trapped region).
|
|
1120
1178
|
* @return {?} The boundary element.
|
|
1121
1179
|
*/
|
|
1122
1180
|
_getRegionBoundary(bound) {
|
|
1181
|
+
// Contains the deprecated version of selector, for temporary backwards comparability.
|
|
1123
1182
|
/** @type {?} */
|
|
1124
|
-
let markers = /** @type {?} */ (this._element.querySelectorAll(`[cdk-focus-region-${bound}], ` +
|
|
1183
|
+
let markers = (/** @type {?} */ (this._element.querySelectorAll(`[cdk-focus-region-${bound}], ` +
|
|
1125
1184
|
`[cdkFocusRegion${bound}], ` +
|
|
1126
|
-
`[cdk-focus-${bound}]`));
|
|
1185
|
+
`[cdk-focus-${bound}]`)));
|
|
1127
1186
|
for (let i = 0; i < markers.length; i++) {
|
|
1128
1187
|
// @breaking-change 8.0.0
|
|
1129
1188
|
if (markers[i].hasAttribute(`cdk-focus-${bound}`)) {
|
|
@@ -1148,9 +1207,10 @@ class FocusTrap {
|
|
|
1148
1207
|
* @return {?} Whether focus was moved successfuly.
|
|
1149
1208
|
*/
|
|
1150
1209
|
focusInitialElement() {
|
|
1210
|
+
// Contains the deprecated version of selector, for temporary backwards comparability.
|
|
1151
1211
|
/** @type {?} */
|
|
1152
|
-
const redirectToElement = /** @type {?} */ (this._element.querySelector(`[cdk-focus-initial], ` +
|
|
1153
|
-
`[cdkFocusInitial]`));
|
|
1212
|
+
const redirectToElement = (/** @type {?} */ (this._element.querySelector(`[cdk-focus-initial], ` +
|
|
1213
|
+
`[cdkFocusInitial]`)));
|
|
1154
1214
|
if (redirectToElement) {
|
|
1155
1215
|
// @breaking-change 8.0.0
|
|
1156
1216
|
if (redirectToElement.hasAttribute(`cdk-focus-initial`)) {
|
|
@@ -1158,6 +1218,11 @@ class FocusTrap {
|
|
|
1158
1218
|
`use 'cdkFocusInitial' instead. The deprecated attribute ` +
|
|
1159
1219
|
`will be removed in 8.0.0`, redirectToElement);
|
|
1160
1220
|
}
|
|
1221
|
+
// Warn the consumer if the element they've pointed to
|
|
1222
|
+
// isn't focusable, when not in production mode.
|
|
1223
|
+
if (isDevMode() && !this._checker.isFocusable(redirectToElement)) {
|
|
1224
|
+
console.warn(`Element matching '[cdkFocusInitial]' is not focusable.`, redirectToElement);
|
|
1225
|
+
}
|
|
1161
1226
|
redirectToElement.focus();
|
|
1162
1227
|
return true;
|
|
1163
1228
|
}
|
|
@@ -1196,6 +1261,7 @@ class FocusTrap {
|
|
|
1196
1261
|
}
|
|
1197
1262
|
/**
|
|
1198
1263
|
* Get the first tabbable element from a DOM subtree (inclusive).
|
|
1264
|
+
* @private
|
|
1199
1265
|
* @param {?} root
|
|
1200
1266
|
* @return {?}
|
|
1201
1267
|
*/
|
|
@@ -1203,12 +1269,14 @@ class FocusTrap {
|
|
|
1203
1269
|
if (this._checker.isFocusable(root) && this._checker.isTabbable(root)) {
|
|
1204
1270
|
return root;
|
|
1205
1271
|
}
|
|
1272
|
+
// Iterate in DOM order. Note that IE doesn't have `children` for SVG so we fall
|
|
1273
|
+
// back to `childNodes` which includes text nodes, comments etc.
|
|
1206
1274
|
/** @type {?} */
|
|
1207
1275
|
let children = root.children || root.childNodes;
|
|
1208
1276
|
for (let i = 0; i < children.length; i++) {
|
|
1209
1277
|
/** @type {?} */
|
|
1210
1278
|
let tabbableChild = children[i].nodeType === this._document.ELEMENT_NODE ?
|
|
1211
|
-
this._getFirstTabbableElement(/** @type {?} */ (children[i])) :
|
|
1279
|
+
this._getFirstTabbableElement((/** @type {?} */ (children[i]))) :
|
|
1212
1280
|
null;
|
|
1213
1281
|
if (tabbableChild) {
|
|
1214
1282
|
return tabbableChild;
|
|
@@ -1218,6 +1286,7 @@ class FocusTrap {
|
|
|
1218
1286
|
}
|
|
1219
1287
|
/**
|
|
1220
1288
|
* Get the last tabbable element from a DOM subtree (inclusive).
|
|
1289
|
+
* @private
|
|
1221
1290
|
* @param {?} root
|
|
1222
1291
|
* @return {?}
|
|
1223
1292
|
*/
|
|
@@ -1225,12 +1294,13 @@ class FocusTrap {
|
|
|
1225
1294
|
if (this._checker.isFocusable(root) && this._checker.isTabbable(root)) {
|
|
1226
1295
|
return root;
|
|
1227
1296
|
}
|
|
1297
|
+
// Iterate in reverse DOM order.
|
|
1228
1298
|
/** @type {?} */
|
|
1229
1299
|
let children = root.children || root.childNodes;
|
|
1230
1300
|
for (let i = children.length - 1; i >= 0; i--) {
|
|
1231
1301
|
/** @type {?} */
|
|
1232
1302
|
let tabbableChild = children[i].nodeType === this._document.ELEMENT_NODE ?
|
|
1233
|
-
this._getLastTabbableElement(/** @type {?} */ (children[i])) :
|
|
1303
|
+
this._getLastTabbableElement((/** @type {?} */ (children[i]))) :
|
|
1234
1304
|
null;
|
|
1235
1305
|
if (tabbableChild) {
|
|
1236
1306
|
return tabbableChild;
|
|
@@ -1240,6 +1310,7 @@ class FocusTrap {
|
|
|
1240
1310
|
}
|
|
1241
1311
|
/**
|
|
1242
1312
|
* Creates an anchor element.
|
|
1313
|
+
* @private
|
|
1243
1314
|
* @return {?}
|
|
1244
1315
|
*/
|
|
1245
1316
|
_createAnchor() {
|
|
@@ -1252,6 +1323,7 @@ class FocusTrap {
|
|
|
1252
1323
|
}
|
|
1253
1324
|
/**
|
|
1254
1325
|
* Toggles the `tabindex` of an anchor, based on the enabled state of the focus trap.
|
|
1326
|
+
* @private
|
|
1255
1327
|
* @param {?} isEnabled Whether the focus trap is enabled.
|
|
1256
1328
|
* @param {?} anchor Anchor on which to toggle the tabindex.
|
|
1257
1329
|
* @return {?}
|
|
@@ -1263,6 +1335,7 @@ class FocusTrap {
|
|
|
1263
1335
|
}
|
|
1264
1336
|
/**
|
|
1265
1337
|
* Executes a function when the zone is stable.
|
|
1338
|
+
* @private
|
|
1266
1339
|
* @param {?} fn
|
|
1267
1340
|
* @return {?}
|
|
1268
1341
|
*/
|
|
@@ -1368,7 +1441,7 @@ class CdkTrapFocus {
|
|
|
1368
1441
|
ngAfterContentInit() {
|
|
1369
1442
|
this.focusTrap.attachAnchors();
|
|
1370
1443
|
if (this.autoCapture) {
|
|
1371
|
-
this._previouslyFocusedElement = /** @type {?} */ (this._document.activeElement);
|
|
1444
|
+
this._previouslyFocusedElement = (/** @type {?} */ (this._document.activeElement));
|
|
1372
1445
|
this.focusTrap.focusInitialElementWhenReady();
|
|
1373
1446
|
}
|
|
1374
1447
|
}
|
|
@@ -1400,8 +1473,10 @@ CdkTrapFocus.propDecorators = {
|
|
|
1400
1473
|
|
|
1401
1474
|
/**
|
|
1402
1475
|
* @fileoverview added by tsickle
|
|
1403
|
-
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
|
|
1476
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
1404
1477
|
*/
|
|
1478
|
+
// The token for the live announcer element is defined in a separate file from LiveAnnouncer
|
|
1479
|
+
// as a workaround for https://github.com/angular/angular/issues/22559
|
|
1405
1480
|
/** @type {?} */
|
|
1406
1481
|
const LIVE_ANNOUNCER_ELEMENT_TOKEN = new InjectionToken('liveAnnouncerElement', {
|
|
1407
1482
|
providedIn: 'root',
|
|
@@ -1417,7 +1492,7 @@ function LIVE_ANNOUNCER_ELEMENT_TOKEN_FACTORY() {
|
|
|
1417
1492
|
|
|
1418
1493
|
/**
|
|
1419
1494
|
* @fileoverview added by tsickle
|
|
1420
|
-
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
|
|
1495
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
1421
1496
|
*/
|
|
1422
1497
|
class LiveAnnouncer {
|
|
1423
1498
|
/**
|
|
@@ -1434,15 +1509,25 @@ class LiveAnnouncer {
|
|
|
1434
1509
|
this._liveElement = elementToken || this._createLiveElement();
|
|
1435
1510
|
}
|
|
1436
1511
|
/**
|
|
1437
|
-
*
|
|
1438
|
-
* @param {
|
|
1439
|
-
* @
|
|
1440
|
-
* @return {?} Promise that will be resolved when the message is added to the DOM.
|
|
1512
|
+
* @param {?} message
|
|
1513
|
+
* @param {...?} args
|
|
1514
|
+
* @return {?}
|
|
1441
1515
|
*/
|
|
1442
|
-
announce(message,
|
|
1443
|
-
|
|
1516
|
+
announce(message, ...args) {
|
|
1517
|
+
/** @type {?} */
|
|
1518
|
+
let politeness;
|
|
1519
|
+
/** @type {?} */
|
|
1520
|
+
let duration;
|
|
1521
|
+
if (args.length === 1 && typeof args[0] === 'number') {
|
|
1522
|
+
duration = args[0];
|
|
1523
|
+
}
|
|
1524
|
+
else {
|
|
1525
|
+
[politeness, duration] = args;
|
|
1526
|
+
}
|
|
1527
|
+
this.clear();
|
|
1528
|
+
clearTimeout(this._previousTimeout);
|
|
1444
1529
|
// TODO: ensure changing the politeness works on all environments we support.
|
|
1445
|
-
this._liveElement.setAttribute('aria-live', politeness);
|
|
1530
|
+
this._liveElement.setAttribute('aria-live', (/** @type {?} */ (politeness)) || 'polite');
|
|
1446
1531
|
// This 100ms timeout is necessary for some browser + screen-reader combinations:
|
|
1447
1532
|
// - Both JAWS and NVDA over IE11 will not announce anything without a non-zero timeout.
|
|
1448
1533
|
// - With Chrome and IE11 with NVDA or JAWS, a repeated (identical) message won't be read a
|
|
@@ -1450,22 +1535,40 @@ class LiveAnnouncer {
|
|
|
1450
1535
|
// (using JAWS 17 at time of this writing).
|
|
1451
1536
|
return this._ngZone.runOutsideAngular(() => {
|
|
1452
1537
|
return new Promise(resolve => {
|
|
1453
|
-
|
|
1538
|
+
clearTimeout(this._previousTimeout);
|
|
1539
|
+
this._previousTimeout = setTimeout(() => {
|
|
1454
1540
|
this._liveElement.textContent = message;
|
|
1455
1541
|
resolve();
|
|
1542
|
+
if (typeof duration === 'number') {
|
|
1543
|
+
this._previousTimeout = setTimeout(() => this.clear(), duration);
|
|
1544
|
+
}
|
|
1456
1545
|
}, 100);
|
|
1457
1546
|
});
|
|
1458
1547
|
});
|
|
1459
1548
|
}
|
|
1549
|
+
/**
|
|
1550
|
+
* Clears the current text from the announcer element. Can be used to prevent
|
|
1551
|
+
* screen readers from reading the text out again while the user is going
|
|
1552
|
+
* through the page landmarks.
|
|
1553
|
+
* @return {?}
|
|
1554
|
+
*/
|
|
1555
|
+
clear() {
|
|
1556
|
+
if (this._liveElement) {
|
|
1557
|
+
this._liveElement.textContent = '';
|
|
1558
|
+
}
|
|
1559
|
+
}
|
|
1460
1560
|
/**
|
|
1461
1561
|
* @return {?}
|
|
1462
1562
|
*/
|
|
1463
1563
|
ngOnDestroy() {
|
|
1564
|
+
clearTimeout(this._previousTimeout);
|
|
1464
1565
|
if (this._liveElement && this._liveElement.parentNode) {
|
|
1465
1566
|
this._liveElement.parentNode.removeChild(this._liveElement);
|
|
1567
|
+
this._liveElement = (/** @type {?} */ (null));
|
|
1466
1568
|
}
|
|
1467
1569
|
}
|
|
1468
1570
|
/**
|
|
1571
|
+
* @private
|
|
1469
1572
|
* @return {?}
|
|
1470
1573
|
*/
|
|
1471
1574
|
_createLiveElement() {
|
|
@@ -1477,7 +1580,7 @@ class LiveAnnouncer {
|
|
|
1477
1580
|
const liveEl = this._document.createElement('div');
|
|
1478
1581
|
// Remove any old containers. This can happen when coming in from a server-side-rendered page.
|
|
1479
1582
|
for (let i = 0; i < previousElements.length; i++) {
|
|
1480
|
-
/** @type {?} */ (
|
|
1583
|
+
(/** @type {?} */ (previousElements[i].parentNode)).removeChild(previousElements[i]);
|
|
1481
1584
|
}
|
|
1482
1585
|
liveEl.classList.add(elementClass);
|
|
1483
1586
|
liveEl.classList.add('cdk-visually-hidden');
|
|
@@ -1537,9 +1640,15 @@ class CdkAriaLive {
|
|
|
1537
1640
|
return this._contentObserver
|
|
1538
1641
|
.observe(this._elementRef)
|
|
1539
1642
|
.subscribe(() => {
|
|
1643
|
+
// Note that we use textContent here, rather than innerText, in order to avoid a reflow.
|
|
1540
1644
|
/** @type {?} */
|
|
1541
|
-
const
|
|
1542
|
-
|
|
1645
|
+
const elementText = this._elementRef.nativeElement.textContent;
|
|
1646
|
+
// The `MutationObserver` fires also for attribute
|
|
1647
|
+
// changes which we don't want to announce.
|
|
1648
|
+
if (elementText !== this._previousAnnouncedText) {
|
|
1649
|
+
this._liveAnnouncer.announce(elementText, this._politeness);
|
|
1650
|
+
this._previousAnnouncedText = elementText;
|
|
1651
|
+
}
|
|
1543
1652
|
});
|
|
1544
1653
|
});
|
|
1545
1654
|
}
|
|
@@ -1571,18 +1680,19 @@ CdkAriaLive.propDecorators = {
|
|
|
1571
1680
|
};
|
|
1572
1681
|
/**
|
|
1573
1682
|
* \@docs-private \@deprecated \@breaking-change 8.0.0
|
|
1574
|
-
* @param {?}
|
|
1683
|
+
* @param {?} parentAnnouncer
|
|
1575
1684
|
* @param {?} liveElement
|
|
1576
1685
|
* @param {?} _document
|
|
1577
1686
|
* @param {?} ngZone
|
|
1578
1687
|
* @return {?}
|
|
1579
1688
|
*/
|
|
1580
|
-
function LIVE_ANNOUNCER_PROVIDER_FACTORY(
|
|
1581
|
-
return
|
|
1689
|
+
function LIVE_ANNOUNCER_PROVIDER_FACTORY(parentAnnouncer, liveElement, _document, ngZone) {
|
|
1690
|
+
return parentAnnouncer || new LiveAnnouncer(liveElement, ngZone, _document);
|
|
1582
1691
|
}
|
|
1583
|
-
/**
|
|
1692
|
+
/**
|
|
1584
1693
|
* \@docs-private \@deprecated \@breaking-change 8.0.0
|
|
1585
|
-
|
|
1694
|
+
* @type {?}
|
|
1695
|
+
*/
|
|
1586
1696
|
const LIVE_ANNOUNCER_PROVIDER = {
|
|
1587
1697
|
// If there is already a LiveAnnouncer available, use that. Otherwise, provide a new one.
|
|
1588
1698
|
provide: LiveAnnouncer,
|
|
@@ -1597,10 +1707,21 @@ const LIVE_ANNOUNCER_PROVIDER = {
|
|
|
1597
1707
|
|
|
1598
1708
|
/**
|
|
1599
1709
|
* @fileoverview added by tsickle
|
|
1600
|
-
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
|
|
1710
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
1601
1711
|
*/
|
|
1712
|
+
// This is the value used by AngularJS Material. Through trial and error (on iPhone 6S) they found
|
|
1713
|
+
// that a value of around 650ms seems appropriate.
|
|
1602
1714
|
/** @type {?} */
|
|
1603
1715
|
const TOUCH_BUFFER_MS = 650;
|
|
1716
|
+
/**
|
|
1717
|
+
* Event listener options that enable capturing and also
|
|
1718
|
+
* mark the the listener as passive if the browser supports it.
|
|
1719
|
+
* @type {?}
|
|
1720
|
+
*/
|
|
1721
|
+
const captureEventListenerOptions = normalizePassiveListenerOptions({
|
|
1722
|
+
passive: true,
|
|
1723
|
+
capture: true
|
|
1724
|
+
});
|
|
1604
1725
|
/**
|
|
1605
1726
|
* Monitors mouse and keyboard events to determine the cause of focus events.
|
|
1606
1727
|
*/
|
|
@@ -1624,14 +1745,54 @@ class FocusMonitor {
|
|
|
1624
1745
|
* Map of elements being monitored to their info.
|
|
1625
1746
|
*/
|
|
1626
1747
|
this._elementInfo = new Map();
|
|
1627
|
-
/**
|
|
1628
|
-
* A map of global objects to lists of current listeners.
|
|
1629
|
-
*/
|
|
1630
|
-
this._unregisterGlobalListeners = () => { };
|
|
1631
1748
|
/**
|
|
1632
1749
|
* The number of elements currently being monitored.
|
|
1633
1750
|
*/
|
|
1634
1751
|
this._monitoredElementCount = 0;
|
|
1752
|
+
/**
|
|
1753
|
+
* Event listener for `keydown` events on the document.
|
|
1754
|
+
* Needs to be an arrow function in order to preserve the context when it gets bound.
|
|
1755
|
+
*/
|
|
1756
|
+
this._documentKeydownListener = () => {
|
|
1757
|
+
// On keydown record the origin and clear any touch event that may be in progress.
|
|
1758
|
+
this._lastTouchTarget = null;
|
|
1759
|
+
this._setOriginForCurrentEventQueue('keyboard');
|
|
1760
|
+
};
|
|
1761
|
+
/**
|
|
1762
|
+
* Event listener for `mousedown` events on the document.
|
|
1763
|
+
* Needs to be an arrow function in order to preserve the context when it gets bound.
|
|
1764
|
+
*/
|
|
1765
|
+
this._documentMousedownListener = () => {
|
|
1766
|
+
// On mousedown record the origin only if there is not touch
|
|
1767
|
+
// target, since a mousedown can happen as a result of a touch event.
|
|
1768
|
+
if (!this._lastTouchTarget) {
|
|
1769
|
+
this._setOriginForCurrentEventQueue('mouse');
|
|
1770
|
+
}
|
|
1771
|
+
};
|
|
1772
|
+
/**
|
|
1773
|
+
* Event listener for `touchstart` events on the document.
|
|
1774
|
+
* Needs to be an arrow function in order to preserve the context when it gets bound.
|
|
1775
|
+
*/
|
|
1776
|
+
this._documentTouchstartListener = (event) => {
|
|
1777
|
+
// When the touchstart event fires the focus event is not yet in the event queue. This means
|
|
1778
|
+
// we can't rely on the trick used above (setting timeout of 1ms). Instead we wait 650ms to
|
|
1779
|
+
// see if a focus happens.
|
|
1780
|
+
if (this._touchTimeoutId != null) {
|
|
1781
|
+
clearTimeout(this._touchTimeoutId);
|
|
1782
|
+
}
|
|
1783
|
+
this._lastTouchTarget = event.target;
|
|
1784
|
+
this._touchTimeoutId = setTimeout(() => this._lastTouchTarget = null, TOUCH_BUFFER_MS);
|
|
1785
|
+
};
|
|
1786
|
+
/**
|
|
1787
|
+
* Event listener for `focus` events on the window.
|
|
1788
|
+
* Needs to be an arrow function in order to preserve the context when it gets bound.
|
|
1789
|
+
*/
|
|
1790
|
+
this._windowFocusListener = () => {
|
|
1791
|
+
// Make a note of when the window regains focus, so we can
|
|
1792
|
+
// restore the origin info for the focused element.
|
|
1793
|
+
this._windowFocused = true;
|
|
1794
|
+
this._windowFocusTimeoutId = setTimeout(() => this._windowFocused = false);
|
|
1795
|
+
};
|
|
1635
1796
|
}
|
|
1636
1797
|
/**
|
|
1637
1798
|
* @param {?} element
|
|
@@ -1648,10 +1809,11 @@ class FocusMonitor {
|
|
|
1648
1809
|
// Check if we're already monitoring this element.
|
|
1649
1810
|
if (this._elementInfo.has(nativeElement)) {
|
|
1650
1811
|
/** @type {?} */
|
|
1651
|
-
let cachedInfo = this._elementInfo.get(nativeElement);
|
|
1652
|
-
((cachedInfo)).checkChildren = checkChildren;
|
|
1653
|
-
return /** @type {?} */ (
|
|
1812
|
+
let cachedInfo = this._elementInfo.get(nativeElement);
|
|
1813
|
+
(/** @type {?} */ (cachedInfo)).checkChildren = checkChildren;
|
|
1814
|
+
return (/** @type {?} */ (cachedInfo)).subject.asObservable();
|
|
1654
1815
|
}
|
|
1816
|
+
// Create monitored element info.
|
|
1655
1817
|
/** @type {?} */
|
|
1656
1818
|
let info = {
|
|
1657
1819
|
unlisten: () => { },
|
|
@@ -1660,6 +1822,7 @@ class FocusMonitor {
|
|
|
1660
1822
|
};
|
|
1661
1823
|
this._elementInfo.set(nativeElement, info);
|
|
1662
1824
|
this._incrementMonitoredElementCount();
|
|
1825
|
+
// Start listening. We need to listen in capture phase since focus events don't bubble.
|
|
1663
1826
|
/** @type {?} */
|
|
1664
1827
|
let focusListener = (event) => this._onFocus(event, nativeElement);
|
|
1665
1828
|
/** @type {?} */
|
|
@@ -1705,7 +1868,7 @@ class FocusMonitor {
|
|
|
1705
1868
|
// `focus` isn't available on the server
|
|
1706
1869
|
if (typeof nativeElement.focus === 'function') {
|
|
1707
1870
|
// Cast the element to `any`, because the TS typings don't have the `options` parameter yet.
|
|
1708
|
-
(/** @type {?} */ (nativeElement)).focus(options);
|
|
1871
|
+
((/** @type {?} */ (nativeElement))).focus(options);
|
|
1709
1872
|
}
|
|
1710
1873
|
}
|
|
1711
1874
|
/**
|
|
@@ -1715,63 +1878,7 @@ class FocusMonitor {
|
|
|
1715
1878
|
this._elementInfo.forEach((_info, element) => this.stopMonitoring(element));
|
|
1716
1879
|
}
|
|
1717
1880
|
/**
|
|
1718
|
-
*
|
|
1719
|
-
* @return {?}
|
|
1720
|
-
*/
|
|
1721
|
-
_registerGlobalListeners() {
|
|
1722
|
-
// Do nothing if we're not on the browser platform.
|
|
1723
|
-
if (!this._platform.isBrowser) {
|
|
1724
|
-
return;
|
|
1725
|
-
}
|
|
1726
|
-
/** @type {?} */
|
|
1727
|
-
let documentKeydownListener = () => {
|
|
1728
|
-
this._lastTouchTarget = null;
|
|
1729
|
-
this._setOriginForCurrentEventQueue('keyboard');
|
|
1730
|
-
};
|
|
1731
|
-
/** @type {?} */
|
|
1732
|
-
let documentMousedownListener = () => {
|
|
1733
|
-
if (!this._lastTouchTarget) {
|
|
1734
|
-
this._setOriginForCurrentEventQueue('mouse');
|
|
1735
|
-
}
|
|
1736
|
-
};
|
|
1737
|
-
/** @type {?} */
|
|
1738
|
-
let documentTouchstartListener = (event) => {
|
|
1739
|
-
if (this._touchTimeoutId != null) {
|
|
1740
|
-
clearTimeout(this._touchTimeoutId);
|
|
1741
|
-
}
|
|
1742
|
-
this._lastTouchTarget = event.target;
|
|
1743
|
-
this._touchTimeoutId = setTimeout(() => this._lastTouchTarget = null, TOUCH_BUFFER_MS);
|
|
1744
|
-
};
|
|
1745
|
-
/** @type {?} */
|
|
1746
|
-
let windowFocusListener = () => {
|
|
1747
|
-
this._windowFocused = true;
|
|
1748
|
-
this._windowFocusTimeoutId = setTimeout(() => this._windowFocused = false);
|
|
1749
|
-
};
|
|
1750
|
-
/** @type {?} */
|
|
1751
|
-
const captureEventListenerOptions = normalizePassiveListenerOptions({
|
|
1752
|
-
passive: true,
|
|
1753
|
-
capture: true
|
|
1754
|
-
});
|
|
1755
|
-
// Note: we listen to events in the capture phase so we can detect them even if the user stops
|
|
1756
|
-
// propagation.
|
|
1757
|
-
this._ngZone.runOutsideAngular(() => {
|
|
1758
|
-
document.addEventListener('keydown', documentKeydownListener, captureEventListenerOptions);
|
|
1759
|
-
document.addEventListener('mousedown', documentMousedownListener, captureEventListenerOptions);
|
|
1760
|
-
document.addEventListener('touchstart', documentTouchstartListener, captureEventListenerOptions);
|
|
1761
|
-
window.addEventListener('focus', windowFocusListener);
|
|
1762
|
-
});
|
|
1763
|
-
this._unregisterGlobalListeners = () => {
|
|
1764
|
-
document.removeEventListener('keydown', documentKeydownListener, captureEventListenerOptions);
|
|
1765
|
-
document.removeEventListener('mousedown', documentMousedownListener, captureEventListenerOptions);
|
|
1766
|
-
document.removeEventListener('touchstart', documentTouchstartListener, captureEventListenerOptions);
|
|
1767
|
-
window.removeEventListener('focus', windowFocusListener);
|
|
1768
|
-
// Clear timeouts for all potentially pending timeouts to prevent the leaks.
|
|
1769
|
-
clearTimeout(this._windowFocusTimeoutId);
|
|
1770
|
-
clearTimeout(this._touchTimeoutId);
|
|
1771
|
-
clearTimeout(this._originTimeoutId);
|
|
1772
|
-
};
|
|
1773
|
-
}
|
|
1774
|
-
/**
|
|
1881
|
+
* @private
|
|
1775
1882
|
* @param {?} element
|
|
1776
1883
|
* @param {?} className
|
|
1777
1884
|
* @param {?} shouldSet
|
|
@@ -1787,6 +1894,7 @@ class FocusMonitor {
|
|
|
1787
1894
|
}
|
|
1788
1895
|
/**
|
|
1789
1896
|
* Sets the focus classes on the element based on the given focus origin.
|
|
1897
|
+
* @private
|
|
1790
1898
|
* @param {?} element The element to update the classes on.
|
|
1791
1899
|
* @param {?=} origin The focus origin.
|
|
1792
1900
|
* @return {?}
|
|
@@ -1804,6 +1912,7 @@ class FocusMonitor {
|
|
|
1804
1912
|
}
|
|
1805
1913
|
/**
|
|
1806
1914
|
* Sets the origin and schedules an async function to clear it at the end of the event queue.
|
|
1915
|
+
* @private
|
|
1807
1916
|
* @param {?} origin The origin to set.
|
|
1808
1917
|
* @return {?}
|
|
1809
1918
|
*/
|
|
@@ -1818,10 +1927,28 @@ class FocusMonitor {
|
|
|
1818
1927
|
}
|
|
1819
1928
|
/**
|
|
1820
1929
|
* Checks whether the given focus event was caused by a touchstart event.
|
|
1930
|
+
* @private
|
|
1821
1931
|
* @param {?} event The focus event to check.
|
|
1822
1932
|
* @return {?} Whether the event was caused by a touch.
|
|
1823
1933
|
*/
|
|
1824
1934
|
_wasCausedByTouch(event) {
|
|
1935
|
+
// Note(mmalerba): This implementation is not quite perfect, there is a small edge case.
|
|
1936
|
+
// Consider the following dom structure:
|
|
1937
|
+
//
|
|
1938
|
+
// <div #parent tabindex="0" cdkFocusClasses>
|
|
1939
|
+
// <div #child (click)="#parent.focus()"></div>
|
|
1940
|
+
// </div>
|
|
1941
|
+
//
|
|
1942
|
+
// If the user touches the #child element and the #parent is programmatically focused as a
|
|
1943
|
+
// result, this code will still consider it to have been caused by the touch event and will
|
|
1944
|
+
// apply the cdk-touch-focused class rather than the cdk-program-focused class. This is a
|
|
1945
|
+
// relatively small edge-case that can be worked around by using
|
|
1946
|
+
// focusVia(parentEl, 'program') to focus the parent element.
|
|
1947
|
+
//
|
|
1948
|
+
// If we decide that we absolutely must handle this case correctly, we can do so by listening
|
|
1949
|
+
// for the first focus event after the touchstart, and then the first blur event after that
|
|
1950
|
+
// focus event. When that blur event fires we know that whatever follows is not a result of the
|
|
1951
|
+
// touchstart.
|
|
1825
1952
|
/** @type {?} */
|
|
1826
1953
|
let focusTarget = event.target;
|
|
1827
1954
|
return this._lastTouchTarget instanceof Node && focusTarget instanceof Node &&
|
|
@@ -1829,16 +1956,33 @@ class FocusMonitor {
|
|
|
1829
1956
|
}
|
|
1830
1957
|
/**
|
|
1831
1958
|
* Handles focus events on a registered element.
|
|
1959
|
+
* @private
|
|
1832
1960
|
* @param {?} event The focus event.
|
|
1833
1961
|
* @param {?} element The monitored element.
|
|
1834
1962
|
* @return {?}
|
|
1835
1963
|
*/
|
|
1836
1964
|
_onFocus(event, element) {
|
|
1965
|
+
// NOTE(mmalerba): We currently set the classes based on the focus origin of the most recent
|
|
1966
|
+
// focus event affecting the monitored element. If we want to use the origin of the first event
|
|
1967
|
+
// instead we should check for the cdk-focused class here and return if the element already has
|
|
1968
|
+
// it. (This only matters for elements that have includesChildren = true).
|
|
1969
|
+
// NOTE(mmalerba): We currently set the classes based on the focus origin of the most recent
|
|
1970
|
+
// focus event affecting the monitored element. If we want to use the origin of the first event
|
|
1971
|
+
// instead we should check for the cdk-focused class here and return if the element already has
|
|
1972
|
+
// it. (This only matters for elements that have includesChildren = true).
|
|
1973
|
+
// If we are not counting child-element-focus as focused, make sure that the event target is the
|
|
1974
|
+
// monitored element itself.
|
|
1837
1975
|
/** @type {?} */
|
|
1838
1976
|
const elementInfo = this._elementInfo.get(element);
|
|
1839
1977
|
if (!elementInfo || (!elementInfo.checkChildren && element !== event.target)) {
|
|
1840
1978
|
return;
|
|
1841
1979
|
}
|
|
1980
|
+
// If we couldn't detect a cause for the focus event, it's due to one of three reasons:
|
|
1981
|
+
// 1) The window has just regained focus, in which case we want to restore the focused state of
|
|
1982
|
+
// the element from before the window blurred.
|
|
1983
|
+
// 2) It was caused by a touch event, in which case we mark the origin as 'touch'.
|
|
1984
|
+
// 3) The element was programmatically focused, in which case we should mark the origin as
|
|
1985
|
+
// 'program'.
|
|
1842
1986
|
/** @type {?} */
|
|
1843
1987
|
let origin = this._origin;
|
|
1844
1988
|
if (!origin) {
|
|
@@ -1863,6 +2007,8 @@ class FocusMonitor {
|
|
|
1863
2007
|
* @return {?}
|
|
1864
2008
|
*/
|
|
1865
2009
|
_onBlur(event, element) {
|
|
2010
|
+
// If we are counting child-element-focus as focused, make sure that we aren't just blurring in
|
|
2011
|
+
// order to focus another child of the monitored element.
|
|
1866
2012
|
/** @type {?} */
|
|
1867
2013
|
const elementInfo = this._elementInfo.get(element);
|
|
1868
2014
|
if (!elementInfo || (elementInfo.checkChildren && event.relatedTarget instanceof Node &&
|
|
@@ -1873,6 +2019,7 @@ class FocusMonitor {
|
|
|
1873
2019
|
this._emitOrigin(elementInfo.subject, null);
|
|
1874
2020
|
}
|
|
1875
2021
|
/**
|
|
2022
|
+
* @private
|
|
1876
2023
|
* @param {?} subject
|
|
1877
2024
|
* @param {?} origin
|
|
1878
2025
|
* @return {?}
|
|
@@ -1881,25 +2028,41 @@ class FocusMonitor {
|
|
|
1881
2028
|
this._ngZone.run(() => subject.next(origin));
|
|
1882
2029
|
}
|
|
1883
2030
|
/**
|
|
2031
|
+
* @private
|
|
1884
2032
|
* @return {?}
|
|
1885
2033
|
*/
|
|
1886
2034
|
_incrementMonitoredElementCount() {
|
|
1887
2035
|
// Register global listeners when first element is monitored.
|
|
1888
|
-
if (++this._monitoredElementCount == 1) {
|
|
1889
|
-
|
|
2036
|
+
if (++this._monitoredElementCount == 1 && this._platform.isBrowser) {
|
|
2037
|
+
// Note: we listen to events in the capture phase so we
|
|
2038
|
+
// can detect them even if the user stops propagation.
|
|
2039
|
+
this._ngZone.runOutsideAngular(() => {
|
|
2040
|
+
document.addEventListener('keydown', this._documentKeydownListener, captureEventListenerOptions);
|
|
2041
|
+
document.addEventListener('mousedown', this._documentMousedownListener, captureEventListenerOptions);
|
|
2042
|
+
document.addEventListener('touchstart', this._documentTouchstartListener, captureEventListenerOptions);
|
|
2043
|
+
window.addEventListener('focus', this._windowFocusListener);
|
|
2044
|
+
});
|
|
1890
2045
|
}
|
|
1891
2046
|
}
|
|
1892
2047
|
/**
|
|
2048
|
+
* @private
|
|
1893
2049
|
* @return {?}
|
|
1894
2050
|
*/
|
|
1895
2051
|
_decrementMonitoredElementCount() {
|
|
1896
2052
|
// Unregister global listeners when last element is unmonitored.
|
|
1897
2053
|
if (!--this._monitoredElementCount) {
|
|
1898
|
-
this.
|
|
1899
|
-
this.
|
|
2054
|
+
document.removeEventListener('keydown', this._documentKeydownListener, captureEventListenerOptions);
|
|
2055
|
+
document.removeEventListener('mousedown', this._documentMousedownListener, captureEventListenerOptions);
|
|
2056
|
+
document.removeEventListener('touchstart', this._documentTouchstartListener, captureEventListenerOptions);
|
|
2057
|
+
window.removeEventListener('focus', this._windowFocusListener);
|
|
2058
|
+
// Clear timeouts for all potentially pending timeouts to prevent the leaks.
|
|
2059
|
+
clearTimeout(this._windowFocusTimeoutId);
|
|
2060
|
+
clearTimeout(this._touchTimeoutId);
|
|
2061
|
+
clearTimeout(this._originTimeoutId);
|
|
1900
2062
|
}
|
|
1901
2063
|
}
|
|
1902
2064
|
/**
|
|
2065
|
+
* @private
|
|
1903
2066
|
* @param {?} element
|
|
1904
2067
|
* @return {?}
|
|
1905
2068
|
*/
|
|
@@ -1968,9 +2131,10 @@ CdkMonitorFocus.propDecorators = {
|
|
|
1968
2131
|
function FOCUS_MONITOR_PROVIDER_FACTORY(parentDispatcher, ngZone, platform) {
|
|
1969
2132
|
return parentDispatcher || new FocusMonitor(ngZone, platform);
|
|
1970
2133
|
}
|
|
1971
|
-
/**
|
|
2134
|
+
/**
|
|
1972
2135
|
* \@docs-private \@deprecated \@breaking-change 8.0.0
|
|
1973
|
-
|
|
2136
|
+
* @type {?}
|
|
2137
|
+
*/
|
|
1974
2138
|
const FOCUS_MONITOR_PROVIDER = {
|
|
1975
2139
|
// If there is already a FocusMonitor available, use that. Otherwise, provide a new one.
|
|
1976
2140
|
provide: FocusMonitor,
|
|
@@ -1980,7 +2144,7 @@ const FOCUS_MONITOR_PROVIDER = {
|
|
|
1980
2144
|
|
|
1981
2145
|
/**
|
|
1982
2146
|
* @fileoverview added by tsickle
|
|
1983
|
-
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
|
|
2147
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
1984
2148
|
*/
|
|
1985
2149
|
|
|
1986
2150
|
/**
|
|
@@ -1998,7 +2162,7 @@ function isFakeMousedownFromScreenReader(event) {
|
|
|
1998
2162
|
|
|
1999
2163
|
/**
|
|
2000
2164
|
* @fileoverview added by tsickle
|
|
2001
|
-
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
|
|
2165
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
2002
2166
|
*/
|
|
2003
2167
|
class A11yModule {
|
|
2004
2168
|
}
|
|
@@ -2012,12 +2176,12 @@ A11yModule.decorators = [
|
|
|
2012
2176
|
|
|
2013
2177
|
/**
|
|
2014
2178
|
* @fileoverview added by tsickle
|
|
2015
|
-
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
|
|
2179
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
2016
2180
|
*/
|
|
2017
2181
|
|
|
2018
2182
|
/**
|
|
2019
2183
|
* @fileoverview added by tsickle
|
|
2020
|
-
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
|
|
2184
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
2021
2185
|
*/
|
|
2022
2186
|
|
|
2023
2187
|
export { ARIA_DESCRIBER_PROVIDER_FACTORY, MESSAGES_CONTAINER_ID, CDK_DESCRIBEDBY_ID_PREFIX, CDK_DESCRIBEDBY_HOST_ATTRIBUTE, AriaDescriber, ARIA_DESCRIBER_PROVIDER, ActiveDescendantKeyManager, FocusKeyManager, ListKeyManager, FocusTrap, FocusTrapFactory, CdkTrapFocus, InteractivityChecker, LIVE_ANNOUNCER_PROVIDER_FACTORY, LiveAnnouncer, CdkAriaLive, LIVE_ANNOUNCER_PROVIDER, LIVE_ANNOUNCER_ELEMENT_TOKEN_FACTORY, LIVE_ANNOUNCER_ELEMENT_TOKEN, FOCUS_MONITOR_PROVIDER_FACTORY, TOUCH_BUFFER_MS, FocusMonitor, CdkMonitorFocus, FOCUS_MONITOR_PROVIDER, isFakeMousedownFromScreenReader, A11yModule };
|