@applicaster/zapp-react-native-ui-components 13.0.7 → 13.0.8-alpha.1940580104
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Components/Cell/Cell.tsx +35 -11
- package/Components/Focusable/Focusable.tsx +8 -0
- package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +6 -4
- package/Components/TextInputTv/__tests__/__snapshots__/TextInputTv.test.js.snap +13 -0
- package/Components/TextInputTv/index.tsx +11 -0
- package/events/index.ts +1 -0
- package/package.json +5 -5
package/Components/Cell/Cell.tsx
CHANGED
|
@@ -15,6 +15,7 @@ import { AccessibilityManager } from "@applicaster/zapp-react-native-utils/appUt
|
|
|
15
15
|
import { styles } from "./styles";
|
|
16
16
|
|
|
17
17
|
type Props = {
|
|
18
|
+
dataLength: number;
|
|
18
19
|
item: ZappEntry;
|
|
19
20
|
index: number;
|
|
20
21
|
shouldScrollHorizontally: (arg1: [any]) => boolean | null | undefined;
|
|
@@ -70,6 +71,8 @@ type State = {
|
|
|
70
71
|
};
|
|
71
72
|
|
|
72
73
|
export class CellComponent extends React.Component<Props, State> {
|
|
74
|
+
accessibilityManager: AccessibilityManager;
|
|
75
|
+
|
|
73
76
|
constructor(props) {
|
|
74
77
|
super(props);
|
|
75
78
|
this.onPress = this.onPress.bind(this);
|
|
@@ -79,10 +82,13 @@ export class CellComponent extends React.Component<Props, State> {
|
|
|
79
82
|
this.hasReceivedFocus = this.hasReceivedFocus.bind(this);
|
|
80
83
|
this.scrollVertically = this.scrollVertically.bind(this);
|
|
81
84
|
this.scrollToIndex = this.scrollToIndex.bind(this);
|
|
85
|
+
this.handleAccessibilityFocus = this.handleAccessibilityFocus.bind(this);
|
|
82
86
|
|
|
83
87
|
this.state = {
|
|
84
88
|
hasFocusableInside: props.CellRenderer.hasFocusableInside?.(props.item),
|
|
85
89
|
};
|
|
90
|
+
|
|
91
|
+
this.accessibilityManager = AccessibilityManager.getInstance();
|
|
86
92
|
}
|
|
87
93
|
|
|
88
94
|
setScreenLayout(componentAnchorPointY, screenLayout) {
|
|
@@ -183,6 +189,30 @@ export class CellComponent extends React.Component<Props, State> {
|
|
|
183
189
|
return !isFocusable ? false : focused || focusableFocused;
|
|
184
190
|
}
|
|
185
191
|
|
|
192
|
+
handleAccessibilityFocus(item, index, dataLength) {
|
|
193
|
+
const accessibilityTitle =
|
|
194
|
+
item?.extensions?.accessibility?.label || item?.title;
|
|
195
|
+
|
|
196
|
+
const accessibilityHint = item?.extensions?.accessibility?.hint;
|
|
197
|
+
|
|
198
|
+
// For loop scrolling, calculate the correct logical index
|
|
199
|
+
const logicalIndex = dataLength ? index % dataLength : index;
|
|
200
|
+
|
|
201
|
+
const positionLabel = dataLength
|
|
202
|
+
? `item ${logicalIndex + 1} of ${dataLength}`
|
|
203
|
+
: "";
|
|
204
|
+
|
|
205
|
+
accessibilityTitle &&
|
|
206
|
+
this.accessibilityManager.addHeading(accessibilityTitle);
|
|
207
|
+
|
|
208
|
+
accessibilityHint &&
|
|
209
|
+
this.accessibilityManager.addHeading(accessibilityHint);
|
|
210
|
+
|
|
211
|
+
this.accessibilityManager.readText({
|
|
212
|
+
text: `${positionLabel}`,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
|
|
186
216
|
componentDidUpdate(prevProps: Readonly<Props>) {
|
|
187
217
|
if (prevProps.item !== this.props.item) {
|
|
188
218
|
this.setState({
|
|
@@ -197,6 +227,7 @@ export class CellComponent extends React.Component<Props, State> {
|
|
|
197
227
|
const {
|
|
198
228
|
item,
|
|
199
229
|
index,
|
|
230
|
+
dataLength,
|
|
200
231
|
component,
|
|
201
232
|
offsetUpdater,
|
|
202
233
|
preferredFocus,
|
|
@@ -257,22 +288,15 @@ export class CellComponent extends React.Component<Props, State> {
|
|
|
257
288
|
style={styles.baseCell}
|
|
258
289
|
isFocusable={isFocusable}
|
|
259
290
|
skipFocusManagerRegistration={skipFocusManagerRegistration}
|
|
291
|
+
{...this.accessibilityManager.getButtonAccessibilityProps(
|
|
292
|
+
item?.extensions?.accessibility?.label || item?.title
|
|
293
|
+
)}
|
|
260
294
|
>
|
|
261
295
|
{(focused, event) => {
|
|
262
296
|
const isFocused = this.isCellFocused(focused);
|
|
263
297
|
|
|
264
298
|
if (isFocused) {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
const accessibilityTitle =
|
|
268
|
-
item?.extensions?.accessibility?.label || item?.title || "";
|
|
269
|
-
|
|
270
|
-
const accessibilityHint =
|
|
271
|
-
item?.extensions?.accessibility?.hint || "";
|
|
272
|
-
|
|
273
|
-
accessibilityManager.readText({
|
|
274
|
-
text: `${accessibilityTitle} ${accessibilityHint}`,
|
|
275
|
-
});
|
|
299
|
+
this.handleAccessibilityFocus(item, index, dataLength);
|
|
276
300
|
}
|
|
277
301
|
|
|
278
302
|
return (
|
|
@@ -5,6 +5,7 @@ import { BaseFocusable } from "../BaseFocusable";
|
|
|
5
5
|
import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils/focusManager";
|
|
6
6
|
import { LONG_KEY_PRESS_TIMEOUT } from "@applicaster/quick-brick-core/const";
|
|
7
7
|
import { withFocusableContext } from "../../Contexts/FocusableGroupContext/withFocusableContext";
|
|
8
|
+
import { AccessibilityManager } from "@applicaster/zapp-react-native-utils/appUtils/accessibilityManager";
|
|
8
9
|
|
|
9
10
|
type Props = {
|
|
10
11
|
initialFocus?: boolean;
|
|
@@ -28,6 +29,7 @@ class Focusable extends BaseFocusable<Props> {
|
|
|
28
29
|
isGroup: boolean;
|
|
29
30
|
mouse: boolean;
|
|
30
31
|
longPressTimeout = null;
|
|
32
|
+
accessibilityManager: AccessibilityManager;
|
|
31
33
|
|
|
32
34
|
constructor(props) {
|
|
33
35
|
super(props);
|
|
@@ -42,6 +44,8 @@ class Focusable extends BaseFocusable<Props> {
|
|
|
42
44
|
this.resetLongPressTimeout = this.resetLongPressTimeout.bind(this);
|
|
43
45
|
this.longPress = this.longPress.bind(this);
|
|
44
46
|
this.press = this.press.bind(this);
|
|
47
|
+
|
|
48
|
+
this.accessibilityManager = AccessibilityManager.getInstance();
|
|
45
49
|
}
|
|
46
50
|
|
|
47
51
|
/**
|
|
@@ -128,6 +132,9 @@ class Focusable extends BaseFocusable<Props> {
|
|
|
128
132
|
const id = this.getId();
|
|
129
133
|
const focusableId = `focusable-${id}`;
|
|
130
134
|
|
|
135
|
+
const accessibilityProps =
|
|
136
|
+
this.accessibilityManager.getWebAccessibilityProps(this.props);
|
|
137
|
+
|
|
131
138
|
return (
|
|
132
139
|
<div
|
|
133
140
|
id={focusableId}
|
|
@@ -140,6 +147,7 @@ class Focusable extends BaseFocusable<Props> {
|
|
|
140
147
|
data-testid={focusableId}
|
|
141
148
|
focused-teststate={focused ? "focused" : "default"}
|
|
142
149
|
style={style}
|
|
150
|
+
{...accessibilityProps}
|
|
143
151
|
>
|
|
144
152
|
{children(focused, { mouse: this.mouse })}
|
|
145
153
|
</div>
|
|
@@ -47,7 +47,7 @@ export function FocusableView({ style, children, item, ...otherProps }: Props) {
|
|
|
47
47
|
|
|
48
48
|
const accessibilityManager = useAccessibilityManager({});
|
|
49
49
|
|
|
50
|
-
const { ttsLabel = "" } =
|
|
50
|
+
const { heading = "", ttsLabel = "" } =
|
|
51
51
|
actionContext?.initialEntryState(item)?.getAccessibility?.(item) || {};
|
|
52
52
|
|
|
53
53
|
const onPress = (event) => {
|
|
@@ -95,10 +95,12 @@ export function FocusableView({ style, children, item, ...otherProps }: Props) {
|
|
|
95
95
|
});
|
|
96
96
|
});
|
|
97
97
|
|
|
98
|
+
if (heading && ttsLabel) {
|
|
99
|
+
accessibilityManager.addHeading(heading);
|
|
100
|
+
}
|
|
101
|
+
|
|
98
102
|
if (ttsLabel) {
|
|
99
|
-
accessibilityManager.readText({
|
|
100
|
-
text: ttsLabel,
|
|
101
|
-
});
|
|
103
|
+
accessibilityManager.readText({ text: `${ttsLabel} button` });
|
|
102
104
|
}
|
|
103
105
|
};
|
|
104
106
|
|
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
exports[`<TextInputTv /> renders 1`] = `
|
|
4
4
|
<input
|
|
5
|
+
accessibilityProps={
|
|
6
|
+
{
|
|
7
|
+
"accessibilityHint": "Enter text into Search",
|
|
8
|
+
"accessibilityLabel": "Search",
|
|
9
|
+
"accessibilityRole": "text",
|
|
10
|
+
"accessible": true,
|
|
11
|
+
"aria-description": "Enter text into Search",
|
|
12
|
+
"aria-label": "Search",
|
|
13
|
+
"aria-role": "text",
|
|
14
|
+
"role": "text",
|
|
15
|
+
"tabindex": 0,
|
|
16
|
+
}
|
|
17
|
+
}
|
|
5
18
|
testID="TextInput-tv"
|
|
6
19
|
/>
|
|
7
20
|
`;
|
|
@@ -4,6 +4,7 @@ import { Appearance, Platform, StyleSheet, TextInput } from "react-native";
|
|
|
4
4
|
import { isFunction } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
5
5
|
import { isWeb } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
6
6
|
import { useIsRTL } from "@applicaster/zapp-react-native-utils/localizationUtils";
|
|
7
|
+
import { useAccessibilityManager } from "@applicaster/zapp-react-native-utils/appUtils/accessibilityManager/hooks";
|
|
7
8
|
|
|
8
9
|
type Props = Partial<{
|
|
9
10
|
style: any;
|
|
@@ -42,6 +43,8 @@ function TextInputTV(props: Props, ref) {
|
|
|
42
43
|
const [colorScheme, setColorScheme] = useState(getInitialColorScheme());
|
|
43
44
|
const isRTL = useIsRTL();
|
|
44
45
|
|
|
46
|
+
const accessibilityManager = useAccessibilityManager({});
|
|
47
|
+
|
|
45
48
|
const onColorChange = useCallback(
|
|
46
49
|
({ colorScheme: color }) => {
|
|
47
50
|
if (color !== colorScheme) {
|
|
@@ -153,6 +156,13 @@ function TextInputTV(props: Props, ref) {
|
|
|
153
156
|
])
|
|
154
157
|
)(props);
|
|
155
158
|
|
|
159
|
+
const getAccessibilityProps = () => {
|
|
160
|
+
return {
|
|
161
|
+
accessibilityProps:
|
|
162
|
+
accessibilityManager.getInputAccessibilityProps("Search"),
|
|
163
|
+
};
|
|
164
|
+
};
|
|
165
|
+
|
|
156
166
|
const inputProps = {
|
|
157
167
|
...getProps(),
|
|
158
168
|
...getStyle(),
|
|
@@ -161,6 +171,7 @@ function TextInputTV(props: Props, ref) {
|
|
|
161
171
|
...getSecureTextEntry(),
|
|
162
172
|
...getOnEndEditing(),
|
|
163
173
|
...getOnPress(),
|
|
174
|
+
...getAccessibilityProps(),
|
|
164
175
|
};
|
|
165
176
|
|
|
166
177
|
if (
|
package/events/index.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/zapp-react-native-ui-components",
|
|
3
|
-
"version": "13.0.
|
|
3
|
+
"version": "13.0.8-alpha.1940580104",
|
|
4
4
|
"description": "Applicaster Zapp React Native ui components for the Quick Brick App",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -31,10 +31,10 @@
|
|
|
31
31
|
"redux-mock-store": "^1.5.3"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@applicaster/applicaster-types": "13.0.
|
|
35
|
-
"@applicaster/zapp-react-native-bridge": "13.0.
|
|
36
|
-
"@applicaster/zapp-react-native-redux": "13.0.
|
|
37
|
-
"@applicaster/zapp-react-native-utils": "13.0.
|
|
34
|
+
"@applicaster/applicaster-types": "13.0.8-alpha.1940580104",
|
|
35
|
+
"@applicaster/zapp-react-native-bridge": "13.0.8-alpha.1940580104",
|
|
36
|
+
"@applicaster/zapp-react-native-redux": "13.0.8-alpha.1940580104",
|
|
37
|
+
"@applicaster/zapp-react-native-utils": "13.0.8-alpha.1940580104",
|
|
38
38
|
"promise": "^8.3.0",
|
|
39
39
|
"react-router-native": "^5.1.2",
|
|
40
40
|
"url": "^0.11.0",
|