@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,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,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -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,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const expo_1 = require("expo");
4
+ // This call loads the native module object from the JSI.
5
+ exports.default = (0, expo_1.requireNativeModule)('ReactNativeAma');
@@ -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,3 @@
1
+ import * as React from 'react';
2
+ import { ReactNativeAmaViewProps } from './ReactNativeAma.types';
3
+ export default function ReactNativeAmaView(props: ReactNativeAmaViewProps): React.JSX.Element;
@@ -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,3 @@
1
+ import * as React from 'react';
2
+ import { ReactNativeAmaViewProps } from './ReactNativeAma.types';
3
+ export default function ReactNativeAmaView(props: ReactNativeAmaViewProps): React.JSX.Element;
@@ -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: (id: string) => void;
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
- const internal_1 = require("@react-native-ama/internal");
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
- const trackError = (id) => {
93
- if (failedItems.includes(id)) {
94
- return;
95
- }
96
- setFailedItems(items => [...items, id]);
97
- react_native_1.AccessibilityInfo.announceForAccessibility("One or more component didn't pass the accessibility check, please check the console for more info");
98
- };
99
- const removeError = (id) => {
100
- setFailedItems(items => {
101
- const index = items.indexOf(id);
102
- if (index >= 0) {
103
- items.splice(index);
104
- return [...items];
105
- }
106
- return items;
107
- });
108
- };
109
- return (<AMAContext.Provider value={Object.assign(Object.assign({}, values), { trackError,
110
- removeError })}>
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
- {failedItems.length > 0 ? (<AMAError count={failedItems.length}/>) : null}
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
- import { PickAccessibleProps } from '@react-native-ama/internal';
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;
@@ -1,4 +1,4 @@
1
- import { PropsWithChildren } from 'react';
1
+ import { PropsWithChildren, type JSX } from 'react';
2
2
  type HideChildrenFromAccessibilityTreeProps = {
3
3
  testID?: string;
4
4
  };
@@ -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
- return react_1.default.isValidElement(child)
32
- ? react_1.default.cloneElement(child, {
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(child.props.children),
37
- })
38
- : child;
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
- `${internal_1.SHELL_COLORS.BG_RED}AMA.${internal_1.SHELL_COLORS.RESET} ${internal_1.SHELL_COLORS.BLUE}useFocus${internal_1.SHELL_COLORS.RESET}: ${internal_1.SHELL_COLORS.YELLOW}Ref element not found${internal_1.SHELL_COLORS.RESET}`);
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
- `${internal_1.SHELL_COLORS.BG_RED}AMA.${internal_1.SHELL_COLORS.RESET} ${internal_1.SHELL_COLORS.BLUE}useFocus${internal_1.SHELL_COLORS.RESET}: ${internal_1.SHELL_COLORS.YELLOW}Error finding node handle${internal_1.SHELL_COLORS.RESET} \n`, error);
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,3 @@
1
+ import { AmaNode } from '../../ReactNativeAma.types';
2
+ import { AmaError } from '../types';
3
+ export declare const checkAriaLabel: (node: AmaNode) => AmaError | null;
@@ -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,3 @@
1
+ import { AmaNode } from '../../ReactNativeAma.types';
2
+ import { AmaError } from '../types';
3
+ export declare const checkAriaRole: (node: AmaNode) => AmaError | null;
@@ -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,3 @@
1
+ import { AmaNode } from '../../ReactNativeAma.types';
2
+ import { AmaError } from '../types';
3
+ export declare const checkContrast: (node: AmaNode) => AmaError | null;
@@ -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;
@@ -0,0 +1,3 @@
1
+ import { AmaNode } from '../../ReactNativeAma.types';
2
+ import { AmaError } from '../types';
3
+ export declare const checkImageAlt: (node: AmaNode) => AmaError | null;