@react-native-ama/core 1.2.1 → 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.
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/package.json +61 -18
  86. package/src/ReactNativeAma.types.ts +70 -0
  87. package/src/ReactNativeAmaModule.ts +18 -0
  88. package/src/ReactNativeAmaModule.web.ts +14 -0
  89. package/src/ReactNativeAmaView.tsx +9 -0
  90. package/src/ReactNativeAmaView.web.tsx +15 -0
  91. package/src/__mocks__/ReactNativeAmaModule.ts +9 -0
  92. package/src/components/AMAProvider.integration.test.tsx +3 -96
  93. package/src/components/AMAProvider.test.tsx +9 -4
  94. package/src/components/AMAProvider.tsx +40 -76
  95. package/src/components/AutofocusContainer.test.tsx +4 -5
  96. package/src/components/AutofocusContainer.tsx +20 -5
  97. package/src/components/HideChildrenFromAccessibilityTree.test.tsx +23 -39
  98. package/src/components/HideChildrenFromAccessibilityTree.tsx +12 -11
  99. package/src/hooks/useFocus.test.ts +20 -20
  100. package/src/hooks/useFocus.ts +14 -6
  101. package/src/hooks/useTimedAction.android.test.ts +0 -1
  102. package/src/hooks/useTimedAction.ios.test.ts +0 -1
  103. package/src/hooks/useTimedAction.ts +0 -1
  104. package/src/index.ts +4 -2
  105. package/src/internals/checks/checkAriaLabel.test.ts +165 -0
  106. package/src/internals/checks/checkAriaLabel.ts +16 -0
  107. package/src/internals/checks/checkAriaRole.test.ts +429 -0
  108. package/src/internals/checks/checkAriaRole.ts +60 -0
  109. package/src/internals/checks/checkContrast.test.ts +278 -0
  110. package/src/internals/checks/checkContrast.ts +109 -0
  111. package/src/internals/checks/checkImageAlt.test.ts +125 -0
  112. package/src/internals/checks/checkImageAlt.ts +23 -0
  113. package/src/internals/checks/checkIsUppercase.test.ts +399 -0
  114. package/src/internals/checks/checkIsUppercase.ts +46 -0
  115. package/src/internals/checks/checkLongNumber.test.ts +111 -0
  116. package/src/internals/checks/checkLongNumber.ts +34 -0
  117. package/src/internals/checks/checkMinimumSize.test.ts +67 -0
  118. package/src/internals/checks/checkMinimumSize.ts +25 -0
  119. package/src/internals/checks/checkTextInput.ts +65 -0
  120. package/src/internals/checks/performChecks.test.ts +171 -0
  121. package/src/internals/checks/performChecks.ts +24 -0
  122. package/src/internals/components/AMAErrorOverlay.test.tsx +139 -0
  123. package/src/internals/components/AMAErrorOverlay.tsx +451 -0
  124. package/src/internals/components/AMARuleError.test.tsx +93 -0
  125. package/src/internals/components/AMARuleError.tsx +225 -0
  126. package/src/internals/config.ts +58 -0
  127. package/src/internals/types.ts +11 -0
  128. package/src/internals/useAMADev.dev.ts +153 -0
  129. package/src/internals/useAMADev.test.ts +260 -0
  130. package/src/internals/useAMADev.ts +17 -0
  131. package/src/internals/useAMADevNodeChecks.dev.ts +178 -0
  132. package/src/internals/useAMADevUiInteraction.dev.ts +164 -0
  133. package/src/internals/utils/amaClearHighlight.test.ts +21 -0
  134. package/src/internals/utils/amaClearHighlight.ts +8 -0
  135. package/src/internals/utils/amaHighlightComponent.test.ts +74 -0
  136. package/src/internals/utils/amaHighlightComponent.ts +46 -0
  137. package/src/internals/utils/constants.ts +33 -0
  138. package/src/internals/utils/devMode.test.ts +99 -0
  139. package/src/internals/utils/getErrorColor.test.ts +18 -0
  140. package/src/internals/utils/getErrorColor.ts +8 -0
  141. package/src/internals/utils/getRuleAction.ts +13 -0
  142. package/src/internals/utils/getRuleErrorInfo.test.ts +59 -0
  143. package/src/internals/utils/getRuleErrorInfo.ts +26 -0
  144. package/src/internals/utils/ignoreContrastCheck.test.ts +34 -0
  145. package/src/internals/utils/ignoreContrastCheck.ts +11 -0
  146. package/src/internals/utils/interpolateAnimation.test.ts +176 -0
  147. package/src/internals/utils/interpolateAnimationStates.ts +55 -0
  148. package/src/internals/utils/isA11yLabelAllowed.test.ts +39 -0
  149. package/src/internals/utils/isA11yLabelAllowed.ts +10 -0
  150. package/src/internals/utils/isRuleDisabled.test.ts +35 -0
  151. package/src/internals/utils/isRuleDisabled.ts +10 -0
  152. package/src/internals/utils/logError.test.ts +148 -0
  153. package/src/internals/utils/logError.ts +41 -0
  154. package/src/internals/utils/logFoundIssues.test.ts +98 -0
  155. package/src/internals/utils/logFoundIssues.ts +22 -0
  156. package/src/internals/utils/logger.test.ts +26 -0
  157. package/src/internals/utils/logger.ts +15 -0
  158. package/src/internals/utils/loggerMethods.test.ts +38 -0
  159. package/src/internals/utils/minimumTouchableSize.test.ts +28 -0
  160. package/src/internals/utils/minimumTouchableSize.tsx +9 -0
  161. package/src/internals/utils/platformHelpers.test.ts +11 -0
  162. package/src/internals/utils/platformHelpers.ts +4 -0
  163. package/src/internals/utils/rules.ts +363 -0
  164. package/dist/scripts/create-config.d.ts +0 -1
  165. package/dist/scripts/create-config.js +0 -23
  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,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkImageAlt = void 0;
4
+ const checkImageAlt = (node) => {
5
+ if (node.type !== 'Image') {
6
+ return null;
7
+ }
8
+ if (node.isAccessible === false) {
9
+ return null;
10
+ }
11
+ const { ariaLabel } = node;
12
+ if (!(ariaLabel === null || ariaLabel === void 0 ? void 0 : ariaLabel.trim())) {
13
+ return {
14
+ rule: 'IMAGE_MISSING_ALT_TEXT',
15
+ viewId: node.viewId,
16
+ };
17
+ }
18
+ return null;
19
+ };
20
+ exports.checkImageAlt = checkImageAlt;
@@ -0,0 +1,8 @@
1
+ import { AmaNode } from '../../ReactNativeAma.types';
2
+ import { AmaError, AmaRule } from '../types';
3
+ export type UppercaseStringChecker = {
4
+ node: AmaNode;
5
+ canBeEmpty?: boolean;
6
+ rule?: AmaRule;
7
+ };
8
+ export declare const checkIsUppercase: ({ node, canBeEmpty, rule, }: UppercaseStringChecker) => AmaError | null;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkIsUppercase = void 0;
4
+ const isA11yLabelAllowed_1 = require("../utils/isA11yLabelAllowed");
5
+ const checkIsUppercase = ({ node, canBeEmpty = true, rule = 'NO_UPPERCASE_TEXT', }) => {
6
+ var _a, _b;
7
+ const text = (_a = node.ariaLabel) !== null && _a !== void 0 ? _a : node.content;
8
+ const isEmpty = !text || ((_b = text === null || text === void 0 ? void 0 : text.trim()) === null || _b === void 0 ? void 0 : _b.length) === 0;
9
+ if ((isEmpty && canBeEmpty) || !node.isAccessible) {
10
+ return null;
11
+ }
12
+ const isAllowed = isA11yLabelAllowed_1.isAccessibilityLabelAllowed === null || isA11yLabelAllowed_1.isAccessibilityLabelAllowed === void 0 ? void 0 : (0, isA11yLabelAllowed_1.isAccessibilityLabelAllowed)(text);
13
+ if (!isAllowed && isUpperCase(text)) {
14
+ return {
15
+ rule,
16
+ label: node.ariaLabel,
17
+ viewId: node.viewId,
18
+ };
19
+ }
20
+ return null;
21
+ };
22
+ exports.checkIsUppercase = checkIsUppercase;
23
+ const NO_LETTERS = /[^\p{L}]/gu;
24
+ const isUpperCase = (string) => {
25
+ const cleanString = string.replace(NO_LETTERS, '');
26
+ if (cleanString.trim().length === 0) {
27
+ return false;
28
+ }
29
+ return cleanString.toUpperCase() === cleanString;
30
+ };
@@ -0,0 +1,3 @@
1
+ import { AmaNode } from '../../ReactNativeAma.types';
2
+ import { AmaError } from '../types';
3
+ export declare const checkLongNumber: (node: AmaNode) => AmaError | null;
@@ -0,0 +1,31 @@
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.checkLongNumber = void 0;
7
+ const config_1 = __importDefault(require("../config"));
8
+ const checkLongNumber = (node) => {
9
+ var _a;
10
+ const text = (_a = node.ariaLabel) !== null && _a !== void 0 ? _a : node.content;
11
+ if (!text || !node.isAccessible) {
12
+ return null;
13
+ }
14
+ const hasFailed = getLongestDigitRun(text) >= config_1.default.longNumberMinLength;
15
+ if (hasFailed) {
16
+ return {
17
+ rule: 'LONG_NUMBER_NOT_FORMATTED',
18
+ label: node.ariaLabel,
19
+ viewId: node.viewId,
20
+ };
21
+ }
22
+ return null;
23
+ };
24
+ exports.checkLongNumber = checkLongNumber;
25
+ const getLongestDigitRun = (text) => {
26
+ const digitRuns = text.match(/\d+/g);
27
+ if (!digitRuns) {
28
+ return 0;
29
+ }
30
+ return Math.max(...digitRuns.map((run) => run.length));
31
+ };
@@ -0,0 +1,3 @@
1
+ import { AmaNode } from '../../ReactNativeAma.types';
2
+ import { AmaError } from '../types';
3
+ export declare const checkMinimumSize: (node: AmaNode) => AmaError | null;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkMinimumSize = void 0;
4
+ const minimumTouchableSize_1 = require("../utils/minimumTouchableSize");
5
+ const checkMinimumSize = (node) => {
6
+ var _a, _b;
7
+ const width = Math.ceil((_a = node.bounds) === null || _a === void 0 ? void 0 : _a[0]);
8
+ const height = Math.ceil((_b = node.bounds) === null || _b === void 0 ? void 0 : _b[1]);
9
+ if (node.type !== 'Pressable') {
10
+ return null;
11
+ }
12
+ if (width < minimumTouchableSize_1.MINIMUM_TOUCHABLE_SIZE || height < minimumTouchableSize_1.MINIMUM_TOUCHABLE_SIZE) {
13
+ return {
14
+ label: node.ariaLabel,
15
+ viewId: node.viewId,
16
+ rule: 'MINIMUM_SIZE',
17
+ extra: `The touchable area must have a minimum size of ${minimumTouchableSize_1.MINIMUM_TOUCHABLE_SIZE}x${minimumTouchableSize_1.MINIMUM_TOUCHABLE_SIZE} found instead: ${width.toFixed(0)}x${height.toFixed(0)}`,
18
+ };
19
+ }
20
+ return null;
21
+ };
22
+ exports.checkMinimumSize = checkMinimumSize;
@@ -0,0 +1,3 @@
1
+ import { AmaNode } from '../../ReactNativeAma.types';
2
+ import { AmaError } from '../types';
3
+ export declare const checkTextInputs: (nodesToCheck: AmaNode[]) => AmaError[];
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkTextInputs = void 0;
4
+ const react_native_1 = require("react-native");
5
+ const isRuleDisabled_1 = require("../utils/isRuleDisabled");
6
+ const RETURN_DONE = react_native_1.Platform.select({ ios: 0, default: 6 });
7
+ const REMOVE_ENDING_REGEXT = /\W$/;
8
+ const removeEndingSymbol = (text) => {
9
+ if (!text) {
10
+ return null;
11
+ }
12
+ const result = text.replace(REMOVE_ENDING_REGEXT, '').trim().toLowerCase();
13
+ return result;
14
+ };
15
+ const checkTextInputs = (nodesToCheck) => {
16
+ const inputs = nodesToCheck.filter((node) => node.type === 'TextInput');
17
+ const errors = [];
18
+ for (const key in inputs) {
19
+ const index = parseInt(key, 10);
20
+ const inputText = inputs[key];
21
+ const canHaveReturnTypeDone = index === inputs.length - 1;
22
+ const ariaLabel = removeEndingSymbol(inputText.ariaLabel);
23
+ const textInputLabel = ariaLabel
24
+ ? nodesToCheck.find(
25
+ // Ignores symbols like ":"
26
+ (node) => node.type === 'Text' && removeEndingSymbol(node.content) === ariaLabel)
27
+ : false;
28
+ const isLabelAlsoAccessible = textInputLabel && (textInputLabel === null || textInputLabel === void 0 ? void 0 : textInputLabel.isAccessible);
29
+ const hasLabel = Boolean(textInputLabel);
30
+ if (inputText.returnType === RETURN_DONE && !canHaveReturnTypeDone) {
31
+ errors.push({
32
+ rule: 'INPUT_INVALID_RETURN_KEY',
33
+ viewId: inputText.viewId,
34
+ });
35
+ }
36
+ if (isLabelAlsoAccessible) {
37
+ errors.push({
38
+ rule: 'INPUT_HAS_FOCUSABLE_LABEL',
39
+ viewId: textInputLabel.viewId,
40
+ });
41
+ }
42
+ if (ariaLabel && !hasLabel) {
43
+ errors.push({
44
+ rule: 'INPUT_HAS_NO_VISIBLE_LABEL',
45
+ viewId: inputText.viewId,
46
+ });
47
+ }
48
+ }
49
+ return errors.filter((item) => !(isRuleDisabled_1.isRuleDisabled === null || isRuleDisabled_1.isRuleDisabled === void 0 ? void 0 : (0, isRuleDisabled_1.isRuleDisabled)(item)));
50
+ };
51
+ exports.checkTextInputs = checkTextInputs;
@@ -0,0 +1,3 @@
1
+ import { AmaNode } from '../../ReactNativeAma.types';
2
+ import { AmaError } from '../types';
3
+ export declare const performChecks: (node: AmaNode) => AmaError[];
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.performChecks = void 0;
4
+ const isRuleDisabled_1 = require("../utils/isRuleDisabled");
5
+ const checkAriaLabel_1 = require("./checkAriaLabel");
6
+ const checkAriaRole_1 = require("./checkAriaRole");
7
+ const checkContrast_1 = require("./checkContrast");
8
+ const checkImageAlt_1 = require("./checkImageAlt");
9
+ const checkIsUppercase_1 = require("./checkIsUppercase");
10
+ const checkLongNumber_1 = require("./checkLongNumber");
11
+ const checkMinimumSize_1 = require("./checkMinimumSize");
12
+ const performChecks = (node) => {
13
+ return [
14
+ (0, checkAriaLabel_1.checkAriaLabel)(node),
15
+ (0, checkAriaRole_1.checkAriaRole)(node),
16
+ (0, checkImageAlt_1.checkImageAlt)(node),
17
+ (0, checkMinimumSize_1.checkMinimumSize)(node),
18
+ (0, checkIsUppercase_1.checkIsUppercase)({ node }),
19
+ (0, checkContrast_1.checkContrast)(node),
20
+ (0, checkLongNumber_1.checkLongNumber)(node),
21
+ ].filter((item) => item !== null && !(isRuleDisabled_1.isRuleDisabled === null || isRuleDisabled_1.isRuleDisabled === void 0 ? void 0 : (0, isRuleDisabled_1.isRuleDisabled)(item)));
22
+ };
23
+ exports.performChecks = performChecks;
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ import { AmaError } from '../types';
3
+ export declare const AMAErrorOverlay: (({ issues }: {
4
+ issues?: AmaError[] | undefined;
5
+ }) => React.JSX.Element | null) | null;
@@ -0,0 +1,334 @@
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
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
27
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
28
+ return new (P || (P = Promise))(function (resolve, reject) {
29
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
30
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
31
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
32
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
33
+ });
34
+ };
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.AMAErrorOverlay = void 0;
37
+ const react_1 = __importStar(require("react"));
38
+ const react_native_1 = require("react-native");
39
+ const amaClearHighlight_1 = require("../utils/amaClearHighlight");
40
+ const amaHighlightComponent_1 = require("../utils/amaHighlightComponent");
41
+ const getRuleErrorInfo_1 = require("../utils/getRuleErrorInfo");
42
+ const logError_1 = require("../utils/logError");
43
+ const rules_1 = require("../utils/rules");
44
+ const AMARuleError_1 = require("./AMARuleError");
45
+ const WINDOW_WIDTH = react_native_1.Dimensions.get('window').width;
46
+ const WINDOW_HEIGHT = react_native_1.Dimensions.get('screen').height;
47
+ const AMAErrorComponent = ({ issues }) => {
48
+ const [activeIssueIndex, setActiveIssueIndex] = (0, react_1.useState)();
49
+ const issueToView = (0, react_1.useRef)(null);
50
+ const previousViewId = (0, react_1.useRef)(null);
51
+ const clearPreviousHighlight = () => {
52
+ var _a;
53
+ if (!previousViewId.current) {
54
+ return;
55
+ }
56
+ amaClearHighlight_1.amaClearHighlight === null || amaClearHighlight_1.amaClearHighlight === void 0 ? void 0 : (0, amaClearHighlight_1.amaClearHighlight)(previousViewId.current);
57
+ // Get all issues for the previous viewId to restore correct count and color
58
+ const issuesForPreviousView = (_a = issues === null || issues === void 0 ? void 0 : issues.filter((issue) => { var _a; return issue.viewId === ((_a = previousViewId.current) === null || _a === void 0 ? void 0 : _a.viewId); })) !== null && _a !== void 0 ? _a : [];
59
+ if (issuesForPreviousView.length > 0) {
60
+ amaHighlightComponent_1.amaHighlightComponent === null || amaHighlightComponent_1.amaHighlightComponent === void 0 ? void 0 : (0, amaHighlightComponent_1.amaHighlightComponent)(issuesForPreviousView);
61
+ }
62
+ };
63
+ const setActiveIssue = (newIndex) => __awaiter(void 0, void 0, void 0, function* () {
64
+ var _a;
65
+ clearPreviousHighlight();
66
+ issueToView.current = issues[newIndex];
67
+ if (issueToView.current) {
68
+ // Get all issues for the current viewId
69
+ const issuesForView = (_a = issues === null || issues === void 0 ? void 0 : issues.filter((issue) => { var _a; return issue.viewId === ((_a = issueToView.current) === null || _a === void 0 ? void 0 : _a.viewId); })) !== null && _a !== void 0 ? _a : [];
70
+ const position = yield (amaHighlightComponent_1.amaHighlightComponent === null || amaHighlightComponent_1.amaHighlightComponent === void 0 ? void 0 : (0, amaHighlightComponent_1.amaHighlightComponent)(issuesForView, 'both'));
71
+ setActiveIssueIndex({ id: newIndex, position: position !== null && position !== void 0 ? position : undefined });
72
+ previousViewId.current = issueToView.current;
73
+ }
74
+ else {
75
+ setActiveIssueIndex(undefined);
76
+ previousViewId.current = null;
77
+ }
78
+ });
79
+ const showNextIssue = () => {
80
+ setActiveIssue((activeIssueIndex === null || activeIssueIndex === void 0 ? void 0 : activeIssueIndex.id) != null ? activeIssueIndex.id + 1 : 0);
81
+ };
82
+ const showPrevIssue = () => {
83
+ setActiveIssue((activeIssueIndex === null || activeIssueIndex === void 0 ? void 0 : activeIssueIndex.id) && (activeIssueIndex === null || activeIssueIndex === void 0 ? void 0 : activeIssueIndex.id) > 0
84
+ ? (activeIssueIndex === null || activeIssueIndex === void 0 ? void 0 : activeIssueIndex.id) - 1
85
+ : 0);
86
+ };
87
+ const closeIssues = () => {
88
+ clearPreviousHighlight();
89
+ setActiveIssueIndex(undefined);
90
+ };
91
+ const showFirstError = () => {
92
+ showNextIssue();
93
+ };
94
+ if (!(issues === null || issues === void 0 ? void 0 : issues.length)) {
95
+ return null;
96
+ }
97
+ const showActiveIssue = activeIssueIndex !== undefined && issueToView.current;
98
+ const failedBarBottom = getFailedBarBottomOffset();
99
+ return (<>
100
+ {showActiveIssue ? (<AMAOverlay issue={issueToView.current} position={activeIssueIndex.position} closeOverlay={closeIssues} onPrevIssue={showPrevIssue} onNextIssue={showNextIssue} onClose={closeIssues} totalIssues={issues.length} issueIndex={activeIssueIndex.id}/>) : null}
101
+ <react_native_1.View style={[styles.failedBar, { bottom: failedBarBottom }]} accessible={false} accessibilityElementsHidden importantForAccessibility="no-hide-descendants">
102
+ <AMAButton onPress={showFirstError} bg="transparent" color="#fff">
103
+ <react_native_1.Text style={styles.buttonText}>
104
+ <react_native_1.Text style={{ color: 'yellow' }}>
105
+ ⚠️ AMA: {issues.length} issue{issues.length !== 1 ? 's' : ''}{' '}
106
+ detected
107
+ </react_native_1.Text>
108
+ <react_native_1.Text style={{ color: '#fafafa' }}>{' ┆ '}</react_native_1.Text>
109
+ <react_native_1.Text style={{ fontWeight: 'bold' }}>Inspect ›</react_native_1.Text>
110
+ </react_native_1.Text>
111
+ </AMAButton>
112
+ </react_native_1.View>
113
+ </>);
114
+ };
115
+ const AMAButton = ({ children, count, singular, bg, onPress, line, disabled, }) => {
116
+ const plural = count ? `${singular}${count !== 1 ? 's' : ''} ` : singular;
117
+ return (<react_native_1.Pressable onPress={disabled ? undefined : onPress} style={({ pressed }) => {
118
+ const opacity = pressed || disabled ? 0.8 : 1;
119
+ const divider = line
120
+ ? {
121
+ borderRightWidth: 1,
122
+ borderRightColor: line,
123
+ }
124
+ : {};
125
+ return Object.assign(Object.assign(Object.assign({}, styles.button), divider), { backgroundColor: bg, opacity });
126
+ }} role="button" aria-label={`Show ${plural}`} aria-disabled={disabled} importantForAccessibility="no" accessibilityElementsHidden>
127
+ {children}
128
+ </react_native_1.Pressable>);
129
+ };
130
+ const AMAOverlay = ({ issue, position, closeOverlay, onNextIssue, onPrevIssue, onClose, totalIssues, issueIndex, }) => {
131
+ position = position || [24, 100, WINDOW_WIDTH - 48, 0];
132
+ const { severity, url } = getRuleErrorInfo_1.getAMARuleErrorInfo(issue);
133
+ const [x, y, width, height] = position;
134
+ const isMoreThanHalfScreen = y / WINDOW_HEIGHT > 0.57;
135
+ const maxHeight = isMoreThanHalfScreen
136
+ ? WINDOW_HEIGHT * 0.43
137
+ : WINDOW_HEIGHT - y - 160;
138
+ const yPosition = isMoreThanHalfScreen
139
+ ? undefined
140
+ : y + height + POINTER_SIZE + SPACER;
141
+ const bottomPosition = isMoreThanHalfScreen
142
+ ? WINDOW_HEIGHT - y + SPACER + POINTER_SIZE
143
+ : undefined;
144
+ const openHelp = () => __awaiter(void 0, void 0, void 0, function* () {
145
+ try {
146
+ yield react_native_1.Share.share({
147
+ message: url,
148
+ });
149
+ }
150
+ catch (error) {
151
+ console.error(error);
152
+ }
153
+ });
154
+ (0, react_1.useEffect)(() => {
155
+ logError_1.logError === null || logError_1.logError === void 0 ? void 0 : (0, logError_1.logError)(issue);
156
+ }, [issue]);
157
+ return (<>
158
+ <react_native_1.Pressable style={styles.transparentOverlay} onPress={closeOverlay} accessible={false} importantForAccessibility="no"/>
159
+ <react_native_1.View style={[
160
+ styles === null || styles === void 0 ? void 0 : styles.callout,
161
+ {
162
+ top: yPosition,
163
+ bottom: bottomPosition,
164
+ borderColor: rules_1.AMA_COLORS[severity],
165
+ },
166
+ ]}>
167
+ <react_native_1.Text style={styles.totalIssues}>
168
+ {issueIndex + 1} / {totalIssues}
169
+ </react_native_1.Text>
170
+ {AMARuleError_1.AMARuleError ? (<AMARuleError_1.AMARuleError issue={issue} onClose={onClose} maxHeight={maxHeight}/>) : null}
171
+
172
+ <react_native_1.View style={styles.actions}>
173
+ <react_native_1.Pressable onPress={onPrevIssue} role="button" hitSlop={{ left: 12, top: 12, bottom: 12, right: 12 }} style={[styles.action, styles.previous]} accessible={false} importantForAccessibility="no">
174
+ <react_native_1.Text>‹ Prev</react_native_1.Text>
175
+ </react_native_1.Pressable>
176
+ <react_native_1.Pressable onPress={openHelp} role="button" hitSlop={{ left: 12, top: 12, bottom: 12, right: 12 }} style={[styles.action, styles.learnMore]} accessible={false} importantForAccessibility="no">
177
+ <react_native_1.Text style={styles.link}>Learn more</react_native_1.Text>
178
+ </react_native_1.Pressable>
179
+
180
+ <react_native_1.Pressable onPress={onNextIssue} role="button" hitSlop={{ left: 12, top: 12, bottom: 12, right: 12 }} style={[styles.action, styles.next]} accessible={false} importantForAccessibility="no">
181
+ <react_native_1.Text style={{ textAlign: 'right' }}>Next ›</react_native_1.Text>
182
+ </react_native_1.Pressable>
183
+ </react_native_1.View>
184
+ </react_native_1.View>
185
+ <react_native_1.View style={[
186
+ styles.triangle,
187
+ {
188
+ left: x + width / 2 - POINTER_SIZE,
189
+ },
190
+ isMoreThanHalfScreen
191
+ ? {
192
+ top: y - POINTER_SIZE - SPACER,
193
+ borderTopWidth: POINTER_SIZE,
194
+ borderTopColor: rules_1.AMA_COLORS[severity],
195
+ borderBottomWidth: 0,
196
+ }
197
+ : {
198
+ top: y + height + SPACER,
199
+ borderBottomColor: rules_1.AMA_COLORS[severity],
200
+ },
201
+ ]}/>
202
+ </>);
203
+ };
204
+ exports.AMAErrorOverlay = __DEV__ ? AMAErrorComponent : null;
205
+ const SPACER = 4;
206
+ const POINTER_SIZE = 8;
207
+ const Z_INDEX = 9999;
208
+ const getFailedBarBottomOffset = () => {
209
+ if (react_native_1.Platform.OS !== 'android') {
210
+ return 40;
211
+ }
212
+ return 60;
213
+ };
214
+ const styles = __DEV__
215
+ ? react_native_1.StyleSheet.create({
216
+ callout: {
217
+ position: 'absolute',
218
+ left: 24,
219
+ right: 24,
220
+ backgroundColor: '#fff',
221
+ padding: 0,
222
+ justifyContent: 'center',
223
+ alignItems: 'center',
224
+ zIndex: Z_INDEX + 1,
225
+ shadowOffset: {
226
+ width: 10,
227
+ height: -10,
228
+ },
229
+ boxShadow: '0px 2px 20px #000',
230
+ shadowOpacity: 0.2,
231
+ shadowRadius: 24,
232
+ elevation: 4,
233
+ borderTopWidth: 2,
234
+ overflow: 'hidden',
235
+ },
236
+ calloutText: {
237
+ color: '#000',
238
+ fontSize: 14,
239
+ marginBottom: 12,
240
+ },
241
+ failedBar: {
242
+ backgroundColor: '#A31420',
243
+ alignSelf: 'center',
244
+ flexDirection: 'row',
245
+ alignItems: 'center',
246
+ shadowOffset: {
247
+ width: 10,
248
+ height: 10,
249
+ },
250
+ boxShadow: '0px 2px 6px #000',
251
+ shadowOpacity: 0.05,
252
+ shadowRadius: 12,
253
+ zIndex: Z_INDEX,
254
+ borderRadius: 20,
255
+ maxWidth: '90%',
256
+ },
257
+ button: {
258
+ flexDirection: 'row',
259
+ alignItems: 'center',
260
+ flex: 1,
261
+ padding: 12,
262
+ },
263
+ buttonText: {
264
+ flex: 1,
265
+ fontSize: 16,
266
+ lineHeight: 24,
267
+ textAlign: 'center',
268
+ color: '#fff',
269
+ },
270
+ transparentOverlay: {
271
+ position: 'absolute',
272
+ left: 0,
273
+ top: 0,
274
+ right: 0,
275
+ bottom: 0,
276
+ zIndex: Z_INDEX - 1,
277
+ backgroundColor: 'transparent',
278
+ },
279
+ actions: {
280
+ flexDirection: 'row',
281
+ justifyContent: 'space-between',
282
+ flex: 1,
283
+ alignItems: 'center',
284
+ alignContent: 'center',
285
+ },
286
+ action: {
287
+ paddingVertical: 8,
288
+ marginBottom: 12,
289
+ width: '27%',
290
+ borderWidth: 1,
291
+ },
292
+ previous: {
293
+ borderLeftWidth: 0,
294
+ borderTopEndRadius: 18,
295
+ borderBottomEndRadius: 18,
296
+ paddingRight: 12,
297
+ paddingLeft: 12,
298
+ },
299
+ next: {
300
+ borderRightWidth: 0,
301
+ borderTopLeftRadius: 18,
302
+ borderBottomLeftRadius: 18,
303
+ paddingRight: 12,
304
+ paddingLeft: 12,
305
+ },
306
+ learnMore: {
307
+ flex: 1,
308
+ alignItems: 'center',
309
+ borderRadius: 24,
310
+ borderWidth: 1,
311
+ marginHorizontal: 24,
312
+ paddingVertical: 8,
313
+ backgroundColor: '#07549C',
314
+ borderColor: '#07549C',
315
+ },
316
+ link: {
317
+ color: '#fff',
318
+ },
319
+ totalIssues: {
320
+ marginTop: 8,
321
+ },
322
+ triangle: {
323
+ position: 'absolute',
324
+ width: 0,
325
+ height: 0,
326
+ borderLeftWidth: POINTER_SIZE,
327
+ borderRightWidth: POINTER_SIZE,
328
+ borderBottomWidth: POINTER_SIZE,
329
+ borderLeftColor: 'transparent',
330
+ borderRightColor: 'transparent',
331
+ zIndex: Z_INDEX + 10,
332
+ },
333
+ })
334
+ : null;
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import { AmaError } from '../types';
3
+ export declare const AMARuleError: (({ issue, maxHeight, onClose, }: {
4
+ issue: AmaError;
5
+ onClose: () => void;
6
+ maxHeight: number;
7
+ }) => React.JSX.Element) | null;