feat(core): first class a11y support (#8909)

This commit is contained in:
Morten Sjøgren
2021-01-29 20:51:51 +01:00
committed by Nathan Walker
parent ef9c3b1f5f
commit c46da3fad9
43 changed files with 2938 additions and 47 deletions

View File

@ -0,0 +1,73 @@
import type { View } from '../ui/core/view';
import type { Page } from '../ui/page';
import type { AccessibilityBlurEventData, AccessibilityFocusChangedEventData, AccessibilityFocusEventData } from './accessibility-types';
const lastFocusedViewOnPageKeyName = '__lastFocusedViewOnPage';
export const accessibilityBlurEvent = 'accessibilityBlur';
export const accessibilityFocusEvent = 'accessibilityFocus';
export const accessibilityFocusChangedEvent = 'accessibilityFocusChanged';
/**
* Send notification when accessibility focus state changes.
* If either receivedFocus or lostFocus is true, 'accessibilityFocusChanged' is send with value true if element received focus
* If receivedFocus, 'accessibilityFocus' is send
* if lostFocus, 'accessibilityBlur' is send
*
* @param {View} view
* @param {boolean} receivedFocus
* @param {boolean} lostFocus
*/
export function notifyAccessibilityFocusState(view: View, receivedFocus: boolean, lostFocus: boolean): void {
if (!receivedFocus && !lostFocus) {
return;
}
view.notify({
eventName: accessibilityFocusChangedEvent,
object: view,
value: !!receivedFocus,
} as AccessibilityFocusChangedEventData);
if (receivedFocus) {
if (view.page) {
view.page[lastFocusedViewOnPageKeyName] = new WeakRef(view);
}
view.notify({
eventName: accessibilityFocusEvent,
object: view,
} as AccessibilityFocusEventData);
} else if (lostFocus) {
view.notify({
eventName: accessibilityBlurEvent,
object: view,
} as AccessibilityBlurEventData);
}
}
export function getLastFocusedViewOnPage(page: Page): View | null {
try {
const lastFocusedViewRef = page[lastFocusedViewOnPageKeyName] as WeakRef<View>;
if (!lastFocusedViewRef) {
return null;
}
const lastFocusedView = lastFocusedViewRef.get();
if (!lastFocusedView) {
return null;
}
if (!lastFocusedView.parent || lastFocusedView.page !== page) {
return null;
}
return lastFocusedView;
} catch {
// ignore
} finally {
delete page[lastFocusedViewOnPageKeyName];
}
return null;
}