a11y.mjs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  1. export { C as CdkMonitorFocus, d as FOCUS_MONITOR_DEFAULT_OPTIONS, F as FocusMonitor, c as FocusMonitorDetectionMode, a as INPUT_MODALITY_DETECTOR_DEFAULT_OPTIONS, b as INPUT_MODALITY_DETECTOR_OPTIONS, I as InputModalityDetector } from './focus-monitor-e2l_RpN3.mjs';
  2. import { a as FocusTrap, I as InteractivityChecker } from './a11y-module-BYox5gpI.mjs';
  3. export { A as A11yModule, d as CdkAriaLive, C as CdkTrapFocus, F as FocusTrapFactory, b as HighContrastMode, H as HighContrastModeDetector, c as IsFocusableConfig, g as LIVE_ANNOUNCER_DEFAULT_OPTIONS, e as LIVE_ANNOUNCER_ELEMENT_TOKEN, f as LIVE_ANNOUNCER_ELEMENT_TOKEN_FACTORY, L as LiveAnnouncer } from './a11y-module-BYox5gpI.mjs';
  4. export { _ as _IdGenerator } from './id-generator-Dw_9dSDu.mjs';
  5. import { DOCUMENT } from '@angular/common';
  6. import * as i0 from '@angular/core';
  7. import { inject, APP_ID, Injectable, InjectionToken, NgZone, Injector } from '@angular/core';
  8. import { P as Platform } from './platform-DmdVEw_C.mjs';
  9. import { _ as _CdkPrivateStyleLoader } from './style-loader-Cu9AvjH9.mjs';
  10. import { _VisuallyHiddenLoader } from './private.mjs';
  11. export { A as ActiveDescendantKeyManager } from './activedescendant-key-manager-DC3-fwQI.mjs';
  12. export { F as FocusKeyManager } from './focus-key-manager-C1rAQJ5z.mjs';
  13. export { L as ListKeyManager } from './list-key-manager-CyOIXo8P.mjs';
  14. import { Subject } from 'rxjs';
  15. import { T as TREE_KEY_MANAGER } from './tree-key-manager-KnCoIkIC.mjs';
  16. export { b as TREE_KEY_MANAGER_FACTORY, c as TREE_KEY_MANAGER_FACTORY_PROVIDER, a as TreeKeyManager } from './tree-key-manager-KnCoIkIC.mjs';
  17. export { i as isFakeMousedownFromScreenReader, a as isFakeTouchstartFromScreenReader } from './fake-event-detection-DWOdFTFz.mjs';
  18. import 'rxjs/operators';
  19. import './keycodes-CpHkExLC.mjs';
  20. import './shadow-dom-B0oHn41l.mjs';
  21. import './backwards-compatibility-DHR38MsD.mjs';
  22. import './passive-listeners-esHZRgIN.mjs';
  23. import './element-x4z00URv.mjs';
  24. import './breakpoints-observer-CljOfYGy.mjs';
  25. import './array-I1yfCXUO.mjs';
  26. import './observers.mjs';
  27. import './typeahead-9ZW4Dtsf.mjs';
  28. import './keycodes.mjs';
  29. import './coercion/private.mjs';
  30. /** IDs are delimited by an empty space, as per the spec. */
  31. const ID_DELIMITER = ' ';
  32. /**
  33. * Adds the given ID to the specified ARIA attribute on an element.
  34. * Used for attributes such as aria-labelledby, aria-owns, etc.
  35. */
  36. function addAriaReferencedId(el, attr, id) {
  37. const ids = getAriaReferenceIds(el, attr);
  38. id = id.trim();
  39. if (ids.some(existingId => existingId.trim() === id)) {
  40. return;
  41. }
  42. ids.push(id);
  43. el.setAttribute(attr, ids.join(ID_DELIMITER));
  44. }
  45. /**
  46. * Removes the given ID from the specified ARIA attribute on an element.
  47. * Used for attributes such as aria-labelledby, aria-owns, etc.
  48. */
  49. function removeAriaReferencedId(el, attr, id) {
  50. const ids = getAriaReferenceIds(el, attr);
  51. id = id.trim();
  52. const filteredIds = ids.filter(val => val !== id);
  53. if (filteredIds.length) {
  54. el.setAttribute(attr, filteredIds.join(ID_DELIMITER));
  55. }
  56. else {
  57. el.removeAttribute(attr);
  58. }
  59. }
  60. /**
  61. * Gets the list of IDs referenced by the given ARIA attribute on an element.
  62. * Used for attributes such as aria-labelledby, aria-owns, etc.
  63. */
  64. function getAriaReferenceIds(el, attr) {
  65. // Get string array of all individual ids (whitespace delimited) in the attribute value
  66. const attrValue = el.getAttribute(attr);
  67. return attrValue?.match(/\S+/g) ?? [];
  68. }
  69. /**
  70. * ID used for the body container where all messages are appended.
  71. * @deprecated No longer being used. To be removed.
  72. * @breaking-change 14.0.0
  73. */
  74. const MESSAGES_CONTAINER_ID = 'cdk-describedby-message-container';
  75. /**
  76. * ID prefix used for each created message element.
  77. * @deprecated To be turned into a private variable.
  78. * @breaking-change 14.0.0
  79. */
  80. const CDK_DESCRIBEDBY_ID_PREFIX = 'cdk-describedby-message';
  81. /**
  82. * Attribute given to each host element that is described by a message element.
  83. * @deprecated To be turned into a private variable.
  84. * @breaking-change 14.0.0
  85. */
  86. const CDK_DESCRIBEDBY_HOST_ATTRIBUTE = 'cdk-describedby-host';
  87. /** Global incremental identifier for each registered message element. */
  88. let nextId = 0;
  89. /**
  90. * Utility that creates visually hidden elements with a message content. Useful for elements that
  91. * want to use aria-describedby to further describe themselves without adding additional visual
  92. * content.
  93. */
  94. class AriaDescriber {
  95. _platform = inject(Platform);
  96. _document = inject(DOCUMENT);
  97. /** Map of all registered message elements that have been placed into the document. */
  98. _messageRegistry = new Map();
  99. /** Container for all registered messages. */
  100. _messagesContainer = null;
  101. /** Unique ID for the service. */
  102. _id = `${nextId++}`;
  103. constructor() {
  104. inject(_CdkPrivateStyleLoader).load(_VisuallyHiddenLoader);
  105. this._id = inject(APP_ID) + '-' + nextId++;
  106. }
  107. describe(hostElement, message, role) {
  108. if (!this._canBeDescribed(hostElement, message)) {
  109. return;
  110. }
  111. const key = getKey(message, role);
  112. if (typeof message !== 'string') {
  113. // We need to ensure that the element has an ID.
  114. setMessageId(message, this._id);
  115. this._messageRegistry.set(key, { messageElement: message, referenceCount: 0 });
  116. }
  117. else if (!this._messageRegistry.has(key)) {
  118. this._createMessageElement(message, role);
  119. }
  120. if (!this._isElementDescribedByMessage(hostElement, key)) {
  121. this._addMessageReference(hostElement, key);
  122. }
  123. }
  124. removeDescription(hostElement, message, role) {
  125. if (!message || !this._isElementNode(hostElement)) {
  126. return;
  127. }
  128. const key = getKey(message, role);
  129. if (this._isElementDescribedByMessage(hostElement, key)) {
  130. this._removeMessageReference(hostElement, key);
  131. }
  132. // If the message is a string, it means that it's one that we created for the
  133. // consumer so we can remove it safely, otherwise we should leave it in place.
  134. if (typeof message === 'string') {
  135. const registeredMessage = this._messageRegistry.get(key);
  136. if (registeredMessage && registeredMessage.referenceCount === 0) {
  137. this._deleteMessageElement(key);
  138. }
  139. }
  140. if (this._messagesContainer?.childNodes.length === 0) {
  141. this._messagesContainer.remove();
  142. this._messagesContainer = null;
  143. }
  144. }
  145. /** Unregisters all created message elements and removes the message container. */
  146. ngOnDestroy() {
  147. const describedElements = this._document.querySelectorAll(`[${CDK_DESCRIBEDBY_HOST_ATTRIBUTE}="${this._id}"]`);
  148. for (let i = 0; i < describedElements.length; i++) {
  149. this._removeCdkDescribedByReferenceIds(describedElements[i]);
  150. describedElements[i].removeAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE);
  151. }
  152. this._messagesContainer?.remove();
  153. this._messagesContainer = null;
  154. this._messageRegistry.clear();
  155. }
  156. /**
  157. * Creates a new element in the visually hidden message container element with the message
  158. * as its content and adds it to the message registry.
  159. */
  160. _createMessageElement(message, role) {
  161. const messageElement = this._document.createElement('div');
  162. setMessageId(messageElement, this._id);
  163. messageElement.textContent = message;
  164. if (role) {
  165. messageElement.setAttribute('role', role);
  166. }
  167. this._createMessagesContainer();
  168. this._messagesContainer.appendChild(messageElement);
  169. this._messageRegistry.set(getKey(message, role), { messageElement, referenceCount: 0 });
  170. }
  171. /** Deletes the message element from the global messages container. */
  172. _deleteMessageElement(key) {
  173. this._messageRegistry.get(key)?.messageElement?.remove();
  174. this._messageRegistry.delete(key);
  175. }
  176. /** Creates the global container for all aria-describedby messages. */
  177. _createMessagesContainer() {
  178. if (this._messagesContainer) {
  179. return;
  180. }
  181. const containerClassName = 'cdk-describedby-message-container';
  182. const serverContainers = this._document.querySelectorAll(`.${containerClassName}[platform="server"]`);
  183. for (let i = 0; i < serverContainers.length; i++) {
  184. // When going from the server to the client, we may end up in a situation where there's
  185. // already a container on the page, but we don't have a reference to it. Clear the
  186. // old container so we don't get duplicates. Doing this, instead of emptying the previous
  187. // container, should be slightly faster.
  188. serverContainers[i].remove();
  189. }
  190. const messagesContainer = this._document.createElement('div');
  191. // We add `visibility: hidden` in order to prevent text in this container from
  192. // being searchable by the browser's Ctrl + F functionality.
  193. // Screen-readers will still read the description for elements with aria-describedby even
  194. // when the description element is not visible.
  195. messagesContainer.style.visibility = 'hidden';
  196. // Even though we use `visibility: hidden`, we still apply `cdk-visually-hidden` so that
  197. // the description element doesn't impact page layout.
  198. messagesContainer.classList.add(containerClassName);
  199. messagesContainer.classList.add('cdk-visually-hidden');
  200. if (!this._platform.isBrowser) {
  201. messagesContainer.setAttribute('platform', 'server');
  202. }
  203. this._document.body.appendChild(messagesContainer);
  204. this._messagesContainer = messagesContainer;
  205. }
  206. /** Removes all cdk-describedby messages that are hosted through the element. */
  207. _removeCdkDescribedByReferenceIds(element) {
  208. // Remove all aria-describedby reference IDs that are prefixed by CDK_DESCRIBEDBY_ID_PREFIX
  209. const originalReferenceIds = getAriaReferenceIds(element, 'aria-describedby').filter(id => id.indexOf(CDK_DESCRIBEDBY_ID_PREFIX) != 0);
  210. element.setAttribute('aria-describedby', originalReferenceIds.join(' '));
  211. }
  212. /**
  213. * Adds a message reference to the element using aria-describedby and increments the registered
  214. * message's reference count.
  215. */
  216. _addMessageReference(element, key) {
  217. const registeredMessage = this._messageRegistry.get(key);
  218. // Add the aria-describedby reference and set the
  219. // describedby_host attribute to mark the element.
  220. addAriaReferencedId(element, 'aria-describedby', registeredMessage.messageElement.id);
  221. element.setAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE, this._id);
  222. registeredMessage.referenceCount++;
  223. }
  224. /**
  225. * Removes a message reference from the element using aria-describedby
  226. * and decrements the registered message's reference count.
  227. */
  228. _removeMessageReference(element, key) {
  229. const registeredMessage = this._messageRegistry.get(key);
  230. registeredMessage.referenceCount--;
  231. removeAriaReferencedId(element, 'aria-describedby', registeredMessage.messageElement.id);
  232. element.removeAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE);
  233. }
  234. /** Returns true if the element has been described by the provided message ID. */
  235. _isElementDescribedByMessage(element, key) {
  236. const referenceIds = getAriaReferenceIds(element, 'aria-describedby');
  237. const registeredMessage = this._messageRegistry.get(key);
  238. const messageId = registeredMessage && registeredMessage.messageElement.id;
  239. return !!messageId && referenceIds.indexOf(messageId) != -1;
  240. }
  241. /** Determines whether a message can be described on a particular element. */
  242. _canBeDescribed(element, message) {
  243. if (!this._isElementNode(element)) {
  244. return false;
  245. }
  246. if (message && typeof message === 'object') {
  247. // We'd have to make some assumptions about the description element's text, if the consumer
  248. // passed in an element. Assume that if an element is passed in, the consumer has verified
  249. // that it can be used as a description.
  250. return true;
  251. }
  252. const trimmedMessage = message == null ? '' : `${message}`.trim();
  253. const ariaLabel = element.getAttribute('aria-label');
  254. // We shouldn't set descriptions if they're exactly the same as the `aria-label` of the
  255. // element, because screen readers will end up reading out the same text twice in a row.
  256. return trimmedMessage ? !ariaLabel || ariaLabel.trim() !== trimmedMessage : false;
  257. }
  258. /** Checks whether a node is an Element node. */
  259. _isElementNode(element) {
  260. return element.nodeType === this._document.ELEMENT_NODE;
  261. }
  262. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: AriaDescriber, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
  263. static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: AriaDescriber, providedIn: 'root' });
  264. }
  265. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: AriaDescriber, decorators: [{
  266. type: Injectable,
  267. args: [{ providedIn: 'root' }]
  268. }], ctorParameters: () => [] });
  269. /** Gets a key that can be used to look messages up in the registry. */
  270. function getKey(message, role) {
  271. return typeof message === 'string' ? `${role || ''}/${message}` : message;
  272. }
  273. /** Assigns a unique ID to an element, if it doesn't have one already. */
  274. function setMessageId(element, serviceId) {
  275. if (!element.id) {
  276. element.id = `${CDK_DESCRIBEDBY_ID_PREFIX}-${serviceId}-${nextId++}`;
  277. }
  278. }
  279. // NoopTreeKeyManager is a "noop" implementation of TreeKeyMangerStrategy. Methods are noops. Does
  280. // not emit to streams.
  281. //
  282. // Used for applications built before TreeKeyManager to opt-out of TreeKeyManager and revert to
  283. // legacy behavior.
  284. /**
  285. * @docs-private
  286. *
  287. * Opt-out of Tree of key manager behavior.
  288. *
  289. * When provided, Tree has same focus management behavior as before TreeKeyManager was introduced.
  290. * - Tree does not respond to keyboard interaction
  291. * - Tree node allows tabindex to be set by Input binding
  292. * - Tree node allows tabindex to be set by attribute binding
  293. *
  294. * @deprecated NoopTreeKeyManager deprecated. Use TreeKeyManager or inject a
  295. * TreeKeyManagerStrategy instead. To be removed in a future version.
  296. *
  297. * @breaking-change 21.0.0
  298. */
  299. class NoopTreeKeyManager {
  300. _isNoopTreeKeyManager = true;
  301. // Provide change as required by TreeKeyManagerStrategy. NoopTreeKeyManager is a "noop"
  302. // implementation that does not emit to streams.
  303. change = new Subject();
  304. destroy() {
  305. this.change.complete();
  306. }
  307. onKeydown() {
  308. // noop
  309. }
  310. getActiveItemIndex() {
  311. // Always return null. NoopTreeKeyManager is a "noop" implementation that does not maintain
  312. // the active item.
  313. return null;
  314. }
  315. getActiveItem() {
  316. // Always return null. NoopTreeKeyManager is a "noop" implementation that does not maintain
  317. // the active item.
  318. return null;
  319. }
  320. focusItem() {
  321. // noop
  322. }
  323. }
  324. /**
  325. * @docs-private
  326. *
  327. * Opt-out of Tree of key manager behavior.
  328. *
  329. * When provided, Tree has same focus management behavior as before TreeKeyManager was introduced.
  330. * - Tree does not respond to keyboard interaction
  331. * - Tree node allows tabindex to be set by Input binding
  332. * - Tree node allows tabindex to be set by attribute binding
  333. *
  334. * @deprecated NoopTreeKeyManager deprecated. Use TreeKeyManager or inject a
  335. * TreeKeyManagerStrategy instead. To be removed in a future version.
  336. *
  337. * @breaking-change 21.0.0
  338. */
  339. function NOOP_TREE_KEY_MANAGER_FACTORY() {
  340. return () => new NoopTreeKeyManager();
  341. }
  342. /**
  343. * @docs-private
  344. *
  345. * Opt-out of Tree of key manager behavior.
  346. *
  347. * When provided, Tree has same focus management behavior as before TreeKeyManager was introduced.
  348. * - Tree does not respond to keyboard interaction
  349. * - Tree node allows tabindex to be set by Input binding
  350. * - Tree node allows tabindex to be set by attribute binding
  351. *
  352. * @deprecated NoopTreeKeyManager deprecated. Use TreeKeyManager or inject a
  353. * TreeKeyManagerStrategy instead. To be removed in a future version.
  354. *
  355. * @breaking-change 21.0.0
  356. */
  357. const NOOP_TREE_KEY_MANAGER_FACTORY_PROVIDER = {
  358. provide: TREE_KEY_MANAGER,
  359. useFactory: NOOP_TREE_KEY_MANAGER_FACTORY,
  360. };
  361. /**
  362. * Class that allows for trapping focus within a DOM element.
  363. *
  364. * This class uses a strategy pattern that determines how it traps focus.
  365. * See FocusTrapInertStrategy.
  366. */
  367. class ConfigurableFocusTrap extends FocusTrap {
  368. _focusTrapManager;
  369. _inertStrategy;
  370. /** Whether the FocusTrap is enabled. */
  371. get enabled() {
  372. return this._enabled;
  373. }
  374. set enabled(value) {
  375. this._enabled = value;
  376. if (this._enabled) {
  377. this._focusTrapManager.register(this);
  378. }
  379. else {
  380. this._focusTrapManager.deregister(this);
  381. }
  382. }
  383. constructor(_element, _checker, _ngZone, _document, _focusTrapManager, _inertStrategy, config, injector) {
  384. super(_element, _checker, _ngZone, _document, config.defer, injector);
  385. this._focusTrapManager = _focusTrapManager;
  386. this._inertStrategy = _inertStrategy;
  387. this._focusTrapManager.register(this);
  388. }
  389. /** Notifies the FocusTrapManager that this FocusTrap will be destroyed. */
  390. destroy() {
  391. this._focusTrapManager.deregister(this);
  392. super.destroy();
  393. }
  394. /** @docs-private Implemented as part of ManagedFocusTrap. */
  395. _enable() {
  396. this._inertStrategy.preventFocus(this);
  397. this.toggleAnchors(true);
  398. }
  399. /** @docs-private Implemented as part of ManagedFocusTrap. */
  400. _disable() {
  401. this._inertStrategy.allowFocus(this);
  402. this.toggleAnchors(false);
  403. }
  404. }
  405. /**
  406. * Lightweight FocusTrapInertStrategy that adds a document focus event
  407. * listener to redirect focus back inside the FocusTrap.
  408. */
  409. class EventListenerFocusTrapInertStrategy {
  410. /** Focus event handler. */
  411. _listener = null;
  412. /** Adds a document event listener that keeps focus inside the FocusTrap. */
  413. preventFocus(focusTrap) {
  414. // Ensure there's only one listener per document
  415. if (this._listener) {
  416. focusTrap._document.removeEventListener('focus', this._listener, true);
  417. }
  418. this._listener = (e) => this._trapFocus(focusTrap, e);
  419. focusTrap._ngZone.runOutsideAngular(() => {
  420. focusTrap._document.addEventListener('focus', this._listener, true);
  421. });
  422. }
  423. /** Removes the event listener added in preventFocus. */
  424. allowFocus(focusTrap) {
  425. if (!this._listener) {
  426. return;
  427. }
  428. focusTrap._document.removeEventListener('focus', this._listener, true);
  429. this._listener = null;
  430. }
  431. /**
  432. * Refocuses the first element in the FocusTrap if the focus event target was outside
  433. * the FocusTrap.
  434. *
  435. * This is an event listener callback. The event listener is added in runOutsideAngular,
  436. * so all this code runs outside Angular as well.
  437. */
  438. _trapFocus(focusTrap, event) {
  439. const target = event.target;
  440. const focusTrapRoot = focusTrap._element;
  441. // Don't refocus if target was in an overlay, because the overlay might be associated
  442. // with an element inside the FocusTrap, ex. mat-select.
  443. if (target && !focusTrapRoot.contains(target) && !target.closest?.('div.cdk-overlay-pane')) {
  444. // Some legacy FocusTrap usages have logic that focuses some element on the page
  445. // just before FocusTrap is destroyed. For backwards compatibility, wait
  446. // to be sure FocusTrap is still enabled before refocusing.
  447. setTimeout(() => {
  448. // Check whether focus wasn't put back into the focus trap while the timeout was pending.
  449. if (focusTrap.enabled && !focusTrapRoot.contains(focusTrap._document.activeElement)) {
  450. focusTrap.focusFirstTabbableElement();
  451. }
  452. });
  453. }
  454. }
  455. }
  456. /** The injection token used to specify the inert strategy. */
  457. const FOCUS_TRAP_INERT_STRATEGY = new InjectionToken('FOCUS_TRAP_INERT_STRATEGY');
  458. /** Injectable that ensures only the most recently enabled FocusTrap is active. */
  459. class FocusTrapManager {
  460. // A stack of the FocusTraps on the page. Only the FocusTrap at the
  461. // top of the stack is active.
  462. _focusTrapStack = [];
  463. /**
  464. * Disables the FocusTrap at the top of the stack, and then pushes
  465. * the new FocusTrap onto the stack.
  466. */
  467. register(focusTrap) {
  468. // Dedupe focusTraps that register multiple times.
  469. this._focusTrapStack = this._focusTrapStack.filter(ft => ft !== focusTrap);
  470. let stack = this._focusTrapStack;
  471. if (stack.length) {
  472. stack[stack.length - 1]._disable();
  473. }
  474. stack.push(focusTrap);
  475. focusTrap._enable();
  476. }
  477. /**
  478. * Removes the FocusTrap from the stack, and activates the
  479. * FocusTrap that is the new top of the stack.
  480. */
  481. deregister(focusTrap) {
  482. focusTrap._disable();
  483. const stack = this._focusTrapStack;
  484. const i = stack.indexOf(focusTrap);
  485. if (i !== -1) {
  486. stack.splice(i, 1);
  487. if (stack.length) {
  488. stack[stack.length - 1]._enable();
  489. }
  490. }
  491. }
  492. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: FocusTrapManager, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
  493. static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: FocusTrapManager, providedIn: 'root' });
  494. }
  495. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: FocusTrapManager, decorators: [{
  496. type: Injectable,
  497. args: [{ providedIn: 'root' }]
  498. }] });
  499. /** Factory that allows easy instantiation of configurable focus traps. */
  500. class ConfigurableFocusTrapFactory {
  501. _checker = inject(InteractivityChecker);
  502. _ngZone = inject(NgZone);
  503. _focusTrapManager = inject(FocusTrapManager);
  504. _document = inject(DOCUMENT);
  505. _inertStrategy;
  506. _injector = inject(Injector);
  507. constructor() {
  508. const inertStrategy = inject(FOCUS_TRAP_INERT_STRATEGY, { optional: true });
  509. // TODO split up the strategies into different modules, similar to DateAdapter.
  510. this._inertStrategy = inertStrategy || new EventListenerFocusTrapInertStrategy();
  511. }
  512. create(element, config = { defer: false }) {
  513. let configObject;
  514. if (typeof config === 'boolean') {
  515. configObject = { defer: config };
  516. }
  517. else {
  518. configObject = config;
  519. }
  520. return new ConfigurableFocusTrap(element, this._checker, this._ngZone, this._document, this._focusTrapManager, this._inertStrategy, configObject, this._injector);
  521. }
  522. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: ConfigurableFocusTrapFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
  523. static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: ConfigurableFocusTrapFactory, providedIn: 'root' });
  524. }
  525. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: ConfigurableFocusTrapFactory, decorators: [{
  526. type: Injectable,
  527. args: [{ providedIn: 'root' }]
  528. }], ctorParameters: () => [] });
  529. export { AriaDescriber, CDK_DESCRIBEDBY_HOST_ATTRIBUTE, CDK_DESCRIBEDBY_ID_PREFIX, ConfigurableFocusTrap, ConfigurableFocusTrapFactory, EventListenerFocusTrapInertStrategy, FOCUS_TRAP_INERT_STRATEGY, FocusTrap, InteractivityChecker, MESSAGES_CONTAINER_ID, NOOP_TREE_KEY_MANAGER_FACTORY, NOOP_TREE_KEY_MANAGER_FACTORY_PROVIDER, NoopTreeKeyManager, TREE_KEY_MANAGER, addAriaReferencedId, getAriaReferenceIds, removeAriaReferencedId };
  530. //# sourceMappingURL=a11y.mjs.map