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 577b1e9dad
commit f2e21a50a7
43 changed files with 2938 additions and 47 deletions

View File

@@ -1,10 +1,14 @@
import { View } from '../core/view';
import { Property, CoercibleProperty } from '../core/properties';
import { EventData } from '../../data/observable';
/**
* Represents a slider component.
*/
export class Slider extends View {
static readonly accessibilityDecrementEvent = 'accessibilityDecrement';
static readonly accessibilityIncrementEvent = 'accessibilityIncrement';
/**
* Gets the native [android widget](http://developer.android.com/reference/android/widget/SeekBar.html) that represents the user interface for this component. Valid only when running on Android OS.
*/
@@ -29,6 +33,11 @@ export class Slider extends View {
* Gets or sets a slider max value. The default value is 100.
*/
maxValue: number;
/**
* Increase/Decrease step size for iOS Increment-/Decrement events
*/
accessibilityStep: number;
}
/**
@@ -45,3 +54,18 @@ export const minValueProperty: Property<Slider, number>;
* Represents the observable property backing the maxValue property of each Slider instance.
*/
export const maxValueProperty: CoercibleProperty<Slider, number>;
/**
* Represents the observable property backing the accessibilityStep property of each Slider instance.
*/
export const accessibilityStepProperty: Property<SliderBase, number>;
interface AccessibilityIncrementEventData extends EventData {
object: Slider;
value?: number;
}
interface AccessibilityDecrementEventData extends EventData {
object: Slider;
value?: number;
}

View File

@@ -3,9 +3,44 @@ import { Background } from '../styling/background';
import { SliderBase, valueProperty, minValueProperty, maxValueProperty } from './slider-common';
import { colorProperty, backgroundColorProperty, backgroundInternalProperty } from '../styling/style-properties';
import { Color } from '../../color';
import { AccessibilityDecrementEventData, AccessibilityIncrementEventData } from '.';
export * from './slider-common';
@NativeClass()
class TNSSlider extends UISlider {
public owner: WeakRef<Slider>;
public static initWithOwner(owner: WeakRef<Slider>) {
const slider = TNSSlider.new() as TNSSlider;
slider.owner = owner;
return slider;
}
public accessibilityIncrement() {
const owner = this.owner.get();
if (!owner) {
this.value += 10;
} else {
this.value = owner._handlerAccessibilityIncrementEvent();
}
this.sendActionsForControlEvents(UIControlEvents.ValueChanged);
}
public accessibilityDecrement() {
const owner = this.owner.get();
if (!owner) {
this.value += 10;
} else {
this.value = owner._handlerAccessibilityDecrementEvent();
}
this.sendActionsForControlEvents(UIControlEvents.ValueChanged);
}
}
@NativeClass
class SliderChangeHandlerImpl extends NSObject {
private _owner: WeakRef<Slider>;
@@ -30,11 +65,11 @@ class SliderChangeHandlerImpl extends NSObject {
}
export class Slider extends SliderBase {
nativeViewProtected: UISlider;
nativeViewProtected: TNSSlider;
private _changeHandler: NSObject;
public createNativeView() {
return UISlider.new();
public createNativeView(): TNSSlider {
return TNSSlider.initWithOwner(new WeakRef(this));
}
public initNativeView(): void {
@@ -47,7 +82,7 @@ export class Slider extends SliderBase {
nativeView.addTargetActionForControlEvents(this._changeHandler, 'sliderValueChanged', UIControlEvents.ValueChanged);
}
public disposeNativeView() {
public disposeNativeView(): void {
this._changeHandler = null;
super.disposeNativeView();
}
@@ -98,4 +133,36 @@ export class Slider extends SliderBase {
[backgroundInternalProperty.setNative](value: Background) {
//
}
private getAccessibilityStep(): number {
if (!this.accessibilityStep || this.accessibilityStep <= 0) {
return 10;
}
return this.accessibilityStep;
}
public _handlerAccessibilityIncrementEvent(): number {
const args: AccessibilityIncrementEventData = {
object: this,
eventName: SliderBase.accessibilityIncrementEvent,
value: this.value + this.getAccessibilityStep(),
};
this.notify(args);
return args.value;
}
public _handlerAccessibilityDecrementEvent(): number {
const args: AccessibilityDecrementEventData = {
object: this,
eventName: SliderBase.accessibilityIncrementEvent,
value: this.value - this.getAccessibilityStep(),
};
this.notify(args);
return args.value;
}
}

View File

@@ -1,13 +1,28 @@
import { Slider as SliderDefinition } from '.';
import { View, CSSType } from '../core/view';
import { Property, CoercibleProperty } from '../core/properties';
import { AccessibilityRole } from '../../accessibility';
import { CoercibleProperty, Property } from '../core/properties';
import { CSSType, View } from '../core/view';
// TODO: Extract base Range class for slider and progress
@CSSType('Slider')
export class SliderBase extends View implements SliderDefinition {
static readonly accessibilityIncrementEvent = 'accessibilityIncrement';
static readonly accessibilityDecrementEvent = 'accessibilityDecrement';
public value: number;
public minValue: number;
public maxValue: number;
get accessibilityStep(): number {
return this.style.accessibilityStep;
}
set accessibilityStep(value: number) {
this.style.accessibilityStep = value;
}
accessible = true;
accessibilityRole = AccessibilityRole.Adjustable;
}
SliderBase.prototype.recycleNativeView = 'auto';