@react-native-ama/core 1.2.1 → 2.0.0-beta.1

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.
Files changed (179) hide show
  1. package/dist/ReactNativeAma.types.d.ts +66 -0
  2. package/dist/ReactNativeAma.types.js +2 -0
  3. package/dist/ReactNativeAmaModule.d.ts +11 -0
  4. package/dist/ReactNativeAmaModule.js +5 -0
  5. package/dist/ReactNativeAmaModule.web.d.ts +9 -0
  6. package/dist/ReactNativeAmaModule.web.js +27 -0
  7. package/dist/ReactNativeAmaView.d.ts +3 -0
  8. package/dist/ReactNativeAmaView.js +32 -0
  9. package/dist/ReactNativeAmaView.web.d.ts +3 -0
  10. package/dist/ReactNativeAmaView.web.js +34 -0
  11. package/dist/{src/components → components}/AMAProvider.d.ts +4 -2
  12. package/dist/{src/components → components}/AMAProvider.js +19 -45
  13. package/dist/{src/components → components}/AutofocusContainer.d.ts +2 -1
  14. package/dist/{src/components → components}/HideChildrenFromAccessibilityTree.d.ts +1 -1
  15. package/dist/{src/components → components}/HideChildrenFromAccessibilityTree.js +7 -5
  16. package/dist/{src/hooks → hooks}/useFocus.js +10 -3
  17. package/dist/{src/index.d.ts → index.d.ts} +3 -2
  18. package/dist/index.js +38 -0
  19. package/dist/internals/checks/checkAriaLabel.d.ts +3 -0
  20. package/dist/internals/checks/checkAriaLabel.js +15 -0
  21. package/dist/internals/checks/checkAriaRole.d.ts +3 -0
  22. package/dist/internals/checks/checkAriaRole.js +48 -0
  23. package/dist/internals/checks/checkContrast.d.ts +3 -0
  24. package/dist/internals/checks/checkContrast.js +84 -0
  25. package/dist/internals/checks/checkImageAlt.d.ts +3 -0
  26. package/dist/internals/checks/checkImageAlt.js +20 -0
  27. package/dist/internals/checks/checkIsUppercase.d.ts +8 -0
  28. package/dist/internals/checks/checkIsUppercase.js +30 -0
  29. package/dist/internals/checks/checkLongNumber.d.ts +3 -0
  30. package/dist/internals/checks/checkLongNumber.js +31 -0
  31. package/dist/internals/checks/checkMinimumSize.d.ts +3 -0
  32. package/dist/internals/checks/checkMinimumSize.js +22 -0
  33. package/dist/internals/checks/checkTextInput.d.ts +3 -0
  34. package/dist/internals/checks/checkTextInput.js +51 -0
  35. package/dist/internals/checks/performChecks.d.ts +3 -0
  36. package/dist/internals/checks/performChecks.js +23 -0
  37. package/dist/internals/components/AMAErrorOverlay.d.ts +5 -0
  38. package/dist/internals/components/AMAErrorOverlay.js +334 -0
  39. package/dist/internals/components/AMARuleError.d.ts +7 -0
  40. package/dist/internals/components/AMARuleError.js +161 -0
  41. package/dist/internals/config.d.ts +23 -0
  42. package/dist/internals/config.js +33 -0
  43. package/dist/internals/types.d.ts +9 -0
  44. package/dist/internals/types.js +2 -0
  45. package/dist/internals/useAMADev.d.ts +8 -0
  46. package/dist/internals/useAMADev.dev.d.ts +2 -0
  47. package/dist/internals/useAMADev.dev.js +110 -0
  48. package/dist/internals/useAMADev.js +6 -0
  49. package/dist/internals/useAMADevNodeChecks.dev.d.ts +16 -0
  50. package/dist/internals/useAMADevNodeChecks.dev.js +115 -0
  51. package/dist/internals/useAMADevUiInteraction.dev.d.ts +7 -0
  52. package/dist/internals/useAMADevUiInteraction.dev.js +100 -0
  53. package/dist/internals/utils/amaClearHighlight.d.ts +2 -0
  54. package/dist/internals/utils/amaClearHighlight.js +12 -0
  55. package/dist/internals/utils/amaHighlightComponent.d.ts +3 -0
  56. package/dist/internals/utils/amaHighlightComponent.js +51 -0
  57. package/dist/internals/utils/constants.d.ts +3 -0
  58. package/dist/internals/utils/constants.js +32 -0
  59. package/dist/internals/utils/getErrorColor.d.ts +2 -0
  60. package/dist/internals/utils/getErrorColor.js +10 -0
  61. package/dist/internals/utils/getRuleAction.d.ts +2 -0
  62. package/dist/internals/utils/getRuleAction.js +40 -0
  63. package/dist/internals/utils/getRuleErrorInfo.d.ts +7 -0
  64. package/dist/internals/utils/getRuleErrorInfo.js +19 -0
  65. package/dist/internals/utils/ignoreContrastCheck.d.ts +1 -0
  66. package/dist/internals/utils/ignoreContrastCheck.js +15 -0
  67. package/dist/internals/utils/interpolateAnimationStates.d.ts +2 -0
  68. package/dist/internals/utils/interpolateAnimationStates.js +43 -0
  69. package/dist/internals/utils/isA11yLabelAllowed.d.ts +1 -0
  70. package/dist/internals/utils/isA11yLabelAllowed.js +14 -0
  71. package/dist/internals/utils/isRuleDisabled.d.ts +2 -0
  72. package/dist/internals/utils/isRuleDisabled.js +10 -0
  73. package/dist/internals/utils/logError.d.ts +2 -0
  74. package/dist/internals/utils/logError.js +36 -0
  75. package/dist/internals/utils/logFoundIssues.d.ts +2 -0
  76. package/dist/internals/utils/logFoundIssues.js +23 -0
  77. package/dist/internals/utils/logger.d.ts +6 -0
  78. package/dist/internals/utils/logger.js +15 -0
  79. package/dist/internals/utils/minimumTouchableSize.d.ts +1 -0
  80. package/dist/internals/utils/minimumTouchableSize.js +9 -0
  81. package/dist/internals/utils/platformHelpers.d.ts +2 -0
  82. package/dist/internals/utils/platformHelpers.js +6 -0
  83. package/dist/internals/utils/rules.d.ts +22 -0
  84. package/dist/internals/utils/rules.js +253 -0
  85. package/dist/scripts/create-config.js +4 -3
  86. package/package.json +62 -20
  87. package/src/ReactNativeAma.types.ts +70 -0
  88. package/src/ReactNativeAmaModule.ts +18 -0
  89. package/src/ReactNativeAmaModule.web.ts +14 -0
  90. package/src/ReactNativeAmaView.tsx +9 -0
  91. package/src/ReactNativeAmaView.web.tsx +15 -0
  92. package/src/__mocks__/ReactNativeAmaModule.ts +9 -0
  93. package/src/components/AMAProvider.integration.test.tsx +3 -96
  94. package/src/components/AMAProvider.test.tsx +9 -4
  95. package/src/components/AMAProvider.tsx +40 -76
  96. package/src/components/AutofocusContainer.test.tsx +4 -5
  97. package/src/components/AutofocusContainer.tsx +20 -5
  98. package/src/components/HideChildrenFromAccessibilityTree.test.tsx +23 -39
  99. package/src/components/HideChildrenFromAccessibilityTree.tsx +12 -11
  100. package/src/hooks/useFocus.test.ts +20 -20
  101. package/src/hooks/useFocus.ts +14 -6
  102. package/src/hooks/useTimedAction.android.test.ts +0 -1
  103. package/src/hooks/useTimedAction.ios.test.ts +0 -1
  104. package/src/hooks/useTimedAction.ts +0 -1
  105. package/src/index.ts +4 -2
  106. package/src/internals/checks/checkAriaLabel.test.ts +165 -0
  107. package/src/internals/checks/checkAriaLabel.ts +16 -0
  108. package/src/internals/checks/checkAriaRole.test.ts +429 -0
  109. package/src/internals/checks/checkAriaRole.ts +60 -0
  110. package/src/internals/checks/checkContrast.test.ts +278 -0
  111. package/src/internals/checks/checkContrast.ts +109 -0
  112. package/src/internals/checks/checkImageAlt.test.ts +125 -0
  113. package/src/internals/checks/checkImageAlt.ts +23 -0
  114. package/src/internals/checks/checkIsUppercase.test.ts +399 -0
  115. package/src/internals/checks/checkIsUppercase.ts +46 -0
  116. package/src/internals/checks/checkLongNumber.test.ts +111 -0
  117. package/src/internals/checks/checkLongNumber.ts +34 -0
  118. package/src/internals/checks/checkMinimumSize.test.ts +67 -0
  119. package/src/internals/checks/checkMinimumSize.ts +25 -0
  120. package/src/internals/checks/checkTextInput.ts +65 -0
  121. package/src/internals/checks/performChecks.test.ts +171 -0
  122. package/src/internals/checks/performChecks.ts +24 -0
  123. package/src/internals/components/AMAErrorOverlay.test.tsx +139 -0
  124. package/src/internals/components/AMAErrorOverlay.tsx +451 -0
  125. package/src/internals/components/AMARuleError.test.tsx +93 -0
  126. package/src/internals/components/AMARuleError.tsx +225 -0
  127. package/src/internals/config.ts +58 -0
  128. package/src/internals/types.ts +11 -0
  129. package/src/internals/useAMADev.dev.ts +153 -0
  130. package/src/internals/useAMADev.test.ts +260 -0
  131. package/src/internals/useAMADev.ts +17 -0
  132. package/src/internals/useAMADevNodeChecks.dev.ts +178 -0
  133. package/src/internals/useAMADevUiInteraction.dev.ts +164 -0
  134. package/src/internals/utils/amaClearHighlight.test.ts +21 -0
  135. package/src/internals/utils/amaClearHighlight.ts +8 -0
  136. package/src/internals/utils/amaHighlightComponent.test.ts +74 -0
  137. package/src/internals/utils/amaHighlightComponent.ts +46 -0
  138. package/src/internals/utils/constants.ts +33 -0
  139. package/src/internals/utils/devMode.test.ts +99 -0
  140. package/src/internals/utils/getErrorColor.test.ts +18 -0
  141. package/src/internals/utils/getErrorColor.ts +8 -0
  142. package/src/internals/utils/getRuleAction.ts +13 -0
  143. package/src/internals/utils/getRuleErrorInfo.test.ts +59 -0
  144. package/src/internals/utils/getRuleErrorInfo.ts +26 -0
  145. package/src/internals/utils/ignoreContrastCheck.test.ts +34 -0
  146. package/src/internals/utils/ignoreContrastCheck.ts +11 -0
  147. package/src/internals/utils/interpolateAnimation.test.ts +176 -0
  148. package/src/internals/utils/interpolateAnimationStates.ts +55 -0
  149. package/src/internals/utils/isA11yLabelAllowed.test.ts +39 -0
  150. package/src/internals/utils/isA11yLabelAllowed.ts +10 -0
  151. package/src/internals/utils/isRuleDisabled.test.ts +35 -0
  152. package/src/internals/utils/isRuleDisabled.ts +10 -0
  153. package/src/internals/utils/logError.test.ts +148 -0
  154. package/src/internals/utils/logError.ts +41 -0
  155. package/src/internals/utils/logFoundIssues.test.ts +98 -0
  156. package/src/internals/utils/logFoundIssues.ts +22 -0
  157. package/src/internals/utils/logger.test.ts +26 -0
  158. package/src/internals/utils/logger.ts +15 -0
  159. package/src/internals/utils/loggerMethods.test.ts +38 -0
  160. package/src/internals/utils/minimumTouchableSize.test.ts +28 -0
  161. package/src/internals/utils/minimumTouchableSize.tsx +9 -0
  162. package/src/internals/utils/platformHelpers.test.ts +11 -0
  163. package/src/internals/utils/platformHelpers.ts +4 -0
  164. package/src/internals/utils/rules.ts +363 -0
  165. package/src/scripts/create-config.ts +21 -0
  166. package/dist/src/hooks/useButtonChecks.d.ts +0 -6
  167. package/dist/src/hooks/useButtonChecks.js +0 -51
  168. package/dist/src/hooks/useChecks.d.ts +0 -15
  169. package/dist/src/hooks/useChecks.js +0 -152
  170. package/dist/src/index.js +0 -20
  171. package/src/hooks/useButtonChecks.ts +0 -73
  172. package/src/hooks/useChecks.test.ts +0 -214
  173. package/src/hooks/useChecks.ts +0 -207
  174. /package/dist/{src/components → components}/AutofocusContainer.js +0 -0
  175. /package/dist/{src/hooks → hooks}/useFocus.d.ts +0 -0
  176. /package/dist/{src/hooks → hooks}/useTimedAction.d.ts +0 -0
  177. /package/dist/{src/hooks → hooks}/useTimedAction.js +0 -0
  178. /package/dist/{src/utils → utils}/numerify.d.ts +0 -0
  179. /package/dist/{src/utils → utils}/numerify.js +0 -0
@@ -0,0 +1,161 @@
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.AMARuleError = void 0;
7
+ /* eslint-disable react-native/no-inline-styles */
8
+ const react_1 = __importDefault(require("react"));
9
+ const react_native_1 = require("react-native");
10
+ const rules_1 = require("../utils/rules");
11
+ const SEVERITIES = __DEV__
12
+ ? {
13
+ Serious: 'Serious',
14
+ Critical: 'Critical',
15
+ Warning: 'Warning',
16
+ }
17
+ : null;
18
+ const REGEX_MARKDOWN = /(`[^`]+`|\*\*[^*]+\*\*)/g;
19
+ exports.AMARuleError = __DEV__
20
+ ? ({ issue, maxHeight, onClose, }) => {
21
+ const ruleHelp = rules_1.RULES_HELP[issue.rule];
22
+ const COLOR_TOKEN_REGEX = /(\(#[0-9A-Fa-f]{3,8}\))/g;
23
+ const renderMarkdown = (text) => {
24
+ const parts = text.split(REGEX_MARKDOWN);
25
+ return parts.map((part, index) => {
26
+ if (part.startsWith('`') && part.endsWith('`') && Code) {
27
+ return <Code key={index}>{part.slice(1, -1)}</Code>;
28
+ }
29
+ if (part.startsWith('**') && part.endsWith('**')) {
30
+ return (<react_native_1.Text key={index} style={[styles === null || styles === void 0 ? void 0 : styles.text, styles === null || styles === void 0 ? void 0 : styles.bold]}>
31
+ {part.slice(2, -2)}
32
+ </react_native_1.Text>);
33
+ }
34
+ return (<react_native_1.Text key={index} style={styles === null || styles === void 0 ? void 0 : styles.text}>
35
+ {part}
36
+ </react_native_1.Text>);
37
+ });
38
+ };
39
+ const renderHowToFix = (text) => {
40
+ if (typeof text === 'string') {
41
+ return <react_native_1.Text style={styles === null || styles === void 0 ? void 0 : styles.text}>{renderMarkdown(text)}</react_native_1.Text>;
42
+ }
43
+ return (<react_native_1.View>
44
+ {text.map((value, index) => {
45
+ return (<react_native_1.Text key={index} style={styles.text}>
46
+ {renderMarkdown(value)}
47
+ </react_native_1.Text>);
48
+ })}
49
+ </react_native_1.View>);
50
+ };
51
+ const renderTextWithColorSwatches = (text) => {
52
+ const parts = text.split(COLOR_TOKEN_REGEX);
53
+ return parts.map((part, index) => {
54
+ if (part.startsWith('(#') && part.endsWith(')')) {
55
+ const color = part.slice(1, -1);
56
+ return (<react_1.default.Fragment key={index}>
57
+ <react_native_1.Text style={styles === null || styles === void 0 ? void 0 : styles.text} importantForAccessibility="no-hide-descendants" accessibilityElementsHidden>
58
+ (
59
+ </react_native_1.Text>
60
+ <react_native_1.Text style={styles.swatchFrame} importantForAccessibility="no-hide-descendants" accessibilityElementsHidden>
61
+ <react_native_1.Text style={[styles.swatchGlyph, { color }]} importantForAccessibility="no-hide-descendants" accessibilityElementsHidden>
62
+
63
+ </react_native_1.Text>
64
+ </react_native_1.Text>
65
+ <react_native_1.Text style={styles === null || styles === void 0 ? void 0 : styles.text} importantForAccessibility="no-hide-descendants" accessibilityElementsHidden accessible={false}>
66
+ {` ${color}`}
67
+ </react_native_1.Text>
68
+ <react_native_1.Text style={styles === null || styles === void 0 ? void 0 : styles.text} importantForAccessibility="no-hide-descendants" accessibilityElementsHidden>
69
+ )
70
+ </react_native_1.Text>
71
+ </react_1.default.Fragment>);
72
+ }
73
+ return (<react_native_1.Text key={index} style={styles === null || styles === void 0 ? void 0 : styles.text}>
74
+ {part}
75
+ </react_native_1.Text>);
76
+ });
77
+ };
78
+ return (<react_native_1.ScrollView style={{ maxHeight, flex: 1, width: '100%', padding: 12 }}>
79
+ <react_native_1.View style={styles.row}>
80
+ <react_native_1.Text style={styles.bold} aria-role="header">
81
+ {SEVERITIES[ruleHelp.severity]}:
82
+ </react_native_1.Text>
83
+ <react_native_1.Text style={styles.flex}>{ruleHelp.issue}</react_native_1.Text>
84
+ <react_native_1.Pressable hitSlop={{ left: 18, top: 18, bottom: 18, right: 18 }} role="button" aria-label="Close Error information" onPress={onClose}>
85
+ <react_native_1.Text> ✖ </react_native_1.Text>
86
+ </react_native_1.Pressable>
87
+ </react_native_1.View>
88
+
89
+ <react_native_1.Text style={[styles.bold, styles === null || styles === void 0 ? void 0 : styles.full]} aria-role="header">
90
+ Why this matters:
91
+ </react_native_1.Text>
92
+ <react_native_1.View style={[styles.row, styles === null || styles === void 0 ? void 0 : styles.column]}>
93
+ <react_native_1.Text style={styles === null || styles === void 0 ? void 0 : styles.text}>{ruleHelp.message}</react_native_1.Text>
94
+ {issue.extra ? (<react_native_1.View style={styles.extraInline}>
95
+ {renderTextWithColorSwatches(String(issue.extra))}
96
+ </react_native_1.View>) : null}
97
+ </react_native_1.View>
98
+ <react_native_1.Text style={[styles.bold, styles === null || styles === void 0 ? void 0 : styles.full]} aria-role="header">
99
+ How to fix:
100
+ </react_native_1.Text>
101
+ <react_native_1.View style={styles.row}>{renderHowToFix(ruleHelp.howToFix)}</react_native_1.View>
102
+ </react_native_1.ScrollView>);
103
+ }
104
+ : null;
105
+ const Code = __DEV__
106
+ ? ({ children }) => {
107
+ const code = typeof children === 'string' ? children.replace(/`/g, '') : children;
108
+ return <react_native_1.Text style={styles.code}> {code} </react_native_1.Text>;
109
+ }
110
+ : null;
111
+ const styles = __DEV__
112
+ ? react_native_1.StyleSheet.create({
113
+ row: {
114
+ flexDirection: 'row',
115
+ alignContent: 'center',
116
+ alignItems: 'center',
117
+ fontSize: 14,
118
+ width: '100%',
119
+ marginBottom: 12,
120
+ flex: 1,
121
+ },
122
+ bold: {
123
+ fontSize: 14,
124
+ fontWeight: 600,
125
+ paddingRight: 12,
126
+ },
127
+ full: {
128
+ width: '100%',
129
+ marginBottom: 4,
130
+ },
131
+ text: {
132
+ lineHeight: 18,
133
+ paddingBottom: 4,
134
+ },
135
+ column: {
136
+ flexDirection: 'column',
137
+ },
138
+ flex: {
139
+ flex: 1,
140
+ },
141
+ code: {
142
+ backgroundColor: '#333',
143
+ color: '#fff',
144
+ },
145
+ extraInline: {
146
+ flexDirection: 'row',
147
+ flexWrap: 'wrap',
148
+ alignItems: 'center',
149
+ },
150
+ swatchFrame: {
151
+ backgroundColor: '#000',
152
+ paddingHorizontal: 2,
153
+ marginHorizontal: 2,
154
+ lineHeight: 14,
155
+ },
156
+ swatchGlyph: {
157
+ fontSize: 11,
158
+ lineHeight: 14,
159
+ },
160
+ })
161
+ : null;
@@ -0,0 +1,23 @@
1
+ import { AmaRule, AmaRuleAction } from './utils/rules';
2
+ export declare const NON_OVERRIDABLE_RULES: string[] | undefined;
3
+ export type HighlightMode = 'border' | 'background' | 'both';
4
+ export type LogMode = 'always' | 'inspect';
5
+ export type AmaProjectConfig = {
6
+ rules: Record<Partial<AmaRule> | 'CONTRAST_CHECKER_MAX_DEPTH' | 'IGNORE_CONTRAST_FOR_DISABLED_ELEMENTS', AmaRuleAction> | null;
7
+ accessibilityLabelExceptions: string[];
8
+ highlight: {
9
+ mode: HighlightMode;
10
+ borderWidth?: number;
11
+ gap?: number;
12
+ };
13
+ log: LogMode;
14
+ uppercaseMinLength: number;
15
+ longNumberMinLength: number;
16
+ checks: {
17
+ ui: boolean;
18
+ forms: boolean;
19
+ delay: number;
20
+ };
21
+ };
22
+ declare let projectRules: AmaProjectConfig;
23
+ export default projectRules;
@@ -0,0 +1,33 @@
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.NON_OVERRIDABLE_RULES = void 0;
7
+ const logger_1 = __importDefault(require("./utils/logger"));
8
+ exports.NON_OVERRIDABLE_RULES = __DEV__
9
+ ? [
10
+ 'NO_ACCESSIBILITY_ROLE',
11
+ 'NO_ACCESSIBILITY_LABEL',
12
+ 'NO_KEYBOARD_TRAP',
13
+ 'NO_UNDEFINED',
14
+ 'INPUT_HAS_NO_VISIBLE_LABEL',
15
+ 'FLATLIST_NO_COUNT_IN_PLURAL_MESSAGE',
16
+ 'BOTTOM_SHEET_CLOSE_ACTION',
17
+ 'INCOMPATIBLE_ACCESSIBILITY_STATE',
18
+ 'INCOMPATIBLE_ACCESSIBILITY_ROLE',
19
+ ]
20
+ : undefined;
21
+ const defaultRules = require('./../../ama.config.json');
22
+ let projectRules = defaultRules;
23
+ try {
24
+ // look upwards to user's project root
25
+ const userDefinedRules = require('./../../../../ama.config.json');
26
+ projectRules = Object.assign(projectRules, userDefinedRules);
27
+ logger_1.default === null || logger_1.default === void 0 ? void 0 : logger_1.default.log("Using project's config file");
28
+ }
29
+ catch (_) {
30
+ logger_1.default === null || logger_1.default === void 0 ? void 0 : logger_1.default.log('Project config not found, using default one!');
31
+ }
32
+ logger_1.default === null || logger_1.default === void 0 ? void 0 : logger_1.default.log(JSON.stringify(projectRules, null, 2));
33
+ exports.default = projectRules;
@@ -0,0 +1,9 @@
1
+ import { AmaRule, AmaRuleAction } from './utils/rules';
2
+ export type { AmaRule, AmaRuleAction };
3
+ export type Position = [number, number, number, number];
4
+ export type AmaError = {
5
+ rule: AmaRule;
6
+ extra?: any;
7
+ label?: string;
8
+ viewId: number;
9
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,8 @@
1
+ import type { RefObject } from 'react';
2
+ import type { AmaError, AmaRule } from './types';
3
+ export type UseAMADevValue = {
4
+ issues: AmaError[];
5
+ trackError: (rule: AmaRule, ref?: RefObject<any>) => void;
6
+ };
7
+ export type UseAMADev = () => UseAMADevValue;
8
+ export declare const useAMADev: UseAMADev | null;
@@ -0,0 +1,2 @@
1
+ import type { UseAMADev } from './useAMADev';
2
+ export declare const useAMADev: UseAMADev | null;
@@ -0,0 +1,110 @@
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.useAMADev = void 0;
7
+ const react_1 = require("react");
8
+ const react_native_1 = require("react-native");
9
+ const ReactNativeAmaModule_1 = __importDefault(require("../ReactNativeAmaModule"));
10
+ const config_1 = __importDefault(require("./config"));
11
+ const useAMADevNodeChecks_dev_1 = require("./useAMADevNodeChecks.dev");
12
+ const useAMADevUiInteraction_dev_1 = require("./useAMADevUiInteraction.dev");
13
+ const amaClearHighlight_1 = require("./utils/amaClearHighlight");
14
+ const logError_1 = require("./utils/logError");
15
+ const logger_1 = __importDefault(require("./utils/logger"));
16
+ const startAMA = __DEV__
17
+ ? () => {
18
+ var _a, _b;
19
+ logger_1.default === null || logger_1.default === void 0 ? void 0 : logger_1.default.log('👀 Start Monitoring 👀: ' + JSON.stringify(config_1.default.checks));
20
+ ReactNativeAmaModule_1.default.start(Object.assign(Object.assign({}, config_1.default.checks), { borderWidth: (_a = config_1.default.highlight) === null || _a === void 0 ? void 0 : _a.borderWidth, gap: (_b = config_1.default.highlight) === null || _b === void 0 ? void 0 : _b.gap }));
21
+ }
22
+ : null;
23
+ exports.useAMADev = __DEV__
24
+ ? () => {
25
+ const isMonitoring = (0, react_1.useRef)(true);
26
+ const lastNodesChecked = (0, react_1.useRef)({});
27
+ const previousNodeIssues = (0, react_1.useRef)([]);
28
+ const jsFailedChecks = (0, react_1.useRef)([]);
29
+ const highlightedIssues = (0, react_1.useRef)({});
30
+ const issuesRef = (0, react_1.useRef)([]);
31
+ const [issues, setIssues] = (0, react_1.useState)([]);
32
+ (0, react_1.useEffect)(() => {
33
+ issuesRef.current = issues;
34
+ }, [issues]);
35
+ const checkNodes = (nodesToCheck) => {
36
+ var _a;
37
+ lastNodesChecked.current = nodesToCheck;
38
+ const nodeIssues = (_a = useAMADevNodeChecks_dev_1.runNodeChecks === null || useAMADevNodeChecks_dev_1.runNodeChecks === void 0 ? void 0 : (0, useAMADevNodeChecks_dev_1.runNodeChecks)({
39
+ nodesToCheck,
40
+ previousNodeIssues: previousNodeIssues.current,
41
+ jsFailedChecks: jsFailedChecks.current,
42
+ highlightedIssues: highlightedIssues.current,
43
+ })) !== null && _a !== void 0 ? _a : [];
44
+ setIssues((currentIssues) => {
45
+ var _a;
46
+ return (_a = useAMADevNodeChecks_dev_1.getNodeIssueState === null || useAMADevNodeChecks_dev_1.getNodeIssueState === void 0 ? void 0 : (0, useAMADevNodeChecks_dev_1.getNodeIssueState)(currentIssues, nodeIssues, nodesToCheck)) !== null && _a !== void 0 ? _a : currentIssues;
47
+ });
48
+ previousNodeIssues.current = nodeIssues;
49
+ };
50
+ const checkResultUiInteraction = (data) => {
51
+ var _a;
52
+ if (!data) {
53
+ return;
54
+ }
55
+ const itemsToFlag = Array.from((_a = useAMADevUiInteraction_dev_1.getItemsWithNoStateUpdated === null || useAMADevUiInteraction_dev_1.getItemsWithNoStateUpdated === void 0 ? void 0 : (0, useAMADevUiInteraction_dev_1.getItemsWithNoStateUpdated)(data, lastNodesChecked.current)) !== null && _a !== void 0 ? _a : []);
56
+ setIssues((prevIssues) => {
57
+ var _a;
58
+ return (_a = useAMADevUiInteraction_dev_1.syncUiInteractionIssues === null || useAMADevUiInteraction_dev_1.syncUiInteractionIssues === void 0 ? void 0 : (0, useAMADevUiInteraction_dev_1.syncUiInteractionIssues)(prevIssues, itemsToFlag, data.rootTag)) !== null && _a !== void 0 ? _a : prevIssues;
59
+ });
60
+ };
61
+ const stopAMA = () => {
62
+ logger_1.default === null || logger_1.default === void 0 ? void 0 : logger_1.default.log('[React Native AMA]: 🙈 Stop Monitoring 🙈');
63
+ for (const issue of issuesRef.current) {
64
+ amaClearHighlight_1.amaClearHighlight === null || amaClearHighlight_1.amaClearHighlight === void 0 ? void 0 : (0, amaClearHighlight_1.amaClearHighlight)(issue);
65
+ }
66
+ highlightedIssues.current = {};
67
+ ReactNativeAmaModule_1.default.stop();
68
+ };
69
+ (0, react_1.useEffect)(() => {
70
+ startAMA === null || startAMA === void 0 ? void 0 : startAMA();
71
+ const amaOnNodesListener = ReactNativeAmaModule_1.default.addListener('onAmaNodes', checkNodes);
72
+ const amaOnUiInteraction = ReactNativeAmaModule_1.default.addListener('onUIInteraction', checkResultUiInteraction);
73
+ return () => {
74
+ stopAMA();
75
+ amaOnNodesListener.remove();
76
+ amaOnUiInteraction.remove();
77
+ };
78
+ }, []);
79
+ const toggleReactNativeAMA = () => {
80
+ if (isMonitoring.current) {
81
+ stopAMA();
82
+ setIssues([]);
83
+ }
84
+ else {
85
+ startAMA === null || startAMA === void 0 ? void 0 : startAMA();
86
+ }
87
+ isMonitoring.current = !isMonitoring.current;
88
+ };
89
+ const trackError = (rule, ref) => {
90
+ var _a, _b;
91
+ const viewId = (_b = (_a = ref === null || ref === void 0 ? void 0 : ref.current) === null || _a === void 0 ? void 0 : _a.__nativeTag) !== null && _b !== void 0 ? _b : -1;
92
+ const issue = { rule, viewId };
93
+ logError_1.logError === null || logError_1.logError === void 0 ? void 0 : (0, logError_1.logError)(issue);
94
+ const alreadyTracked = jsFailedChecks.current.some((item) => item.viewId === viewId && item.rule === rule);
95
+ if (!alreadyTracked) {
96
+ jsFailedChecks.current.push(issue);
97
+ setIssues((currentIssues) => [...currentIssues, issue]);
98
+ checkNodes(lastNodesChecked.current);
99
+ }
100
+ };
101
+ (0, react_1.useEffect)(() => {
102
+ react_native_1.DevSettings.addMenuItem('Toggle React Native AMA', toggleReactNativeAMA);
103
+ // eslint-disable-next-line react-hooks/exhaustive-deps
104
+ }, []);
105
+ return {
106
+ issues,
107
+ trackError,
108
+ };
109
+ }
110
+ : null;
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useAMADev = void 0;
4
+ exports.useAMADev = __DEV__
5
+ ? require('./useAMADev.dev').useAMADev
6
+ : null;
@@ -0,0 +1,16 @@
1
+ import type { AmaNodes } from '../ReactNativeAma.types';
2
+ import type { AmaError } from './types';
3
+ type HighlightedIssues = Record<number, number>;
4
+ type RunNodeChecksOptions = {
5
+ nodesToCheck: AmaNodes;
6
+ previousNodeIssues: AmaError[];
7
+ jsFailedChecks: AmaError[];
8
+ highlightedIssues: HighlightedIssues;
9
+ };
10
+ type RunNodeChecks = (options: RunNodeChecksOptions) => AmaError[];
11
+ type CollectNodeIssues = (nodesToCheck: AmaNodes) => AmaError[];
12
+ type GetNodeIssueState = (currentIssues: AmaError[], nodeIssues: AmaError[], nodesToCheck: AmaNodes) => AmaError[];
13
+ export declare const runNodeChecks: RunNodeChecks | null;
14
+ export declare const collectNodeIssues: CollectNodeIssues | null;
15
+ export declare const getNodeIssueState: GetNodeIssueState | null;
16
+ export {};
@@ -0,0 +1,115 @@
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.getNodeIssueState = exports.collectNodeIssues = exports.runNodeChecks = void 0;
7
+ const checkTextInput_1 = require("./checks/checkTextInput");
8
+ const performChecks_1 = require("./checks/performChecks");
9
+ const config_1 = __importDefault(require("./config"));
10
+ const amaClearHighlight_1 = require("./utils/amaClearHighlight");
11
+ const amaHighlightComponent_1 = require("./utils/amaHighlightComponent");
12
+ const logFoundIssues_1 = require("./utils/logFoundIssues");
13
+ exports.runNodeChecks = __DEV__
14
+ ? ({ nodesToCheck, previousNodeIssues, jsFailedChecks, highlightedIssues }) => {
15
+ var _a;
16
+ const nodeIssues = (_a = exports.collectNodeIssues === null || exports.collectNodeIssues === void 0 ? void 0 : (0, exports.collectNodeIssues)(nodesToCheck)) !== null && _a !== void 0 ? _a : [];
17
+ if (previousNodeIssues.length) {
18
+ clearFixedNodeIssues === null || clearFixedNodeIssues === void 0 ? void 0 : clearFixedNodeIssues(previousNodeIssues, nodeIssues, jsFailedChecks);
19
+ }
20
+ logFoundIssues_1.logFoundIssues === null || logFoundIssues_1.logFoundIssues === void 0 ? void 0 : (0, logFoundIssues_1.logFoundIssues)(nodeIssues);
21
+ syncHighlightedIssues === null || syncHighlightedIssues === void 0 ? void 0 : syncHighlightedIssues(nodeIssues, jsFailedChecks, highlightedIssues);
22
+ return nodeIssues;
23
+ }
24
+ : null;
25
+ exports.collectNodeIssues = __DEV__
26
+ ? (nodesToCheck) => {
27
+ const nodes = Object.values(nodesToCheck);
28
+ let hasAtLeastOneHeader = false;
29
+ let hasTextInput = false;
30
+ const nodeIssues = [];
31
+ for (const node of nodes) {
32
+ if (node.type === 'TextInput') {
33
+ hasTextInput = true;
34
+ }
35
+ if (!hasAtLeastOneHeader && (isHeaderNode === null || isHeaderNode === void 0 ? void 0 : isHeaderNode(node))) {
36
+ hasAtLeastOneHeader = true;
37
+ }
38
+ nodeIssues.push(...(0, performChecks_1.performChecks)(node));
39
+ }
40
+ if (hasTextInput && config_1.default.checks.forms) {
41
+ nodeIssues.push(...(0, checkTextInput_1.checkTextInputs)(nodes));
42
+ }
43
+ if (!hasAtLeastOneHeader) {
44
+ nodeIssues.push({ rule: 'NO_HEADER_FOUND', viewId: -1 });
45
+ }
46
+ return nodeIssues;
47
+ }
48
+ : null;
49
+ exports.getNodeIssueState = __DEV__
50
+ ? (currentIssues, nodeIssues, nodesToCheck) => {
51
+ var _a, _b;
52
+ const issuesToKeep = (_a = keepNoStateHandledOrKeyboardTrapIssuesStillInView === null || keepNoStateHandledOrKeyboardTrapIssuesStillInView === void 0 ? void 0 : keepNoStateHandledOrKeyboardTrapIssuesStillInView(currentIssues, nodesToCheck)) !== null && _a !== void 0 ? _a : [];
53
+ return [
54
+ ...issuesToKeep,
55
+ ...((_b = sortIssuesByViewId === null || sortIssuesByViewId === void 0 ? void 0 : sortIssuesByViewId(nodeIssues)) !== null && _b !== void 0 ? _b : nodeIssues),
56
+ ];
57
+ }
58
+ : null;
59
+ const isHeaderNode = __DEV__
60
+ ? (node) => {
61
+ var _a;
62
+ return node.type === 'Text' &&
63
+ (((_a = node.traits) === null || _a === void 0 ? void 0 : _a.includes('header')) || node.ariaRole === 'header');
64
+ }
65
+ : null;
66
+ const clearFixedNodeIssues = __DEV__
67
+ ? (previousNodeIssues, nodeIssues, jsIssues) => {
68
+ const fixedIssues = previousNodeIssues.filter((issue) => nodeIssues.find((item) => item.viewId === issue.viewId) ===
69
+ undefined && issue.rule !== 'NO_ACCESSIBILITY_STATE_SET');
70
+ for (const issue of fixedIssues) {
71
+ amaClearHighlight_1.amaClearHighlight === null || amaClearHighlight_1.amaClearHighlight === void 0 ? void 0 : (0, amaClearHighlight_1.amaClearHighlight)(issue);
72
+ const jsIndex = jsIssues.findIndex((item) => item.viewId === issue.viewId && item.rule === issue.rule);
73
+ if (jsIndex >= 0) {
74
+ jsIssues.splice(jsIndex, 1);
75
+ }
76
+ }
77
+ }
78
+ : null;
79
+ const syncHighlightedIssues = __DEV__
80
+ ? (nodeIssues, jsFailedChecks, highlightedIssues) => {
81
+ var _a;
82
+ const issuesByViewId = (_a = groupIssuesByViewId === null || groupIssuesByViewId === void 0 ? void 0 : groupIssuesByViewId([...nodeIssues, ...jsFailedChecks])) !== null && _a !== void 0 ? _a : {};
83
+ for (const viewIdStr of Object.keys(issuesByViewId)) {
84
+ const viewId = Number(viewIdStr);
85
+ const issuesForView = issuesByViewId[viewId];
86
+ if (highlightedIssues[viewId] !== issuesForView.length) {
87
+ amaHighlightComponent_1.amaHighlightComponent === null || amaHighlightComponent_1.amaHighlightComponent === void 0 ? void 0 : (0, amaHighlightComponent_1.amaHighlightComponent)(issuesForView);
88
+ highlightedIssues[viewId] = issuesForView.length;
89
+ }
90
+ }
91
+ }
92
+ : null;
93
+ const groupIssuesByViewId = __DEV__
94
+ ? (issues) => {
95
+ return issues.reduce((groupedIssues, issue) => {
96
+ if (issue.viewId >= 0) {
97
+ if (!groupedIssues[issue.viewId]) {
98
+ groupedIssues[issue.viewId] = [];
99
+ }
100
+ groupedIssues[issue.viewId].push(issue);
101
+ }
102
+ return groupedIssues;
103
+ }, {});
104
+ }
105
+ : null;
106
+ const sortIssuesByViewId = __DEV__
107
+ ? (issues) => [...issues].sort((a, b) => a.viewId - b.viewId)
108
+ : null;
109
+ const keepNoStateHandledOrKeyboardTrapIssuesStillInView = __DEV__
110
+ ? (issues, nodesInView) => {
111
+ return issues.filter((item) => (item.rule === 'NO_ACCESSIBILITY_STATE_SET' ||
112
+ item.rule === 'NO_KEYBOARD_TRAP') &&
113
+ nodesInView[item.viewId]);
114
+ }
115
+ : null;
@@ -0,0 +1,7 @@
1
+ import type { AmaNode, AmaUiSnapshotsData } from '../ReactNativeAma.types';
2
+ import type { AmaError } from './types';
3
+ type GetItemsWithNoStateUpdated = (data: AmaUiSnapshotsData, nodesInView: Record<number, AmaNode>) => Set<number>;
4
+ type SyncUiInteractionIssues = (prevIssues: AmaError[], itemsToFlag: number[], rootTag: number) => AmaError[];
5
+ export declare const getItemsWithNoStateUpdated: GetItemsWithNoStateUpdated | null;
6
+ export declare const syncUiInteractionIssues: SyncUiInteractionIssues | null;
7
+ export {};
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.syncUiInteractionIssues = exports.getItemsWithNoStateUpdated = void 0;
4
+ const amaClearHighlight_1 = require("./utils/amaClearHighlight");
5
+ const amaHighlightComponent_1 = require("./utils/amaHighlightComponent");
6
+ const A11Y_STATE_KEYS = [
7
+ 'parentId',
8
+ 'isChecked',
9
+ 'isBusy',
10
+ 'isSelected',
11
+ 'isDisabled',
12
+ 'isExpanded',
13
+ ];
14
+ exports.getItemsWithNoStateUpdated = __DEV__
15
+ ? (data, nodesInView) => {
16
+ var _a, _b;
17
+ const viewsBefore = data.before;
18
+ const viewsAfter = (_a = data.afterSettled) !== null && _a !== void 0 ? _a : data.after;
19
+ const issues = new Set();
20
+ const afterKeys = Object.keys(viewsAfter).map(Number);
21
+ if (!afterKeys.includes(data.rootTag) ||
22
+ data.beforeModalVisible !== data.afterModalVisible) {
23
+ return issues;
24
+ }
25
+ // The tapped element is no longer in the UI, usually after navigation.
26
+ if (!nodesInView[data.rootTag]) {
27
+ return issues;
28
+ }
29
+ let hasSomethingChanged = false;
30
+ for (const tagId of afterKeys) {
31
+ const snapBefore = viewsBefore[tagId];
32
+ const snapAfter = viewsAfter[tagId];
33
+ if (!snapBefore) {
34
+ hasSomethingChanged = true;
35
+ continue;
36
+ }
37
+ const subKeys = Object.keys(snapAfter).filter((key) => key !== 'parentId');
38
+ for (const subKey of subKeys) {
39
+ const hasPropertyChanged = !A11Y_STATE_KEYS.includes(subKey) &&
40
+ snapBefore[subKey] !== snapAfter[subKey];
41
+ if (hasPropertyChanged) {
42
+ hasSomethingChanged = true;
43
+ break;
44
+ }
45
+ }
46
+ }
47
+ if (hasSomethingChanged) {
48
+ const parentId = data.rootTag;
49
+ const after = data.after[parentId];
50
+ const settled = (_b = data.afterSettled) === null || _b === void 0 ? void 0 : _b[parentId];
51
+ const before = data.before[parentId];
52
+ const hasStateChanged = A11Y_STATE_KEYS.some((key) => before[key] !== after[key] ||
53
+ (settled && before[key] !== settled[key]));
54
+ if (parentId && !hasStateChanged) {
55
+ issues.add(parentId);
56
+ }
57
+ }
58
+ return issues;
59
+ }
60
+ : null;
61
+ exports.syncUiInteractionIssues = __DEV__
62
+ ? (prevIssues, itemsToFlag, rootTag) => {
63
+ var _a;
64
+ if (itemsToFlag.length === 0) {
65
+ return (_a = clearNoStateIssueForRoot === null || clearNoStateIssueForRoot === void 0 ? void 0 : clearNoStateIssueForRoot(prevIssues, rootTag)) !== null && _a !== void 0 ? _a : prevIssues;
66
+ }
67
+ const newIssues = itemsToFlag
68
+ .map((viewId) => {
69
+ const found = prevIssues.find((item) => item.viewId === viewId &&
70
+ item.rule === 'NO_ACCESSIBILITY_STATE_SET');
71
+ if (found) {
72
+ return null;
73
+ }
74
+ const issue = {
75
+ rule: 'NO_ACCESSIBILITY_STATE_SET',
76
+ viewId,
77
+ };
78
+ amaHighlightComponent_1.amaHighlightComponent === null || amaHighlightComponent_1.amaHighlightComponent === void 0 ? void 0 : (0, amaHighlightComponent_1.amaHighlightComponent)(issue);
79
+ return issue;
80
+ })
81
+ .filter((issue) => { var _a; return (_a = nonNullable === null || nonNullable === void 0 ? void 0 : nonNullable(issue)) !== null && _a !== void 0 ? _a : false; });
82
+ if (newIssues.length === 0) {
83
+ return prevIssues;
84
+ }
85
+ return [...prevIssues, ...newIssues];
86
+ }
87
+ : null;
88
+ const clearNoStateIssueForRoot = __DEV__
89
+ ? (issues, rootTag) => {
90
+ const issueIndex = issues.findIndex((item) => item.viewId === rootTag && item.rule === 'NO_ACCESSIBILITY_STATE_SET');
91
+ if (issueIndex < 0) {
92
+ return issues;
93
+ }
94
+ amaClearHighlight_1.amaClearHighlight === null || amaClearHighlight_1.amaClearHighlight === void 0 ? void 0 : (0, amaClearHighlight_1.amaClearHighlight)(issues[issueIndex]);
95
+ return issues.filter((_, index) => index !== issueIndex);
96
+ }
97
+ : null;
98
+ const nonNullable = __DEV__
99
+ ? (value) => value !== null && value !== undefined
100
+ : null;
@@ -0,0 +1,2 @@
1
+ import { AmaError } from '../types';
2
+ export declare const amaClearHighlight: ((issue: AmaError) => void) | null;
@@ -0,0 +1,12 @@
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.amaClearHighlight = void 0;
7
+ const ReactNativeAmaModule_1 = __importDefault(require("../../ReactNativeAmaModule"));
8
+ exports.amaClearHighlight = __DEV__
9
+ ? (issue) => {
10
+ ReactNativeAmaModule_1.default.clearHighlight(issue.viewId);
11
+ }
12
+ : null;
@@ -0,0 +1,3 @@
1
+ import { HighlightMode } from '../config';
2
+ import { AmaError } from '../types';
3
+ export declare const amaHighlightComponent: ((issues: AmaError | AmaError[], mode?: HighlightMode) => Promise<import("../types").Position | null>) | null;