PageSourceSearch

https://invaprom.ru/bitrix/js/ui/a11y/dist/a11y.bundle.js?179031521363634

js invaprom.ru collected 2026-10-10 00:47:45 UTC 63,634 bytes, 2,116 lines download raw bytes

1/* eslint-disable */
2this.BX = this.BX || {};
3this.BX.UI = this.BX.UI || {};
4(function (exports, main_core) {
5	'use strict';
6
7	const focusableElements = ['a[href]', 'input:not([disabled]):not([type=hidden])', 'select:not([disabled])', 'textarea:not([disabled])', 'button:not([disabled])', 'area[href]', 'summary', 'iframe', 'object', 'embed', 'audio[controls]', 'video[controls]', '[contenteditable]:not([contenteditable="false"])', '[tabindex]:not([disabled]):not([hidden])'];
8	const FOCUSABLE_SELECTOR = focusableElements.join(',');
9
10	const supportsCheckVisibility = !main_core.Type.isUndefined(window.Element) && 'checkVisibility' in window.Element.prototype;
11	const NON_TEXT_INPUT_TYPES = new Set(['button', 'checkbox', 'color', 'file', 'hidden', 'image', 'radio', 'range', 'reset', 'submit']);
12	const NON_EDITABLE_INPUT_TYPES = new Set(['button', 'checkbox', 'file', 'hidden', 'image', 'radio', 'range', 'reset', 'submit']);
13	class InteractivityChecker {
14		static isDisabled(element) {
15			return main_core.Type.isElementNode(element) && (element.hasAttribute('disabled') || element.getAttribute('aria-disabled') === 'true');
16		}
17		static isTextInput(element) {
18			if (!main_core.Type.isElementNode(element)) {
19				return false;
20			}
21			if (element.tagName === 'INPUT') {
22				return !NON_TEXT_INPUT_TYPES.has(element.type);
23			}
24			return element.tagName === 'TEXTAREA' || element.isContentEditable;
25		}
26		static isEditable(element) {
27			if (!main_core.Type.isElementNode(element)) {
28				return false;
29			}
30			if (element.tagName === 'INPUT') {
31				return !NON_EDITABLE_INPUT_TYPES.has(element.type);
32			}
33			return element.tagName === 'TEXTAREA' || element.tagName === 'SELECT' || element.isContentEditable;
34		}
35		static isVisible(element) {
36			if (!main_core.Type.isElementNode(element) || !element.isConnected) {
37				return false;
38			}
39			if (supportsCheckVisibility) {
40				return element.checkVisibility({
41					visibilityProperty: true,
42					opacityProperty: true
43				});
44			}
45			const hasGeometry = element.offsetWidth > 0 || element.offsetHeight > 0 || element.getClientRects().length > 0;
46			return hasGeometry && getComputedStyle(element).visibility === 'visible';
47		}
48		static isTabbable(element) {
49			if (!this.isFocusable(element)) {
50				return false;
51			}
52			return !this.hasNegativeTabIndex(element);
53		}
54		static hasNegativeTabIndex(element) {
55			const tabindex = element?.getAttribute('tabindex');
56			if (tabindex === null) {
57				return false;
58			}
59			return Number.parseInt(tabindex, 10) < 0;
60		}
61		static isFocusable(element) {
62			if (!main_core.Type.isElementNode(element) || element.closest('[inert]') || !element.isConnected) {
63				return false;
64			}
65			return element.matches(FOCUSABLE_SELECTOR) && this.isVisible(element);
66		}
67	}
68
69	const STORAGE_KEY = 'bx:a11y:debug';
70	const ALL = '*';
71	const CATEGORY_LABELS = {
72		'focus-monitor': 'FocusMonitor',
73		'focus-trap': 'FocusTrap',
74		'focus-zone': 'FocusZone',
75		'input-modality': 'InputModality',
76		'live-announcer': 'LiveAnnouncer'
77	};
78	class AccessibilityLogger {
79		static #categories = new Set();
80		static #all = false;
81		static #initialized = false;
82		static #init() {
83			if (this.#initialized) {
84				return;
85			}
86			this.#initialized = true;
87			try {
88				const raw = localStorage.getItem(STORAGE_KEY);
89				if (raw === ALL) {
90					this.#all = true;
91				} else if (raw) {
92					const parsed = JSON.parse(raw);
93					if (Array.isArray(parsed)) {
94						for (const category of parsed) {
95							this.#categories.add(category);
96						}
97					}
98				}
99			} catch {
100			}
101		}
102		static enable(category) {
103			this.#init();
104			if (category) {
105				this.#categories.add(category);
106			} else {
107				this.#all = true;
108			}
109			this.#save();
110		}
111		static disable(category) {
112			this.#init();
113			if (category) {
114				this.#categories.delete(category);
115			} else {
116				this.#all = false;
117				this.#categories.clear();
118			}
119			this.#save();
120		}
121		static isEnabled(category) {
122			this.#init();
123			return this.#all || this.#categories.has(category);
124		}
125		static log(category, message, ...args) {
126			if (!this.isEnabled(category)) {
127				return;
128			}
129			const label = CATEGORY_LABELS[category] || category;
130			console.log(`%c[${label}]%c ${message}`, 'color: #0075ff; font-weight: bold;', 'color: inherit; font-weight: normal;', ...args);
131		}
132		static logNode(category, message, node) {
133			if (!this.isEnabled(category) || !main_core.Type.isElementNode(node)) {
134				return;
135			}
136			const tag = node.tagName.toLowerCase();
137			const classes = node.className ? `.${[...node.classList].join('.')}` : '';
138			const id = node.id ? `#${node.id}` : '';
139			const selector = `${tag}${classes}${id}`;
140			const role = node.getAttribute('role');
141			const labelledBy = node.getAttribute('aria-labelledby');
142			const labelledByText = labelledBy ? labelledBy.split(/\s+/).map(labelId => document.getElementById(labelId)?.textContent?.trim()).filter(Boolean).join(' ') : '';
143			const ariaLabel = (node.getAttribute('aria-label') || labelledByText || node.textContent.trim().slice(0, 30) || '—').replaceAll(/\s+/g, ' ');
144			const attrs = [role && `role="${role}"`, node.getAttribute('aria-expanded') !== null && `aria-expanded="${node.getAttribute('aria-expanded')}"`, node.getAttribute('href') && `href="${node.getAttribute('href')}"`, node.getAttribute('tabindex') && `tabindex="${node.getAttribute('tabindex')}"`].filter(Boolean).join(' ');
145			const label = CATEGORY_LABELS[category] || category;
146			const parts = [`%c[${label}]%c ${message}`, `%c${selector}%c`, `"%c${ariaLabel}%c"`, attrs && `%c${attrs}%c`].filter(Boolean).join(' ');
147			console.log(parts, 'color: #0075ff; font-weight: bold;',
148			'color: inherit; font-weight: normal;',
149			'color: #0075ff; font-weight: bold;',
150			'color: inherit; font-weight: normal;',
151			'color: #e36209; font-style: italic;',
152			'color: inherit; font-style: normal;',
153			...(attrs ? ['color: #9b59b6;',
154			'color: inherit;'
155			] : []));
156		}
157		static warn(category, message, ...args) {
158			if (!this.isEnabled(category)) {
159				return;
160			}
161			const label = CATEGORY_LABELS[category] || category;
162			console.warn(`[${label}] ${message}`, ...args);
163		}
164		static #save() {
165			try {
166				if (this.#all) {
167					localStorage.setItem(STORAGE_KEY, ALL);
168				} else if (this.#categories.size > 0) {
169					localStorage.setItem(STORAGE_KEY, JSON.stringify([...this.#categories]));
170				} else {
171					localStorage.removeItem(STORAGE_KEY);
172				}
173			} catch {
174			}
175		}
176	}
177
178	const RESTORE_FOCUS_EVENT = 'a11y:restore-focus';
179	class FocusNavigator {
180		static get FOCUSABLE_SELECTOR() {
181			return FOCUSABLE_SELECTOR;
182		}
183		static isFocusLost(node) {
184			const activeElement = this.getActiveElement(node);
185			return activeElement === null || activeElement.tagName === 'BODY';
186		}
187		static getFirst(container, options) {
188			return this.#traverse(container, 'first', options);
189		}
190		static getLast(container, options) {
191			return this.#traverse(container, 'last', options);
192		}
193		static getNext(container, options) {
194			return this.#traverse(container, 'next', options);
195		}
196		static getPrevious(container, options) {
197			return this.#traverse(container, 'previous', options);
198		}
199		static focusFirst(container, options) {
200			return this.focusTarget(this.#traverse(container, 'first', options), options);
201		}
202		static focusLast(container, options) {
203			return this.focusTarget(this.#traverse(container, 'last', options), options);
204		}
205		static focusNext(container, options) {
206			return this.focusTarget(this.#traverse(container, 'next', options), options);
207		}
208		static focusPrevious(container, options) {
209			return this.focusTarget(this.#traverse(container, 'previous', options), options);
210		}
211		static focusContainer(container, options) {
212			if (!container.hasAttribute('tabindex')) {
213				container.setAttribute('tabindex', '-1');
214			}
215			this.focusTarget(container, options);
216			return container;
217		}
218		static getActiveElement(node) {
219			const {
220				activeElement
221			} = this.#getDocument(node);
222			if (activeElement?.tagName === 'IFRAME' && activeElement.contentDocument?.body) {
223				const iframe = activeElement;
224				return this.getActiveElement(iframe.contentDocument?.body);
225			}
226			if (main_core.Type.isElementNode(activeElement)) {
227				return activeElement;
228			}
229			return null;
230		}
231		static createWalker(container, options) {
232			const {
233				tabbableOnly = false,
234				accept
235			} = options ?? {};
236			const ownerDocument = container.ownerDocument ?? document;
237			return ownerDocument.createTreeWalker(container, NodeFilter.SHOW_ELEMENT, {
238				acceptNode(node) {
239					const el = node;
240					if (!InteractivityChecker.isFocusable(el)) {
241						return NodeFilter.FILTER_SKIP;
242					}
243					if (tabbableOnly && el.tabIndex < 0) {
244						return NodeFilter.FILTER_SKIP;
245					}
246					if (accept && !accept(el) && el.tagName !== 'IFRAME') {
247						return NodeFilter.FILTER_SKIP;
248					}
249					return NodeFilter.FILTER_ACCEPT;
250				}
251			});
252		}
253		static *#walk(container, options) {
254			const walker = this.createWalker(container, options);
255			for (let node = walker.nextNode(); node !== null; node = walker.nextNode()) {
256				const el = node;
257				if (el.tagName === 'IFRAME') {
258					try {
259						const iframe = el;
260						const body = iframe.contentDocument?.body;
261						if (body) {
262							yield* this.#walk(body, options);
263							continue;
264						}
265					} catch {
266					}
267				}
268				yield el;
269			}
270		}
271		static #traverse(container, direction, options) {
272			const walkerOptions = {
273				tabbableOnly: options?.tabbableOnly ?? true,
274				accept: options?.accept
275			};
276			switch (direction) {
277				case 'first':
278					{
279						return this.#walk(container, walkerOptions).next().value ?? null;
280					}
281				case 'last':
282					{
283						let last = null;
284						for (const el of this.#walk(container, walkerOptions)) {
285							last = el;
286						}
287						return last;
288					}
289				case 'next':
290					{
291						const from = this.#resolveFrom(container, options);
292						let found = from === null;
293						for (const el of this.#walk(container, walkerOptions)) {
294							if (found) {
295								return el;
296							}
297							if (el === from) {
298								found = true;
299							}
300						}
301						if (options?.wrap) {
302							return this.#walk(container, walkerOptions).next().value ?? null;
303						}
304						return null;
305					}
306				case 'previous':
307					{
308						const from = this.#resolveFrom(container, options);
309						let prev = null;
310						for (const el of this.#walk(container, walkerOptions)) {
311							if (el === from) {
312								break;
313							}
314							prev = el;
315						}
316						if (prev) {
317							return prev;
318						}
319						if (options?.wrap) {
320							return this.#traverse(container, 'last', options);
321						}
322						return null;
323					}
324			}
325			return null;
326		}
327		static focusBySelector(container, selector, options) {
328			const {
329				accept: outerAccept,
330				...rest
331			} = options ?? {};
332			const accept = el => {
333				return el.matches(selector) && (outerAccept ? outerAccept(el) : true);
334			};
335			const from = this.#resolveFrom(container, options);
336			let found = from === null;
337			for (const el of this.#walk(container, {
338				...rest,
339				accept
340			})) {
341				if (found) {
342					return this.focusTarget(el, options);
343				}
344				if (el === from) {
345					found = true;
346				}
347			}
348			if (options?.wrap) {
349				const el = this.#walk(container, {
350					...rest,
351					accept
352				}).next().value;
353				if (el) {
354					return this.focusTarget(el, options);
355				}
356			}
357			return null;
358		}
359		static #resolveFrom(container, options) {
360			const from = options?.from ?? this.getActiveElement(container);
361			if (!from || container === from) {
362				return null;
363			}
364			if (container.contains(from)) {
365				return from;
366			}
367			let doc = from.ownerDocument;
368			while (doc !== null) {
369				const frame = doc.defaultView?.frameElement;
370				if (!frame) {
371					return null;
372				}
373				if (container.contains(frame)) {
374					return from;
375				}
376				doc = frame.ownerDocument;
377			}
378			return null;
379		}
380		static focusTarget(target, options) {
381			if (!target) {
382				return null;
383			}
384			const {
385				preventScroll,
386				focusVisible
387			} = options ?? {};
388			target.focus({
389				preventScroll,
390				focusVisible
391			});
392			return target;
393		}
394		static restoreFocus(target, options) {
395			if (!main_core.Type.isElementNode(target)) {
396				return null;
397			}
398			try {
399				const customEvent = new CustomEvent(RESTORE_FOCUS_EVENT, {
400					bubbles: true,
401					cancelable: true
402				});
403				const dispatchResult = target.dispatchEvent(customEvent);
404				if (dispatchResult) {
405					this.focusTarget(target, options);
406					AccessibilityLogger.log('focus-monitor', 'restored focus to', target);
407					return target;
408				}
409			} catch {
410				AccessibilityLogger.warn('focus-monitor', 'failed to restore focus to', target);
411			}
412			return null;
413		}
414		static #getDocument(node) {
415			if (!node) {
416				return document;
417			}
418			if (node.window === node) {
419				return node.document;
420			}
421			return node.ownerDocument ?? document;
422		}
423	}
424
425	class FocusHistory {
426		#limit;
427		#stack = [];
428		constructor(limit = 25) {
429			this.#limit = limit;
430		}
431		record(el) {
432			if (!InteractivityChecker.isFocusable(el)) {
433				return;
434			}
435			if (this.#stack[this.#stack.length - 1]?.deref() === el) {
436				return;
437			}
438			for (let i = this.#stack.length - 1; i >= 0; i--) {
439				const current = this.#stack[i].deref();
440				if (!current) {
441					this.#stack.splice(i, 1);
442					continue;
443				}
444				if (current === el) {
445					this.#stack.splice(i, 1);
446					break;
447				}
448			}
449			AccessibilityLogger.logNode('focus-monitor', 'recorded', el);
450			this.#stack.push(new WeakRef(el));
451			this.#trimByWindow(el.ownerDocument);
452		}
453		getLastValid() {
454			for (let i = this.#stack.length - 1; i >= 0; i--) {
455				const el = this.#stack[i].deref();
456				if (!el) {
457					this.#stack.splice(i, 1);
458					continue;
459				}
460				if (InteractivityChecker.isFocusable(el)) {
461					this.#stack.length = i + 1;
462					return el;
463				}
464				this.#stack.splice(i, 1);
465			}
466			return null;
467		}
468		#trimByWindow(doc) {
469			const docIndexes = [];
470			for (let i = this.#stack.length - 1; i >= 0; i--) {
471				const current = this.#stack[i].deref();
472				if (!current) {
473					this.#stack.splice(i, 1);
474					continue;
475				}
476				if (current.ownerDocument === doc) {
477					docIndexes.push(i);
478				}
479			}
480			const excess = docIndexes.length - this.#limit;
481			if (excess <= 0) {
482				return;
483			}
484			for (let j = docIndexes.length - excess; j < docIndexes.length; j++) {
485				this.#stack.splice(docIndexes[j], 1);
486			}
487		}
488	}
489
490	const NAV_KEYS = new Set(['Tab', 'Escape', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Home', 'End']);
491	const BARE_MODIFIER_KEYS = new Set(['Alt', 'AltGraph', 'CapsLock', 'Control', 'Meta', 'NumLock', 'ScrollLock', 'Shift']);
492	const POINTER_TYPES = new Set(['mouse', 'pen', 'touch']);
493	class InputModalityTracker {
494		#modality = 'unknown';
495		#pointerType = null;
496		#lastNavKey = null;
497		#lastNavShift = false;
498		#attachedDocs = [];
499		#detachHandlers = new WeakMap();
500		attach(doc) {
501			if (this.#detachHandlers.has(doc)) {
502				return;
503			}
504			const onKeyDown = event => {
505				if (InputModalityTracker.isBareModifier(event.key)) {
506					return;
507				}
508				if (NAV_KEYS.has(event.key)) {
509					this.#lastNavKey = event.key;
510					this.#lastNavShift = event.shiftKey;
511				} else {
512					this.#lastNavKey = null;
513					this.#lastNavShift = false;
514				}
515				this.#setModality('keyboard');
516			};
517			const onPointer = event => {
518				this.#pointerType = POINTER_TYPES.has(event.pointerType) ? event.pointerType : 'mouse';
519				this.#lastNavKey = null;
520				this.#lastNavShift = false;
521				this.#setModality('pointer');
522			};
523			main_core.Event.bind(doc, 'keydown', onKeyDown, true);
524			main_core.Event.bind(doc, 'pointerdown', onPointer, true);
525			const detach = () => {
526				main_core.Event.unbind(doc, 'keydown', onKeyDown, true);
527				main_core.Event.unbind(doc, 'pointerdown', onPointer, true);
528			};
529			this.#attachedDocs.push(new WeakRef(doc));
530			this.#detachHandlers.set(doc, detach);
531			doc.documentElement.dataset.inputModality = this.#modality;
532		}
533		detach(doc) {
534			const detach = this.#detachHandlers.get(doc);
535			if (detach) {
536				detach();
537				this.#detachHandlers.delete(doc);
538				this.#cleanupWeakRefs();
539			}
540		}
541		static isBareModifier(key) {
542			return BARE_MODIFIER_KEYS.has(key);
543		}
544		static enableDebug() {
545			AccessibilityLogger.enable('input-modality');
546		}
547		static disableDebug() {
548			AccessibilityLogger.disable('input-modality');
549		}
550		#setModality(modality) {
551			if (this.#modality !== modality) {
552				AccessibilityLogger.log('input-modality', `${this.#modality} -> ${modality}`);
553				this.#modality = modality;
554				this.#updateAllDocuments();
555			}
556		}
557		#updateAllDocuments() {
558			const aliveRefs = [];
559			for (const weakRef of this.#attachedDocs) {
560				const doc = weakRef.deref();
561				if (doc) {
562					doc.documentElement.dataset.inputModality = this.#modality;
563					aliveRefs.push(weakRef);
564				}
565			}
566			this.#attachedDocs = aliveRefs;
567		}
568		#cleanupWeakRefs() {
569			this.#attachedDocs = this.#attachedDocs.filter(weakRef => {
570				const doc = weakRef.deref();
571				return doc && this.#detachHandlers.has(doc);
572			});
573		}
574		getLastModality() {
575			return this.#modality;
576		}
577		getLastPointerType() {
578			return this.#modality === 'pointer' ? this.#pointerType : null;
579		}
580		getLastNavigationKey() {
581			return this.#modality === 'keyboard' ? this.#lastNavKey : null;
582		}
583		isLastNavigationReversed() {
584			return this.#modality === 'keyboard' && this.#lastNavKey === 'Tab' && this.#lastNavShift;
585		}
586	}
587
588	class AccessibilitySettings {
589		static useFocusTrapInDialogs() {
590			const settings = main_core.Extension.getSettings('ui.a11y');
591			return settings.get('useFocusTrapInDialogs') === true;
592		}
593		static restoreLostFocus() {
594			const settings = main_core.Extension.getSettings('ui.a11y');
595			return settings.get('restoreLostFocus') === true;
596		}
597		static suppressFocusOnRestore() {
598			const settings = main_core.Extension.getSettings('ui.a11y');
599			return settings.get('suppressFocusOnRestore') === true;
600		}
601	}
602
603	class FocusMonitor {
604		static #instance = null;
605		#history;
606		#modality;
607		#documents = new WeakMap();
608		constructor() {
609			this.#history = new FocusHistory(25);
610			this.#modality = new InputModalityTracker();
611			this.#attachDocument(document);
612		}
613		static get Instance() {
614			return this.initialize();
615		}
616		static initialize() {
617			const topWindow = main_core.Page.getRootWindow();
618			if (topWindow !== window) {
619				const monitor = main_core.Reflection.getClass('top.BX.UI.Accessibility.FocusMonitor');
620				if (monitor !== null) {
621					return monitor.Instance;
622				}
623			}
624			if (this.#instance === null) {
625				this.#instance = new FocusMonitor();
626			}
627			return this.#instance;
628		}
629		static enableDebug() {
630			AccessibilityLogger.enable('focus-monitor');
631		}
632		static disableDebug() {
633			AccessibilityLogger.disable('focus-monitor');
634		}
635		static shouldRestoreLostFocus() {
636			return AccessibilitySettings.restoreLostFocus();
637		}
638		#attachDocument(doc) {
639			if (this.#documents.has(doc)) {
640				return;
641			}
642			let pendingRestore = null;
643			const onFocusIn = event => {
644				if (pendingRestore !== null) {
645					clearTimeout(pendingRestore);
646					pendingRestore = null;
647				}
648				const target = event.target;
649				if (main_core.Type.isElementNode(target)) {
650					this.#history.record(target);
651					if (target.tagName === 'IFRAME') {
652						this.attachIframe(target);
653					}
654				}
655			};
656			const onFocusOut = () => {
657				if (pendingRestore !== null) {
658					return;
659				}
660				pendingRestore = window.setTimeout(() => {
661					pendingRestore = null;
662					this.#tryRestoreLostFocus(doc);
663				}, 0);
664			};
665			doc.addEventListener('focusin', onFocusIn, true);
666			doc.addEventListener('focusout', onFocusOut, true);
667			const observer = this.#attachObserver(doc);
668			this.#modality.attach(doc);
669			this.#documents.set(doc, {
670				detach: () => {
671					if (pendingRestore !== null) {
672						clearTimeout(pendingRestore);
673					}
674					doc.removeEventListener('focusin', onFocusIn, true);
675					doc.removeEventListener('focusout', onFocusOut, true);
676					this.#modality.detach(doc);
677					observer?.disconnect();
678				}
679			});
680		}
681		attachIframe(iframe) {
682			if (!main_core.Type.isElementNode(iframe) || iframe.tagName !== 'IFRAME') {
683				return;
684			}
685			try {
686				const doc = iframe.contentDocument;
687				if (!doc) {
688					return;
689				}
690				const state = this.#documents.get(doc);
691				if (state) {
692					return;
693				}
694				this.#attachDocument(doc);
695			} catch {
696			}
697		}
698		detachIframe(iframe) {
699			try {
700				const doc = iframe.contentDocument;
701				if (!doc) {
702					return;
703				}
704				const state = this.#documents.get(doc);
705				if (state) {
706					state.detach();
707					this.#documents.delete(doc);
708				}
709			} catch {
710			}
711		}
712		#tryRestoreLostFocus(doc) {
713			if (!FocusMonitor.shouldRestoreLostFocus()) {
714				return;
715			}
716			const active = doc.activeElement;
717			if (active && active !== doc.body) {
718				return;
719			}
720			if (this.#modality.getLastModality() !== 'keyboard') {
721				return;
722			}
723			const target = this.#history.getLastValid();
724			if (target) {
725				this.#restoreElementFocus(target);
726				return;
727			}
728			this.#restoreFocusToRoot(doc);
729		}
730		restoreFocus() {
731			const target = this.#history.getLastValid();
732			if (target) {
733				this.#restoreElementFocus(target);
734				return;
735			}
736			this.#restoreFocusToRoot(document);
737		}
738		#restoreFocusToRoot(doc) {
739			AccessibilityLogger.log('focus-monitor', 'restoring focus to root');
740			FocusNavigator.restoreFocus(this.getRoot(doc), {
741				preventScroll: true
742			});
743		}
744		getRoot(doc = document) {
745			return doc.querySelector('[data-focus-root]') || doc.querySelector('main') || doc.body;
746		}
747		#restoreElementFocus(el) {
748			if (!el.isConnected) {
749				return;
750			}
751			const ownerWindow = el.ownerDocument.defaultView;
752			if (!ownerWindow) {
753				return;
754			}
755			const activeElement = FocusNavigator.getActiveElement(el);
756			if (activeElement === el) {
757				return;
758			}
759			if (ownerWindow === window) {
760				FocusNavigator.restoreFocus(el, {
761					preventScroll: true
762				});
763				return;
764			}
765			ownerWindow.requestAnimationFrame(() => {
766				FocusNavigator.restoreFocus(el, {
767					preventScroll: true
768				});
769			});
770		}
771		getLastInputModality() {
772			return this.#modality.getLastModality();
773		}
774		getModalityTracker() {
775			return this.#modality;
776		}
777		#attachObserver(doc) {
778			if (!FocusMonitor.shouldRestoreLostFocus()) {
779				return null;
780			}
781			if (main_core.Browser.isFirefox() || main_core.Browser.isSafari()) {
782				const observer = new MutationObserver(mutations => {
783					this.#tryRestoreLostFocus(doc);
784				});
785				const observe = () => observer.observe(doc.body, {
786					childList: true,
787					subtree: true,
788					characterData: false
789				});
790				if (doc.readyState === 'loading') {
791					doc.addEventListener('DOMContentLoaded', observe);
792				} else {
793					observe();
794				}
795				return observer;
796			}
797			return null;
798		}
799	}
800
801	const PRECEDING = Node.DOCUMENT_POSITION_PRECEDING | Node.DOCUMENT_POSITION_CONTAINS;
802	const FOLLOWING = Node.DOCUMENT_POSITION_FOLLOWING | Node.DOCUMENT_POSITION_CONTAINED_BY;
803	const outsideIsolationOwnership = new WeakMap();
804	class FocusTrap {
805		#id = `focus-trap-${main_core.Text.getRandom()}`;
806		#container;
807		#options;
808		#active = false;
809		#looped = true;
810		#initialized = false;
811		#restoreFocus = null;
812		#preventScroll = true;
813		#startFocusBoundary = null;
814		#endFocusBoundary = null;
815		#lastFocusedElement = null;
816		#outsideIsolationElements = null;
817		#startFocusHandler = this.#handleStartBoundaryFocus.bind(this);
818		#endFocusHandler = this.#handleEndBoundaryFocus.bind(this);
819		constructor(container, options = {}) {
820			this.#container = container;
821			this.#options = main_core.Type.isPlainObject(options) ? options : {};
822			this.setRestoreFocus(this.#options.restoreFocus ?? null);
823			if (this.#options.looped !== undefined) {
824				this.setLooped(this.#options.looped);
825			}
826			if (this.#options.preventScroll !== undefined) {
827				this.setPreventScroll(this.#options.preventScroll);
828			}
829		}
830		static enableDebug() {
831			AccessibilityLogger.enable('focus-trap');
832		}
833		static disableDebug() {
834			AccessibilityLogger.disable('focus-trap');
835		}
836		activate(options = {}) {
837			if (this.#active) {
838				return;
839			}
840			if (!this.#initialized) {
841				this.#init();
842			}
843			if (this.#lastFocusedElement === null) {
844				this.captureActiveElement();
845			}
846			this.#active = true;
847			if (this.#looped) {
848				this.#setBoundariesFocusable(true);
849			}
850			const {
851				initialFocus
852			} = {
853				initialFocus: true,
854				...options
855			};
856			if (initialFocus) {
857				this.applyInitialFocus();
858			}
859			this.#setOutsideIsolation(true);
860		}
861		deactivate() {
862			if (!this.#active) {
863				return;
864			}
865			this.#active = false;
866			this.#setBoundariesFocusable(false);
867			this.#setOutsideIsolation(false);
868			this.restoreFocus();
869		}
870		destroy() {
871			this.deactivate();
872			if (!this.#initialized) {
873				return;
874			}
875			main_core.Event.unbind(this.#startFocusBoundary, 'focus', this.#startFocusHandler);
876			main_core.Event.unbind(this.#endFocusBoundary, 'focus', this.#endFocusHandler);
877			main_core.Dom.remove(this.#startFocusBoundary);
878			main_core.Dom.remove(this.#endFocusBoundary);
879			this.#initialized = false;
880		}
881		setLooped(flag) {
882			if (!main_core.Type.isBoolean(flag)) {
883				return;
884			}
885			this.#looped = flag;
886			if (this.#active) {
887				this.#setBoundariesFocusable(flag);
888			}
889		}
890		setPreventScroll(flag) {
891			this.#preventScroll = main_core.Type.isBoolean(flag) ? flag : true;
892		}
893		isLooped() {
894			return this.#looped;
895		}
896		isActive() {
897			return this.#active;
898		}
899		setLastFocusedElement(el) {
900			if (main_core.Type.isElementNode(el) && el.tagName !== 'BODY' && !this.contains(el)) {
901				this.#lastFocusedElement = el;
902				AccessibilityLogger.logNode('focus-trap', 'set last focus', el);
903			}
904		}
905		captureActiveElement() {
906			const activeElement = FocusNavigator.getActiveElement();
907			if (activeElement !== null) {
908				this.setLastFocusedElement(activeElement);
909			}
910			return activeElement;
911		}
912		contains(el) {
913			return this.#container.contains(el);
914		}
915		focusFirst(options) {
916			return FocusNavigator.focusFirst(this.#container, this.#prepareFocusOptions(options));
917		}
918		focusLast(options) {
919			return FocusNavigator.focusLast(this.#container, this.#prepareFocusOptions(options));
920		}
921		focusNext(options) {
922			return FocusNavigator.focusNext(this.#container, this.#prepareFocusOptions(options));
923		}
924		focusPrevious(options) {
925			return FocusNavigator.focusPrevious(this.#container, this.#prepareFocusOptions(options));
926		}
927		focusContainer(options) {
928			return FocusNavigator.focusContainer(this.#container, this.#prepareFocusOptions(options));
929		}
930		focusBySelector(selector, options) {
931			return FocusNavigator.focusBySelector(this.#container, selector, this.#prepareFocusOptions(options));
932		}
933		#prepareFocusOptions(options) {
934			const preparedOptions = main_core.Type.isPlainObject(options) ? {
935				...options
936			} : {};
937			if (main_core.Type.isNil(preparedOptions.preventScroll)) {
938				preparedOptions.preventScroll = this.#preventScroll;
939			}
940			return preparedOptions;
941		}
942		getId() {
943			return this.#id;
944		}
945		#init() {
946			this.#startFocusBoundary = this.#createFocusBoundary();
947			this.#endFocusBoundary = this.#createFocusBoundary();
948			main_core.Event.bind(this.#startFocusBoundary, 'focus', this.#startFocusHandler);
949			main_core.Event.bind(this.#endFocusBoundary, 'focus', this.#endFocusHandler);
950			this.#container.insertAdjacentElement('beforebegin', this.#startFocusBoundary);
951			this.#container.insertAdjacentElement('afterend', this.#endFocusBoundary);
952			this.#initialized = true;
953		}
954		#createFocusBoundary() {
955			const el = document.createElement('div');
956			el.setAttribute('aria-hidden', 'true');
957			el.setAttribute('data-focus-trap', this.getId());
958			main_core.Dom.style(el, {
959				position: 'fixed',
960				width: 0,
961				height: 0,
962				opacity: '0',
963				pointerEvents: 'none',
964				outline: 'none'
965			});
966			return el;
967		}
968		#handleStartBoundaryFocus(event) {
969			if (!this.#active || !this.#startFocusBoundary) {
970				return;
971			}
972			const position = event.relatedTarget ? this.#startFocusBoundary.compareDocumentPosition(event.relatedTarget) : 0;
973			const isBackward = position & FOLLOWING;
974			if (!isBackward) {
975				if (!this.focusFirst()) {
976					this.focusContainer();
977				}
978				return;
979			}
980			const target = this.#options.startBoundary ? this.#resolveBoundary(this.#options.startBoundary) : null;
981			if (target) {
982				FocusNavigator.focusTarget(target, {
983					preventScroll: this.#preventScroll
984				});
985				return;
986			}
987			if (!this.focusLast()) {
988				this.focusContainer();
989			}
990		}
991		#handleEndBoundaryFocus(event) {
992			if (!this.#active || !this.#endFocusBoundary) {
993				return;
994			}
995			const position = event.relatedTarget ? this.#endFocusBoundary.compareDocumentPosition(event.relatedTarget) : 0;
996			const isBackward = position & PRECEDING;
997			if (!isBackward) {
998				if (!this.focusLast()) {
999					this.focusContainer();
1000				}
1001				return;
1002			}
1003			const target = this.#options.endBoundary ? this.#resolveBoundary(this.#options.endBoundary) : null;
1004			if (target) {
1005				FocusNavigator.focusTarget(target, {
1006					preventScroll: this.#preventScroll
1007				});
1008				return;
1009			}
1010			if (!this.focusFirst()) {
1011				this.focusContainer();
1012			}
1013		}
1014		#resolveBoundary(boundary) {
1015			if (main_core.Type.isStringFilled(boundary)) {
1016				const el = document.querySelector(boundary);
1017				return el !== null && main_core.Type.isElementNode(el) && InteractivityChecker.isFocusable(el) ? el : null;
1018			}
1019			if (main_core.Type.isElementNode(boundary) && InteractivityChecker.isFocusable(boundary)) {
1020				return boundary;
1021			}
1022			if (main_core.Type.isFunction(boundary)) {
1023				const el = boundary();
1024				return main_core.Type.isElementNode(el) && InteractivityChecker.isFocusable(el) ? el : null;
1025			}
1026			return null;
1027		}
1028		#setBoundariesFocusable(enabled) {
1029			const tabindex = enabled ? '0' : '-1';
1030			this.#startFocusBoundary?.setAttribute('tabindex', tabindex);
1031			this.#endFocusBoundary?.setAttribute('tabindex', tabindex);
1032		}
1033		applyInitialFocus() {
1034			const initialFocus = this.#options.initialFocus ?? true;
1035			if (initialFocus === false) {
1036				return;
1037			}
1038			if (!this.#options.forceInitialFocus) {
1039				const activeElement = FocusNavigator.getActiveElement(this.#container);
1040				if (activeElement && this.#container.contains(activeElement) && activeElement !== this.#container) {
1041					return;
1042				}
1043			}
1044			const candidates = Array.isArray(initialFocus) ? initialFocus : [initialFocus];
1045			for (const candidate of candidates) {
1046				if (this.#tryInitialFocus(candidate)) {
1047					return;
1048				}
1049			}
1050			this.focusContainer();
1051		}
1052		#tryInitialFocus(initialFocus) {
1053			if (initialFocus === false) {
1054				return false;
1055			}
1056			if (initialFocus === 'container') {
1057				this.focusContainer();
1058				return true;
1059			}
1060			if (main_core.Type.isStringFilled(initialFocus)) {
1061				return this.focusBySelector(initialFocus) !== null;
1062			}
1063			if (main_core.Type.isFunction(initialFocus)) {
1064				const el = initialFocus();
1065				if (InteractivityChecker.isFocusable(el)) {
1066					FocusNavigator.focusTarget(el, {
1067						preventScroll: this.#preventScroll
1068					});
1069					return true;
1070				}
1071				return false;
1072			}
1073			if (initialFocus === true || initialFocus === 'first-tabbable' || main_core.Type.isNil(initialFocus)) {
1074				return Boolean(this.focusFirst());
1075			}
1076			return false;
1077		}
1078		setRestoreFocus(restore) {
1079			if (main_core.Type.isBoolean(restore) || main_core.Type.isNull(restore) || main_core.Type.isStringFilled(restore) || main_core.Type.isFunction(restore) || main_core.Type.isElementNode(restore)) {
1080				this.#restoreFocus = restore;
1081			}
1082		}
1083		restoreFocus() {
1084			try {
1085				if (this.#restoreFocus === null && this.#shouldKeepCurrentFocus()) {
1086					this.#scheduleLostFocusRestore(this.#lastFocusedElement);
1087					return;
1088				}
1089				const restoreFocus = this.#restoreFocus ?? true;
1090				if (restoreFocus === false) {
1091					return;
1092				}
1093				if (main_core.Type.isStringFilled(restoreFocus)) {
1094					const doc = this.#container.ownerDocument ?? document;
1095					let el = null;
1096					try {
1097						el = doc.querySelector(restoreFocus);
1098					} catch {
1099						console.error('FocusTrap: invalid restoreFocus selector provided');
1100					}
1101					if (el !== null && InteractivityChecker.isFocusable(el)) {
1102						FocusNavigator.restoreFocus(el, {
1103							preventScroll: true
1104						});
1105						return;
1106					}
1107				}
1108				if (main_core.Type.isElementNode(restoreFocus) && InteractivityChecker.isFocusable(restoreFocus)) {
1109					FocusNavigator.restoreFocus(restoreFocus, {
1110						preventScroll: true
1111					});
1112					return;
1113				}
1114				if (main_core.Type.isFunction(restoreFocus)) {
1115					const el = restoreFocus();
1116					if (InteractivityChecker.isFocusable(el)) {
1117						FocusNavigator.restoreFocus(el, {
1118							preventScroll: true
1119						});
1120						return;
1121					}
1122				}
1123				if (this.#lastFocusedElement !== null && InteractivityChecker.isFocusable(this.#lastFocusedElement)) {
1124					let eventListeners = [];
1125					const suppressFocusOnRestore = main_core.Type.isBoolean(this.#options.suppressFocusOnRestore) ? this.#options.suppressFocusOnRestore : AccessibilitySettings.suppressFocusOnRestore();
1126					try {
1127						if (suppressFocusOnRestore) {
1128							eventListeners = main_core.Event.getEventListeners(this.#lastFocusedElement, 'focus');
1129							if (eventListeners.length > 0) {
1130								main_core.Event.unbindAll(this.#lastFocusedElement, 'focus');
1131							}
1132						}
1133						AccessibilityLogger.logNode('focus-trap', 'back to last focus', this.#lastFocusedElement);
1134						FocusNavigator.restoreFocus(this.#lastFocusedElement, {
1135							preventScroll: true
1136						});
1137					} finally {
1138						if (suppressFocusOnRestore) {
1139							for (const eventListener of eventListeners) {
1140								main_core.Event.bind(this.#lastFocusedElement, 'focus', eventListener.listener);
1141							}
1142						}
1143					}
1144					return;
1145				}
1146				FocusMonitor.Instance.restoreFocus();
1147			} finally {
1148				this.#lastFocusedElement = null;
1149			}
1150		}
1151		#shouldKeepCurrentFocus() {
1152			if (FocusNavigator.isFocusLost(this.#container)) {
1153				return false;
1154			}
1155			const activeElement = FocusNavigator.getActiveElement(this.#container);
1156			return activeElement !== null && !this.#containsElement(activeElement);
1157		}
1158		#scheduleLostFocusRestore(lastFocusedElement) {
1159			setTimeout(() => {
1160				if (!FocusNavigator.isFocusLost(this.#container)) {
1161					return;
1162				}
1163				if (lastFocusedElement !== null && InteractivityChecker.isFocusable(lastFocusedElement)) {
1164					AccessibilityLogger.logNode('focus-trap', 'back to last focus (lost)', lastFocusedElement);
1165					FocusNavigator.restoreFocus(lastFocusedElement, {
1166						preventScroll: true
1167					});
1168					return;
1169				}
1170				FocusMonitor.Instance.restoreFocus();
1171			}, 0);
1172		}
1173		#containsElement(element) {
1174			if (this.contains(element)) {
1175				return true;
1176			}
1177			let doc = element.ownerDocument;
1178			while (doc?.defaultView?.frameElement) {
1179				const frame = doc.defaultView.frameElement;
1180				if (main_core.Type.isElementNode(frame) && this.contains(frame)) {
1181					return true;
1182				}
1183				doc = frame.ownerDocument;
1184			}
1185			return false;
1186		}
1187		#setOutsideIsolation(enable) {
1188			if (enable && this.#options.isolateOutside !== true) {
1189				return;
1190			}
1191			if (enable) {
1192				this.#captureOutsideIsolationSnapshot();
1193			} else {
1194				for (const el of this.#outsideIsolationElements ?? []) {
1195					this.#releaseOutsideIsolation(el);
1196				}
1197				this.#outsideIsolationElements = null;
1198			}
1199		}
1200		#captureOutsideIsolationSnapshot() {
1201			const containers = [this.#container, ...this.#getOutsideExceptionElements()];
1202			const topLevelContainers = containers.filter(el => {
1203				return !containers.some(other => other !== el && other.contains(el));
1204			});
1205			const adjacentElements = this.#getAdjacentElements(topLevelContainers);
1206			this.#outsideIsolationElements = new Set();
1207			for (const el of adjacentElements) {
1208				if (el === this.#container || this.#container.contains(el) || el.getAttribute('data-focus-trap') === this.getId()) {
1209					continue;
1210				}
1211				if (el.parentNode?.nodeName === 'BODY' && el.offsetWidth === 0 && el.offsetHeight === 0) {
1212					continue;
1213				}
1214				this.#outsideIsolationElements.add(el);
1215				this.#acquireOutsideIsolation(el);
1216			}
1217		}
1218		#acquireOutsideIsolation(element) {
1219			const ownership = outsideIsolationOwnership.get(element);
1220			if (ownership) {
1221				ownership.ownerCount++;
1222			} else {
1223				outsideIsolationOwnership.set(element, {
1224					ownerCount: 1,
1225					wasInert: element.inert || element.hasAttribute('inert')
1226				});
1227			}
1228			element.setAttribute('inert', 'true');
1229		}
1230		#releaseOutsideIsolation(element) {
1231			const ownership = outsideIsolationOwnership.get(element);
1232			if (!ownership) {
1233				return;
1234			}
1235			ownership.ownerCount--;
1236			if (ownership.ownerCount > 0) {
1237				return;
1238			}
1239			outsideIsolationOwnership.delete(element);
1240			if (!ownership.wasInert) {
1241				element.removeAttribute('inert');
1242			}
1243		}
1244		#getAdjacentElements(containers) {
1245			const adjacentElements = new Set();
1246			const containerAncestors = new Set();
1247			for (const container of containers) {
1248				let currentElement = container;
1249				while (currentElement && currentElement.tagName !== 'BODY') {
1250					containerAncestors.add(currentElement);
1251					const parent = currentElement.parentElement;
1252					const siblings = parent ? parent.children : [];
1253					for (const sibling of siblings) {
1254						if (sibling.tagName !== 'SCRIPT' && sibling.tagName !== 'STYLE' && !sibling.getAttribute('data-a11y-ignore-inert') && main_core.Type.isElementNode(sibling)) {
1255							adjacentElements.add(sibling);
1256						}
1257					}
1258					currentElement = parent;
1259				}
1260			}
1261			containerAncestors.forEach(el => {
1262				adjacentElements.delete(el);
1263			});
1264			return adjacentElements;
1265		}
1266		#getOutsideExceptionElements() {
1267			if (!main_core.Type.isArrayFilled(this.#options.outsideExceptionSelectors)) {
1268				return [];
1269			}
1270			try {
1271				const selectors = this.#options.outsideExceptionSelectors.join(',');
1272				return [...document.querySelectorAll(selectors)];
1273			} catch {
1274				console.error('FocusTrap: invalid outsideExceptionSelectors provided');
1275				return [];
1276			}
1277		}
1278	}
1279
1280	const FocusTrapDirective = {
1281		mounted(el, binding) {
1282			const {
1283				active,
1284				options
1285			} = normalizeValue(binding.value);
1286			el.__focusTrap = new FocusTrap(el, options);
1287			if (active) {
1288				el.__focusTrap.activate();
1289			}
1290		},
1291		updated(el, binding) {
1292			const {
1293				active,
1294				options
1295			} = normalizeValue(binding.value);
1296			const {
1297				active: prevActive,
1298				options: prevOptions
1299			} = normalizeValue(binding.oldValue);
1300			if (options !== prevOptions && options) {
1301				el.__focusTrap?.destroy();
1302				el.__focusTrap = new FocusTrap(el, options);
1303			}
1304			const trap = el.__focusTrap;
1305			if (!trap) {
1306				return;
1307			}
1308			if (active) {
1309				trap.activate();
1310			} else {
1311				trap.deactivate();
1312			}
1313		},
1314		unmounted(el) {
1315			el.__focusTrap?.destroy();
1316			delete el.__focusTrap;
1317		}
1318	};
1319	function normalizeValue(value) {
1320		if (main_core.Type.isBoolean(value)) {
1321			return {
1322				active: value
1323			};
1324		}
1325		if (main_core.Type.isPlainObject(value)) {
1326			return {
1327				active: value.active !== false,
1328				options: value.options
1329			};
1330		}
1331		return {
1332			active: false
1333		};
1334	}
1335
1336	class LiveAnnouncer {
1337		static #instance = null;
1338		#el;
1339		#queue = [];
1340		#isSpeaking = false;
1341		#frameId = null;
1342		#timerId = null;
1343		#ready = false;
1344		#readyFrameId = null;
1345		#baseDelay = 500;
1346		#charDelay = 30;
1347		#maxDelay = 4000;
1348		#maxMessageLength = 160;
1349		static enableDebug() {
1350			AccessibilityLogger.enable('live-announcer');
1351		}
1352		static disableDebug() {
1353			AccessibilityLogger.disable('live-announcer');
1354		}
1355		static announce(message, politeness = 'polite') {
1356			if (!LiveAnnouncer.#instance) {
1357				LiveAnnouncer.#instance = new LiveAnnouncer();
1358			}
1359			LiveAnnouncer.#instance.announce(message, politeness);
1360		}
1361		static destroy() {
1362			LiveAnnouncer.#instance?.destroy();
1363			LiveAnnouncer.#instance = null;
1364		}
1365		constructor(options) {
1366			const {
1367				politeness = 'polite',
1368				container = document.body || document.documentElement,
1369				baseDelay,
1370				charDelay,
1371				maxDelay,
1372				maxMessageLength
1373			} = options ?? {};
1374			if (main_core.Type.isNumber(baseDelay)) {
1375				this.#baseDelay = baseDelay;
1376			}
1377			if (main_core.Type.isNumber(charDelay)) {
1378				this.#charDelay = charDelay;
1379			}
1380			if (main_core.Type.isNumber(maxDelay)) {
1381				this.#maxDelay = maxDelay;
1382			}
1383			if (main_core.Type.isNumber(maxMessageLength)) {
1384				this.#maxMessageLength = maxMessageLength;
1385			}
1386			this.#el = this.#createLiveRegion(politeness);
1387			main_core.Dom.append(this.#el, container);
1388			this.#readyFrameId = requestAnimationFrame(() => {
1389				this.#readyFrameId = null;
1390				this.#ready = true;
1391				this.#process();
1392			});
1393		}
1394		announce(message, politeness = 'polite') {
1395			const normalized = this.#normalizeMessage(message);
1396			if (!normalized) {
1397				return;
1398			}
1399			AccessibilityLogger.log('live-announcer', `[${politeness}] ${normalized}`);
1400			const last = this.#queue[this.#queue.length - 1];
1401			if (last && last.message === normalized && last.politeness === politeness) {
1402				return;
1403			}
1404			if (politeness === 'assertive') {
1405				this.#clearPendingAnnouncement();
1406				this.#queue.unshift({
1407					message: normalized,
1408					politeness
1409				});
1410			} else {
1411				this.#queue.push({
1412					message: normalized,
1413					politeness
1414				});
1415			}
1416			this.#process();
1417		}
1418		destroy() {
1419			if (this.#readyFrameId !== null) {
1420				cancelAnimationFrame(this.#readyFrameId);
1421				this.#readyFrameId = null;
1422			}
1423			this.#queue.length = 0;
1424			this.#clearPendingAnnouncement();
1425			this.#el.remove();
1426		}
1427		#process() {
1428			if (!this.#ready || this.#isSpeaking || this.#queue.length === 0) {
1429				return;
1430			}
1431			const item = this.#queue.shift();
1432			if (!item) {
1433				return;
1434			}
1435			this.#isSpeaking = true;
1436			const {
1437				message,
1438				politeness
1439			} = item;
1440			const delay = this.#getDelay(message);
1441			this.#el.setAttribute('aria-live', politeness);
1442			this.#el.textContent = '';
1443			this.#frameId = requestAnimationFrame(() => {
1444				this.#frameId = null;
1445				this.#el.textContent = message;
1446				this.#timerId = setTimeout(() => {
1447					this.#timerId = null;
1448					this.#isSpeaking = false;
1449					if (this.#queue.length === 0) {
1450						this.#el.textContent = '';
1451					}
1452					this.#process();
1453				}, delay);
1454			});
1455		}
1456		#clearPendingAnnouncement() {
1457			this.#isSpeaking = false;
1458			if (this.#frameId !== null) {
1459				cancelAnimationFrame(this.#frameId);
1460				this.#frameId = null;
1461			}
1462			if (this.#timerId !== null) {
1463				clearTimeout(this.#timerId);
1464				this.#timerId = null;
1465			}
1466			this.#el.textContent = '';
1467		}
1468		#getDelay(message) {
1469			const delay = this.#baseDelay + message.length * this.#charDelay;
1470			return Math.min(delay, this.#maxDelay);
1471		}
1472		#normalizeMessage(message) {
1473			if (!main_core.Type.isStringFilled(message)) {
1474				return '';
1475			}
1476			const text = message.trim();
1477			if (!text) {
1478				return '';
1479			}
1480			if (text.length <= this.#maxMessageLength) {
1481				return text;
1482			}
1483			const truncated = text.slice(0, this.#maxMessageLength - 1);
1484			const trimmedToWord = truncated.replace(/\s+\S*$/, '');
1485			return `${trimmedToWord || truncated}\u2026`;
1486		}
1487		#createLiveRegion(politeness) {
1488			const el = document.createElement('div');
1489			el.setAttribute('aria-live', politeness);
1490			el.setAttribute('aria-atomic', 'true');
1491			el.setAttribute('data-a11y-ignore-inert', 'true');
1492			main_core.Dom.style(el, {
1493				position: 'absolute',
1494				width: '1px',
1495				height: '1px',
1496				margin: '-1px',
1497				padding: '0',
1498				overflow: 'hidden',
1499				clip: 'rect(0 0 0 0)',
1500				whiteSpace: 'nowrap',
1501				border: '0'
1502			});
1503			return el;
1504		}
1505	}
1506
1507	const ARROW_HORIZONTAL = 0b0000000001;
1508	const ARROW_VERTICAL = 0b0000000010;
1509	const JK_BITS = 0b0000000100;
1510	const HL_BITS = 0b0000001000;
1511	const HOME_AND_END = 0b0000010000;
1512	const WS_BITS = 0b0000100000;
1513	const AD_BITS = 0b0001000000;
1514	const TAB_BIT = 0b0010000000;
1515	const PAGE_UP_DOWN = 0b0100000000;
1516	const BACKSPACE_BIT = 0b1000000000;
1517	const FocusKeys = {
1518		ArrowHorizontal: ARROW_HORIZONTAL,
1519		ArrowVertical: ARROW_VERTICAL,
1520		JK: JK_BITS,
1521		HL: HL_BITS,
1522		HomeAndEnd: HOME_AND_END,
1523		WS: WS_BITS,
1524		AD: AD_BITS,
1525		Tab: TAB_BIT,
1526		PageUpDown: PAGE_UP_DOWN,
1527		Backspace: BACKSPACE_BIT,
1528		ArrowAll: ARROW_HORIZONTAL | ARROW_VERTICAL,
1529		HJKL: HL_BITS | JK_BITS,
1530		WASD: WS_BITS | AD_BITS,
1531		All: ARROW_HORIZONTAL | ARROW_VERTICAL | JK_BITS | HL_BITS | HOME_AND_END | WS_BITS | AD_BITS | TAB_BIT | PAGE_UP_DOWN | BACKSPACE_BIT
1532	};
1533
1534	const ActiveDescendant = {
1535		ELEMENT_ATTR: 'data-active-descendant',
1536		CONTAINER_ATTR: 'data-has-active-descendant',
1537		EXPLICIT: 'activated-by-keyboard',
1538		IMPLICIT: 'activated-by-other'
1539	};
1540	const KEY_TO_BIT = {
1541		ArrowLeft: FocusKeys.ArrowHorizontal,
1542		ArrowDown: FocusKeys.ArrowVertical,
1543		ArrowUp: FocusKeys.ArrowVertical,
1544		ArrowRight: FocusKeys.ArrowHorizontal,
1545		h: FocusKeys.HL,
1546		j: FocusKeys.JK,
1547		k: FocusKeys.JK,
1548		l: FocusKeys.HL,
1549		a: FocusKeys.AD,
1550		s: FocusKeys.WS,
1551		w: FocusKeys.WS,
1552		d: FocusKeys.AD,
1553		Tab: FocusKeys.Tab,
1554		Home: FocusKeys.HomeAndEnd,
1555		End: FocusKeys.HomeAndEnd,
1556		PageUp: FocusKeys.PageUpDown,
1557		PageDown: FocusKeys.PageUpDown,
1558		Backspace: FocusKeys.Backspace
1559	};
1560	const KEY_TO_DIRECTION = {
1561		ArrowLeft: 'previous',
1562		ArrowDown: 'next',
1563		ArrowUp: 'previous',
1564		ArrowRight: 'next',
1565		h: 'previous',
1566		j: 'next',
1567		k: 'previous',
1568		l: 'next',
1569		a: 'previous',
1570		s: 'next',
1571		w: 'previous',
1572		d: 'next',
1573		Tab: 'next',
1574		Home: 'start',
1575		End: 'end',
1576		PageUp: 'start',
1577		PageDown: 'end',
1578		Backspace: 'previous'
1579	};
1580	class FocusZone {
1581		#container;
1582		#options;
1583		#active = false;
1584		#bindKeys;
1585		#focusOutBehavior;
1586		#focusInStrategy;
1587		#preventScroll;
1588		#ignoreHoverEvents;
1589		#tabbableOnly;
1590		#elementSet = new Set();
1591		#savedTabIndex = new WeakMap();
1592		#currentFocusedElement = null;
1593		#activeDescendantControl = null;
1594		#observer = null;
1595		#syncFrameId = null;
1596		#bindings = [];
1597		#generatedContainerId = false;
1598		#generatedElementIds = new WeakSet();
1599		#keyDownHandler = this.#handleKeyDown.bind(this);
1600		#focusInHandler = this.#handleFocusIn.bind(this);
1601		#mouseMoveHandler = this.#handleMouseMove.bind(this);
1602		#controlFocusInHandler = this.#handleControlFocusIn.bind(this);
1603		#controlFocusOutHandler = this.#handleControlFocusOut.bind(this);
1604		constructor(container, options = {}) {
1605			this.#container = container;
1606			this.#options = main_core.Type.isPlainObject(options) ? options : {};
1607			this.#activeDescendantControl = this.#options.activeDescendantControl ?? null;
1608			this.#focusOutBehavior = this.#options.focusOutBehavior ?? 'stop';
1609			this.#focusInStrategy = this.#options.focusInStrategy ?? 'previous';
1610			this.#preventScroll = this.#options.preventScroll ?? false;
1611			this.#ignoreHoverEvents = this.#options.ignoreHoverEvents ?? false;
1612			this.#tabbableOnly = this.#options.tabbableOnly ?? false;
1613			this.#bindKeys = this.#options.bindKeys ?? (this.#options.getNextFocusable ? FocusKeys.ArrowAll : FocusKeys.ArrowVertical) | FocusKeys.HomeAndEnd;
1614		}
1615		static enableDebug() {
1616			AccessibilityLogger.enable('focus-zone');
1617		}
1618		static disableDebug() {
1619			AccessibilityLogger.disable('focus-zone');
1620		}
1621		activate() {
1622			if (this.#active) {
1623				return;
1624			}
1625			this.#active = true;
1626			this.#elementSet = this.#collectFocusableSet();
1627			for (const element of this.#elementSet) {
1628				this.#saveAndSetTabIndex(element);
1629			}
1630			if (this.#activeDescendantControl) {
1631				if (!this.#container.id) {
1632					this.#container.setAttribute('id', `fz-${main_core.Text.getRandom()}`);
1633					this.#generatedContainerId = true;
1634				}
1635				this.#activeDescendantControl.setAttribute('aria-controls', this.#container.id);
1636			}
1637			const preventInitialFocus = this.#focusInStrategy === 'initial' && this.#activeDescendantControl;
1638			if (!preventInitialFocus) {
1639				this.#updateFocusedElement(this.#resolveInitialFocusedElement());
1640			}
1641			this.#attachEventListeners();
1642			this.#attachObserver();
1643			AccessibilityLogger.log('focus-zone', `activated with ${this.#elementSet.size} elements`);
1644		}
1645		deactivate() {
1646			if (!this.#active) {
1647				return;
1648			}
1649			this.#active = false;
1650			if (this.#observer) {
1651				this.#observer.disconnect();
1652				this.#observer = null;
1653			}
1654			if (this.#syncFrameId !== null) {
1655				cancelAnimationFrame(this.#syncFrameId);
1656				this.#syncFrameId = null;
1657			}
1658			this.#detachEventListeners();
1659			for (const element of this.#elementSet) {
1660				this.#restoreTabIndex(element);
1661				if (this.#generatedElementIds.has(element)) {
1662					element.removeAttribute('id');
1663					this.#generatedElementIds.delete(element);
1664				}
1665			}
1666			if (this.#activeDescendantControl) {
1667				this.#clearActiveDescendant();
1668				this.#activeDescendantControl.removeAttribute('aria-controls');
1669			}
1670			if (this.#generatedContainerId) {
1671				this.#container.removeAttribute('id');
1672				this.#generatedContainerId = false;
1673			}
1674			this.#elementSet.clear();
1675			this.#currentFocusedElement = null;
1676			AccessibilityLogger.log('focus-zone', 'deactivated');
1677		}
1678		isActive() {
1679			return this.#active;
1680		}
1681		getCurrentFocusedElement() {
1682			return this.#currentFocusedElement;
1683		}
1684		refreshElements() {
1685			if (this.#active) {
1686				this.#syncFocusableElements();
1687			}
1688		}
1689		#collectFocusableSet() {
1690			const elements = new Set();
1691			const walker = FocusNavigator.createWalker(this.#container, {
1692				tabbableOnly: this.#tabbableOnly,
1693				accept: this.#options.focusableElementFilter
1694			});
1695			for (let node = walker.nextNode(); node !== null; node = walker.nextNode()) {
1696				elements.add(node);
1697			}
1698			return elements;
1699		}
1700		#getNavigatorOptions(from = null, wrap = false) {
1701			return {
1702				from: from ?? undefined,
1703				tabbableOnly: false,
1704				accept: el => this.#elementSet.has(el),
1705				wrap
1706			};
1707		}
1708		#findManagedAncestor(node) {
1709			let el = main_core.Type.isElementNode(node) ? node : node.parentElement;
1710			while (el && el !== this.#container) {
1711				if (this.#elementSet.has(el)) {
1712					return el;
1713				}
1714				el = el.parentElement;
1715			}
1716			return null;
1717		}
1718		#saveAndSetTabIndex(element) {
1719			if (!this.#savedTabIndex.has(element)) {
1720				this.#savedTabIndex.set(element, element.getAttribute('tabindex'));
1721			}
1722			element.setAttribute('tabindex', '-1');
1723		}
1724		#restoreTabIndex(element) {
1725			const savedIndex = this.#savedTabIndex.get(element);
1726			if (savedIndex !== undefined) {
1727				if (savedIndex === null) {
1728					element.removeAttribute('tabindex');
1729				} else {
1730					element.setAttribute('tabindex', savedIndex);
1731				}
1732				this.#savedTabIndex.delete(element);
1733			}
1734		}
1735		#updateFocusedElement(to = null, directlyActivated = false) {
1736			const from = this.#currentFocusedElement;
1737			this.#currentFocusedElement = to;
1738			if (this.#activeDescendantControl) {
1739				if (to && FocusNavigator.getActiveElement() === this.#activeDescendantControl) {
1740					this.#setActiveDescendant(from, to, directlyActivated);
1741				} else {
1742					this.#clearActiveDescendant();
1743				}
1744				return;
1745			}
1746			if (from && from !== to && this.#savedTabIndex.has(from)) {
1747				from.setAttribute('tabindex', '-1');
1748			}
1749			if (to) {
1750				to.setAttribute('tabindex', '0');
1751			}
1752		}
1753		#setActiveDescendant(from, to, directlyActivated = false) {
1754			if (!to.id) {
1755				to.setAttribute('id', `fz-${main_core.Text.getRandom()}`);
1756				this.#generatedElementIds.add(to);
1757			}
1758			if (from && from !== to) {
1759				from.removeAttribute(ActiveDescendant.ELEMENT_ATTR);
1760			}
1761			if (!this.#activeDescendantControl) {
1762				return;
1763			}
1764			const previousId = this.#activeDescendantControl.getAttribute('aria-activedescendant');
1765			const nextActivationMode = directlyActivated ? ActiveDescendant.EXPLICIT : ActiveDescendant.IMPLICIT;
1766			const currentActivationMode = to.getAttribute(ActiveDescendant.ELEMENT_ATTR);
1767			if (previousId === to.id && currentActivationMode === nextActivationMode) {
1768				return;
1769			}
1770			this.#activeDescendantControl.setAttribute('aria-activedescendant', to.id);
1771			this.#container.setAttribute(ActiveDescendant.CONTAINER_ATTR, to.id);
1772			to.setAttribute(ActiveDescendant.ELEMENT_ATTR, nextActivationMode);
1773			AccessibilityLogger.logNode('focus-zone', 'active descendant ->', to);
1774			this.#options.onActiveDescendantChanged?.(to, from, directlyActivated);
1775		}
1776		#clearActiveDescendant(previousElement = this.#currentFocusedElement) {
1777			if (this.#focusInStrategy === 'first') {
1778				this.#currentFocusedElement = null;
1779			}
1780			this.#activeDescendantControl?.removeAttribute('aria-activedescendant');
1781			this.#container.removeAttribute(ActiveDescendant.CONTAINER_ATTR);
1782			if (previousElement) {
1783				previousElement.removeAttribute(ActiveDescendant.ELEMENT_ATTR);
1784			}
1785			const stale = this.#container.querySelectorAll(`[${ActiveDescendant.ELEMENT_ATTR}]`);
1786			for (const element of stale) {
1787				element.removeAttribute(ActiveDescendant.ELEMENT_ATTR);
1788			}
1789			this.#options.onActiveDescendantChanged?.(null, previousElement, false);
1790		}
1791		#handleKeyDown(event) {
1792			const keyBit = KEY_TO_BIT[event.key];
1793			if (keyBit === undefined || this.#elementSet.size === 0) {
1794				return;
1795			}
1796			if (event.defaultPrevented || (keyBit & this.#bindKeys) === 0 || FocusZone.#isNativeInputKey(event, FocusNavigator.getActiveElement())) {
1797				return;
1798			}
1799			const direction = FocusZone.#getDirection(event);
1800			let nextElement = null;
1801			if (this.#options.getNextFocusable) {
1802				nextElement = this.#options.getNextFocusable(direction, FocusNavigator.getActiveElement() ?? null, event);
1803			}
1804			if (!nextElement) {
1805				const wrap = this.#focusOutBehavior === 'wrap' && event.key !== 'Tab';
1806				const navOptions = this.#getNavigatorOptions(this.#currentFocusedElement, wrap);
1807				switch (direction) {
1808					case 'previous':
1809						{
1810							nextElement = FocusNavigator.getPrevious(this.#container, navOptions);
1811							break;
1812						}
1813					case 'next':
1814						{
1815							nextElement = FocusNavigator.getNext(this.#container, navOptions);
1816							break;
1817						}
1818					case 'start':
1819						{
1820							nextElement = FocusNavigator.getFirst(this.#container, navOptions);
1821							break;
1822						}
1823					default:
1824						{
1825							nextElement = FocusNavigator.getLast(this.#container, navOptions);
1826						}
1827				}
1828			}
1829			if (this.#activeDescendantControl) {
1830				this.#updateFocusedElement(nextElement || this.#currentFocusedElement, true);
1831			} else if (nextElement) {
1832				nextElement.focus({
1833					preventScroll: this.#preventScroll
1834				});
1835			}
1836			if (event.key !== 'Tab' || nextElement) {
1837				event.preventDefault();
1838			}
1839		}
1840		#handleFocusIn(event) {
1841			if (!main_core.Type.isElementNode(event.target)) {
1842				return;
1843			}
1844			if (this.#activeDescendantControl) {
1845				this.#handleFocusInActiveDescendant(event);
1846			} else {
1847				this.#handleFocusInRovingTabindex(event);
1848			}
1849		}
1850		#handleFocusInActiveDescendant(event) {
1851			const target = event.target;
1852			if (this.#elementSet.has(target)) {
1853				this.#activeDescendantControl?.focus({
1854					preventScroll: this.#preventScroll
1855				});
1856				this.#updateFocusedElement(target);
1857			}
1858		}
1859		#handleFocusInRovingTabindex(event) {
1860			const target = event.target;
1861			const tracker = FocusMonitor.Instance.getModalityTracker();
1862			const isPointerFocus = tracker.getLastModality() === 'pointer';
1863			if (isPointerFocus) {
1864				if (this.#elementSet.has(target)) {
1865					this.#updateFocusedElement(target);
1866				}
1867				return;
1868			}
1869			if (!this.#elementSet.has(target)) {
1870				return;
1871			}
1872			if (this.#focusInStrategy === 'previous') {
1873				this.#updateFocusedElement(target);
1874			} else if (this.#focusInStrategy === 'closest' || this.#focusInStrategy === 'first') {
1875				if (this.#isFocusEnteringFromOutside(event.relatedTarget)) {
1876					const targetElement = this.#getEntryFocusedElement();
1877					if (targetElement) {
1878						targetElement.focus({
1879							preventScroll: this.#preventScroll
1880						});
1881					}
1882					return;
1883				}
1884				this.#updateFocusedElement(target);
1885			} else if (main_core.Type.isFunction(this.#focusInStrategy)) {
1886				if (this.#isFocusEnteringFromOutside(event.relatedTarget)) {
1887					const elementToFocus = this.#focusInStrategy(event.relatedTarget);
1888					if (elementToFocus && this.#elementSet.has(elementToFocus)) {
1889						elementToFocus.focus({
1890							preventScroll: this.#preventScroll
1891						});
1892						return;
1893					}
1894					AccessibilityLogger.warn('focus-zone', 'focusInStrategy returned an element outside the managed focus set.');
1895				}
1896				this.#updateFocusedElement(target);
1897			}
1898		}
1899		#resolveInitialFocusedElement() {
1900			if (main_core.Type.isFunction(this.#focusInStrategy)) {
1901				const element = this.#focusInStrategy(this.#currentFocusedElement);
1902				return element && this.#elementSet.has(element) ? element : null;
1903			}
1904			return FocusNavigator.getFirst(this.#container, this.#getNavigatorOptions());
1905		}
1906		#getEntryFocusedElement() {
1907			const navOptions = this.#getNavigatorOptions();
1908			return FocusMonitor.Instance.getModalityTracker().isLastNavigationReversed() ? FocusNavigator.getLast(this.#container, navOptions) : FocusNavigator.getFirst(this.#container, navOptions);
1909		}
1910		#isFocusEnteringFromOutside(relatedTarget) {
1911			return main_core.Type.isElementNode(relatedTarget) && !this.#container.contains(relatedTarget);
1912		}
1913		#handleMouseMove(event) {
1914			const {
1915				target
1916			} = event;
1917			if (!main_core.Type.isElementNode(target)) {
1918				return;
1919			}
1920			const managedElement = this.#findManagedAncestor(target);
1921			if (managedElement) {
1922				this.#updateFocusedElement(managedElement);
1923			}
1924		}
1925		#handleControlFocusIn() {
1926			const preventInitialFocus = this.#focusInStrategy === 'initial' && this.#activeDescendantControl;
1927			if (this.#currentFocusedElement) {
1928				this.#setActiveDescendant(null, this.#currentFocusedElement);
1929			} else if (!preventInitialFocus) {
1930				this.#updateFocusedElement(FocusNavigator.getFirst(this.#container, this.#getNavigatorOptions()));
1931			}
1932		}
1933		#handleControlFocusOut() {
1934			this.#clearActiveDescendant();
1935		}
1936		#listen(target, event, handler, capture = false) {
1937			main_core.Event.bind(target, event, handler, capture);
1938			this.#bindings.push([target, event, handler, capture]);
1939		}
1940		#attachEventListeners() {
1941			const keyboardTarget = this.#activeDescendantControl ?? this.#container;
1942			this.#listen(keyboardTarget, 'keydown', this.#keyDownHandler);
1943			this.#listen(this.#container, 'focusin', this.#focusInHandler);
1944			if (this.#activeDescendantControl) {
1945				if (!this.#ignoreHoverEvents) {
1946					this.#listen(this.#container, 'mousemove', this.#mouseMoveHandler, true);
1947				}
1948				this.#listen(this.#activeDescendantControl, 'focusin', this.#controlFocusInHandler);
1949				this.#listen(this.#activeDescendantControl, 'focusout', this.#controlFocusOutHandler);
1950			}
1951		}
1952		#detachEventListeners() {
1953			for (const [target, event, handler, capture] of this.#bindings) {
1954				main_core.Event.unbind(target, event, handler, capture);
1955			}
1956			this.#bindings = [];
1957		}
1958		#attachObserver() {
1959			this.#observer = new MutationObserver(mutations => {
1960				if (this.#isOwnTabIndexWrite(mutations)) {
1961					return;
1962				}
1963				this.#scheduleSyncFocusableElements();
1964			});
1965			this.#observer.observe(this.#container, {
1966				attributes: true,
1967				subtree: true,
1968				childList: true,
1969				attributeFilter: ['hidden', 'disabled', 'tabindex', 'inert', 'contenteditable', 'aria-disabled']
1970			});
1971		}
1972		#isOwnTabIndexWrite(mutations) {
1973			if (this.#tabbableOnly) {
1974				return false;
1975			}
1976			return mutations.every(record => {
1977				return record.type === 'attributes' && record.attributeName === 'tabindex' && this.#elementSet.has(record.target);
1978			});
1979		}
1980		#scheduleSyncFocusableElements() {
1981			if (!this.#active || this.#syncFrameId !== null) {
1982				return;
1983			}
1984			this.#syncFrameId = requestAnimationFrame(() => {
1985				this.#syncFrameId = null;
1986				this.#syncFocusableElements();
1987			});
1988		}
1989		#syncFocusableElements() {
1990			if (!this.#active) {
1991				return;
1992			}
1993			const newSet = this.#collectFocusableSet();
1994			const oldSet = this.#elementSet;
1995			for (const element of oldSet) {
1996				if (!newSet.has(element)) {
1997					this.#restoreTabIndex(element);
1998				}
1999			}
2000			for (const element of newSet) {
2001				if (!oldSet.has(element)) {
2002					this.#saveAndSetTabIndex(element);
2003				}
2004			}
2005			this.#elementSet = newSet;
2006			if (this.#currentFocusedElement && !newSet.has(this.#currentFocusedElement)) {
2007				this.#updateFocusedElement(FocusNavigator.getFirst(this.#container, this.#getNavigatorOptions()));
2008			} else if (!this.#currentFocusedElement && newSet.size > 0) {
2009				const preventInitialFocus = this.#focusInStrategy === 'initial' && this.#activeDescendantControl;
2010				if (!preventInitialFocus) {
2011					this.#updateFocusedElement(FocusNavigator.getFirst(this.#container, this.#getNavigatorOptions()));
2012				}
2013			}
2014		}
2015		static #getDirection(event) {
2016			const direction = KEY_TO_DIRECTION[event.key];
2017			if (event.key === 'Tab' && event.shiftKey) {
2018				return 'previous';
2019			}
2020			const isMac = main_core.Browser.isMac();
2021			if (isMac && event.metaKey || !isMac && event.ctrlKey) {
2022				if (event.key === 'ArrowLeft' || event.key === 'ArrowUp') {
2023					return 'start';
2024				}
2025				if (event.key === 'ArrowRight' || event.key === 'ArrowDown') {
2026					return 'end';
2027				}
2028			}
2029			return direction;
2030		}
2031		static #isNativeInputKey(event, activeElement) {
2032			const {
2033				key,
2034				metaKey,
2035				altKey
2036			} = event;
2037			const codePoint = key.codePointAt(0) ?? 0;
2038			const isSingleChar = key.length === 1 || key.length === 2 && codePoint >= 0xD800 && codePoint <= 0xDBFF;
2039			const isEditable = InteractivityChecker.isEditable(activeElement);
2040			const isSelect = activeElement?.tagName === 'SELECT';
2041			if (isEditable && (isSingleChar || key === 'Home' || key === 'End')) {
2042				return true;
2043			}
2044			if (isSelect) {
2045				const isMac = main_core.Browser.isMac();
2046				if (key === 'ArrowDown' && isMac && !metaKey) {
2047					return true;
2048				}
2049				return key === 'ArrowDown' && !isMac && altKey;
2050			}
2051			if (isEditable) {
2052				const isInputElement = activeElement?.tagName === 'TEXTAREA' || activeElement?.tagName === 'INPUT';
2053				const inputEl = activeElement;
2054				const cursorAtStart = isInputElement && inputEl.selectionStart === 0 && inputEl.selectionEnd === 0;
2055				const cursorAtEnd = isInputElement && inputEl.selectionStart === inputEl.value.length && inputEl.selectionEnd === inputEl.value.length;
2056				if (key === 'ArrowLeft' && !cursorAtStart) {
2057					return true;
2058				}
2059				if (key === 'ArrowRight' && !cursorAtEnd) {
2060					return true;
2061				}
2062				const isContentEditable = main_core.Type.isElementNode(activeElement) && activeElement.isContentEditable;
2063				if (activeElement?.tagName === 'TEXTAREA' || isContentEditable) {
2064					if (key === 'PageUp' || key === 'PageDown') {
2065						return true;
2066					}
2067					if (key === 'ArrowUp' && !cursorAtStart) {
2068						return true;
2069					}
2070					if (key === 'ArrowDown' && !cursorAtEnd) {
2071						return true;
2072					}
2073				}
2074			}
2075			return false;
2076		}
2077	}
2078
2079	class VisuallyHidden extends HTMLElement {
2080		connectedCallback() {
2081			Object.assign(this.style, {
2082				position: 'absolute',
2083				width: '1px',
2084				height: '1px',
2085				padding: '0',
2086				margin: '-1px',
2087				overflow: 'hidden',
2088				clip: 'rect(0, 0, 0, 0)',
2089				whiteSpace: 'nowrap',
2090				border: '0'
2091			});
2092		}
2093	}
2094	if (!customElements.get('visually-hidden')) {
2095		customElements.define('visually-hidden', VisuallyHidden);
2096	}
2097
2098	FocusMonitor.initialize();
2099
2100	exports.AccessibilityLogger = AccessibilityLogger;
2101	exports.AccessibilitySettings = AccessibilitySettings;
2102	exports.ActiveDescendant = ActiveDescendant;
2103	exports.FocusKeys = FocusKeys;
2104	exports.FocusMonitor = FocusMonitor;
2105	exports.FocusNavigator = FocusNavigator;
2106	exports.FocusTrap = FocusTrap;
2107	exports.FocusTrapDirective = FocusTrapDirective;
2108	exports.FocusZone = FocusZone;
2109	exports.InputModalityTracker = InputModalityTracker;
2110	exports.InteractivityChecker = InteractivityChecker;
2111	exports.LiveAnnouncer = LiveAnnouncer;
2112	exports.RESTORE_FOCUS_EVENT = RESTORE_FOCUS_EVENT;
2113	exports.VisuallyHidden = VisuallyHidden;
2114
2115})(this.BX.UI.Accessibility = this.BX.UI.Accessibility || {}, BX);
2116//# sourceMappingURL=a11y.bundle.js.map

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.