@angular/cdk 19.0.0-next.9 → 19.0.0-rc.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/fesm2022/a11y.mjs +313 -266
- package/fesm2022/a11y.mjs.map +1 -1
- package/fesm2022/accordion.mjs +41 -44
- package/fesm2022/accordion.mjs.map +1 -1
- package/fesm2022/bidi.mjs +19 -19
- package/fesm2022/bidi.mjs.map +1 -1
- package/fesm2022/cdk.mjs +1 -1
- package/fesm2022/cdk.mjs.map +1 -1
- package/fesm2022/clipboard.mjs +31 -26
- package/fesm2022/clipboard.mjs.map +1 -1
- package/fesm2022/collections.mjs +30 -28
- package/fesm2022/collections.mjs.map +1 -1
- package/fesm2022/dialog.mjs +210 -131
- package/fesm2022/dialog.mjs.map +1 -1
- package/fesm2022/drag-drop.mjs +721 -477
- package/fesm2022/drag-drop.mjs.map +1 -1
- package/fesm2022/layout.mjs +18 -17
- package/fesm2022/layout.mjs.map +1 -1
- package/fesm2022/listbox.mjs +76 -62
- package/fesm2022/listbox.mjs.map +1 -1
- package/fesm2022/menu.mjs +231 -203
- package/fesm2022/menu.mjs.map +1 -1
- package/fesm2022/observers/private.mjs +15 -12
- package/fesm2022/observers/private.mjs.map +1 -1
- package/fesm2022/observers.mjs +22 -23
- package/fesm2022/observers.mjs.map +1 -1
- package/fesm2022/overlay.mjs +410 -278
- package/fesm2022/overlay.mjs.map +1 -1
- package/fesm2022/platform.mjs +49 -50
- package/fesm2022/platform.mjs.map +1 -1
- package/fesm2022/portal.mjs +110 -74
- package/fesm2022/portal.mjs.map +1 -1
- package/fesm2022/private.mjs +7 -8
- package/fesm2022/private.mjs.map +1 -1
- package/fesm2022/scrolling.mjs +179 -158
- package/fesm2022/scrolling.mjs.map +1 -1
- package/fesm2022/stepper.mjs +97 -65
- package/fesm2022/stepper.mjs.map +1 -1
- package/fesm2022/table.mjs +443 -232
- package/fesm2022/table.mjs.map +1 -1
- package/fesm2022/testing/selenium-webdriver.mjs +6 -0
- package/fesm2022/testing/selenium-webdriver.mjs.map +1 -1
- package/fesm2022/testing/testbed.mjs +16 -7
- package/fesm2022/testing/testbed.mjs.map +1 -1
- package/fesm2022/testing.mjs +7 -2
- package/fesm2022/testing.mjs.map +1 -1
- package/fesm2022/text-field.mjs +50 -41
- package/fesm2022/text-field.mjs.map +1 -1
- package/fesm2022/tree.mjs +220 -118
- package/fesm2022/tree.mjs.map +1 -1
- package/package.json +1 -1
- package/schematics/ng-add/index.js +1 -1
- package/schematics/ng-add/index.mjs +1 -1
- package/table/index.d.ts +20 -1
package/fesm2022/a11y.mjs
CHANGED
|
@@ -2,6 +2,7 @@ import { DOCUMENT } from '@angular/common';
|
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
3
|
import { inject, APP_ID, Injectable, QueryList, isSignal, effect, InjectionToken, afterNextRender, NgZone, Injector, ElementRef, booleanAttribute, Directive, Input, EventEmitter, Output, NgModule } from '@angular/core';
|
|
4
4
|
import { Platform, _getFocusedElementPierceShadowDom, normalizePassiveListenerOptions, _getEventTarget, _getShadowRoot } from '@angular/cdk/platform';
|
|
5
|
+
import { _CdkPrivateStyleLoader, _VisuallyHiddenLoader } from '@angular/cdk/private';
|
|
5
6
|
import { Subject, Subscription, isObservable, of, BehaviorSubject } from 'rxjs';
|
|
6
7
|
import { A, Z, ZERO, NINE, hasModifierKey, PAGE_DOWN, PAGE_UP, END, HOME, LEFT_ARROW, RIGHT_ARROW, UP_ARROW, DOWN_ARROW, TAB, ALT, CONTROL, MAC_META, META, SHIFT } from '@angular/cdk/keycodes';
|
|
7
8
|
import { tap, debounceTime, filter, map, take, skip, distinctUntilChanged, takeUntil } from 'rxjs/operators';
|
|
@@ -76,15 +77,16 @@ let nextId = 0;
|
|
|
76
77
|
* content.
|
|
77
78
|
*/
|
|
78
79
|
class AriaDescriber {
|
|
80
|
+
_platform = inject(Platform);
|
|
81
|
+
_document = inject(DOCUMENT);
|
|
82
|
+
/** Map of all registered message elements that have been placed into the document. */
|
|
83
|
+
_messageRegistry = new Map();
|
|
84
|
+
/** Container for all registered messages. */
|
|
85
|
+
_messagesContainer = null;
|
|
86
|
+
/** Unique ID for the service. */
|
|
87
|
+
_id = `${nextId++}`;
|
|
79
88
|
constructor() {
|
|
80
|
-
|
|
81
|
-
this._document = inject(DOCUMENT);
|
|
82
|
-
/** Map of all registered message elements that have been placed into the document. */
|
|
83
|
-
this._messageRegistry = new Map();
|
|
84
|
-
/** Container for all registered messages. */
|
|
85
|
-
this._messagesContainer = null;
|
|
86
|
-
/** Unique ID for the service. */
|
|
87
|
-
this._id = `${nextId++}`;
|
|
89
|
+
inject(_CdkPrivateStyleLoader).load(_VisuallyHiddenLoader);
|
|
88
90
|
this._id = inject(APP_ID) + '-' + nextId++;
|
|
89
91
|
}
|
|
90
92
|
describe(hostElement, message, role) {
|
|
@@ -242,8 +244,8 @@ class AriaDescriber {
|
|
|
242
244
|
_isElementNode(element) {
|
|
243
245
|
return element.nodeType === this._document.ELEMENT_NODE;
|
|
244
246
|
}
|
|
245
|
-
static
|
|
246
|
-
static
|
|
247
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: AriaDescriber, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
248
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: AriaDescriber, providedIn: 'root' });
|
|
247
249
|
}
|
|
248
250
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: AriaDescriber, decorators: [{
|
|
249
251
|
type: Injectable,
|
|
@@ -266,14 +268,15 @@ const DEFAULT_TYPEAHEAD_DEBOUNCE_INTERVAL_MS = 200;
|
|
|
266
268
|
* `role="listbox"` or `role="tree"` and other related roles.
|
|
267
269
|
*/
|
|
268
270
|
class Typeahead {
|
|
271
|
+
_letterKeyStream = new Subject();
|
|
272
|
+
_items = [];
|
|
273
|
+
_selectedItemIndex = -1;
|
|
274
|
+
/** Buffer for the letters that the user has pressed */
|
|
275
|
+
_pressedLetters = [];
|
|
276
|
+
_skipPredicateFn;
|
|
277
|
+
_selectedItem = new Subject();
|
|
278
|
+
selectedItem = this._selectedItem;
|
|
269
279
|
constructor(initialItems, config) {
|
|
270
|
-
this._letterKeyStream = new Subject();
|
|
271
|
-
this._items = [];
|
|
272
|
-
this._selectedItemIndex = -1;
|
|
273
|
-
/** Buffer for the letters that the user has pressed */
|
|
274
|
-
this._pressedLetters = [];
|
|
275
|
-
this._selectedItem = new Subject();
|
|
276
|
-
this.selectedItem = this._selectedItem;
|
|
277
280
|
const typeAheadInterval = typeof config?.debounceInterval === 'number'
|
|
278
281
|
? config.debounceInterval
|
|
279
282
|
: DEFAULT_TYPEAHEAD_DEBOUNCE_INTERVAL_MS;
|
|
@@ -346,28 +349,26 @@ class Typeahead {
|
|
|
346
349
|
* of items, it will set the active item correctly when arrow events occur.
|
|
347
350
|
*/
|
|
348
351
|
class ListKeyManager {
|
|
352
|
+
_items;
|
|
353
|
+
_activeItemIndex = -1;
|
|
354
|
+
_activeItem = null;
|
|
355
|
+
_wrap = false;
|
|
356
|
+
_typeaheadSubscription = Subscription.EMPTY;
|
|
357
|
+
_itemChangesSubscription;
|
|
358
|
+
_vertical = true;
|
|
359
|
+
_horizontal;
|
|
360
|
+
_allowedModifierKeys = [];
|
|
361
|
+
_homeAndEnd = false;
|
|
362
|
+
_pageUpAndDown = { enabled: false, delta: 10 };
|
|
363
|
+
_effectRef;
|
|
364
|
+
_typeahead;
|
|
365
|
+
/**
|
|
366
|
+
* Predicate function that can be used to check whether an item should be skipped
|
|
367
|
+
* by the key manager. By default, disabled items are skipped.
|
|
368
|
+
*/
|
|
369
|
+
_skipPredicateFn = (item) => item.disabled;
|
|
349
370
|
constructor(_items, injector) {
|
|
350
371
|
this._items = _items;
|
|
351
|
-
this._activeItemIndex = -1;
|
|
352
|
-
this._activeItem = null;
|
|
353
|
-
this._wrap = false;
|
|
354
|
-
this._typeaheadSubscription = Subscription.EMPTY;
|
|
355
|
-
this._vertical = true;
|
|
356
|
-
this._allowedModifierKeys = [];
|
|
357
|
-
this._homeAndEnd = false;
|
|
358
|
-
this._pageUpAndDown = { enabled: false, delta: 10 };
|
|
359
|
-
/**
|
|
360
|
-
* Predicate function that can be used to check whether an item should be skipped
|
|
361
|
-
* by the key manager. By default, disabled items are skipped.
|
|
362
|
-
*/
|
|
363
|
-
this._skipPredicateFn = (item) => item.disabled;
|
|
364
|
-
/**
|
|
365
|
-
* Stream that emits any time the TAB key is pressed, so components can react
|
|
366
|
-
* when focus is shifted off of the list.
|
|
367
|
-
*/
|
|
368
|
-
this.tabOut = new Subject();
|
|
369
|
-
/** Stream that emits whenever the active item of the list manager changes. */
|
|
370
|
-
this.change = new Subject();
|
|
371
372
|
// We allow for the items to be an array because, in some cases, the consumer may
|
|
372
373
|
// not have access to a QueryList of the items they want to manage (e.g. when the
|
|
373
374
|
// items aren't being collected via `ViewChildren` or `ContentChildren`).
|
|
@@ -381,6 +382,13 @@ class ListKeyManager {
|
|
|
381
382
|
this._effectRef = effect(() => this._itemsChanged(_items()), { injector });
|
|
382
383
|
}
|
|
383
384
|
}
|
|
385
|
+
/**
|
|
386
|
+
* Stream that emits any time the TAB key is pressed, so components can react
|
|
387
|
+
* when focus is shifted off of the list.
|
|
388
|
+
*/
|
|
389
|
+
tabOut = new Subject();
|
|
390
|
+
/** Stream that emits whenever the active item of the list manager changes. */
|
|
391
|
+
change = new Subject();
|
|
384
392
|
/**
|
|
385
393
|
* Sets the predicate function that determines which items should be skipped by the
|
|
386
394
|
* list key manager.
|
|
@@ -700,10 +708,7 @@ class ActiveDescendantKeyManager extends ListKeyManager {
|
|
|
700
708
|
}
|
|
701
709
|
|
|
702
710
|
class FocusKeyManager extends ListKeyManager {
|
|
703
|
-
|
|
704
|
-
super(...arguments);
|
|
705
|
-
this._origin = 'program';
|
|
706
|
-
}
|
|
711
|
+
_origin = 'program';
|
|
707
712
|
/**
|
|
708
713
|
* Sets the focus origin that will be passed in to the items for any subsequent `focus` calls.
|
|
709
714
|
* @param origin Focus origin to be used when focusing items.
|
|
@@ -726,6 +731,33 @@ class FocusKeyManager extends ListKeyManager {
|
|
|
726
731
|
* keyboard events occur.
|
|
727
732
|
*/
|
|
728
733
|
class TreeKeyManager {
|
|
734
|
+
/** The index of the currently active (focused) item. */
|
|
735
|
+
_activeItemIndex = -1;
|
|
736
|
+
/** The currently active (focused) item. */
|
|
737
|
+
_activeItem = null;
|
|
738
|
+
/** Whether or not we activate the item when it's focused. */
|
|
739
|
+
_shouldActivationFollowFocus = false;
|
|
740
|
+
/**
|
|
741
|
+
* The orientation that the tree is laid out in. In `rtl` mode, the behavior of Left and
|
|
742
|
+
* Right arrow are switched.
|
|
743
|
+
*/
|
|
744
|
+
_horizontalOrientation = 'ltr';
|
|
745
|
+
/**
|
|
746
|
+
* Predicate function that can be used to check whether an item should be skipped
|
|
747
|
+
* by the key manager.
|
|
748
|
+
*
|
|
749
|
+
* The default value for this doesn't skip any elements in order to keep tree items focusable
|
|
750
|
+
* when disabled. This aligns with ARIA guidelines:
|
|
751
|
+
* https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#focusabilityofdisabledcontrols.
|
|
752
|
+
*/
|
|
753
|
+
_skipPredicateFn = (_item) => false;
|
|
754
|
+
/** Function to determine equivalent items. */
|
|
755
|
+
_trackByFn = (item) => item;
|
|
756
|
+
/** Synchronous cache of the items to manage. */
|
|
757
|
+
_items = [];
|
|
758
|
+
_typeahead;
|
|
759
|
+
_typeaheadSubscription = Subscription.EMPTY;
|
|
760
|
+
_hasInitialFocused = false;
|
|
729
761
|
_initializeFocus() {
|
|
730
762
|
if (this._hasInitialFocused || this._items.length === 0) {
|
|
731
763
|
return;
|
|
@@ -762,34 +794,6 @@ class TreeKeyManager {
|
|
|
762
794
|
* default interval of 200ms.
|
|
763
795
|
*/
|
|
764
796
|
constructor(items, config) {
|
|
765
|
-
/** The index of the currently active (focused) item. */
|
|
766
|
-
this._activeItemIndex = -1;
|
|
767
|
-
/** The currently active (focused) item. */
|
|
768
|
-
this._activeItem = null;
|
|
769
|
-
/** Whether or not we activate the item when it's focused. */
|
|
770
|
-
this._shouldActivationFollowFocus = false;
|
|
771
|
-
/**
|
|
772
|
-
* The orientation that the tree is laid out in. In `rtl` mode, the behavior of Left and
|
|
773
|
-
* Right arrow are switched.
|
|
774
|
-
*/
|
|
775
|
-
this._horizontalOrientation = 'ltr';
|
|
776
|
-
/**
|
|
777
|
-
* Predicate function that can be used to check whether an item should be skipped
|
|
778
|
-
* by the key manager.
|
|
779
|
-
*
|
|
780
|
-
* The default value for this doesn't skip any elements in order to keep tree items focusable
|
|
781
|
-
* when disabled. This aligns with ARIA guidelines:
|
|
782
|
-
* https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#focusabilityofdisabledcontrols.
|
|
783
|
-
*/
|
|
784
|
-
this._skipPredicateFn = (_item) => false;
|
|
785
|
-
/** Function to determine equivalent items. */
|
|
786
|
-
this._trackByFn = (item) => item;
|
|
787
|
-
/** Synchronous cache of the items to manage. */
|
|
788
|
-
this._items = [];
|
|
789
|
-
this._typeaheadSubscription = Subscription.EMPTY;
|
|
790
|
-
this._hasInitialFocused = false;
|
|
791
|
-
/** Stream that emits any time the focused item changes. */
|
|
792
|
-
this.change = new Subject();
|
|
793
797
|
// We allow for the items to be an array or Observable because, in some cases, the consumer may
|
|
794
798
|
// not have access to a QueryList of the items they want to manage (e.g. when the
|
|
795
799
|
// items aren't being collected via `ViewChildren` or `ContentChildren`).
|
|
@@ -830,6 +834,8 @@ class TreeKeyManager {
|
|
|
830
834
|
this._setTypeAhead(config.typeAheadDebounceInterval);
|
|
831
835
|
}
|
|
832
836
|
}
|
|
837
|
+
/** Stream that emits any time the focused item changes. */
|
|
838
|
+
change = new Subject();
|
|
833
839
|
/** Cleans up the key manager. */
|
|
834
840
|
destroy() {
|
|
835
841
|
this._typeaheadSubscription.unsubscribe();
|
|
@@ -1084,12 +1090,10 @@ const TREE_KEY_MANAGER_FACTORY_PROVIDER = {
|
|
|
1084
1090
|
* @breaking-change 21.0.0
|
|
1085
1091
|
*/
|
|
1086
1092
|
class NoopTreeKeyManager {
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
this.change = new Subject();
|
|
1092
|
-
}
|
|
1093
|
+
_isNoopTreeKeyManager = true;
|
|
1094
|
+
// Provide change as required by TreeKeyManagerStrategy. NoopTreeKeyManager is a "noop"
|
|
1095
|
+
// implementation that does not emit to streams.
|
|
1096
|
+
change = new Subject();
|
|
1093
1097
|
destroy() {
|
|
1094
1098
|
this.change.complete();
|
|
1095
1099
|
}
|
|
@@ -1152,12 +1156,10 @@ const NOOP_TREE_KEY_MANAGER_FACTORY_PROVIDER = {
|
|
|
1152
1156
|
* Configuration for the isFocusable method.
|
|
1153
1157
|
*/
|
|
1154
1158
|
class IsFocusableConfig {
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
this.ignoreVisibility = false;
|
|
1160
|
-
}
|
|
1159
|
+
/**
|
|
1160
|
+
* Whether to count an element as focusable even if it is not currently visible.
|
|
1161
|
+
*/
|
|
1162
|
+
ignoreVisibility = false;
|
|
1161
1163
|
}
|
|
1162
1164
|
// The InteractivityChecker leans heavily on the ally.js accessibility utilities.
|
|
1163
1165
|
// Methods like `isTabbable` are only covering specific edge-cases for the browsers which are
|
|
@@ -1167,9 +1169,8 @@ class IsFocusableConfig {
|
|
|
1167
1169
|
* tabbable.
|
|
1168
1170
|
*/
|
|
1169
1171
|
class InteractivityChecker {
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
}
|
|
1172
|
+
_platform = inject(Platform);
|
|
1173
|
+
constructor() { }
|
|
1173
1174
|
/**
|
|
1174
1175
|
* Gets whether an element is disabled.
|
|
1175
1176
|
*
|
|
@@ -1274,8 +1275,8 @@ class InteractivityChecker {
|
|
|
1274
1275
|
!this.isDisabled(element) &&
|
|
1275
1276
|
(config?.ignoreVisibility || this.isVisible(element)));
|
|
1276
1277
|
}
|
|
1277
|
-
static
|
|
1278
|
-
static
|
|
1278
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: InteractivityChecker, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1279
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: InteractivityChecker, providedIn: 'root' });
|
|
1279
1280
|
}
|
|
1280
1281
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: InteractivityChecker, decorators: [{
|
|
1281
1282
|
type: Injectable,
|
|
@@ -1383,6 +1384,17 @@ function getWindow(node) {
|
|
|
1383
1384
|
* Things like `tabIndex > 0`, flex `order`, and shadow roots can cause the two to be misaligned.
|
|
1384
1385
|
*/
|
|
1385
1386
|
class FocusTrap {
|
|
1387
|
+
_element;
|
|
1388
|
+
_checker;
|
|
1389
|
+
_ngZone;
|
|
1390
|
+
_document;
|
|
1391
|
+
_injector;
|
|
1392
|
+
_startAnchor;
|
|
1393
|
+
_endAnchor;
|
|
1394
|
+
_hasAttached = false;
|
|
1395
|
+
// Event listeners for the anchors. Need to be regular functions so that we can unbind them later.
|
|
1396
|
+
startAnchorListener = () => this.focusLastTabbableElement();
|
|
1397
|
+
endAnchorListener = () => this.focusFirstTabbableElement();
|
|
1386
1398
|
/** Whether the focus trap is active. */
|
|
1387
1399
|
get enabled() {
|
|
1388
1400
|
return this._enabled;
|
|
@@ -1394,6 +1406,7 @@ class FocusTrap {
|
|
|
1394
1406
|
this._toggleAnchorTabIndex(value, this._endAnchor);
|
|
1395
1407
|
}
|
|
1396
1408
|
}
|
|
1409
|
+
_enabled = true;
|
|
1397
1410
|
constructor(_element, _checker, _ngZone, _document, deferAnchors = false,
|
|
1398
1411
|
/** @breaking-change 20.0.0 param to become required */
|
|
1399
1412
|
_injector) {
|
|
@@ -1402,11 +1415,6 @@ class FocusTrap {
|
|
|
1402
1415
|
this._ngZone = _ngZone;
|
|
1403
1416
|
this._document = _document;
|
|
1404
1417
|
this._injector = _injector;
|
|
1405
|
-
this._hasAttached = false;
|
|
1406
|
-
// Event listeners for the anchors. Need to be regular functions so that we can unbind them later.
|
|
1407
|
-
this.startAnchorListener = () => this.focusLastTabbableElement();
|
|
1408
|
-
this.endAnchorListener = () => this.focusFirstTabbableElement();
|
|
1409
|
-
this._enabled = true;
|
|
1410
1418
|
if (!deferAnchors) {
|
|
1411
1419
|
this.attachAnchors();
|
|
1412
1420
|
}
|
|
@@ -1652,11 +1660,12 @@ class FocusTrap {
|
|
|
1652
1660
|
* Factory that allows easy instantiation of focus traps.
|
|
1653
1661
|
*/
|
|
1654
1662
|
class FocusTrapFactory {
|
|
1663
|
+
_checker = inject(InteractivityChecker);
|
|
1664
|
+
_ngZone = inject(NgZone);
|
|
1665
|
+
_document = inject(DOCUMENT);
|
|
1666
|
+
_injector = inject(Injector);
|
|
1655
1667
|
constructor() {
|
|
1656
|
-
|
|
1657
|
-
this._ngZone = inject(NgZone);
|
|
1658
|
-
this._document = inject(DOCUMENT);
|
|
1659
|
-
this._injector = inject(Injector);
|
|
1668
|
+
inject(_CdkPrivateStyleLoader).load(_VisuallyHiddenLoader);
|
|
1660
1669
|
}
|
|
1661
1670
|
/**
|
|
1662
1671
|
* Creates a focus-trapped region around the given element.
|
|
@@ -1668,8 +1677,8 @@ class FocusTrapFactory {
|
|
|
1668
1677
|
create(element, deferCaptureElements = false) {
|
|
1669
1678
|
return new FocusTrap(element, this._checker, this._ngZone, this._document, deferCaptureElements, this._injector);
|
|
1670
1679
|
}
|
|
1671
|
-
static
|
|
1672
|
-
static
|
|
1680
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: FocusTrapFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1681
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: FocusTrapFactory, providedIn: 'root' });
|
|
1673
1682
|
}
|
|
1674
1683
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: FocusTrapFactory, decorators: [{
|
|
1675
1684
|
type: Injectable,
|
|
@@ -1677,6 +1686,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0-next.10",
|
|
|
1677
1686
|
}], ctorParameters: () => [] });
|
|
1678
1687
|
/** Directive for trapping focus within a region. */
|
|
1679
1688
|
class CdkTrapFocus {
|
|
1689
|
+
_elementRef = inject(ElementRef);
|
|
1690
|
+
_focusTrapFactory = inject(FocusTrapFactory);
|
|
1691
|
+
/** Underlying FocusTrap instance. */
|
|
1692
|
+
focusTrap;
|
|
1693
|
+
/** Previously focused element to restore focus to upon destroy when using autoCapture. */
|
|
1694
|
+
_previouslyFocusedElement = null;
|
|
1680
1695
|
/** Whether the focus trap is active. */
|
|
1681
1696
|
get enabled() {
|
|
1682
1697
|
return this.focusTrap?.enabled || false;
|
|
@@ -1686,11 +1701,12 @@ class CdkTrapFocus {
|
|
|
1686
1701
|
this.focusTrap.enabled = value;
|
|
1687
1702
|
}
|
|
1688
1703
|
}
|
|
1704
|
+
/**
|
|
1705
|
+
* Whether the directive should automatically move focus into the trapped region upon
|
|
1706
|
+
* initialization and return focus to the previous activeElement upon destruction.
|
|
1707
|
+
*/
|
|
1708
|
+
autoCapture;
|
|
1689
1709
|
constructor() {
|
|
1690
|
-
this._elementRef = inject(ElementRef);
|
|
1691
|
-
this._focusTrapFactory = inject(FocusTrapFactory);
|
|
1692
|
-
/** Previously focused element to restore focus to upon destroy when using autoCapture. */
|
|
1693
|
-
this._previouslyFocusedElement = null;
|
|
1694
1710
|
const platform = inject(Platform);
|
|
1695
1711
|
if (platform.isBrowser) {
|
|
1696
1712
|
this.focusTrap = this._focusTrapFactory.create(this._elementRef.nativeElement, true);
|
|
@@ -1729,8 +1745,8 @@ class CdkTrapFocus {
|
|
|
1729
1745
|
this._previouslyFocusedElement = _getFocusedElementPierceShadowDom();
|
|
1730
1746
|
this.focusTrap?.focusInitialElementWhenReady();
|
|
1731
1747
|
}
|
|
1732
|
-
static
|
|
1733
|
-
static
|
|
1748
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: CdkTrapFocus, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
1749
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "19.0.0-next.10", type: CdkTrapFocus, isStandalone: true, selector: "[cdkTrapFocus]", inputs: { enabled: ["cdkTrapFocus", "enabled", booleanAttribute], autoCapture: ["cdkTrapFocusAutoCapture", "autoCapture", booleanAttribute] }, exportAs: ["cdkTrapFocus"], usesOnChanges: true, ngImport: i0 });
|
|
1734
1750
|
}
|
|
1735
1751
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: CdkTrapFocus, decorators: [{
|
|
1736
1752
|
type: Directive,
|
|
@@ -1753,6 +1769,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0-next.10",
|
|
|
1753
1769
|
* See FocusTrapInertStrategy.
|
|
1754
1770
|
*/
|
|
1755
1771
|
class ConfigurableFocusTrap extends FocusTrap {
|
|
1772
|
+
_focusTrapManager;
|
|
1773
|
+
_inertStrategy;
|
|
1756
1774
|
/** Whether the FocusTrap is enabled. */
|
|
1757
1775
|
get enabled() {
|
|
1758
1776
|
return this._enabled;
|
|
@@ -1794,10 +1812,8 @@ class ConfigurableFocusTrap extends FocusTrap {
|
|
|
1794
1812
|
* listener to redirect focus back inside the FocusTrap.
|
|
1795
1813
|
*/
|
|
1796
1814
|
class EventListenerFocusTrapInertStrategy {
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
this._listener = null;
|
|
1800
|
-
}
|
|
1815
|
+
/** Focus event handler. */
|
|
1816
|
+
_listener = null;
|
|
1801
1817
|
/** Adds a document event listener that keeps focus inside the FocusTrap. */
|
|
1802
1818
|
preventFocus(focusTrap) {
|
|
1803
1819
|
// Ensure there's only one listener per document
|
|
@@ -1848,11 +1864,9 @@ const FOCUS_TRAP_INERT_STRATEGY = new InjectionToken('FOCUS_TRAP_INERT_STRATEGY'
|
|
|
1848
1864
|
|
|
1849
1865
|
/** Injectable that ensures only the most recently enabled FocusTrap is active. */
|
|
1850
1866
|
class FocusTrapManager {
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
this._focusTrapStack = [];
|
|
1855
|
-
}
|
|
1867
|
+
// A stack of the FocusTraps on the page. Only the FocusTrap at the
|
|
1868
|
+
// top of the stack is active.
|
|
1869
|
+
_focusTrapStack = [];
|
|
1856
1870
|
/**
|
|
1857
1871
|
* Disables the FocusTrap at the top of the stack, and then pushes
|
|
1858
1872
|
* the new FocusTrap onto the stack.
|
|
@@ -1882,8 +1896,8 @@ class FocusTrapManager {
|
|
|
1882
1896
|
}
|
|
1883
1897
|
}
|
|
1884
1898
|
}
|
|
1885
|
-
static
|
|
1886
|
-
static
|
|
1899
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: FocusTrapManager, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1900
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: FocusTrapManager, providedIn: 'root' });
|
|
1887
1901
|
}
|
|
1888
1902
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: FocusTrapManager, decorators: [{
|
|
1889
1903
|
type: Injectable,
|
|
@@ -1892,12 +1906,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0-next.10",
|
|
|
1892
1906
|
|
|
1893
1907
|
/** Factory that allows easy instantiation of configurable focus traps. */
|
|
1894
1908
|
class ConfigurableFocusTrapFactory {
|
|
1909
|
+
_checker = inject(InteractivityChecker);
|
|
1910
|
+
_ngZone = inject(NgZone);
|
|
1911
|
+
_focusTrapManager = inject(FocusTrapManager);
|
|
1912
|
+
_document = inject(DOCUMENT);
|
|
1913
|
+
_inertStrategy;
|
|
1914
|
+
_injector = inject(Injector);
|
|
1895
1915
|
constructor() {
|
|
1896
|
-
this._checker = inject(InteractivityChecker);
|
|
1897
|
-
this._ngZone = inject(NgZone);
|
|
1898
|
-
this._focusTrapManager = inject(FocusTrapManager);
|
|
1899
|
-
this._document = inject(DOCUMENT);
|
|
1900
|
-
this._injector = inject(Injector);
|
|
1901
1916
|
const inertStrategy = inject(FOCUS_TRAP_INERT_STRATEGY, { optional: true });
|
|
1902
1917
|
// TODO split up the strategies into different modules, similar to DateAdapter.
|
|
1903
1918
|
this._inertStrategy = inertStrategy || new EventListenerFocusTrapInertStrategy();
|
|
@@ -1912,8 +1927,8 @@ class ConfigurableFocusTrapFactory {
|
|
|
1912
1927
|
}
|
|
1913
1928
|
return new ConfigurableFocusTrap(element, this._checker, this._ngZone, this._document, this._focusTrapManager, this._inertStrategy, configObject, this._injector);
|
|
1914
1929
|
}
|
|
1915
|
-
static
|
|
1916
|
-
static
|
|
1930
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: ConfigurableFocusTrapFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1931
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: ConfigurableFocusTrapFactory, providedIn: 'root' });
|
|
1917
1932
|
}
|
|
1918
1933
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: ConfigurableFocusTrapFactory, decorators: [{
|
|
1919
1934
|
type: Injectable,
|
|
@@ -1997,70 +2012,76 @@ const modalityEventListenerOptions = normalizePassiveListenerOptions({
|
|
|
1997
2012
|
* undefined.
|
|
1998
2013
|
*/
|
|
1999
2014
|
class InputModalityDetector {
|
|
2015
|
+
_platform = inject(Platform);
|
|
2016
|
+
/** Emits whenever an input modality is detected. */
|
|
2017
|
+
modalityDetected;
|
|
2018
|
+
/** Emits when the input modality changes. */
|
|
2019
|
+
modalityChanged;
|
|
2000
2020
|
/** The most recently detected input modality. */
|
|
2001
2021
|
get mostRecentModality() {
|
|
2002
2022
|
return this._modality.value;
|
|
2003
2023
|
}
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2024
|
+
/**
|
|
2025
|
+
* The most recently detected input modality event target. Is null if no input modality has been
|
|
2026
|
+
* detected or if the associated event target is null for some unknown reason.
|
|
2027
|
+
*/
|
|
2028
|
+
_mostRecentTarget = null;
|
|
2029
|
+
/** The underlying BehaviorSubject that emits whenever an input modality is detected. */
|
|
2030
|
+
_modality = new BehaviorSubject(null);
|
|
2031
|
+
/** Options for this InputModalityDetector. */
|
|
2032
|
+
_options;
|
|
2033
|
+
/**
|
|
2034
|
+
* The timestamp of the last touch input modality. Used to determine whether mousedown events
|
|
2035
|
+
* should be attributed to mouse or touch.
|
|
2036
|
+
*/
|
|
2037
|
+
_lastTouchMs = 0;
|
|
2038
|
+
/**
|
|
2039
|
+
* Handles keydown events. Must be an arrow function in order to preserve the context when it gets
|
|
2040
|
+
* bound.
|
|
2041
|
+
*/
|
|
2042
|
+
_onKeydown = (event) => {
|
|
2043
|
+
// If this is one of the keys we should ignore, then ignore it and don't update the input
|
|
2044
|
+
// modality to keyboard.
|
|
2045
|
+
if (this._options?.ignoreKeys?.some(keyCode => keyCode === event.keyCode)) {
|
|
2046
|
+
return;
|
|
2047
|
+
}
|
|
2048
|
+
this._modality.next('keyboard');
|
|
2049
|
+
this._mostRecentTarget = _getEventTarget(event);
|
|
2050
|
+
};
|
|
2051
|
+
/**
|
|
2052
|
+
* Handles mousedown events. Must be an arrow function in order to preserve the context when it
|
|
2053
|
+
* gets bound.
|
|
2054
|
+
*/
|
|
2055
|
+
_onMousedown = (event) => {
|
|
2056
|
+
// Touches trigger both touch and mouse events, so we need to distinguish between mouse events
|
|
2057
|
+
// that were triggered via mouse vs touch. To do so, check if the mouse event occurs closely
|
|
2058
|
+
// after the previous touch event.
|
|
2059
|
+
if (Date.now() - this._lastTouchMs < TOUCH_BUFFER_MS) {
|
|
2060
|
+
return;
|
|
2061
|
+
}
|
|
2062
|
+
// Fake mousedown events are fired by some screen readers when controls are activated by the
|
|
2063
|
+
// screen reader. Attribute them to keyboard input modality.
|
|
2064
|
+
this._modality.next(isFakeMousedownFromScreenReader(event) ? 'keyboard' : 'mouse');
|
|
2065
|
+
this._mostRecentTarget = _getEventTarget(event);
|
|
2066
|
+
};
|
|
2067
|
+
/**
|
|
2068
|
+
* Handles touchstart events. Must be an arrow function in order to preserve the context when it
|
|
2069
|
+
* gets bound.
|
|
2070
|
+
*/
|
|
2071
|
+
_onTouchstart = (event) => {
|
|
2072
|
+
// Same scenario as mentioned in _onMousedown, but on touch screen devices, fake touchstart
|
|
2073
|
+
// events are fired. Again, attribute to keyboard input modality.
|
|
2074
|
+
if (isFakeTouchstartFromScreenReader(event)) {
|
|
2028
2075
|
this._modality.next('keyboard');
|
|
2029
|
-
|
|
2030
|
-
}
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
this.
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
// after the previous touch event.
|
|
2039
|
-
if (Date.now() - this._lastTouchMs < TOUCH_BUFFER_MS) {
|
|
2040
|
-
return;
|
|
2041
|
-
}
|
|
2042
|
-
// Fake mousedown events are fired by some screen readers when controls are activated by the
|
|
2043
|
-
// screen reader. Attribute them to keyboard input modality.
|
|
2044
|
-
this._modality.next(isFakeMousedownFromScreenReader(event) ? 'keyboard' : 'mouse');
|
|
2045
|
-
this._mostRecentTarget = _getEventTarget(event);
|
|
2046
|
-
};
|
|
2047
|
-
/**
|
|
2048
|
-
* Handles touchstart events. Must be an arrow function in order to preserve the context when it
|
|
2049
|
-
* gets bound.
|
|
2050
|
-
*/
|
|
2051
|
-
this._onTouchstart = (event) => {
|
|
2052
|
-
// Same scenario as mentioned in _onMousedown, but on touch screen devices, fake touchstart
|
|
2053
|
-
// events are fired. Again, attribute to keyboard input modality.
|
|
2054
|
-
if (isFakeTouchstartFromScreenReader(event)) {
|
|
2055
|
-
this._modality.next('keyboard');
|
|
2056
|
-
return;
|
|
2057
|
-
}
|
|
2058
|
-
// Store the timestamp of this touch event, as it's used to distinguish between mouse events
|
|
2059
|
-
// triggered via mouse vs touch.
|
|
2060
|
-
this._lastTouchMs = Date.now();
|
|
2061
|
-
this._modality.next('touch');
|
|
2062
|
-
this._mostRecentTarget = _getEventTarget(event);
|
|
2063
|
-
};
|
|
2076
|
+
return;
|
|
2077
|
+
}
|
|
2078
|
+
// Store the timestamp of this touch event, as it's used to distinguish between mouse events
|
|
2079
|
+
// triggered via mouse vs touch.
|
|
2080
|
+
this._lastTouchMs = Date.now();
|
|
2081
|
+
this._modality.next('touch');
|
|
2082
|
+
this._mostRecentTarget = _getEventTarget(event);
|
|
2083
|
+
};
|
|
2084
|
+
constructor() {
|
|
2064
2085
|
const ngZone = inject(NgZone);
|
|
2065
2086
|
const document = inject(DOCUMENT);
|
|
2066
2087
|
const options = inject(INPUT_MODALITY_DETECTOR_OPTIONS, { optional: true });
|
|
@@ -2089,8 +2110,8 @@ class InputModalityDetector {
|
|
|
2089
2110
|
document.removeEventListener('touchstart', this._onTouchstart, modalityEventListenerOptions);
|
|
2090
2111
|
}
|
|
2091
2112
|
}
|
|
2092
|
-
static
|
|
2093
|
-
static
|
|
2113
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: InputModalityDetector, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2114
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: InputModalityDetector, providedIn: 'root' });
|
|
2094
2115
|
}
|
|
2095
2116
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: InputModalityDetector, decorators: [{
|
|
2096
2117
|
type: Injectable,
|
|
@@ -2110,12 +2131,16 @@ const LIVE_ANNOUNCER_DEFAULT_OPTIONS = new InjectionToken('LIVE_ANNOUNCER_DEFAUL
|
|
|
2110
2131
|
|
|
2111
2132
|
let uniqueIds = 0;
|
|
2112
2133
|
class LiveAnnouncer {
|
|
2134
|
+
_ngZone = inject(NgZone);
|
|
2135
|
+
_defaultOptions = inject(LIVE_ANNOUNCER_DEFAULT_OPTIONS, {
|
|
2136
|
+
optional: true,
|
|
2137
|
+
});
|
|
2138
|
+
_liveElement;
|
|
2139
|
+
_document = inject(DOCUMENT);
|
|
2140
|
+
_previousTimeout;
|
|
2141
|
+
_currentPromise;
|
|
2142
|
+
_currentResolve;
|
|
2113
2143
|
constructor() {
|
|
2114
|
-
this._ngZone = inject(NgZone);
|
|
2115
|
-
this._defaultOptions = inject(LIVE_ANNOUNCER_DEFAULT_OPTIONS, {
|
|
2116
|
-
optional: true,
|
|
2117
|
-
});
|
|
2118
|
-
this._document = inject(DOCUMENT);
|
|
2119
2144
|
const elementToken = inject(LIVE_ANNOUNCER_ELEMENT_TOKEN, { optional: true });
|
|
2120
2145
|
this._liveElement = elementToken || this._createLiveElement();
|
|
2121
2146
|
}
|
|
@@ -2223,8 +2248,8 @@ class LiveAnnouncer {
|
|
|
2223
2248
|
}
|
|
2224
2249
|
}
|
|
2225
2250
|
}
|
|
2226
|
-
static
|
|
2227
|
-
static
|
|
2251
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: LiveAnnouncer, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2252
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: LiveAnnouncer, providedIn: 'root' });
|
|
2228
2253
|
}
|
|
2229
2254
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: LiveAnnouncer, decorators: [{
|
|
2230
2255
|
type: Injectable,
|
|
@@ -2235,6 +2260,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0-next.10",
|
|
|
2235
2260
|
* with a wider range of browsers and screen readers.
|
|
2236
2261
|
*/
|
|
2237
2262
|
class CdkAriaLive {
|
|
2263
|
+
_elementRef = inject(ElementRef);
|
|
2264
|
+
_liveAnnouncer = inject(LiveAnnouncer);
|
|
2265
|
+
_contentObserver = inject(ContentObserver);
|
|
2266
|
+
_ngZone = inject(NgZone);
|
|
2238
2267
|
/** The aria-live politeness level to use when announcing messages. */
|
|
2239
2268
|
get politeness() {
|
|
2240
2269
|
return this._politeness;
|
|
@@ -2262,20 +2291,21 @@ class CdkAriaLive {
|
|
|
2262
2291
|
});
|
|
2263
2292
|
}
|
|
2264
2293
|
}
|
|
2294
|
+
_politeness = 'polite';
|
|
2295
|
+
/** Time in milliseconds after which to clear out the announcer element. */
|
|
2296
|
+
duration;
|
|
2297
|
+
_previousAnnouncedText;
|
|
2298
|
+
_subscription;
|
|
2265
2299
|
constructor() {
|
|
2266
|
-
|
|
2267
|
-
this._liveAnnouncer = inject(LiveAnnouncer);
|
|
2268
|
-
this._contentObserver = inject(ContentObserver);
|
|
2269
|
-
this._ngZone = inject(NgZone);
|
|
2270
|
-
this._politeness = 'polite';
|
|
2300
|
+
inject(_CdkPrivateStyleLoader).load(_VisuallyHiddenLoader);
|
|
2271
2301
|
}
|
|
2272
2302
|
ngOnDestroy() {
|
|
2273
2303
|
if (this._subscription) {
|
|
2274
2304
|
this._subscription.unsubscribe();
|
|
2275
2305
|
}
|
|
2276
2306
|
}
|
|
2277
|
-
static
|
|
2278
|
-
static
|
|
2307
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: CdkAriaLive, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
2308
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.0.0-next.10", type: CdkAriaLive, isStandalone: true, selector: "[cdkAriaLive]", inputs: { politeness: ["cdkAriaLive", "politeness"], duration: ["cdkAriaLiveDuration", "duration"] }, exportAs: ["cdkAriaLive"], ngImport: i0 });
|
|
2279
2309
|
}
|
|
2280
2310
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: CdkAriaLive, decorators: [{
|
|
2281
2311
|
type: Directive,
|
|
@@ -2318,65 +2348,76 @@ const captureEventListenerOptions = normalizePassiveListenerOptions({
|
|
|
2318
2348
|
});
|
|
2319
2349
|
/** Monitors mouse and keyboard events to determine the cause of focus events. */
|
|
2320
2350
|
class FocusMonitor {
|
|
2351
|
+
_ngZone = inject(NgZone);
|
|
2352
|
+
_platform = inject(Platform);
|
|
2353
|
+
_inputModalityDetector = inject(InputModalityDetector);
|
|
2354
|
+
/** The focus origin that the next focus event is a result of. */
|
|
2355
|
+
_origin = null;
|
|
2356
|
+
/** The FocusOrigin of the last focus event tracked by the FocusMonitor. */
|
|
2357
|
+
_lastFocusOrigin;
|
|
2358
|
+
/** Whether the window has just been focused. */
|
|
2359
|
+
_windowFocused = false;
|
|
2360
|
+
/** The timeout id of the window focus timeout. */
|
|
2361
|
+
_windowFocusTimeoutId;
|
|
2362
|
+
/** The timeout id of the origin clearing timeout. */
|
|
2363
|
+
_originTimeoutId;
|
|
2364
|
+
/**
|
|
2365
|
+
* Whether the origin was determined via a touch interaction. Necessary as properly attributing
|
|
2366
|
+
* focus events to touch interactions requires special logic.
|
|
2367
|
+
*/
|
|
2368
|
+
_originFromTouchInteraction = false;
|
|
2369
|
+
/** Map of elements being monitored to their info. */
|
|
2370
|
+
_elementInfo = new Map();
|
|
2371
|
+
/** The number of elements currently being monitored. */
|
|
2372
|
+
_monitoredElementCount = 0;
|
|
2373
|
+
/**
|
|
2374
|
+
* Keeps track of the root nodes to which we've currently bound a focus/blur handler,
|
|
2375
|
+
* as well as the number of monitored elements that they contain. We have to treat focus/blur
|
|
2376
|
+
* handlers differently from the rest of the events, because the browser won't emit events
|
|
2377
|
+
* to the document when focus moves inside of a shadow root.
|
|
2378
|
+
*/
|
|
2379
|
+
_rootNodeFocusListenerCount = new Map();
|
|
2380
|
+
/**
|
|
2381
|
+
* The specified detection mode, used for attributing the origin of a focus
|
|
2382
|
+
* event.
|
|
2383
|
+
*/
|
|
2384
|
+
_detectionMode;
|
|
2385
|
+
/**
|
|
2386
|
+
* Event listener for `focus` events on the window.
|
|
2387
|
+
* Needs to be an arrow function in order to preserve the context when it gets bound.
|
|
2388
|
+
*/
|
|
2389
|
+
_windowFocusListener = () => {
|
|
2390
|
+
// Make a note of when the window regains focus, so we can
|
|
2391
|
+
// restore the origin info for the focused element.
|
|
2392
|
+
this._windowFocused = true;
|
|
2393
|
+
this._windowFocusTimeoutId = window.setTimeout(() => (this._windowFocused = false));
|
|
2394
|
+
};
|
|
2395
|
+
/** Used to reference correct document/window */
|
|
2396
|
+
_document = inject(DOCUMENT, { optional: true });
|
|
2397
|
+
/** Subject for stopping our InputModalityDetector subscription. */
|
|
2398
|
+
_stopInputModalityDetector = new Subject();
|
|
2321
2399
|
constructor() {
|
|
2322
|
-
this._ngZone = inject(NgZone);
|
|
2323
|
-
this._platform = inject(Platform);
|
|
2324
|
-
this._inputModalityDetector = inject(InputModalityDetector);
|
|
2325
|
-
/** The focus origin that the next focus event is a result of. */
|
|
2326
|
-
this._origin = null;
|
|
2327
|
-
/** Whether the window has just been focused. */
|
|
2328
|
-
this._windowFocused = false;
|
|
2329
|
-
/**
|
|
2330
|
-
* Whether the origin was determined via a touch interaction. Necessary as properly attributing
|
|
2331
|
-
* focus events to touch interactions requires special logic.
|
|
2332
|
-
*/
|
|
2333
|
-
this._originFromTouchInteraction = false;
|
|
2334
|
-
/** Map of elements being monitored to their info. */
|
|
2335
|
-
this._elementInfo = new Map();
|
|
2336
|
-
/** The number of elements currently being monitored. */
|
|
2337
|
-
this._monitoredElementCount = 0;
|
|
2338
|
-
/**
|
|
2339
|
-
* Keeps track of the root nodes to which we've currently bound a focus/blur handler,
|
|
2340
|
-
* as well as the number of monitored elements that they contain. We have to treat focus/blur
|
|
2341
|
-
* handlers differently from the rest of the events, because the browser won't emit events
|
|
2342
|
-
* to the document when focus moves inside of a shadow root.
|
|
2343
|
-
*/
|
|
2344
|
-
this._rootNodeFocusListenerCount = new Map();
|
|
2345
|
-
/**
|
|
2346
|
-
* Event listener for `focus` events on the window.
|
|
2347
|
-
* Needs to be an arrow function in order to preserve the context when it gets bound.
|
|
2348
|
-
*/
|
|
2349
|
-
this._windowFocusListener = () => {
|
|
2350
|
-
// Make a note of when the window regains focus, so we can
|
|
2351
|
-
// restore the origin info for the focused element.
|
|
2352
|
-
this._windowFocused = true;
|
|
2353
|
-
this._windowFocusTimeoutId = window.setTimeout(() => (this._windowFocused = false));
|
|
2354
|
-
};
|
|
2355
|
-
/** Used to reference correct document/window */
|
|
2356
|
-
this._document = inject(DOCUMENT, { optional: true });
|
|
2357
|
-
/** Subject for stopping our InputModalityDetector subscription. */
|
|
2358
|
-
this._stopInputModalityDetector = new Subject();
|
|
2359
|
-
/**
|
|
2360
|
-
* Event listener for `focus` and 'blur' events on the document.
|
|
2361
|
-
* Needs to be an arrow function in order to preserve the context when it gets bound.
|
|
2362
|
-
*/
|
|
2363
|
-
this._rootNodeFocusAndBlurListener = (event) => {
|
|
2364
|
-
const target = _getEventTarget(event);
|
|
2365
|
-
// We need to walk up the ancestor chain in order to support `checkChildren`.
|
|
2366
|
-
for (let element = target; element; element = element.parentElement) {
|
|
2367
|
-
if (event.type === 'focus') {
|
|
2368
|
-
this._onFocus(event, element);
|
|
2369
|
-
}
|
|
2370
|
-
else {
|
|
2371
|
-
this._onBlur(event, element);
|
|
2372
|
-
}
|
|
2373
|
-
}
|
|
2374
|
-
};
|
|
2375
2400
|
const options = inject(FOCUS_MONITOR_DEFAULT_OPTIONS, {
|
|
2376
2401
|
optional: true,
|
|
2377
2402
|
});
|
|
2378
2403
|
this._detectionMode = options?.detectionMode || FocusMonitorDetectionMode.IMMEDIATE;
|
|
2379
2404
|
}
|
|
2405
|
+
/**
|
|
2406
|
+
* Event listener for `focus` and 'blur' events on the document.
|
|
2407
|
+
* Needs to be an arrow function in order to preserve the context when it gets bound.
|
|
2408
|
+
*/
|
|
2409
|
+
_rootNodeFocusAndBlurListener = (event) => {
|
|
2410
|
+
const target = _getEventTarget(event);
|
|
2411
|
+
// We need to walk up the ancestor chain in order to support `checkChildren`.
|
|
2412
|
+
for (let element = target; element; element = element.parentElement) {
|
|
2413
|
+
if (event.type === 'focus') {
|
|
2414
|
+
this._onFocus(event, element);
|
|
2415
|
+
}
|
|
2416
|
+
else {
|
|
2417
|
+
this._onBlur(event, element);
|
|
2418
|
+
}
|
|
2419
|
+
}
|
|
2420
|
+
};
|
|
2380
2421
|
monitor(element, checkChildren = false) {
|
|
2381
2422
|
const nativeElement = coerceElement(element);
|
|
2382
2423
|
// Do nothing if we're not on the browser platform or the passed in node isn't an element.
|
|
@@ -2679,8 +2720,8 @@ class FocusMonitor {
|
|
|
2679
2720
|
}
|
|
2680
2721
|
return false;
|
|
2681
2722
|
}
|
|
2682
|
-
static
|
|
2683
|
-
static
|
|
2723
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: FocusMonitor, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2724
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: FocusMonitor, providedIn: 'root' });
|
|
2684
2725
|
}
|
|
2685
2726
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: FocusMonitor, decorators: [{
|
|
2686
2727
|
type: Injectable,
|
|
@@ -2696,12 +2737,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0-next.10",
|
|
|
2696
2737
|
* 2) cdkMonitorSubtreeFocus: considers an element focused if it or any of its children are focused.
|
|
2697
2738
|
*/
|
|
2698
2739
|
class CdkMonitorFocus {
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
}
|
|
2740
|
+
_elementRef = inject(ElementRef);
|
|
2741
|
+
_focusMonitor = inject(FocusMonitor);
|
|
2742
|
+
_monitorSubscription;
|
|
2743
|
+
_focusOrigin = null;
|
|
2744
|
+
cdkFocusChange = new EventEmitter();
|
|
2745
|
+
constructor() { }
|
|
2705
2746
|
get focusOrigin() {
|
|
2706
2747
|
return this._focusOrigin;
|
|
2707
2748
|
}
|
|
@@ -2720,8 +2761,8 @@ class CdkMonitorFocus {
|
|
|
2720
2761
|
this._monitorSubscription.unsubscribe();
|
|
2721
2762
|
}
|
|
2722
2763
|
}
|
|
2723
|
-
static
|
|
2724
|
-
static
|
|
2764
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: CdkMonitorFocus, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
2765
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.0.0-next.10", type: CdkMonitorFocus, isStandalone: true, selector: "[cdkMonitorElementFocus], [cdkMonitorSubtreeFocus]", outputs: { cdkFocusChange: "cdkFocusChange" }, exportAs: ["cdkMonitorFocus"], ngImport: i0 });
|
|
2725
2766
|
}
|
|
2726
2767
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: CdkMonitorFocus, decorators: [{
|
|
2727
2768
|
type: Directive,
|
|
@@ -2758,9 +2799,15 @@ const HIGH_CONTRAST_MODE_ACTIVE_CSS_CLASS = 'cdk-high-contrast-active';
|
|
|
2758
2799
|
* browser extension.
|
|
2759
2800
|
*/
|
|
2760
2801
|
class HighContrastModeDetector {
|
|
2802
|
+
_platform = inject(Platform);
|
|
2803
|
+
/**
|
|
2804
|
+
* Figuring out the high contrast mode and adding the body classes can cause
|
|
2805
|
+
* some expensive layouts. This flag is used to ensure that we only do it once.
|
|
2806
|
+
*/
|
|
2807
|
+
_hasCheckedHighContrastMode;
|
|
2808
|
+
_document = inject(DOCUMENT);
|
|
2809
|
+
_breakpointSubscription;
|
|
2761
2810
|
constructor() {
|
|
2762
|
-
this._platform = inject(Platform);
|
|
2763
|
-
this._document = inject(DOCUMENT);
|
|
2764
2811
|
this._breakpointSubscription = inject(BreakpointObserver)
|
|
2765
2812
|
.observe('(forced-colors: active)')
|
|
2766
2813
|
.subscribe(() => {
|
|
@@ -2825,8 +2872,8 @@ class HighContrastModeDetector {
|
|
|
2825
2872
|
}
|
|
2826
2873
|
}
|
|
2827
2874
|
}
|
|
2828
|
-
static
|
|
2829
|
-
static
|
|
2875
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: HighContrastModeDetector, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2876
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: HighContrastModeDetector, providedIn: 'root' });
|
|
2830
2877
|
}
|
|
2831
2878
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: HighContrastModeDetector, decorators: [{
|
|
2832
2879
|
type: Injectable,
|
|
@@ -2837,9 +2884,9 @@ class A11yModule {
|
|
|
2837
2884
|
constructor() {
|
|
2838
2885
|
inject(HighContrastModeDetector)._applyBodyHighContrastModeCssClasses();
|
|
2839
2886
|
}
|
|
2840
|
-
static
|
|
2841
|
-
static
|
|
2842
|
-
static
|
|
2887
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: A11yModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
2888
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.0.0-next.10", ngImport: i0, type: A11yModule, imports: [ObserversModule, CdkAriaLive, CdkTrapFocus, CdkMonitorFocus], exports: [CdkAriaLive, CdkTrapFocus, CdkMonitorFocus] });
|
|
2889
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: A11yModule, imports: [ObserversModule] });
|
|
2843
2890
|
}
|
|
2844
2891
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0-next.10", ngImport: i0, type: A11yModule, decorators: [{
|
|
2845
2892
|
type: NgModule,
|