@react-native-ama/core 1.2.0 → 2.0.0-beta.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/ReactNativeAma.types.d.ts +66 -0
- package/dist/ReactNativeAma.types.js +2 -0
- package/dist/ReactNativeAmaModule.d.ts +11 -0
- package/dist/ReactNativeAmaModule.js +5 -0
- package/dist/ReactNativeAmaModule.web.d.ts +9 -0
- package/dist/ReactNativeAmaModule.web.js +27 -0
- package/dist/ReactNativeAmaView.d.ts +3 -0
- package/dist/ReactNativeAmaView.js +32 -0
- package/dist/ReactNativeAmaView.web.d.ts +3 -0
- package/dist/ReactNativeAmaView.web.js +34 -0
- package/dist/{src/components → components}/AMAProvider.d.ts +4 -2
- package/dist/{src/components → components}/AMAProvider.js +19 -45
- package/dist/{src/components → components}/AutofocusContainer.d.ts +2 -1
- package/dist/{src/components → components}/HideChildrenFromAccessibilityTree.d.ts +1 -1
- package/dist/{src/components → components}/HideChildrenFromAccessibilityTree.js +7 -5
- package/dist/{src/hooks → hooks}/useFocus.js +10 -3
- package/dist/{src/index.d.ts → index.d.ts} +3 -2
- package/dist/index.js +38 -0
- package/dist/internals/checks/checkAriaLabel.d.ts +3 -0
- package/dist/internals/checks/checkAriaLabel.js +15 -0
- package/dist/internals/checks/checkAriaRole.d.ts +3 -0
- package/dist/internals/checks/checkAriaRole.js +48 -0
- package/dist/internals/checks/checkContrast.d.ts +3 -0
- package/dist/internals/checks/checkContrast.js +84 -0
- package/dist/internals/checks/checkImageAlt.d.ts +3 -0
- package/dist/internals/checks/checkImageAlt.js +20 -0
- package/dist/internals/checks/checkIsUppercase.d.ts +8 -0
- package/dist/internals/checks/checkIsUppercase.js +30 -0
- package/dist/internals/checks/checkLongNumber.d.ts +3 -0
- package/dist/internals/checks/checkLongNumber.js +31 -0
- package/dist/internals/checks/checkMinimumSize.d.ts +3 -0
- package/dist/internals/checks/checkMinimumSize.js +22 -0
- package/dist/internals/checks/checkTextInput.d.ts +3 -0
- package/dist/internals/checks/checkTextInput.js +51 -0
- package/dist/internals/checks/performChecks.d.ts +3 -0
- package/dist/internals/checks/performChecks.js +23 -0
- package/dist/internals/components/AMAErrorOverlay.d.ts +5 -0
- package/dist/internals/components/AMAErrorOverlay.js +334 -0
- package/dist/internals/components/AMARuleError.d.ts +7 -0
- package/dist/internals/components/AMARuleError.js +161 -0
- package/dist/internals/config.d.ts +23 -0
- package/dist/internals/config.js +33 -0
- package/dist/internals/types.d.ts +9 -0
- package/dist/internals/types.js +2 -0
- package/dist/internals/useAMADev.d.ts +8 -0
- package/dist/internals/useAMADev.dev.d.ts +2 -0
- package/dist/internals/useAMADev.dev.js +110 -0
- package/dist/internals/useAMADev.js +6 -0
- package/dist/internals/useAMADevNodeChecks.dev.d.ts +16 -0
- package/dist/internals/useAMADevNodeChecks.dev.js +115 -0
- package/dist/internals/useAMADevUiInteraction.dev.d.ts +7 -0
- package/dist/internals/useAMADevUiInteraction.dev.js +100 -0
- package/dist/internals/utils/amaClearHighlight.d.ts +2 -0
- package/dist/internals/utils/amaClearHighlight.js +12 -0
- package/dist/internals/utils/amaHighlightComponent.d.ts +3 -0
- package/dist/internals/utils/amaHighlightComponent.js +51 -0
- package/dist/internals/utils/constants.d.ts +3 -0
- package/dist/internals/utils/constants.js +32 -0
- package/dist/internals/utils/getErrorColor.d.ts +2 -0
- package/dist/internals/utils/getErrorColor.js +10 -0
- package/dist/internals/utils/getRuleAction.d.ts +2 -0
- package/dist/internals/utils/getRuleAction.js +40 -0
- package/dist/internals/utils/getRuleErrorInfo.d.ts +7 -0
- package/dist/internals/utils/getRuleErrorInfo.js +19 -0
- package/dist/internals/utils/ignoreContrastCheck.d.ts +1 -0
- package/dist/internals/utils/ignoreContrastCheck.js +15 -0
- package/dist/internals/utils/interpolateAnimationStates.d.ts +2 -0
- package/dist/internals/utils/interpolateAnimationStates.js +43 -0
- package/dist/internals/utils/isA11yLabelAllowed.d.ts +1 -0
- package/dist/internals/utils/isA11yLabelAllowed.js +14 -0
- package/dist/internals/utils/isRuleDisabled.d.ts +2 -0
- package/dist/internals/utils/isRuleDisabled.js +10 -0
- package/dist/internals/utils/logError.d.ts +2 -0
- package/dist/internals/utils/logError.js +36 -0
- package/dist/internals/utils/logFoundIssues.d.ts +2 -0
- package/dist/internals/utils/logFoundIssues.js +23 -0
- package/dist/internals/utils/logger.d.ts +6 -0
- package/dist/internals/utils/logger.js +15 -0
- package/dist/internals/utils/minimumTouchableSize.d.ts +1 -0
- package/dist/internals/utils/minimumTouchableSize.js +9 -0
- package/dist/internals/utils/platformHelpers.d.ts +2 -0
- package/dist/internals/utils/platformHelpers.js +6 -0
- package/dist/internals/utils/rules.d.ts +22 -0
- package/dist/internals/utils/rules.js +253 -0
- package/package.json +61 -18
- package/src/ReactNativeAma.types.ts +70 -0
- package/src/ReactNativeAmaModule.ts +18 -0
- package/src/ReactNativeAmaModule.web.ts +14 -0
- package/src/ReactNativeAmaView.tsx +9 -0
- package/src/ReactNativeAmaView.web.tsx +15 -0
- package/src/__mocks__/ReactNativeAmaModule.ts +9 -0
- package/src/components/AMAProvider.integration.test.tsx +3 -96
- package/src/components/AMAProvider.test.tsx +9 -4
- package/src/components/AMAProvider.tsx +40 -76
- package/src/components/AutofocusContainer.test.tsx +4 -5
- package/src/components/AutofocusContainer.tsx +20 -5
- package/src/components/HideChildrenFromAccessibilityTree.test.tsx +23 -39
- package/src/components/HideChildrenFromAccessibilityTree.tsx +12 -11
- package/src/hooks/useFocus.test.ts +20 -20
- package/src/hooks/useFocus.ts +14 -6
- package/src/hooks/useTimedAction.android.test.ts +0 -1
- package/src/hooks/useTimedAction.ios.test.ts +0 -1
- package/src/hooks/useTimedAction.ts +0 -1
- package/src/index.ts +4 -2
- package/src/internals/checks/checkAriaLabel.test.ts +165 -0
- package/src/internals/checks/checkAriaLabel.ts +16 -0
- package/src/internals/checks/checkAriaRole.test.ts +429 -0
- package/src/internals/checks/checkAriaRole.ts +60 -0
- package/src/internals/checks/checkContrast.test.ts +278 -0
- package/src/internals/checks/checkContrast.ts +109 -0
- package/src/internals/checks/checkImageAlt.test.ts +125 -0
- package/src/internals/checks/checkImageAlt.ts +23 -0
- package/src/internals/checks/checkIsUppercase.test.ts +399 -0
- package/src/internals/checks/checkIsUppercase.ts +46 -0
- package/src/internals/checks/checkLongNumber.test.ts +111 -0
- package/src/internals/checks/checkLongNumber.ts +34 -0
- package/src/internals/checks/checkMinimumSize.test.ts +67 -0
- package/src/internals/checks/checkMinimumSize.ts +25 -0
- package/src/internals/checks/checkTextInput.ts +65 -0
- package/src/internals/checks/performChecks.test.ts +171 -0
- package/src/internals/checks/performChecks.ts +24 -0
- package/src/internals/components/AMAErrorOverlay.test.tsx +139 -0
- package/src/internals/components/AMAErrorOverlay.tsx +451 -0
- package/src/internals/components/AMARuleError.test.tsx +93 -0
- package/src/internals/components/AMARuleError.tsx +225 -0
- package/src/internals/config.ts +58 -0
- package/src/internals/types.ts +11 -0
- package/src/internals/useAMADev.dev.ts +153 -0
- package/src/internals/useAMADev.test.ts +260 -0
- package/src/internals/useAMADev.ts +17 -0
- package/src/internals/useAMADevNodeChecks.dev.ts +178 -0
- package/src/internals/useAMADevUiInteraction.dev.ts +164 -0
- package/src/internals/utils/amaClearHighlight.test.ts +21 -0
- package/src/internals/utils/amaClearHighlight.ts +8 -0
- package/src/internals/utils/amaHighlightComponent.test.ts +74 -0
- package/src/internals/utils/amaHighlightComponent.ts +46 -0
- package/src/internals/utils/constants.ts +33 -0
- package/src/internals/utils/devMode.test.ts +99 -0
- package/src/internals/utils/getErrorColor.test.ts +18 -0
- package/src/internals/utils/getErrorColor.ts +8 -0
- package/src/internals/utils/getRuleAction.ts +13 -0
- package/src/internals/utils/getRuleErrorInfo.test.ts +59 -0
- package/src/internals/utils/getRuleErrorInfo.ts +26 -0
- package/src/internals/utils/ignoreContrastCheck.test.ts +34 -0
- package/src/internals/utils/ignoreContrastCheck.ts +11 -0
- package/src/internals/utils/interpolateAnimation.test.ts +176 -0
- package/src/internals/utils/interpolateAnimationStates.ts +55 -0
- package/src/internals/utils/isA11yLabelAllowed.test.ts +39 -0
- package/src/internals/utils/isA11yLabelAllowed.ts +10 -0
- package/src/internals/utils/isRuleDisabled.test.ts +35 -0
- package/src/internals/utils/isRuleDisabled.ts +10 -0
- package/src/internals/utils/logError.test.ts +148 -0
- package/src/internals/utils/logError.ts +41 -0
- package/src/internals/utils/logFoundIssues.test.ts +98 -0
- package/src/internals/utils/logFoundIssues.ts +22 -0
- package/src/internals/utils/logger.test.ts +26 -0
- package/src/internals/utils/logger.ts +15 -0
- package/src/internals/utils/loggerMethods.test.ts +38 -0
- package/src/internals/utils/minimumTouchableSize.test.ts +28 -0
- package/src/internals/utils/minimumTouchableSize.tsx +9 -0
- package/src/internals/utils/platformHelpers.test.ts +11 -0
- package/src/internals/utils/platformHelpers.ts +4 -0
- package/src/internals/utils/rules.ts +363 -0
- package/dist/scripts/create-config.d.ts +0 -1
- package/dist/scripts/create-config.js +0 -23
- package/dist/src/hooks/useButtonChecks.d.ts +0 -6
- package/dist/src/hooks/useButtonChecks.js +0 -51
- package/dist/src/hooks/useChecks.d.ts +0 -15
- package/dist/src/hooks/useChecks.js +0 -152
- package/dist/src/index.js +0 -20
- package/src/hooks/useButtonChecks.ts +0 -73
- package/src/hooks/useChecks.test.ts +0 -214
- package/src/hooks/useChecks.ts +0 -207
- /package/dist/{src/components → components}/AutofocusContainer.js +0 -0
- /package/dist/{src/hooks → hooks}/useFocus.d.ts +0 -0
- /package/dist/{src/hooks → hooks}/useTimedAction.d.ts +0 -0
- /package/dist/{src/hooks → hooks}/useTimedAction.js +0 -0
- /package/dist/{src/utils → utils}/numerify.d.ts +0 -0
- /package/dist/{src/utils → utils}/numerify.js +0 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { StyleProp, ViewStyle } from 'react-native';
|
|
2
|
+
export type OnLoadEventPayload = {
|
|
3
|
+
url: string;
|
|
4
|
+
};
|
|
5
|
+
export type AmaNode = {
|
|
6
|
+
type: 'Pressable' | 'Text' | 'TextInput' | 'Image';
|
|
7
|
+
viewId: number;
|
|
8
|
+
bounds: [number, number, number, number];
|
|
9
|
+
hitSlop?: {
|
|
10
|
+
top: number;
|
|
11
|
+
left: number;
|
|
12
|
+
bottom: number;
|
|
13
|
+
right: number;
|
|
14
|
+
};
|
|
15
|
+
ariaLabel?: string;
|
|
16
|
+
ariaRole?: string;
|
|
17
|
+
traits?: string[];
|
|
18
|
+
content?: string;
|
|
19
|
+
fg?: string;
|
|
20
|
+
bg?: string;
|
|
21
|
+
fontSize?: number;
|
|
22
|
+
isBold?: boolean;
|
|
23
|
+
isEnabled?: boolean;
|
|
24
|
+
returnType?: number;
|
|
25
|
+
hasOnSubmitEditing: boolean;
|
|
26
|
+
isAccessible?: boolean;
|
|
27
|
+
};
|
|
28
|
+
export type AmaNodes = Record<number, AmaNode>;
|
|
29
|
+
export type AmaUiSnapshot = {
|
|
30
|
+
fgColor?: string;
|
|
31
|
+
bgColor?: string;
|
|
32
|
+
x: number;
|
|
33
|
+
y: number;
|
|
34
|
+
width: number;
|
|
35
|
+
height: number;
|
|
36
|
+
parentId: number;
|
|
37
|
+
isPressable: boolean;
|
|
38
|
+
isChecked: boolean;
|
|
39
|
+
isBusy: boolean;
|
|
40
|
+
isSelected: boolean;
|
|
41
|
+
isDisabled: boolean;
|
|
42
|
+
isExpanded: boolean;
|
|
43
|
+
};
|
|
44
|
+
export type AmaUiSnapshotsData = {
|
|
45
|
+
rootTag: number;
|
|
46
|
+
before: Record<number, AmaUiSnapshot>;
|
|
47
|
+
after: Record<number, AmaUiSnapshot>;
|
|
48
|
+
afterSettled?: Record<number, AmaUiSnapshot>;
|
|
49
|
+
beforeModalVisible: boolean;
|
|
50
|
+
afterModalVisible: boolean;
|
|
51
|
+
};
|
|
52
|
+
export type AmaUiSnapshotKeys = keyof AmaUiSnapshot;
|
|
53
|
+
export type ReactNativeAmaModuleEvents = {
|
|
54
|
+
onAmaNodes: (nodes: AmaNodes) => void;
|
|
55
|
+
onUIInteraction: (nodes: AmaUiSnapshotsData) => void;
|
|
56
|
+
};
|
|
57
|
+
export type ChangeEventPayload = {
|
|
58
|
+
value: string;
|
|
59
|
+
};
|
|
60
|
+
export type ReactNativeAmaViewProps = {
|
|
61
|
+
url: string;
|
|
62
|
+
onLoad: (event: {
|
|
63
|
+
nativeEvent: OnLoadEventPayload;
|
|
64
|
+
}) => void;
|
|
65
|
+
style?: StyleProp<ViewStyle>;
|
|
66
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { NativeModule } from 'expo';
|
|
2
|
+
import { ReactNativeAmaModuleEvents } from './ReactNativeAma.types';
|
|
3
|
+
import { Position } from './internals/types';
|
|
4
|
+
declare class ReactNativeAmaModule extends NativeModule<ReactNativeAmaModuleEvents> {
|
|
5
|
+
start(config?: any): void;
|
|
6
|
+
stop(): void;
|
|
7
|
+
highlight(viewId: number, mode: 'background' | 'border' | 'both', color: string, issueCount: number): Promise<Position>;
|
|
8
|
+
clearHighlight(viewId: number): void;
|
|
9
|
+
}
|
|
10
|
+
declare const _default: ReactNativeAmaModule;
|
|
11
|
+
export default _default;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { NativeModule } from 'expo';
|
|
2
|
+
import { AmaNodes, ReactNativeAmaModuleEvents } from './ReactNativeAma.types';
|
|
3
|
+
declare class ReactNativeAmaModule extends NativeModule<ReactNativeAmaModuleEvents> {
|
|
4
|
+
PI: number;
|
|
5
|
+
setValueAsync(nodes: AmaNodes): Promise<void>;
|
|
6
|
+
hello(): string;
|
|
7
|
+
}
|
|
8
|
+
declare const _default: typeof ReactNativeAmaModule;
|
|
9
|
+
export default _default;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const expo_1 = require("expo");
|
|
13
|
+
class ReactNativeAmaModule extends expo_1.NativeModule {
|
|
14
|
+
constructor() {
|
|
15
|
+
super(...arguments);
|
|
16
|
+
this.PI = Math.PI;
|
|
17
|
+
}
|
|
18
|
+
setValueAsync(nodes) {
|
|
19
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
20
|
+
this.emit('onAmaNodes', nodes);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
hello() {
|
|
24
|
+
return 'Hello world! 👋';
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.default = (0, expo_1.registerWebModule)(ReactNativeAmaModule, 'ReactNativeAmaModule');
|
|
@@ -0,0 +1,32 @@
|
|
|
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
|
+
const expo_1 = require("expo");
|
|
27
|
+
const React = __importStar(require("react"));
|
|
28
|
+
const NativeView = (0, expo_1.requireNativeView)('ReactNativeAma');
|
|
29
|
+
function ReactNativeAmaView(props) {
|
|
30
|
+
return <NativeView {...props}/>;
|
|
31
|
+
}
|
|
32
|
+
exports.default = ReactNativeAmaView;
|
|
@@ -0,0 +1,34 @@
|
|
|
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
|
+
const React = __importStar(require("react"));
|
|
27
|
+
function ReactNativeAmaView(props) {
|
|
28
|
+
return (<div>
|
|
29
|
+
<iframe
|
|
30
|
+
// eslint-disable-next-line react-native/no-inline-styles
|
|
31
|
+
style={{ flex: 1 }} src={props.url} onLoad={() => props.onLoad({ nativeEvent: { url: props.url } })}/>
|
|
32
|
+
</div>);
|
|
33
|
+
}
|
|
34
|
+
exports.default = ReactNativeAmaView;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
import type { AmaRule } from '../internals/types';
|
|
2
3
|
type AMAProviderProps = {
|
|
3
4
|
children: React.ReactNode;
|
|
4
5
|
};
|
|
@@ -9,14 +10,15 @@ type SharedContextValue = {
|
|
|
9
10
|
isInvertColorsEnabled: boolean;
|
|
10
11
|
isReduceMotionEnabled: boolean;
|
|
11
12
|
isReduceTransparencyEnabled: boolean;
|
|
13
|
+
isHighTextContrastEnabled: boolean;
|
|
14
|
+
isDarkerSystemColorsEnabled: boolean;
|
|
12
15
|
reactNavigationScreenOptions: {
|
|
13
16
|
animationEnabled: boolean;
|
|
14
17
|
animation: 'default' | 'fade';
|
|
15
18
|
};
|
|
16
19
|
};
|
|
17
20
|
export type AMADevContextValue = SharedContextValue & {
|
|
18
|
-
trackError: (
|
|
19
|
-
removeError: (id: string) => void;
|
|
21
|
+
trackError: (rule: AmaRule, ref?: React.RefObject<any>) => void;
|
|
20
22
|
};
|
|
21
23
|
export type AMAProdContextValue = SharedContextValue & {};
|
|
22
24
|
export type AMAContextValue = AMADevContextValue | AMAProdContextValue;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/* eslint-disable react-native/no-inline-styles */
|
|
3
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
3
|
if (k2 === undefined) k2 = k;
|
|
5
4
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -25,7 +24,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
25
24
|
};
|
|
26
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
26
|
exports.useAMAContext = exports.AMAProvider = exports.isDevContextValue = void 0;
|
|
28
|
-
|
|
27
|
+
/* eslint-disable react-native/no-inline-styles */
|
|
29
28
|
const React = __importStar(require("react"));
|
|
30
29
|
const react_native_1 = require("react-native");
|
|
31
30
|
const eventsMapping = {
|
|
@@ -35,6 +34,8 @@ const eventsMapping = {
|
|
|
35
34
|
boldTextChanged: 'isBoldTextEnabled',
|
|
36
35
|
invertColorsChanged: 'isInvertColorsEnabled',
|
|
37
36
|
screenReaderChanged: 'isScreenReaderEnabled',
|
|
37
|
+
highTextContrastChanged: 'isHighTextContrastEnabled',
|
|
38
|
+
darkerSystemColorsChanged: 'isDarkerSystemColorsEnabled',
|
|
38
39
|
};
|
|
39
40
|
const isDevContextValue = (value) => value.trackError !== undefined;
|
|
40
41
|
exports.isDevContextValue = isDevContextValue;
|
|
@@ -45,17 +46,27 @@ const DEFAULT_VALUES = {
|
|
|
45
46
|
isInvertColorsEnabled: false,
|
|
46
47
|
isReduceMotionEnabled: false,
|
|
47
48
|
isScreenReaderEnabled: false,
|
|
49
|
+
isHighTextContrastEnabled: false,
|
|
50
|
+
isDarkerSystemColorsEnabled: false,
|
|
48
51
|
reactNavigationScreenOptions: {
|
|
49
52
|
animationEnabled: true,
|
|
50
53
|
animation: 'default',
|
|
51
54
|
},
|
|
52
55
|
};
|
|
53
56
|
const AMAContext = React.createContext(null);
|
|
57
|
+
const AMAErrorOverlay = __DEV__
|
|
58
|
+
? require('../internals/components/AMAErrorOverlay')
|
|
59
|
+
.AMAErrorOverlay
|
|
60
|
+
: null;
|
|
61
|
+
const useAMADev = __DEV__
|
|
62
|
+
? require('../internals/useAMADev').useAMADev
|
|
63
|
+
: null;
|
|
54
64
|
const AMAProvider = ({ children }) => {
|
|
55
65
|
const [values, setValues] = React.useState(DEFAULT_VALUES);
|
|
66
|
+
const { issues, trackError } = (__DEV__ && (useAMADev === null || useAMADev === void 0 ? void 0 : useAMADev())) || {};
|
|
56
67
|
const handleAccessibilityInfoChanged = (key) => {
|
|
57
68
|
return (newValue) => {
|
|
58
|
-
setValues(oldValues => {
|
|
69
|
+
setValues((oldValues) => {
|
|
59
70
|
const newValues = Object.assign({}, oldValues);
|
|
60
71
|
newValues[key] = newValue;
|
|
61
72
|
if (key === 'isReduceMotionEnabled') {
|
|
@@ -74,44 +85,25 @@ const AMAProvider = ({ children }) => {
|
|
|
74
85
|
allInitPromises.push(react_native_1.AccessibilityInfo[contextKey]());
|
|
75
86
|
return react_native_1.AccessibilityInfo.addEventListener(eventName, handleAccessibilityInfoChanged(contextKey));
|
|
76
87
|
});
|
|
77
|
-
Promise.all(allInitPromises).then(promisesValues => {
|
|
88
|
+
Promise.all(allInitPromises).then((promisesValues) => {
|
|
78
89
|
const newValues = Object.values(eventsMapping).reduce((list, key, index) => {
|
|
79
90
|
list[key] = promisesValues[index];
|
|
80
91
|
return list;
|
|
81
92
|
}, {});
|
|
82
|
-
setValues(oldValues => {
|
|
93
|
+
setValues((oldValues) => {
|
|
83
94
|
return Object.assign(Object.assign({}, oldValues), newValues);
|
|
84
95
|
});
|
|
85
96
|
});
|
|
86
97
|
return () => {
|
|
87
|
-
subscriptions.forEach(subscription => subscription === null || subscription === void 0 ? void 0 : subscription.remove());
|
|
98
|
+
subscriptions.forEach((subscription) => subscription === null || subscription === void 0 ? void 0 : subscription.remove());
|
|
88
99
|
};
|
|
89
100
|
}, []);
|
|
90
|
-
const [failedItems, setFailedItems] = React.useState([]);
|
|
91
101
|
if (__DEV__) {
|
|
92
|
-
|
|
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 })}>
|
|
102
|
+
return (<AMAContext.Provider value={Object.assign(Object.assign({}, values), { trackError: trackError || (() => { }) })}>
|
|
111
103
|
<react_native_1.View style={{ flex: 1 }}>
|
|
112
104
|
<>
|
|
113
105
|
{children}
|
|
114
|
-
{
|
|
106
|
+
{AMAErrorOverlay && <AMAErrorOverlay issues={issues}/>}
|
|
115
107
|
</>
|
|
116
108
|
</react_native_1.View>
|
|
117
109
|
</AMAContext.Provider>);
|
|
@@ -119,24 +111,6 @@ const AMAProvider = ({ children }) => {
|
|
|
119
111
|
return <AMAContext.Provider value={values}>{children}</AMAContext.Provider>;
|
|
120
112
|
};
|
|
121
113
|
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
114
|
const useAMAContext = () => {
|
|
141
115
|
const context = React.useContext(AMAContext);
|
|
142
116
|
if (!context) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { TouchableWithoutFeedbackProps, ViewProps } from 'react-native';
|
|
3
|
-
|
|
3
|
+
type AccessibilityPropKeys = 'accessibilityActions' | 'accessibilityElementsHidden' | 'accessibilityHint' | 'accessibilityLabel' | 'accessibilityLiveRegion' | 'accessibilityRole' | 'accessibilityState' | 'accessibilityViewIsModal' | 'onAccessibilityAction' | 'testID';
|
|
4
|
+
type PickAccessibleProps<T> = Pick<T, Extract<keyof T, AccessibilityPropKeys>>;
|
|
4
5
|
type TouchableAccessibleProps = PickAccessibleProps<TouchableWithoutFeedbackProps>;
|
|
5
6
|
export type AutofocusContainerProps = React.PropsWithChildren<(({
|
|
6
7
|
wrapChildrenInAccessibleView?: true;
|
|
@@ -28,13 +28,15 @@ const HideChildrenFromAccessibilityTreeIOS = ({ children, }) => {
|
|
|
28
28
|
};
|
|
29
29
|
const hideChildrenFromAccessibilityTree = (component) => {
|
|
30
30
|
return (react_1.default.Children.map(component, child => {
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
if (react_1.default.isValidElement(child)) {
|
|
32
|
+
const element = child;
|
|
33
|
+
return react_1.default.cloneElement(element, {
|
|
33
34
|
// @ts-ignore
|
|
34
35
|
importantForAccessibility: 'no',
|
|
35
36
|
accessibilityElementsHidden: true,
|
|
36
|
-
children: hideChildrenFromAccessibilityTree(
|
|
37
|
-
})
|
|
38
|
-
|
|
37
|
+
children: hideChildrenFromAccessibilityTree(element.props.children),
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
return child;
|
|
39
41
|
}) || null);
|
|
40
42
|
};
|
|
@@ -24,9 +24,16 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
26
|
exports.useFocus = void 0;
|
|
27
|
-
const internal_1 = require("@react-native-ama/internal");
|
|
28
27
|
const React = __importStar(require("react"));
|
|
29
28
|
const react_native_1 = require("react-native");
|
|
29
|
+
const SHELL_COLORS = __DEV__
|
|
30
|
+
? {
|
|
31
|
+
BG_RED: '\x1b[41m',
|
|
32
|
+
RESET: '\x1b[0m',
|
|
33
|
+
BLUE: '\x1b[34m',
|
|
34
|
+
YELLOW: '\x1b[33m',
|
|
35
|
+
}
|
|
36
|
+
: null;
|
|
30
37
|
const useFocus = (refComponent) => {
|
|
31
38
|
const setFocus = React.useCallback((component) => {
|
|
32
39
|
if (!component) {
|
|
@@ -44,14 +51,14 @@ const useFocus = (refComponent) => {
|
|
|
44
51
|
else if (__DEV__) {
|
|
45
52
|
console.warn(
|
|
46
53
|
// @ts-ignore
|
|
47
|
-
`${
|
|
54
|
+
`${SHELL_COLORS.BG_RED}AMA.${SHELL_COLORS.RESET} ${SHELL_COLORS.BLUE}useFocus${SHELL_COLORS.RESET}: ${SHELL_COLORS.YELLOW}Ref element not found${SHELL_COLORS.RESET}`);
|
|
48
55
|
}
|
|
49
56
|
}
|
|
50
57
|
catch (error) {
|
|
51
58
|
if (__DEV__) {
|
|
52
59
|
console.warn(
|
|
53
60
|
// @ts-ignore
|
|
54
|
-
`${
|
|
61
|
+
`${SHELL_COLORS.BG_RED}AMA.${SHELL_COLORS.RESET} ${SHELL_COLORS.BLUE}useFocus${SHELL_COLORS.RESET}: ${SHELL_COLORS.YELLOW}Error finding node handle${SHELL_COLORS.RESET} \n`, error);
|
|
55
62
|
}
|
|
56
63
|
}
|
|
57
64
|
});
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export { AutofocusContainer, type AutofocusContainerProps, } from './components/AutofocusContainer';
|
|
2
2
|
export { AMAProvider, useAMAContext, type AMAContextValue, type AMADevContextValue, type AMAProdContextValue, } from './components/AMAProvider';
|
|
3
3
|
export { HideChildrenFromAccessibilityTree } from './components/HideChildrenFromAccessibilityTree';
|
|
4
|
-
export { useButtonChecks } from './hooks/useButtonChecks';
|
|
5
|
-
export { useChecks } from './hooks/useChecks';
|
|
6
4
|
export { useFocus } from './hooks/useFocus';
|
|
7
5
|
export { useTimedAction } from './hooks/useTimedAction';
|
|
6
|
+
export { default } from './ReactNativeAmaModule';
|
|
7
|
+
export { default as ReactNativeAmaView } from './ReactNativeAmaView';
|
|
8
|
+
export * from './ReactNativeAma.types';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
17
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
|
+
};
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.ReactNativeAmaView = exports.default = exports.useTimedAction = exports.useFocus = exports.HideChildrenFromAccessibilityTree = exports.useAMAContext = exports.AMAProvider = exports.AutofocusContainer = void 0;
|
|
21
|
+
// Components
|
|
22
|
+
var AutofocusContainer_1 = require("./components/AutofocusContainer");
|
|
23
|
+
Object.defineProperty(exports, "AutofocusContainer", { enumerable: true, get: function () { return AutofocusContainer_1.AutofocusContainer; } });
|
|
24
|
+
var AMAProvider_1 = require("./components/AMAProvider");
|
|
25
|
+
Object.defineProperty(exports, "AMAProvider", { enumerable: true, get: function () { return AMAProvider_1.AMAProvider; } });
|
|
26
|
+
Object.defineProperty(exports, "useAMAContext", { enumerable: true, get: function () { return AMAProvider_1.useAMAContext; } });
|
|
27
|
+
var HideChildrenFromAccessibilityTree_1 = require("./components/HideChildrenFromAccessibilityTree");
|
|
28
|
+
Object.defineProperty(exports, "HideChildrenFromAccessibilityTree", { enumerable: true, get: function () { return HideChildrenFromAccessibilityTree_1.HideChildrenFromAccessibilityTree; } });
|
|
29
|
+
// Hooks
|
|
30
|
+
var useFocus_1 = require("./hooks/useFocus");
|
|
31
|
+
Object.defineProperty(exports, "useFocus", { enumerable: true, get: function () { return useFocus_1.useFocus; } });
|
|
32
|
+
var useTimedAction_1 = require("./hooks/useTimedAction");
|
|
33
|
+
Object.defineProperty(exports, "useTimedAction", { enumerable: true, get: function () { return useTimedAction_1.useTimedAction; } });
|
|
34
|
+
var ReactNativeAmaModule_1 = require("./ReactNativeAmaModule");
|
|
35
|
+
Object.defineProperty(exports, "default", { enumerable: true, get: function () { return __importDefault(ReactNativeAmaModule_1).default; } });
|
|
36
|
+
var ReactNativeAmaView_1 = require("./ReactNativeAmaView");
|
|
37
|
+
Object.defineProperty(exports, "ReactNativeAmaView", { enumerable: true, get: function () { return __importDefault(ReactNativeAmaView_1).default; } });
|
|
38
|
+
__exportStar(require("./ReactNativeAma.types"), exports);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkAriaLabel = void 0;
|
|
4
|
+
const checkAriaLabel = (node) => {
|
|
5
|
+
const { ariaLabel } = node;
|
|
6
|
+
if (['Pressable', 'TextInput'].includes(node.type) && !ariaLabel) {
|
|
7
|
+
return {
|
|
8
|
+
rule: 'NO_ACCESSIBILITY_LABEL',
|
|
9
|
+
label: node.ariaLabel,
|
|
10
|
+
viewId: node.viewId,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
return null;
|
|
14
|
+
};
|
|
15
|
+
exports.checkAriaLabel = checkAriaLabel;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkAriaRole = void 0;
|
|
4
|
+
const react_native_1 = require("react-native");
|
|
5
|
+
const checkAriaRole = (node) => {
|
|
6
|
+
var _a;
|
|
7
|
+
const { ariaRole, traits } = node;
|
|
8
|
+
const filteredTraits = traits === null || traits === void 0 ? void 0 : traits.filter((trait) => trait !== 'notEnabled' && trait !== 'selected');
|
|
9
|
+
const a11yRole = (_a = ariaRole !== null && ariaRole !== void 0 ? ariaRole : filteredTraits === null || filteredTraits === void 0 ? void 0 : filteredTraits.join('')) !== null && _a !== void 0 ? _a : '';
|
|
10
|
+
if (node.type !== 'Pressable') {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
if (!a11yRole) {
|
|
14
|
+
return {
|
|
15
|
+
rule: 'NO_ACCESSIBILITY_ROLE',
|
|
16
|
+
label: node.ariaLabel,
|
|
17
|
+
viewId: node.viewId,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
if (!checkPlatformSupportsRole(a11yRole, react_native_1.Platform.OS)) {
|
|
21
|
+
return {
|
|
22
|
+
label: node.ariaLabel,
|
|
23
|
+
viewId: node.viewId,
|
|
24
|
+
extra: `"${a11yRole}" is not a native role for "${react_native_1.Platform.OS}"`,
|
|
25
|
+
rule: 'INCOMPATIBLE_ACCESSIBILITY_ROLE',
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
};
|
|
30
|
+
exports.checkAriaRole = checkAriaRole;
|
|
31
|
+
const checkPlatformSupportsRole = (role, platform) => {
|
|
32
|
+
const supportedPlatforms = MAPPED_ROLE_CHECKS[role.toLocaleLowerCase()] || [];
|
|
33
|
+
return supportedPlatforms.includes(platform);
|
|
34
|
+
};
|
|
35
|
+
const MAPPED_ROLE_CHECKS = {
|
|
36
|
+
none: ['ios', 'android'],
|
|
37
|
+
button: ['ios', 'android'],
|
|
38
|
+
switch: ['ios', 'android'],
|
|
39
|
+
checkbox: ['android'],
|
|
40
|
+
tab: ['android', 'ios'],
|
|
41
|
+
togglebutton: ['android'],
|
|
42
|
+
radio: ['android'],
|
|
43
|
+
adjustable: ['ios'],
|
|
44
|
+
link: ['ios', 'android'],
|
|
45
|
+
search: ['ios', 'android'],
|
|
46
|
+
header: ['ios', 'android'],
|
|
47
|
+
image: ['ios', 'android'],
|
|
48
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkContrast = void 0;
|
|
4
|
+
const ignoreContrastCheck_1 = require("../utils/ignoreContrastCheck");
|
|
5
|
+
const getRuleAction_1 = require("../utils/getRuleAction");
|
|
6
|
+
function hexToRgb(hex) {
|
|
7
|
+
if (!hex || typeof hex !== 'string') {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
|
|
11
|
+
hex = hex.replace(shorthandRegex, (_, r, g, b) => r + r + g + g + b + b);
|
|
12
|
+
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
13
|
+
return result
|
|
14
|
+
? {
|
|
15
|
+
r: parseInt(result[1], 16),
|
|
16
|
+
g: parseInt(result[2], 16),
|
|
17
|
+
b: parseInt(result[3], 16),
|
|
18
|
+
}
|
|
19
|
+
: null;
|
|
20
|
+
}
|
|
21
|
+
function getLuminance(hex) {
|
|
22
|
+
const rgb = hexToRgb(hex);
|
|
23
|
+
if (!rgb) {
|
|
24
|
+
return 0;
|
|
25
|
+
}
|
|
26
|
+
const [r, g, b] = [rgb.r, rgb.g, rgb.b].map((v) => {
|
|
27
|
+
v /= 255; // Normalize to 0-1 range
|
|
28
|
+
return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
|
|
29
|
+
});
|
|
30
|
+
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|
31
|
+
}
|
|
32
|
+
function getContrastRatio(fgHex, bgHex) {
|
|
33
|
+
const lum1 = getLuminance(fgHex);
|
|
34
|
+
const lum2 = getLuminance(bgHex);
|
|
35
|
+
const lighter = Math.max(lum1, lum2);
|
|
36
|
+
const darker = Math.min(lum1, lum2);
|
|
37
|
+
return (lighter + 0.05) / (darker + 0.05);
|
|
38
|
+
}
|
|
39
|
+
const checkContrast = (node) => {
|
|
40
|
+
const { fg, bg, fontSize, isBold, isEnabled } = node;
|
|
41
|
+
if (!isEnabled && (ignoreContrastCheck_1.shouldIgnoreContrastCheckForDisabledElement === null || ignoreContrastCheck_1.shouldIgnoreContrastCheckForDisabledElement === void 0 ? void 0 : (0, ignoreContrastCheck_1.shouldIgnoreContrastCheckForDisabledElement)())) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* We need to skip node without content as it might be an icon only Button.
|
|
46
|
+
* In this case we can't perform a contrast check as is hard to perform
|
|
47
|
+
* a contrast check on SVGs
|
|
48
|
+
*/
|
|
49
|
+
if (!fg ||
|
|
50
|
+
!bg ||
|
|
51
|
+
!node.content ||
|
|
52
|
+
node.type === 'TextInput' ||
|
|
53
|
+
!node.isAccessible) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
const contrastRatio = getContrastRatio(fg, bg);
|
|
57
|
+
// Determine if the text is "large" according to WCAG standards.
|
|
58
|
+
// 18pt is considered large, or 14pt if bold.
|
|
59
|
+
const isLargeText = fontSize && (fontSize >= 18 || (fontSize >= 14 && isBold));
|
|
60
|
+
const requiredRatioAA = isLargeText ? 3.0 : 4.5;
|
|
61
|
+
const requiredRatioAAA = isLargeText ? 4.5 : 7.0;
|
|
62
|
+
const passesAA = contrastRatio >= requiredRatioAA;
|
|
63
|
+
const passesAAA = contrastRatio >= requiredRatioAAA;
|
|
64
|
+
const aaaAction = getRuleAction_1.getRuleAction === null || getRuleAction_1.getRuleAction === void 0 ? void 0 : (0, getRuleAction_1.getRuleAction)('CONTRAST_FAILED_AAA');
|
|
65
|
+
const shouldCheckAAA = aaaAction && aaaAction !== 'PLEASE_FORGIVE_ME';
|
|
66
|
+
if (!passesAAA && shouldCheckAAA) {
|
|
67
|
+
return {
|
|
68
|
+
label: node.ariaLabel,
|
|
69
|
+
viewId: node.viewId,
|
|
70
|
+
rule: 'CONTRAST_FAILED_AAA',
|
|
71
|
+
extra: `The color contrast between the foreground (${fg}) and background (${bg}) is ${contrastRatio.toFixed(2)}, which is below the required minimum of ${requiredRatioAAA}.`,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
if (!passesAA) {
|
|
75
|
+
return {
|
|
76
|
+
label: node.ariaLabel,
|
|
77
|
+
viewId: node.viewId,
|
|
78
|
+
rule: 'CONTRAST_FAILED',
|
|
79
|
+
extra: `The color contrast between the foreground (${fg}) and background (${bg}) is ${contrastRatio.toFixed(2)}, which is below the required minimum of ${requiredRatioAA}.`,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
};
|
|
84
|
+
exports.checkContrast = checkContrast;
|