@react-native-ama/core 0.0.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{core/src/components → components}/AMAProvider.js +1 -2
- package/dist/{core/src/index.js → index.js} +3 -3
- package/package.json +30 -5
- package/src/components/AMAProvider.d.ts +26 -0
- package/src/components/AMAProvider.js +147 -0
- package/src/components/AMAProvider.tsx +1 -3
- package/src/components/AutofocusContainer.d.ts +9 -0
- package/src/components/AutofocusContainer.js +58 -0
- package/src/components/HideChildrenFromAccessibilityTree.d.ts +6 -0
- package/src/components/HideChildrenFromAccessibilityTree.js +40 -0
- package/src/components/HideChildrenFromAccessibilityTree.test.tsx +2 -1
- package/src/hooks/useButtonChecks.d.ts +8 -0
- package/src/hooks/useButtonChecks.js +51 -0
- package/src/hooks/useChecks.d.ts +15 -0
- package/src/hooks/useChecks.js +152 -0
- package/src/hooks/useChecks.test.ts +1 -1
- package/src/hooks/useFocus.d.ts +4 -0
- package/{dist/internal/src/utils/maybeGenerateStringFromElement.js → src/hooks/useFocus.js} +26 -22
- package/src/hooks/useFocus.test.ts +1 -0
- package/src/hooks/useTimedAction.d.ts +3 -0
- package/src/hooks/useTimedAction.js +63 -0
- package/src/index.d.ts +7 -0
- package/src/index.js +20 -0
- package/src/index.ts +1 -1
- package/dist/internal/src/checks/checkAccessibilityRole.d.ts +0 -3
- package/dist/internal/src/checks/checkAccessibilityRole.js +0 -32
- package/dist/internal/src/checks/checkFocusTrap.d.ts +0 -8
- package/dist/internal/src/checks/checkFocusTrap.js +0 -34
- package/dist/internal/src/checks/checkForAccessibilityState.d.ts +0 -7
- package/dist/internal/src/checks/checkForAccessibilityState.js +0 -48
- package/dist/internal/src/checks/checkMinimumSize.d.ts +0 -3
- package/dist/internal/src/checks/checkMinimumSize.js +0 -29
- package/dist/internal/src/checks/contrastChecker.d.ts +0 -8
- package/dist/internal/src/checks/contrastChecker.js +0 -77
- package/dist/internal/src/checks/noUndefinedProperty.d.ts +0 -8
- package/dist/internal/src/checks/noUndefinedProperty.js +0 -14
- package/dist/internal/src/checks/uppercaseChecker.d.ts +0 -9
- package/dist/internal/src/checks/uppercaseChecker.js +0 -18
- package/dist/internal/src/checks/uppercaseStringChecker.d.ts +0 -8
- package/dist/internal/src/checks/uppercaseStringChecker.js +0 -29
- package/dist/internal/src/index.d.ts +0 -20
- package/dist/internal/src/index.js +0 -56
- package/dist/internal/src/types.d.ts +0 -17
- package/dist/internal/src/types.js +0 -2
- package/dist/internal/src/utils/applyStyle.d.ts +0 -10
- package/dist/internal/src/utils/applyStyle.js +0 -33
- package/dist/internal/src/utils/constants.d.ts +0 -3
- package/dist/internal/src/utils/constants.js +0 -32
- package/dist/internal/src/utils/error.style.d.ts +0 -6
- package/dist/internal/src/utils/error.style.js +0 -11
- package/dist/internal/src/utils/generateAccessibilityStateFromProp.d.ts +0 -9
- package/dist/internal/src/utils/generateAccessibilityStateFromProp.js +0 -35
- package/dist/internal/src/utils/getPropertyFromStyle.d.ts +0 -2
- package/dist/internal/src/utils/getPropertyFromStyle.js +0 -10
- package/dist/internal/src/utils/interpolateAnimationStates.d.ts +0 -2
- package/dist/internal/src/utils/interpolateAnimationStates.js +0 -43
- package/dist/internal/src/utils/isFocused.d.ts +0 -2
- package/dist/internal/src/utils/isFocused.js +0 -7
- package/dist/internal/src/utils/logger.d.ts +0 -16
- package/dist/internal/src/utils/logger.js +0 -53
- package/dist/internal/src/utils/logger.rules.d.ts +0 -15
- package/dist/internal/src/utils/logger.rules.js +0 -74
- package/dist/internal/src/utils/maybeGenerateStringFromElement.d.ts +0 -3
- package/dist/internal/src/utils/minimumTouchableSize.d.ts +0 -3
- package/dist/internal/src/utils/minimumTouchableSize.js +0 -9
- package/dist/{core/src/components → components}/AMAProvider.d.ts +0 -0
- package/dist/{core/src/components → components}/AutofocusContainer.d.ts +0 -0
- package/dist/{core/src/components → components}/AutofocusContainer.js +0 -0
- package/dist/{core/src/components → components}/HideChildrenFromAccessibilityTree.d.ts +0 -0
- package/dist/{core/src/components → components}/HideChildrenFromAccessibilityTree.js +0 -0
- package/dist/{core/src/hooks → hooks}/useButtonChecks.d.ts +0 -0
- package/dist/{core/src/hooks → hooks}/useButtonChecks.js +0 -0
- package/dist/{core/src/hooks → hooks}/useChecks.d.ts +0 -0
- package/dist/{core/src/hooks → hooks}/useChecks.js +0 -0
- package/dist/{core/src/hooks → hooks}/useFocus.d.ts +0 -0
- package/dist/{core/src/hooks → hooks}/useFocus.js +0 -0
- package/dist/{core/src/hooks → hooks}/useTimedAction.d.ts +0 -0
- package/dist/{core/src/hooks → hooks}/useTimedAction.js +0 -0
- package/dist/{core/src/index.d.ts → index.d.ts} +1 -1
- /package/dist/{core/src/utils → utils}/numerify.d.ts +0 -0
- /package/dist/{core/src/utils → utils}/numerify.js +0 -0
|
@@ -36,7 +36,6 @@ const eventsMapping = {
|
|
|
36
36
|
invertColorsChanged: 'isInvertColorsEnabled',
|
|
37
37
|
screenReaderChanged: 'isScreenReaderEnabled',
|
|
38
38
|
};
|
|
39
|
-
const isDev = __DEV__;
|
|
40
39
|
const isDevContextValue = (value) => value.trackError !== undefined;
|
|
41
40
|
exports.isDevContextValue = isDevContextValue;
|
|
42
41
|
const DEFAULT_VALUES = {
|
|
@@ -89,7 +88,7 @@ const AMAProvider = ({ children }) => {
|
|
|
89
88
|
};
|
|
90
89
|
}, []);
|
|
91
90
|
const [failedItems, setFailedItems] = React.useState([]);
|
|
92
|
-
if (
|
|
91
|
+
if (__DEV__) {
|
|
93
92
|
const trackError = (id) => {
|
|
94
93
|
if (failedItems.includes(id)) {
|
|
95
94
|
return;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useTimedAction = exports.useFocus = exports.useChecks = exports.useButtonChecks = exports.
|
|
3
|
+
exports.useTimedAction = exports.useFocus = exports.useChecks = exports.useButtonChecks = exports.HideChildrenFromAccessibilityTree = exports.useAMAContext = exports.AMAProvider = exports.AutofocusContainer = void 0;
|
|
4
4
|
// Components
|
|
5
5
|
var AutofocusContainer_1 = require("./components/AutofocusContainer");
|
|
6
6
|
Object.defineProperty(exports, "AutofocusContainer", { enumerable: true, get: function () { return AutofocusContainer_1.AutofocusContainer; } });
|
|
7
|
-
var HideChildrenFromAccessibilityTree_1 = require("./components/HideChildrenFromAccessibilityTree");
|
|
8
|
-
Object.defineProperty(exports, "HideChildrenFromAccessibilityTree", { enumerable: true, get: function () { return HideChildrenFromAccessibilityTree_1.HideChildrenFromAccessibilityTree; } });
|
|
9
7
|
var AMAProvider_1 = require("./components/AMAProvider");
|
|
10
8
|
Object.defineProperty(exports, "AMAProvider", { enumerable: true, get: function () { return AMAProvider_1.AMAProvider; } });
|
|
11
9
|
Object.defineProperty(exports, "useAMAContext", { enumerable: true, get: function () { return AMAProvider_1.useAMAContext; } });
|
|
10
|
+
var HideChildrenFromAccessibilityTree_1 = require("./components/HideChildrenFromAccessibilityTree");
|
|
11
|
+
Object.defineProperty(exports, "HideChildrenFromAccessibilityTree", { enumerable: true, get: function () { return HideChildrenFromAccessibilityTree_1.HideChildrenFromAccessibilityTree; } });
|
|
12
12
|
// Hooks
|
|
13
13
|
var useButtonChecks_1 = require("./hooks/useButtonChecks");
|
|
14
14
|
Object.defineProperty(exports, "useButtonChecks", { enumerable: true, get: function () { return useButtonChecks_1.useButtonChecks; } });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-native-ama/core",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Accessible Mobile App Library for React Native",
|
|
5
5
|
"private": false,
|
|
6
6
|
"react-native": "src/index",
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
],
|
|
22
22
|
"scripts": {
|
|
23
23
|
"build": "rm -rf dist && tsc -p ./tsconfig.build.json",
|
|
24
|
-
"typecheck": "tsc --noEmit"
|
|
24
|
+
"typecheck": "tsc --noEmit",
|
|
25
|
+
"test": "jest"
|
|
25
26
|
},
|
|
26
27
|
"dependencies": {
|
|
27
28
|
"@react-native-ama/internal": "*"
|
|
@@ -29,7 +30,7 @@
|
|
|
29
30
|
"peerDependencies": {
|
|
30
31
|
"react": "*",
|
|
31
32
|
"react-native": "*"
|
|
32
|
-
},
|
|
33
|
+
},
|
|
33
34
|
"keywords": [
|
|
34
35
|
"react-native",
|
|
35
36
|
"a11y",
|
|
@@ -48,6 +49,30 @@
|
|
|
48
49
|
"provenance": true
|
|
49
50
|
},
|
|
50
51
|
"author": "",
|
|
51
|
-
"license": "MIT"
|
|
52
|
-
|
|
52
|
+
"license": "MIT",
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"babel-jest": "^29.7.0"
|
|
55
|
+
},
|
|
56
|
+
"jest": {
|
|
57
|
+
"preset": "react-native",
|
|
58
|
+
"modulePathIgnorePatterns": [
|
|
59
|
+
"<rootDir>/node_modules",
|
|
60
|
+
"<rootDir>/dist/"
|
|
61
|
+
],
|
|
62
|
+
"collectCoverageFrom": [
|
|
63
|
+
"src/**/*.{ts,tsx}"
|
|
64
|
+
],
|
|
65
|
+
"coverageThreshold": {
|
|
66
|
+
"global": {
|
|
67
|
+
"statements": 90,
|
|
68
|
+
"branches": 82,
|
|
69
|
+
"functions": 83,
|
|
70
|
+
"lines": 91
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
"transformIgnorePatterns": [
|
|
74
|
+
"node_modules/(?!(@react-native|react-native|react-native-reanimated/))"
|
|
75
|
+
],
|
|
76
|
+
"verbose": true
|
|
77
|
+
}
|
|
53
78
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
type AMAProviderProps = {
|
|
3
|
+
children: React.ReactNode;
|
|
4
|
+
};
|
|
5
|
+
type SharedContextValue = {
|
|
6
|
+
isBoldTextEnabled: boolean;
|
|
7
|
+
isScreenReaderEnabled: boolean;
|
|
8
|
+
isGrayscaleEnabled: boolean;
|
|
9
|
+
isInvertColorsEnabled: boolean;
|
|
10
|
+
isReduceMotionEnabled: boolean;
|
|
11
|
+
isReduceTransparencyEnabled: boolean;
|
|
12
|
+
reactNavigationScreenOptions: {
|
|
13
|
+
animationEnabled: boolean;
|
|
14
|
+
animation: 'default' | 'fade';
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
export type AMADevContextValue = SharedContextValue & {
|
|
18
|
+
trackError: (id: string) => void;
|
|
19
|
+
removeError: (id: string) => void;
|
|
20
|
+
};
|
|
21
|
+
export type AMAProdContextValue = SharedContextValue & {};
|
|
22
|
+
export type AMAContextValue = AMADevContextValue | AMAProdContextValue;
|
|
23
|
+
export declare const isDevContextValue: (value: AMAContextValue) => value is AMADevContextValue;
|
|
24
|
+
export declare const AMAProvider: React.FC<AMAProviderProps>;
|
|
25
|
+
export declare const useAMAContext: () => AMAContextValue;
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* eslint-disable react-native/no-inline-styles */
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
20
|
+
if (mod && mod.__esModule) return mod;
|
|
21
|
+
var result = {};
|
|
22
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
23
|
+
__setModuleDefault(result, mod);
|
|
24
|
+
return result;
|
|
25
|
+
};
|
|
26
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
|
+
exports.useAMAContext = exports.AMAProvider = exports.isDevContextValue = void 0;
|
|
28
|
+
const internal_1 = require("@react-native-ama/internal");
|
|
29
|
+
const React = __importStar(require("react"));
|
|
30
|
+
const react_native_1 = require("react-native");
|
|
31
|
+
const eventsMapping = {
|
|
32
|
+
reduceTransparencyChanged: 'isReduceTransparencyEnabled',
|
|
33
|
+
reduceMotionChanged: 'isReduceMotionEnabled',
|
|
34
|
+
grayscaleChanged: 'isGrayscaleEnabled',
|
|
35
|
+
boldTextChanged: 'isBoldTextEnabled',
|
|
36
|
+
invertColorsChanged: 'isInvertColorsEnabled',
|
|
37
|
+
screenReaderChanged: 'isScreenReaderEnabled',
|
|
38
|
+
};
|
|
39
|
+
const isDevContextValue = (value) => value.trackError !== undefined;
|
|
40
|
+
exports.isDevContextValue = isDevContextValue;
|
|
41
|
+
const DEFAULT_VALUES = {
|
|
42
|
+
isReduceTransparencyEnabled: false,
|
|
43
|
+
isBoldTextEnabled: false,
|
|
44
|
+
isGrayscaleEnabled: false,
|
|
45
|
+
isInvertColorsEnabled: false,
|
|
46
|
+
isReduceMotionEnabled: false,
|
|
47
|
+
isScreenReaderEnabled: false,
|
|
48
|
+
reactNavigationScreenOptions: {
|
|
49
|
+
animationEnabled: true,
|
|
50
|
+
animation: 'default',
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
const AMAContext = React.createContext(null);
|
|
54
|
+
const AMAProvider = ({ children }) => {
|
|
55
|
+
const [values, setValues] = React.useState(DEFAULT_VALUES);
|
|
56
|
+
const handleAccessibilityInfoChanged = (key) => {
|
|
57
|
+
return (newValue) => {
|
|
58
|
+
setValues(oldValues => {
|
|
59
|
+
const newValues = Object.assign({}, oldValues);
|
|
60
|
+
newValues[key] = newValue;
|
|
61
|
+
if (key === 'isReduceMotionEnabled') {
|
|
62
|
+
newValues.reactNavigationScreenOptions.animationEnabled = !newValue;
|
|
63
|
+
newValues.reactNavigationScreenOptions.animation = newValue
|
|
64
|
+
? 'fade'
|
|
65
|
+
: 'default';
|
|
66
|
+
}
|
|
67
|
+
return Object.assign(Object.assign({}, oldValues), newValues);
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
React.useEffect(() => {
|
|
72
|
+
const allInitPromises = [];
|
|
73
|
+
const subscriptions = Object.entries(eventsMapping).map(([eventName, contextKey]) => {
|
|
74
|
+
allInitPromises.push(react_native_1.AccessibilityInfo[contextKey]());
|
|
75
|
+
return react_native_1.AccessibilityInfo.addEventListener(eventName, handleAccessibilityInfoChanged(contextKey));
|
|
76
|
+
});
|
|
77
|
+
Promise.all(allInitPromises).then(promisesValues => {
|
|
78
|
+
const newValues = Object.values(eventsMapping).reduce((list, key, index) => {
|
|
79
|
+
list[key] = promisesValues[index];
|
|
80
|
+
return list;
|
|
81
|
+
}, {});
|
|
82
|
+
setValues(oldValues => {
|
|
83
|
+
return Object.assign(Object.assign({}, oldValues), newValues);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
return () => {
|
|
87
|
+
subscriptions.forEach(subscription => subscription === null || subscription === void 0 ? void 0 : subscription.remove());
|
|
88
|
+
};
|
|
89
|
+
}, []);
|
|
90
|
+
const [failedItems, setFailedItems] = React.useState([]);
|
|
91
|
+
if (__DEV__) {
|
|
92
|
+
const trackError = (id) => {
|
|
93
|
+
if (failedItems.includes(id)) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
setFailedItems(items => [...items, id]);
|
|
97
|
+
react_native_1.AccessibilityInfo.announceForAccessibility("One or more component didn't pass the accessibility check, please check the console for more info");
|
|
98
|
+
};
|
|
99
|
+
const removeError = (id) => {
|
|
100
|
+
setFailedItems(items => {
|
|
101
|
+
const index = items.indexOf(id);
|
|
102
|
+
if (index >= 0) {
|
|
103
|
+
items.splice(index);
|
|
104
|
+
return [...items];
|
|
105
|
+
}
|
|
106
|
+
return items;
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
return (<AMAContext.Provider value={Object.assign(Object.assign({}, values), { trackError,
|
|
110
|
+
removeError })}>
|
|
111
|
+
<react_native_1.View style={{ flex: 1 }}>
|
|
112
|
+
<>
|
|
113
|
+
{children}
|
|
114
|
+
{failedItems.length > 0 ? (<AMAError count={failedItems.length}/>) : null}
|
|
115
|
+
</>
|
|
116
|
+
</react_native_1.View>
|
|
117
|
+
</AMAContext.Provider>);
|
|
118
|
+
}
|
|
119
|
+
return <AMAContext.Provider value={values}>{children}</AMAContext.Provider>;
|
|
120
|
+
};
|
|
121
|
+
exports.AMAProvider = AMAProvider;
|
|
122
|
+
const AMAError = ({ count }) => {
|
|
123
|
+
const error = `${count} component(s) didn't pass the accessibility check(s)`;
|
|
124
|
+
return (<react_native_1.View accessibilityLabel={error} accessibilityHint="Please check the console for more info..." style={{
|
|
125
|
+
paddingHorizontal: 24,
|
|
126
|
+
paddingTop: 24,
|
|
127
|
+
paddingBottom: 48,
|
|
128
|
+
backgroundColor: internal_1.RED,
|
|
129
|
+
}} testID="amaError">
|
|
130
|
+
<react_native_1.View accessible={true}>
|
|
131
|
+
<react_native_1.Text style={{ color: 'white', fontSize: 16, lineHeight: 26 }} testID="amaError.message">
|
|
132
|
+
{error}
|
|
133
|
+
</react_native_1.Text>
|
|
134
|
+
<react_native_1.Text style={{ color: 'white', fontSize: 16, lineHeight: 24 }}>
|
|
135
|
+
Please check the console for more info...
|
|
136
|
+
</react_native_1.Text>
|
|
137
|
+
</react_native_1.View>
|
|
138
|
+
</react_native_1.View>);
|
|
139
|
+
};
|
|
140
|
+
const useAMAContext = () => {
|
|
141
|
+
const context = React.useContext(AMAContext);
|
|
142
|
+
if (!context) {
|
|
143
|
+
throw new Error('Please wrap your app with <AMAProvider />');
|
|
144
|
+
}
|
|
145
|
+
return context;
|
|
146
|
+
};
|
|
147
|
+
exports.useAMAContext = useAMAContext;
|
|
@@ -59,8 +59,6 @@ const eventsMapping: AccessibilityInfoEvents = {
|
|
|
59
59
|
screenReaderChanged: 'isScreenReaderEnabled',
|
|
60
60
|
};
|
|
61
61
|
|
|
62
|
-
const isDev = __DEV__;
|
|
63
|
-
|
|
64
62
|
export const isDevContextValue = (
|
|
65
63
|
value: AMAContextValue,
|
|
66
64
|
): value is AMADevContextValue =>
|
|
@@ -144,7 +142,7 @@ export const AMAProvider: React.FC<AMAProviderProps> = ({ children }) => {
|
|
|
144
142
|
|
|
145
143
|
const [failedItems, setFailedItems] = React.useState<string[]>([]);
|
|
146
144
|
|
|
147
|
-
if (
|
|
145
|
+
if (__DEV__) {
|
|
148
146
|
const trackError = (id: string) => {
|
|
149
147
|
if (failedItems.includes(id)) {
|
|
150
148
|
return;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { ViewProps } from 'react-native';
|
|
3
|
+
type AutofocusContainerProps = React.PropsWithChildren<({
|
|
4
|
+
wrapChildrenInAccessibleView?: true;
|
|
5
|
+
} & ViewProps) | {
|
|
6
|
+
wrapChildrenInAccessibleView: false;
|
|
7
|
+
}>;
|
|
8
|
+
export declare const AutofocusContainer: ({ children, wrapChildrenInAccessibleView, ...viewProps }: AutofocusContainerProps) => React.JSX.Element;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
26
|
+
var t = {};
|
|
27
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
28
|
+
t[p] = s[p];
|
|
29
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
30
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
31
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
32
|
+
t[p[i]] = s[p[i]];
|
|
33
|
+
}
|
|
34
|
+
return t;
|
|
35
|
+
};
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
exports.AutofocusContainer = void 0;
|
|
38
|
+
const React = __importStar(require("react"));
|
|
39
|
+
const react_native_1 = require("react-native");
|
|
40
|
+
const useFocus_1 = require("../hooks/useFocus");
|
|
41
|
+
const AutofocusContainer = (_a) => {
|
|
42
|
+
var { children, wrapChildrenInAccessibleView = true } = _a, viewProps = __rest(_a, ["children", "wrapChildrenInAccessibleView"]);
|
|
43
|
+
const containerRef = React.useRef(null);
|
|
44
|
+
const { setFocus } = (0, useFocus_1.useFocus)();
|
|
45
|
+
React.useEffect(() => {
|
|
46
|
+
setTimeout(() => {
|
|
47
|
+
setFocus(containerRef.current);
|
|
48
|
+
}, 0);
|
|
49
|
+
}, [setFocus]);
|
|
50
|
+
return wrapChildrenInAccessibleView ? (<react_native_1.TouchableWithoutFeedback ref={containerRef}>
|
|
51
|
+
<react_native_1.View accessible={true} testID="autofocusContainer.accessibleView" {...viewProps}>
|
|
52
|
+
{children}
|
|
53
|
+
</react_native_1.View>
|
|
54
|
+
</react_native_1.TouchableWithoutFeedback>) : (<react_native_1.TouchableWithoutFeedback ref={containerRef}>
|
|
55
|
+
{children}
|
|
56
|
+
</react_native_1.TouchableWithoutFeedback>);
|
|
57
|
+
};
|
|
58
|
+
exports.AutofocusContainer = AutofocusContainer;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { PropsWithChildren } from 'react';
|
|
2
|
+
type HideChildrenFromAccessibilityTreeProps = {
|
|
3
|
+
testID?: string;
|
|
4
|
+
};
|
|
5
|
+
export declare const HideChildrenFromAccessibilityTree: (props: PropsWithChildren<HideChildrenFromAccessibilityTreeProps>) => JSX.Element;
|
|
6
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.HideChildrenFromAccessibilityTree = void 0;
|
|
7
|
+
const react_1 = __importDefault(require("react"));
|
|
8
|
+
const react_native_1 = require("react-native");
|
|
9
|
+
const AMAProvider_1 = require("./AMAProvider");
|
|
10
|
+
const HideChildrenFromAccessibilityTree = (props) => {
|
|
11
|
+
const { isScreenReaderEnabled } = (0, AMAProvider_1.useAMAContext)();
|
|
12
|
+
if (!isScreenReaderEnabled) {
|
|
13
|
+
return <>{props.children}</>;
|
|
14
|
+
}
|
|
15
|
+
return react_native_1.Platform.select({
|
|
16
|
+
default: <HideChildrenFromAccessibilityAndroid {...props}/>,
|
|
17
|
+
ios: <HideChildrenFromAccessibilityTreeIOS {...props}/>,
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
exports.HideChildrenFromAccessibilityTree = HideChildrenFromAccessibilityTree;
|
|
21
|
+
const HideChildrenFromAccessibilityAndroid = ({ children, testID, }) => {
|
|
22
|
+
return (<react_native_1.View importantForAccessibility="no-hide-descendants" testID={testID}>
|
|
23
|
+
{children}
|
|
24
|
+
</react_native_1.View>);
|
|
25
|
+
};
|
|
26
|
+
const HideChildrenFromAccessibilityTreeIOS = ({ children, }) => {
|
|
27
|
+
return hideChildrenFromAccessibilityTree(children);
|
|
28
|
+
};
|
|
29
|
+
const hideChildrenFromAccessibilityTree = (component) => {
|
|
30
|
+
return (react_1.default.Children.map(component, child => {
|
|
31
|
+
return react_1.default.isValidElement(child)
|
|
32
|
+
? react_1.default.cloneElement(child, {
|
|
33
|
+
// @ts-ignore
|
|
34
|
+
importantForAccessibility: 'no',
|
|
35
|
+
accessibilityElementsHidden: true,
|
|
36
|
+
children: hideChildrenFromAccessibilityTree(child.props.children),
|
|
37
|
+
})
|
|
38
|
+
: child;
|
|
39
|
+
}) || null);
|
|
40
|
+
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable jest/no-disabled-tests */
|
|
1
2
|
import { act, render } from '@testing-library/react-native';
|
|
2
3
|
import { flushMicroTasks } from '@testing-library/react-native/build/flush-micro-tasks';
|
|
3
4
|
import * as React from 'react';
|
|
@@ -10,7 +11,7 @@ beforeEach(() => {
|
|
|
10
11
|
jest.clearAllMocks();
|
|
11
12
|
});
|
|
12
13
|
|
|
13
|
-
describe('HideChildrenFromAccessibilityTree', () => {
|
|
14
|
+
describe.skip('HideChildrenFromAccessibilityTree', () => {
|
|
14
15
|
describe('iOS', () => {
|
|
15
16
|
beforeEach(() => {
|
|
16
17
|
const Platform = jest.requireActual(
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import type { PressableStateCallbackType } from 'react-native';
|
|
3
|
+
export declare const useButtonChecks: ((props: Record<string, any>, children?: React.ReactNode | ((state: PressableStateCallbackType) => React.ReactNode), shouldPerformContrastCheck?: boolean) => {
|
|
4
|
+
onLayout: (event: import("react-native").LayoutChangeEvent) => void;
|
|
5
|
+
debugStyle: any[] | ((...params: any) => any) | {
|
|
6
|
+
[x: string]: any;
|
|
7
|
+
} | undefined;
|
|
8
|
+
} | null) | null;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useButtonChecks = void 0;
|
|
4
|
+
const internal_1 = require("@react-native-ama/internal");
|
|
5
|
+
const useChecks_1 = require("./useChecks");
|
|
6
|
+
exports.useButtonChecks = __DEV__
|
|
7
|
+
? (props, children, shouldPerformContrastCheck = true) => {
|
|
8
|
+
const checks = (0, useChecks_1.useChecks)();
|
|
9
|
+
if (checks === null) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
const { noUndefinedProperty, contrastChecker, onLayout, noUppercaseStringChecker, checkCompatibleAccessibilityState, checkAccessibilityRole, debugStyle, } = checks;
|
|
13
|
+
let style = props.style || {};
|
|
14
|
+
const isAccessible = props.accessible !== false;
|
|
15
|
+
isAccessible &&
|
|
16
|
+
noUndefinedProperty({
|
|
17
|
+
properties: props,
|
|
18
|
+
property: 'accessibilityRole',
|
|
19
|
+
rule: 'NO_ACCESSIBILITY_ROLE',
|
|
20
|
+
});
|
|
21
|
+
isAccessible &&
|
|
22
|
+
noUndefinedProperty({
|
|
23
|
+
properties: props,
|
|
24
|
+
property: 'accessibilityLabel',
|
|
25
|
+
rule: 'NO_ACCESSIBILITY_LABEL',
|
|
26
|
+
});
|
|
27
|
+
isAccessible &&
|
|
28
|
+
noUppercaseStringChecker({
|
|
29
|
+
text: props.accessibilityLabel,
|
|
30
|
+
});
|
|
31
|
+
checkCompatibleAccessibilityState({
|
|
32
|
+
accessibilityStates: props === null || props === void 0 ? void 0 : props.accessibilityState,
|
|
33
|
+
accessibilityRole: props === null || props === void 0 ? void 0 : props.accessiblityRole,
|
|
34
|
+
});
|
|
35
|
+
checkAccessibilityRole(props.accessibilityRole);
|
|
36
|
+
const contrastCheckerCallback = shouldPerformContrastCheck
|
|
37
|
+
? contrastChecker
|
|
38
|
+
: undefined;
|
|
39
|
+
const theStyle = internal_1.applyStyle === null || internal_1.applyStyle === void 0 ? void 0 : (0, internal_1.applyStyle)({
|
|
40
|
+
style,
|
|
41
|
+
debugStyle,
|
|
42
|
+
// @ts-ignore
|
|
43
|
+
children,
|
|
44
|
+
contrastCheckerCallback,
|
|
45
|
+
});
|
|
46
|
+
return {
|
|
47
|
+
onLayout,
|
|
48
|
+
debugStyle: theStyle,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
: null;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { LogParams, type CheckFocusTrap, type ContrastChecker, type NoUndefinedProperty, type UppercaseChecker, type UppercaseStringChecker } from '@react-native-ama/internal';
|
|
2
|
+
import { AccessibilityRole, LayoutChangeEvent } from 'react-native';
|
|
3
|
+
export declare const useChecks: () => {
|
|
4
|
+
logResult: (name: string, result: LogParams | LogParams[] | null) => Record<string, any>;
|
|
5
|
+
noUndefinedProperty: <T>(params: NoUndefinedProperty<T>) => Record<string, any>;
|
|
6
|
+
contrastChecker: (params: ContrastChecker) => Record<string, any>;
|
|
7
|
+
onLayout: (event: LayoutChangeEvent) => void;
|
|
8
|
+
noUppercaseStringChecker: (params: UppercaseStringChecker) => Record<string, any>;
|
|
9
|
+
uppercaseChecker: (params: UppercaseChecker) => Record<string, any>;
|
|
10
|
+
checkFocusTrap: (params: CheckFocusTrap) => void;
|
|
11
|
+
minimumSizeFailed: boolean;
|
|
12
|
+
checkCompatibleAccessibilityState: (props: Record<string, any>) => void;
|
|
13
|
+
checkAccessibilityRole: (param: AccessibilityRole) => void;
|
|
14
|
+
debugStyle: any;
|
|
15
|
+
} | null;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.useChecks = void 0;
|
|
27
|
+
const internal_1 = require("@react-native-ama/internal");
|
|
28
|
+
const React = __importStar(require("react"));
|
|
29
|
+
const react_native_1 = require("react-native");
|
|
30
|
+
const AMAProvider_1 = require("../components/AMAProvider");
|
|
31
|
+
const useChecks = () => {
|
|
32
|
+
const context = (0, AMAProvider_1.useAMAContext)();
|
|
33
|
+
if (!(0, AMAProvider_1.isDevContextValue)(context)) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Because the AMA Error view cannot be removed by default, this hacky solution
|
|
38
|
+
* allows the dev to hide it if all the issues have been solved.
|
|
39
|
+
*/
|
|
40
|
+
const fakeRandom = React.useRef('' + Date.now() + Math.random() * 42);
|
|
41
|
+
const hasErrors = React.useRef(false);
|
|
42
|
+
const failedTests = React.useRef([]);
|
|
43
|
+
const shouldCheckLayout = React.useRef(true);
|
|
44
|
+
const layoutCheckTimeout = React.useRef();
|
|
45
|
+
const [minimumSizeFailed, setMinimumSizeFailed] = React.useState(false);
|
|
46
|
+
const [debugStyle, setDebugStyle] = React.useState({});
|
|
47
|
+
const { trackError, removeError } = context;
|
|
48
|
+
const logResult = (name, result) => {
|
|
49
|
+
const index = failedTests.current.indexOf(name);
|
|
50
|
+
if (result === null) {
|
|
51
|
+
if (index >= 0 && hasErrors.current) {
|
|
52
|
+
failedTests.current.splice(index);
|
|
53
|
+
hasErrors.current = false;
|
|
54
|
+
react_native_1.InteractionManager.runAfterInteractions(() => {
|
|
55
|
+
removeError(fakeRandom.current);
|
|
56
|
+
setTimeout(() => {
|
|
57
|
+
setDebugStyle({});
|
|
58
|
+
}, 100);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const results = Array.isArray(result) ? result : [result];
|
|
63
|
+
results.forEach(logParam => {
|
|
64
|
+
if (logParam === null) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const action = internal_1.getRuleAction === null || internal_1.getRuleAction === void 0 ? void 0 : (0, internal_1.getRuleAction)(logParam.rule);
|
|
68
|
+
const hasFailed = action === 'MUST_NOT' || action === 'MUST';
|
|
69
|
+
if (index < 0) {
|
|
70
|
+
// @ts-ignore
|
|
71
|
+
internal_1.logFailure === null || internal_1.logFailure === void 0 ? void 0 : (0, internal_1.logFailure)(Object.assign({ action }, logParam));
|
|
72
|
+
}
|
|
73
|
+
if (!hasFailed) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
else if (index >= 0) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
failedTests.current.push(name);
|
|
80
|
+
react_native_1.InteractionManager.runAfterInteractions(() => {
|
|
81
|
+
trackError(fakeRandom.current);
|
|
82
|
+
setDebugStyle(internal_1.ERROR_STYLE);
|
|
83
|
+
});
|
|
84
|
+
hasErrors.current = true;
|
|
85
|
+
});
|
|
86
|
+
// @ts-ignore
|
|
87
|
+
return hasErrors.current ? internal_1.ERROR_STYLE : {};
|
|
88
|
+
};
|
|
89
|
+
const noUndefinedProperty = (params) => logResult(`noUndefinedProperty ${params.property}`, (0, internal_1.noUndefinedProperty)(params));
|
|
90
|
+
const contrastChecker = (params) => logResult('contrastChecker', (0, internal_1.contrastChecker)(params));
|
|
91
|
+
const checkMinimumSize = (params) => {
|
|
92
|
+
return logResult('checkMinimumSize', (0, internal_1.checkMinimumSize)(params));
|
|
93
|
+
};
|
|
94
|
+
const noUppercaseStringChecker = (params) => logResult('accessibilityLabelChecker', (0, internal_1.uppercaseStringChecker)(params));
|
|
95
|
+
const uppercaseChecker = (params) => logResult('uppercaseChecker', (0, internal_1.uppercaseChecker)(params));
|
|
96
|
+
const checkFocusTrap = (params) => {
|
|
97
|
+
(0, internal_1.checkFocusTrap)(params).then(result => {
|
|
98
|
+
logResult('checkFocusTrap', result);
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
const checkAccessibilityRole = (param) => {
|
|
102
|
+
logResult('checkAccessibilityRole', (0, internal_1.checkAccessibilityRole)(param));
|
|
103
|
+
};
|
|
104
|
+
const checkCompatibleAccessibilityState = (props) => {
|
|
105
|
+
const amaStates = ['checked', 'selected'];
|
|
106
|
+
const params = {
|
|
107
|
+
accessibilityRole: props.accessibilityRole,
|
|
108
|
+
accessibilityState: props === null || props === void 0 ? void 0 : props.accessibilityState,
|
|
109
|
+
};
|
|
110
|
+
amaStates.forEach(amaState => {
|
|
111
|
+
if (amaState in props) {
|
|
112
|
+
// @ts-ignore
|
|
113
|
+
params[amaState] = props[amaState];
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
logResult('checkCompatibleAccessibilityState', (0, internal_1.checkForAccessibilityState)(params));
|
|
117
|
+
};
|
|
118
|
+
const onLayout = (event) => {
|
|
119
|
+
/**
|
|
120
|
+
* When the check fails there are situation when adding a border makes the
|
|
121
|
+
* component meet the minimum size requirement, and this causes a loop as the
|
|
122
|
+
* state is update continuously between true and false.
|
|
123
|
+
* To "avoid" that we wait at least 100ms before checking the size again, as
|
|
124
|
+
* this gives the dev time to hot-reload the changes.
|
|
125
|
+
*/
|
|
126
|
+
if (!shouldCheckLayout.current) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
shouldCheckLayout.current = false;
|
|
130
|
+
// @ts-ignore
|
|
131
|
+
clearTimeout(layoutCheckTimeout.current);
|
|
132
|
+
layoutCheckTimeout.current = setTimeout(() => {
|
|
133
|
+
shouldCheckLayout.current = true;
|
|
134
|
+
}, 1000);
|
|
135
|
+
const result = checkMinimumSize(event);
|
|
136
|
+
setMinimumSizeFailed(Object.keys(result).length > 0);
|
|
137
|
+
};
|
|
138
|
+
return {
|
|
139
|
+
logResult,
|
|
140
|
+
noUndefinedProperty,
|
|
141
|
+
contrastChecker,
|
|
142
|
+
onLayout,
|
|
143
|
+
noUppercaseStringChecker,
|
|
144
|
+
uppercaseChecker,
|
|
145
|
+
checkFocusTrap,
|
|
146
|
+
minimumSizeFailed,
|
|
147
|
+
checkCompatibleAccessibilityState,
|
|
148
|
+
checkAccessibilityRole,
|
|
149
|
+
debugStyle,
|
|
150
|
+
};
|
|
151
|
+
};
|
|
152
|
+
exports.useChecks = useChecks;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import * as Logger from '@react-native-ama/internal';
|
|
2
1
|
import { type RuleAction } from '@react-native-ama/internal';
|
|
3
2
|
import * as CheckForAccessibilityRole from '@react-native-ama/internal/src/checks/checkAccessibilityRole';
|
|
4
3
|
import * as CheckForAccessibilityState from '@react-native-ama/internal/src/checks/checkForAccessibilityState';
|
|
4
|
+
import * as Logger from '@react-native-ama/internal/src/utils/logger';
|
|
5
5
|
import { renderHook } from '@testing-library/react-native';
|
|
6
6
|
|
|
7
7
|
import * as AMAProvider from '../components/AMAProvider';
|