[change] Remove deprecated accessibility APIs

Removes 'accessible', 'accessibilityState', and 'accessibilityValue' props.
This commit is contained in:
Nicolas Gallagher
2022-03-02 10:06:20 -08:00
parent 9583155523
commit 174ebb3c5d
15 changed files with 87 additions and 346 deletions
@@ -1,4 +1,9 @@
/* eslint-env jasmine, jest */
/**
* Copyright (c) Nicolas Gallagher.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import ActivityIndicator from '..';
import React from 'react';
@@ -14,8 +14,6 @@ import * as React from 'react';
import StyleSheet from '../StyleSheet';
import View from '../View';
const accessibilityValue = { max: 1, min: 0 };
const createSvgCircle = (style) => (
<circle cx="16" cy="16" fill="none" r="14" strokeWidth="4" style={style} />
);
@@ -59,7 +57,8 @@ const ActivityIndicator: React.AbstractComponent<
<View
{...other}
accessibilityRole="progressbar"
accessibilityValue={accessibilityValue}
accessibilityValueMax={1}
accessibilityValueMin={0}
ref={forwardedRef}
style={[styles.container, style]}
>
@@ -47,7 +47,12 @@ const ModalContent: React.AbstractComponent<
}, [transparent]);
return (
<View accessibilityRole={active ? 'dialog' : null} aria-modal ref={forwardedRef} style={style}>
<View
accessibilityModal={true}
accessibilityRole={active ? 'dialog' : null}
ref={forwardedRef}
style={style}
>
<View style={styles.container}>{children}</View>
</View>
);
+9 -17
View File
@@ -36,32 +36,24 @@ const ProgressBar: React.AbstractComponent<
} = props;
const percentageProgress = progress * 100;
const progressRef = React.useRef(null);
React.useEffect(() => {
const width = indeterminate ? '25%' : `${percentageProgress}%`;
if (progressRef.current != null) {
progressRef.current.setNativeProps({
style: { width }
});
}
}, [indeterminate, percentageProgress, progressRef]);
const width = indeterminate ? '25%' : `${percentageProgress}%`;
return (
<View
{...other}
accessibilityRole="progressbar"
accessibilityValue={{
max: 100,
min: 0,
now: indeterminate ? null : percentageProgress
}}
accessibilityValueMax={100}
accessibilityValueMin={0}
accessibilityValueNow={indeterminate ? null : percentageProgress}
ref={ref}
style={[styles.track, style, { backgroundColor: trackColor }]}
>
<View
ref={progressRef}
style={[styles.progress, indeterminate && styles.animation, { backgroundColor: color }]}
style={[
{ backgroundColor: color, width },
styles.progress,
indeterminate && styles.animation
]}
/>
</View>
);
-13
View File
@@ -72,19 +72,6 @@ export type TextProps = {
| 'listitem'
| 'none'
| 'text',
accessibilityState?: {
busy?: ?boolean,
checked?: ?boolean | 'mixed',
disabled?: ?boolean,
expanded?: ?boolean,
grabbed?: ?boolean,
hidden?: ?boolean,
invalid?: ?boolean,
pressed?: ?boolean,
readonly?: ?boolean,
required?: ?boolean,
selected?: ?boolean
},
dir?: 'auto' | 'ltr' | 'rtl',
numberOfLines?: ?number,
onPress?: (e: any) => void,
+1 -20
View File
@@ -113,27 +113,8 @@ export type ViewStyle = {
export type ViewProps = {
...AccessibilityProps,
accessibilityState?: {
busy?: ?boolean,
checked?: ?boolean | 'mixed',
disabled?: ?boolean,
expanded?: ?boolean,
grabbed?: ?boolean,
hidden?: ?boolean,
invalid?: ?boolean,
modal?: ?boolean,
pressed?: ?boolean,
readonly?: ?boolean,
required?: ?boolean,
selected?: ?boolean
},
accessibilityValue?: {
max?: ?number,
min?: ?number,
now?: ?number,
text?: ?string
},
children?: ?any,
dir?: 'ltr' | 'rtl',
focusable?: ?boolean,
nativeID?: ?string,
onBlur?: (e: any) => void,
@@ -1,49 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`modules/createDOMProps includes base reset style for browser-styled elements 1`] = `"css-reset-4rbku5"`;
exports[`modules/createDOMProps includes base reset style for browser-styled elements 2`] = `"css-reset-4rbku5"`;
exports[`modules/createDOMProps includes base reset style for browser-styled elements 3`] = `"css-reset-4rbku5"`;
exports[`modules/createDOMProps includes base reset style for browser-styled elements 4`] = `"css-reset-4rbku5"`;
exports[`modules/createDOMProps includes cursor style for pressable roles 1`] = `"css-cursor-18t94o4"`;
exports[`modules/createDOMProps includes cursor style for pressable roles 2`] = `"css-cursor-18t94o4"`;
exports[`modules/createDOMProps prop "accessibilityState" values are "false" 1`] = `
Object {
"aria-busy": false,
"aria-checked": false,
"aria-expanded": false,
"aria-grabbed": false,
"aria-invalid": false,
"aria-modal": false,
"aria-pressed": false,
"aria-readonly": false,
"aria-required": false,
"aria-selected": false,
}
`;
exports[`modules/createDOMProps prop "accessibilityState" values are "true" 1`] = `
Object {
"aria-busy": true,
"aria-checked": true,
"aria-disabled": true,
"aria-expanded": true,
"aria-grabbed": true,
"aria-hidden": true,
"aria-invalid": true,
"aria-modal": true,
"aria-pressed": true,
"aria-readonly": true,
"aria-required": true,
"aria-selected": true,
"disabled": true,
"hidden": true,
}
`;
exports[`modules/createDOMProps prop "accessibilityState" values are "undefined" 1`] = `Object {}`;
@@ -118,43 +118,6 @@ describe('modules/createDOMProps', () => {
expect(props.role).toEqual('button');
});
describe('prop "accessibilityState"', () => {
function createAccessibilityState(value) {
return {
busy: value,
checked: value,
disabled: value,
expanded: value,
grabbed: value,
hidden: value,
invalid: value,
modal: value,
pressed: value,
readonly: value,
required: value,
selected: value
};
}
test('values are "undefined"', () => {
const accessibilityState = createAccessibilityState(undefined);
const props = createProps({ accessibilityState });
expect(props).toMatchSnapshot();
});
test('values are "false"', () => {
const accessibilityState = createAccessibilityState(false);
const props = createProps({ accessibilityState });
expect(props).toMatchSnapshot();
});
test('values are "true"', () => {
const accessibilityState = createAccessibilityState(true);
const props = createProps({ accessibilityState });
expect(props).toMatchSnapshot();
});
});
test('prop "className" is preserved', () => {
const className = 'external-class-name';
const props = createProps({ className });
@@ -172,16 +135,4 @@ describe('modules/createDOMProps', () => {
const props = createProps({ testID });
expect(props['data-testid']).toEqual(testID);
});
test('includes cursor style for pressable roles', () => {
expect(createDOMProps('span', { accessibilityRole: 'link' }).className).toMatchSnapshot();
expect(createDOMProps('span', { accessibilityRole: 'button' }).className).toMatchSnapshot();
});
test('includes base reset style for browser-styled elements', () => {
expect(createDOMProps('a').className).toMatchSnapshot();
expect(createDOMProps('button').className).toMatchSnapshot();
expect(createDOMProps('li').className).toMatchSnapshot();
expect(createDOMProps('ul').className).toMatchSnapshot();
});
});
@@ -123,45 +123,15 @@ const createDOMProps = (elementType, props) => {
pointerEvents,
style: providedStyle,
testID,
// Deprecated
accessible,
accessibilityState,
accessibilityValue,
isRTL,
// Rest
...domProps
} = props;
const disabled =
(accessibilityState != null && accessibilityState.disabled === true) || accessibilityDisabled;
const disabled = accessibilityDisabled;
const role = AccessibilityUtil.propsToAriaRole(props);
// DEPRECATED
if (accessibilityState != null) {
for (const prop in accessibilityState) {
const value = accessibilityState[prop];
if (value != null) {
if (prop === 'disabled' || prop === 'hidden') {
if (value === true) {
domProps[`aria-${prop}`] = value;
// also set prop directly to pick up host elementType behaviour
domProps[prop] = value;
}
} else {
domProps[`aria-${prop}`] = value;
}
}
}
}
if (accessibilityValue != null) {
for (const prop in accessibilityValue) {
const value = accessibilityValue[prop];
if (value != null) {
domProps[`aria-value${prop}`] = value;
}
}
}
// ACCESSIBILITY
if (accessibilityActiveDescendant != null) {
domProps['aria-activedescendant'] = accessibilityActiveDescendant;
@@ -336,23 +306,22 @@ const createDOMProps = (elementType, props) => {
// FOCUS
// "focusable" indicates that an element may be a keyboard tab-stop.
const _focusable = focusable != null ? focusable : accessible;
if (_focusable === false) {
if (focusable === false) {
domProps.tabIndex = '-1';
}
if (
// These native elements are focusable by default
// These native elements are keyboard focusable by default
elementType === 'a' ||
elementType === 'button' ||
elementType === 'input' ||
elementType === 'select' ||
elementType === 'textarea'
) {
if (_focusable === false || accessibilityDisabled === true) {
if (focusable === false || accessibilityDisabled === true) {
domProps.tabIndex = '-1';
}
} else if (
// These roles are made focusable by default
// These roles are made keyboard focusable by default
role === 'button' ||
role === 'checkbox' ||
role === 'link' ||
@@ -360,12 +329,12 @@ const createDOMProps = (elementType, props) => {
role === 'textbox' ||
role === 'switch'
) {
if (_focusable !== false) {
if (focusable !== false) {
domProps.tabIndex = '0';
}
} else {
// Everything else must explicitly set the prop
if (_focusable === true) {
if (focusable === true) {
domProps.tabIndex = '0';
}
}
@@ -64,11 +64,7 @@ export const accessibilityProps = {
accessibilityValueNow: true,
accessibilityValueText: true,
dir: true,
focusable: true,
// Deprecated
accessible: true,
accessibilityState: true,
accessibilityValue: true
focusable: true
};
export const clickProps = {
+1 -5
View File
@@ -11,11 +11,7 @@ export default function pick(obj: Object, list: { [string]: boolean }): Object {
const nextObj = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
if (
list[key] === true ||
// Temporary until ARIA is mapped to explicit props
key.indexOf('aria-') === 0
) {
if (list[key] === true) {
nextObj[key] = obj[key];
}
}
@@ -1,13 +0,0 @@
/* eslint-env jasmine, jest */
import { prefixInlineStyles } from '..';
describe('modules/prefixStyles', () => {
test('handles array values for inline styles', () => {
const style = {
display: ['-webkit-flex', 'flex']
};
expect(prefixInlineStyles(style)).toEqual({ display: 'flex' });
});
});
@@ -14,19 +14,4 @@ type StyleModifier = (style: Object) => Object;
const prefixAll: StyleModifier = createPrefixer(staticData);
export const prefixInlineStyles: StyleModifier = (style) => {
const prefixedStyles = prefixAll(style);
// React@15 removed undocumented support for fallback values in
// inline-styles. Revert array values to the standard CSS value
Object.keys(prefixedStyles).forEach((prop) => {
const value = prefixedStyles[prop];
if (Array.isArray(value)) {
prefixedStyles[prop] = value[value.length - 1];
}
});
return prefixedStyles;
};
export default prefixAll;
+43 -109
View File
@@ -2,11 +2,6 @@ import backgroundClip from 'inline-style-prefixer/lib/plugins/backgroundClip';
import crossFade from 'inline-style-prefixer/lib/plugins/crossFade';
import cursor from 'inline-style-prefixer/lib/plugins/cursor';
import filter from 'inline-style-prefixer/lib/plugins/filter';
import flex from 'inline-style-prefixer/lib/plugins/flex';
import flexboxIE from 'inline-style-prefixer/lib/plugins/flexboxIE';
import flexboxOld from 'inline-style-prefixer/lib/plugins/flexboxOld';
import gradient from 'inline-style-prefixer/lib/plugins/gradient';
import grid from 'inline-style-prefixer/lib/plugins/grid';
import imageSet from 'inline-style-prefixer/lib/plugins/imageSet';
import logical from 'inline-style-prefixer/lib/plugins/logical';
import position from 'inline-style-prefixer/lib/plugins/position';
@@ -14,7 +9,6 @@ import sizing from 'inline-style-prefixer/lib/plugins/sizing';
import transition from 'inline-style-prefixer/lib/plugins/transition';
const w = ['Webkit'];
const m = ['Moz'];
const ms = ['ms'];
const wm = ['Webkit', 'Moz'];
const wms = ['Webkit', 'ms'];
const wmms = ['Webkit', 'Moz', 'ms'];
@@ -25,11 +19,6 @@ export default {
crossFade,
cursor,
filter,
flex,
flexboxIE,
flexboxOld,
gradient,
grid,
imageSet,
logical,
position,
@@ -37,112 +26,57 @@ export default {
transition
],
prefixMap: {
animation: w,
animationDelay: w,
animationDirection: w,
animationFillMode: w,
animationDuration: w,
animationIterationCount: w,
animationName: w,
animationPlayState: w,
animationTimingFunction: w,
appearance: wm,
userSelect: wmms,
textEmphasisPosition: w,
textEmphasis: w,
textEmphasisStyle: w,
textEmphasisColor: w,
boxDecorationBreak: w,
appearance: wmms,
userSelect: wm,
textEmphasisPosition: wms,
textEmphasis: wms,
textEmphasisStyle: wms,
textEmphasisColor: wms,
boxDecorationBreak: wms,
clipPath: w,
maskImage: w,
maskMode: w,
maskRepeat: w,
maskPosition: w,
maskClip: w,
maskOrigin: w,
maskSize: w,
maskComposite: w,
mask: w,
maskBorderSource: w,
maskBorderMode: w,
maskBorderSlice: w,
maskBorderWidth: w,
maskBorderOutset: w,
maskBorderRepeat: w,
maskBorder: w,
maskType: w,
maskImage: wms,
maskMode: wms,
maskRepeat: wms,
maskPosition: wms,
maskClip: wms,
maskOrigin: wms,
maskSize: wms,
maskComposite: wms,
mask: wms,
maskBorderSource: wms,
maskBorderMode: wms,
maskBorderSlice: wms,
maskBorderWidth: wms,
maskBorderOutset: wms,
maskBorderRepeat: wms,
maskBorder: wms,
maskType: wms,
textDecorationStyle: w,
textDecorationSkip: w,
textDecorationLine: w,
textDecorationColor: w,
filter: w,
fontFeatureSettings: w,
breakAfter: wmms,
breakBefore: wmms,
breakInside: wmms,
columnCount: wm,
columnFill: wm,
columnGap: wm,
columnRule: wm,
columnRuleColor: wm,
columnRuleStyle: wm,
columnRuleWidth: wm,
columns: wm,
columnSpan: wm,
columnWidth: wm,
writingMode: wms,
flex: wms,
flexBasis: w,
flexDirection: wms,
flexGrow: w,
flexFlow: wms,
flexShrink: w,
flexWrap: wms,
alignContent: w,
alignItems: w,
alignSelf: w,
justifyContent: w,
order: w,
transform: w,
transformOrigin: w,
transformOriginX: w,
transformOriginY: w,
backfaceVisibility: w,
perspective: w,
perspectiveOrigin: w,
transformStyle: w,
transformOriginZ: w,
breakAfter: w,
breakBefore: w,
breakInside: w,
columnCount: w,
columnFill: w,
columnGap: w,
columnRule: w,
columnRuleColor: w,
columnRuleStyle: w,
columnRuleWidth: w,
columns: w,
columnSpan: w,
columnWidth: w,
backdropFilter: w,
fontKerning: w,
scrollSnapType: wms,
scrollSnapPointsX: wms,
scrollSnapPointsY: wms,
scrollSnapDestination: wms,
scrollSnapCoordinate: wms,
shapeImageThreshold: w,
shapeImageMargin: w,
shapeImageOutside: w,
hyphens: wmms,
flowInto: wms,
flowFrom: wms,
regionFragment: wms,
hyphens: w,
flowInto: w,
flowFrom: w,
regionFragment: w,
textOrientation: w,
textAlignLast: m,
tabSize: m,
wrapFlow: ms,
wrapThrough: ms,
wrapMargin: ms,
touchAction: ms,
textSizeAdjust: ['ms', 'Webkit'],
borderImage: w,
borderImageOutset: w,
borderImageRepeat: w,
borderImageSlice: w,
borderImageSource: w,
borderImageWidth: w,
transitionDelay: w,
transitionDuration: w,
transitionProperty: w,
transitionTimingFunction: w
fontKerning: w,
textSizeAdjust: w
}
};
@@ -15,14 +15,19 @@ import createDOMProps from '../createDOMProps';
import useStable from '../useStable';
import { useRef } from 'react';
let didWarn = false;
const emptyObject = {};
function setNativeProps(node, nativeProps, classList, pointerEvents, style, previousStyleRef) {
function setNativeProps(node, nativeProps, pointerEvents, style, previousStyleRef) {
if (!didWarn) {
console.warn('setNativeProps is deprecated. Please update props using React state instead.');
didWarn = true;
}
if (node != null && nativeProps) {
const domProps = createDOMProps(null, {
pointerEvents,
...nativeProps,
classList: [classList, nativeProps.className],
style: [style, nativeProps.style]
});
@@ -50,17 +55,15 @@ function setNativeProps(node, nativeProps, classList, pointerEvents, style, prev
* API like `ReactNative.measure(hostRef, callback)` is added to React Native.
*/
export default function usePlatformMethods({
classList,
pointerEvents,
style
}: {
classList?: Array<string | boolean>,
style?: GenericStyleProp<*>,
pointerEvents?: $PropertyType<ViewProps, 'pointerEvents'>
}): (hostNode: any) => void {
const previousStyleRef = useRef(null);
const setNativePropsArgsRef = useRef(null);
setNativePropsArgsRef.current = { classList, pointerEvents, style };
setNativePropsArgsRef.current = { pointerEvents, style };
// Avoid creating a new ref on every render. The props only need to be
// available to 'setNativeProps' when it is called.
@@ -71,8 +74,8 @@ export default function usePlatformMethods({
UIManager.measureLayout(hostNode, relativeToNode, failure, success);
hostNode.measureInWindow = (callback) => UIManager.measureInWindow(hostNode, callback);
hostNode.setNativeProps = (nativeProps) => {
const { classList, style, pointerEvents } = setNativePropsArgsRef.current || emptyObject;
setNativeProps(hostNode, nativeProps, classList, pointerEvents, style, previousStyleRef);
const { style, pointerEvents } = setNativePropsArgsRef.current || emptyObject;
setNativeProps(hostNode, nativeProps, pointerEvents, style, previousStyleRef);
};
}
});