@applicaster/zapp-react-native-ui-components 14.0.0-alpha.1661204539 → 14.0.0-alpha.1740013076
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/AnimatedInOut/index.tsx +5 -3
- package/Components/AudioPlayer/index.tsx +15 -0
- package/Components/AudioPlayer/mobile/Layout.tsx +66 -0
- package/Components/AudioPlayer/{__tests__/__snapshots__/audioPlayer.test.js.snap → mobile/__tests__/__snapshots__/audioPlayerMobileLayout.test.js.snap} +2 -2
- package/Components/AudioPlayer/mobile/__tests__/audioPlayerMobileLayout.test.js +18 -0
- package/Components/AudioPlayer/mobile/index.tsx +18 -0
- package/Components/AudioPlayer/tv/Artwork.tsx +41 -0
- package/Components/AudioPlayer/{Channel.tsx → tv/Channel.tsx} +7 -7
- package/Components/AudioPlayer/tv/Layout.tsx +168 -0
- package/Components/AudioPlayer/{Runtime.tsx → tv/Runtime.tsx} +9 -2
- package/Components/AudioPlayer/{Summary.tsx → tv/Summary.tsx} +17 -10
- package/Components/AudioPlayer/tv/Title.tsx +46 -0
- package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/Runtime.test.js.snap +4 -4
- package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/artWork.test.js.snap +9 -4
- package/Components/AudioPlayer/tv/__tests__/__snapshots__/audioPlayer.test.js.snap +164 -0
- package/Components/AudioPlayer/tv/__tests__/__snapshots__/channel.test.js.snap +19 -0
- package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/summary.test.js.snap +2 -3
- package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/title.test.js.snap +2 -3
- package/Components/AudioPlayer/{__tests__ → tv/__tests__}/audioPlayer.test.js +7 -3
- package/Components/AudioPlayer/{helpers.tsx → tv/helpers.tsx} +13 -7
- package/Components/AudioPlayer/{AudioPlayer.tsx → tv/index.tsx} +18 -57
- package/Components/AudioPlayer/types.ts +40 -0
- package/Components/BaseFocusable/index.tsx +23 -12
- package/Components/Cell/Cell.tsx +91 -64
- package/Components/Cell/CellWithFocusable.tsx +3 -0
- package/Components/Cell/__tests__/CellWIthFocusable.test.js +3 -2
- package/Components/Cell/index.js +7 -3
- package/Components/ComponentResolver/index.ts +1 -1
- package/Components/FeedLoader/FeedLoader.tsx +7 -16
- package/Components/FeedLoader/FeedLoaderHOC.tsx +21 -0
- package/Components/FeedLoader/index.js +2 -8
- package/Components/Focusable/Focusable.tsx +12 -3
- package/Components/Focusable/FocusableTvOS.tsx +5 -5
- package/Components/Focusable/FocusableiOS.tsx +2 -2
- package/Components/Focusable/__tests__/index.android.test.tsx +3 -0
- package/Components/Focusable/index.android.tsx +12 -8
- package/Components/Focusable/index.tsx +1 -1
- package/Components/FocusableGroup/FocusableTvOS.tsx +1 -1
- package/Components/FocusableList/index.tsx +6 -2
- package/Components/FreezeWithCallback/__tests__/index.test.tsx +67 -43
- package/Components/GeneralContentScreen/GeneralContentScreen.tsx +0 -2
- package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +42 -59
- package/Components/GeneralContentScreen/utils/useCurationAPI.ts +13 -10
- package/Components/HandlePlayable/HandlePlayable.tsx +25 -9
- package/Components/Layout/TV/LayoutBackground.tsx +1 -1
- package/Components/Layout/TV/__tests__/index.test.tsx +0 -1
- package/Components/MasterCell/DefaultComponents/ActionButton.tsx +6 -2
- package/Components/MasterCell/DefaultComponents/Button.tsx +1 -1
- package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +4 -39
- package/Components/MasterCell/DefaultComponents/Image/hoc/withDimensions.tsx +1 -1
- package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +1 -1
- package/Components/MasterCell/DefaultComponents/Text/index.tsx +27 -6
- package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +10 -10
- package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +18 -18
- package/Components/MasterCell/SharedUI/CollapsibleTextContainer/__tests__/index.test.tsx +10 -10
- package/Components/MasterCell/elementMapper.tsx +1 -2
- package/Components/MasterCell/index.tsx +1 -1
- package/Components/MasterCell/utils/behaviorProvider.ts +19 -6
- package/Components/MasterCell/utils/index.ts +9 -13
- package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +13 -18
- package/Components/OfflineHandler/__tests__/__snapshots__/index.test.tsx.snap +9 -0
- package/Components/OfflineHandler/__tests__/index.test.tsx +26 -35
- package/Components/PlayerContainer/ErrorDisplay/index.ts +1 -1
- package/Components/PlayerContainer/PlayerContainer.tsx +66 -67
- package/Components/PlayerContainer/ProgramInfo/index.tsx +1 -1
- package/Components/PlayerContainer/index.ts +1 -1
- package/Components/PlayerImageBackground/index.tsx +1 -1
- package/Components/River/ComponentsMap/ComponentsMap.tsx +1 -6
- package/Components/River/ComponentsMap/hooks/__tests__/useLoadingState.test.ts +378 -0
- package/Components/River/ComponentsMap/hooks/useLoadingState.ts +2 -2
- package/Components/River/RefreshControl.tsx +11 -17
- package/Components/River/RiverItem.tsx +8 -8
- package/Components/River/TV/River.tsx +2 -20
- package/Components/River/TV/index.tsx +3 -1
- package/Components/River/TV/withPipesV1DataLoader.tsx +43 -0
- package/Components/River/TV/withRiverDataLoader.tsx +17 -0
- package/Components/River/TV/withTVEventHandler.tsx +1 -1
- package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +2 -6
- package/Components/River/__tests__/river.test.js +12 -26
- package/Components/River/index.tsx +1 -1
- package/Components/Screen/__tests__/Screen.test.tsx +28 -29
- package/Components/Screen/__tests__/navigationHandler.test.ts +133 -22
- package/Components/Screen/navigationHandler.ts +20 -2
- package/Components/ScreenRevealManager/ScreenRevealManager.ts +76 -0
- package/Components/ScreenRevealManager/__tests__/ScreenRevealManager.test.ts +107 -0
- package/Components/ScreenRevealManager/__tests__/withScreenRevealManager.test.tsx +96 -0
- package/Components/ScreenRevealManager/index.ts +1 -0
- package/Components/ScreenRevealManager/withScreenRevealManager.tsx +79 -0
- package/Components/Tabs/TV/Tabs.android.tsx +1 -3
- package/Components/Tabs/Tabs.tsx +2 -3
- package/Components/TextInputTv/__tests__/__snapshots__/TextInputTv.test.js.snap +13 -0
- package/Components/TextInputTv/index.tsx +11 -0
- package/Components/TopMarginApplicator/TopMarginApplicator.tsx +16 -15
- package/Components/Touchable/__tests__/__snapshots__/touchable.test.tsx.snap +34 -0
- package/Components/Touchable/__tests__/touchable.test.tsx +12 -17
- package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +15 -9
- package/Components/VideoLive/animationUtils.ts +3 -3
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +3 -9
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.web.tsx +294 -0
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.web.tsx +93 -0
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +32 -8
- package/Components/VideoModal/PlayerDetails.tsx +24 -2
- package/Components/VideoModal/PlayerWrapper.tsx +26 -142
- package/Components/VideoModal/VideoModal.tsx +3 -17
- package/Components/VideoModal/__tests__/PlayerDetails.test.tsx +5 -5
- package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +1 -7
- package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +44 -180
- package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +17 -55
- package/Components/VideoModal/hooks/index.ts +0 -2
- package/Components/VideoModal/hooks/useDelayedPlayerDetails.ts +15 -26
- package/Components/VideoModal/hooks/useModalSize.ts +18 -2
- package/Components/VideoModal/utils.ts +6 -0
- package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +12 -16
- package/Components/Viewport/ViewportTracker/__tests__/viewportTracker.test.js +84 -24
- package/Components/Viewport/VisibilitySensor/VisibilitySensor.tsx +3 -3
- package/Components/default-cell-renderer/viewTrees/tv/DefaultCell/index.ts +3 -3
- package/Contexts/CellFocusedStateContext/index.tsx +27 -0
- package/Contexts/ConfigutaionContext/__tests__/ConfigurationProvider.test.tsx +3 -3
- package/Contexts/ScreenContext/index.tsx +46 -6
- package/Decorators/ConfigurationWrapper/__tests__/withConfigurationProvider.test.tsx +3 -3
- package/Decorators/ConfigurationWrapper/withConfigurationProvider.tsx +2 -2
- package/Decorators/RiverFeedLoader/__tests__/__snapshots__/riverFeedLoader.test.tsx.snap +221 -209
- package/Decorators/RiverFeedLoader/__tests__/riverFeedLoader.test.tsx +14 -16
- package/Decorators/RiverFeedLoader/__tests__/utils.test.ts +0 -20
- package/Decorators/RiverFeedLoader/index.tsx +21 -9
- package/Decorators/RiverFeedLoader/utils/index.ts +0 -23
- package/Decorators/RiverResolver/__tests__/riverResolver.test.tsx +3 -6
- package/Decorators/ZappPipesDataConnector/ResolverSelector.tsx +25 -0
- package/Decorators/ZappPipesDataConnector/__tests__/NullFeedResolver.test.tsx +78 -0
- package/Decorators/ZappPipesDataConnector/__tests__/ResolverSelector.test.tsx +205 -0
- package/Decorators/ZappPipesDataConnector/__tests__/StaticFeedResolver.test.tsx +251 -0
- package/Decorators/ZappPipesDataConnector/__tests__/UrlFeedResolver.test.tsx +368 -0
- package/Decorators/ZappPipesDataConnector/__tests__/utils.test.ts +39 -0
- package/Decorators/ZappPipesDataConnector/index.tsx +27 -308
- package/Decorators/ZappPipesDataConnector/resolvers/NullFeedResolver.tsx +25 -0
- package/Decorators/ZappPipesDataConnector/resolvers/StaticFeedResolver.tsx +87 -0
- package/Decorators/ZappPipesDataConnector/resolvers/UrlFeedResolver.tsx +266 -0
- package/Decorators/ZappPipesDataConnector/types.ts +29 -0
- package/Decorators/ZappPipesDataConnector/utils/mongoFilter.ts +738 -0
- package/Decorators/ZappPipesDataConnector/utils/useFilter.tsx +157 -0
- package/events/index.ts +1 -0
- package/index.d.ts +0 -1
- package/package.json +5 -10
- package/Components/AudioPlayer/Artwork.tsx +0 -35
- package/Components/AudioPlayer/AudioPlayerLayout.tsx +0 -202
- package/Components/AudioPlayer/Title.tsx +0 -39
- package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayerLayout.test.js.snap +0 -66
- package/Components/AudioPlayer/__tests__/__snapshots__/channel.test.js.snap +0 -28
- package/Components/AudioPlayer/__tests__/audioPlayerLayout.test.js +0 -26
- package/Components/AudioPlayer/index.ts +0 -1
- package/Components/River/__tests__/__snapshots__/river.test.js.snap +0 -27
- package/Components/VideoModal/hooks/useBackgroundColor.ts +0 -10
- /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/Runtime.test.js +0 -0
- /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/artWork.test.js +0 -0
- /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/channel.test.js +0 -0
- /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/summary.test.js +0 -0
- /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/title.test.js +0 -0
package/Components/Cell/Cell.tsx
CHANGED
|
@@ -8,6 +8,7 @@ import { getItemType } from "@applicaster/zapp-react-native-utils/navigationUtil
|
|
|
8
8
|
import { SCREEN_TYPES } from "@applicaster/zapp-react-native-utils/navigationUtils/itemTypes";
|
|
9
9
|
import { sendSelectCellEvent } from "@applicaster/zapp-react-native-utils/analyticsUtils";
|
|
10
10
|
import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
11
|
+
import { CellFocusedStateContextProvider } from "@applicaster/zapp-react-native-ui-components/Contexts/CellFocusedStateContext";
|
|
11
12
|
|
|
12
13
|
import { CellWithFocusable } from "./CellWithFocusable";
|
|
13
14
|
import { BaseFocusable } from "../BaseFocusable";
|
|
@@ -15,6 +16,7 @@ import { AccessibilityManager } from "@applicaster/zapp-react-native-utils/appUt
|
|
|
15
16
|
import { styles } from "./styles";
|
|
16
17
|
|
|
17
18
|
type Props = {
|
|
19
|
+
dataLength: number;
|
|
18
20
|
item: ZappEntry;
|
|
19
21
|
index: number;
|
|
20
22
|
shouldScrollHorizontally: (arg1: [any]) => boolean | null | undefined;
|
|
@@ -67,9 +69,12 @@ type Props = {
|
|
|
67
69
|
|
|
68
70
|
type State = {
|
|
69
71
|
hasFocusableInside: boolean;
|
|
72
|
+
cellFocused: boolean;
|
|
70
73
|
};
|
|
71
74
|
|
|
72
75
|
export class CellComponent extends React.Component<Props, State> {
|
|
76
|
+
accessibilityManager: AccessibilityManager;
|
|
77
|
+
|
|
73
78
|
constructor(props) {
|
|
74
79
|
super(props);
|
|
75
80
|
this.onPress = this.onPress.bind(this);
|
|
@@ -79,10 +84,14 @@ export class CellComponent extends React.Component<Props, State> {
|
|
|
79
84
|
this.hasReceivedFocus = this.hasReceivedFocus.bind(this);
|
|
80
85
|
this.scrollVertically = this.scrollVertically.bind(this);
|
|
81
86
|
this.scrollToIndex = this.scrollToIndex.bind(this);
|
|
87
|
+
this.handleAccessibilityFocus = this.handleAccessibilityFocus.bind(this);
|
|
82
88
|
|
|
83
89
|
this.state = {
|
|
84
90
|
hasFocusableInside: props.CellRenderer.hasFocusableInside?.(props.item),
|
|
91
|
+
cellFocused: false,
|
|
85
92
|
};
|
|
93
|
+
|
|
94
|
+
this.accessibilityManager = AccessibilityManager.getInstance();
|
|
86
95
|
}
|
|
87
96
|
|
|
88
97
|
setScreenLayout(componentAnchorPointY, screenLayout) {
|
|
@@ -130,6 +139,8 @@ export class CellComponent extends React.Component<Props, State> {
|
|
|
130
139
|
} = this.props;
|
|
131
140
|
|
|
132
141
|
if (isFocusable) {
|
|
142
|
+
this.setState({ cellFocused: true });
|
|
143
|
+
|
|
133
144
|
if (
|
|
134
145
|
shouldUpdate &&
|
|
135
146
|
shouldScrollVertically?.(mouse, focusable, id, title)
|
|
@@ -139,7 +150,9 @@ export class CellComponent extends React.Component<Props, State> {
|
|
|
139
150
|
}
|
|
140
151
|
}
|
|
141
152
|
|
|
142
|
-
onBlur() {
|
|
153
|
+
onBlur() {
|
|
154
|
+
this.setState({ cellFocused: false });
|
|
155
|
+
}
|
|
143
156
|
|
|
144
157
|
willReceiveFocus() {}
|
|
145
158
|
|
|
@@ -183,6 +196,25 @@ export class CellComponent extends React.Component<Props, State> {
|
|
|
183
196
|
return !isFocusable ? false : focused || focusableFocused;
|
|
184
197
|
}
|
|
185
198
|
|
|
199
|
+
handleAccessibilityFocus(index, dataLength) {
|
|
200
|
+
// For loop scrolling, calculate the correct logical index
|
|
201
|
+
const logicalIndex = dataLength ? index % dataLength : index;
|
|
202
|
+
|
|
203
|
+
const positionLabel = dataLength
|
|
204
|
+
? `item ${logicalIndex + 1} of ${dataLength}`
|
|
205
|
+
: "";
|
|
206
|
+
|
|
207
|
+
if (this.state.hasFocusableInside) {
|
|
208
|
+
this.accessibilityManager.readText({
|
|
209
|
+
text: " ",
|
|
210
|
+
});
|
|
211
|
+
} else {
|
|
212
|
+
this.accessibilityManager.readText({
|
|
213
|
+
text: `${positionLabel}`,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
186
218
|
componentDidUpdate(prevProps: Readonly<Props>) {
|
|
187
219
|
if (prevProps.item !== this.props.item) {
|
|
188
220
|
this.setState({
|
|
@@ -191,6 +223,8 @@ export class CellComponent extends React.Component<Props, State> {
|
|
|
191
223
|
),
|
|
192
224
|
});
|
|
193
225
|
}
|
|
226
|
+
|
|
227
|
+
this.handleAccessibilityFocus(this.props.index, this.props.dataLength);
|
|
194
228
|
}
|
|
195
229
|
|
|
196
230
|
render() {
|
|
@@ -212,7 +246,6 @@ export class CellComponent extends React.Component<Props, State> {
|
|
|
212
246
|
} = this.props;
|
|
213
247
|
|
|
214
248
|
const { id } = item;
|
|
215
|
-
|
|
216
249
|
const focusableId = join("-", [component?.id, id, index]);
|
|
217
250
|
|
|
218
251
|
const handleFocus = (focusable, mouse) => {
|
|
@@ -223,73 +256,67 @@ export class CellComponent extends React.Component<Props, State> {
|
|
|
223
256
|
|
|
224
257
|
if (this.state.hasFocusableInside) {
|
|
225
258
|
return (
|
|
226
|
-
<
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
259
|
+
<CellFocusedStateContextProvider cellFocused={this.state.cellFocused}>
|
|
260
|
+
<CellWithFocusable
|
|
261
|
+
CellRenderer={CellRenderer}
|
|
262
|
+
item={item}
|
|
263
|
+
id={focusableId}
|
|
264
|
+
groupId={groupId || component?.id}
|
|
265
|
+
onFocus={handleFocus}
|
|
266
|
+
onBlur={onBlur || this.onBlur}
|
|
267
|
+
index={index}
|
|
268
|
+
scrollTo={this.scrollToIndex()}
|
|
269
|
+
isFocusable={isFocusable}
|
|
270
|
+
skipFocusManagerRegistration={skipFocusManagerRegistration}
|
|
271
|
+
behavior={behavior}
|
|
272
|
+
/>
|
|
273
|
+
</CellFocusedStateContextProvider>
|
|
238
274
|
);
|
|
239
275
|
}
|
|
240
276
|
|
|
241
277
|
return (
|
|
242
|
-
<
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
<Focusable
|
|
248
|
-
id={focusableId}
|
|
249
|
-
groupId={groupId || component?.id}
|
|
250
|
-
onFocus={handleFocus}
|
|
251
|
-
onBlur={onBlur || this.onBlur}
|
|
252
|
-
onPress={this.onPress}
|
|
253
|
-
willReceiveFocus={willReceiveFocus || this.willReceiveFocus}
|
|
254
|
-
hasReceivedFocus={hasReceivedFocus || this.hasReceivedFocus}
|
|
255
|
-
preferredFocus={preferredFocus}
|
|
256
|
-
offsetUpdater={offsetUpdater}
|
|
257
|
-
style={styles.baseCell}
|
|
258
|
-
isFocusable={isFocusable}
|
|
259
|
-
skipFocusManagerRegistration={skipFocusManagerRegistration}
|
|
278
|
+
<CellFocusedStateContextProvider cellFocused={this.state.cellFocused}>
|
|
279
|
+
<View
|
|
280
|
+
testID={`${component?.id}-${id}`}
|
|
281
|
+
accessible={false}
|
|
282
|
+
style={styles.touchableCell}
|
|
260
283
|
>
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
284
|
+
<Focusable
|
|
285
|
+
id={focusableId}
|
|
286
|
+
groupId={groupId || component?.id}
|
|
287
|
+
onFocus={handleFocus}
|
|
288
|
+
onBlur={onBlur || this.onBlur}
|
|
289
|
+
onPress={this.onPress}
|
|
290
|
+
willReceiveFocus={willReceiveFocus || this.willReceiveFocus}
|
|
291
|
+
hasReceivedFocus={hasReceivedFocus || this.hasReceivedFocus}
|
|
292
|
+
preferredFocus={preferredFocus}
|
|
293
|
+
offsetUpdater={offsetUpdater}
|
|
294
|
+
style={styles.baseCell}
|
|
295
|
+
isFocusable={isFocusable}
|
|
296
|
+
skipFocusManagerRegistration={skipFocusManagerRegistration}
|
|
297
|
+
{...this.accessibilityManager.getButtonAccessibilityProps(
|
|
298
|
+
item?.extensions?.accessibility?.label || item?.title
|
|
299
|
+
)}
|
|
300
|
+
>
|
|
301
|
+
{(focused, event) => {
|
|
302
|
+
const isFocused = this.isCellFocused(focused);
|
|
303
|
+
|
|
304
|
+
return (
|
|
305
|
+
<FocusableCell
|
|
306
|
+
{...{
|
|
307
|
+
index,
|
|
308
|
+
CellRenderer,
|
|
309
|
+
item,
|
|
310
|
+
focused: isFocused,
|
|
311
|
+
scrollTo: this.scrollToIndex(event),
|
|
312
|
+
behavior,
|
|
313
|
+
}}
|
|
314
|
+
/>
|
|
315
|
+
);
|
|
316
|
+
}}
|
|
317
|
+
</Focusable>
|
|
318
|
+
</View>
|
|
319
|
+
</CellFocusedStateContextProvider>
|
|
293
320
|
);
|
|
294
321
|
}
|
|
295
322
|
}
|
|
@@ -14,6 +14,7 @@ type Props = {
|
|
|
14
14
|
id: string;
|
|
15
15
|
groupId: string;
|
|
16
16
|
onFocus: Function;
|
|
17
|
+
onBlur?: Function;
|
|
17
18
|
index: number;
|
|
18
19
|
scrollTo: Function;
|
|
19
20
|
preferredFocus?: boolean;
|
|
@@ -33,6 +34,7 @@ export function CellWithFocusable(props: Props) {
|
|
|
33
34
|
id,
|
|
34
35
|
groupId,
|
|
35
36
|
onFocus,
|
|
37
|
+
onBlur = noop,
|
|
36
38
|
scrollTo = noop,
|
|
37
39
|
preferredFocus,
|
|
38
40
|
skipFocusManagerRegistration,
|
|
@@ -78,6 +80,7 @@ export function CellWithFocusable(props: Props) {
|
|
|
78
80
|
const onGroupBlur = React.useCallback(() => {
|
|
79
81
|
if (!skipFocusManagerRegistration) {
|
|
80
82
|
setIsFocused(false);
|
|
83
|
+
onBlur?.();
|
|
81
84
|
}
|
|
82
85
|
}, [skipFocusManagerRegistration]);
|
|
83
86
|
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { View } from "react-native";
|
|
2
2
|
import React from "react";
|
|
3
|
-
import { act
|
|
3
|
+
import { act } from "@testing-library/react-native";
|
|
4
4
|
import { CellWithFocusable } from "../CellWithFocusable.tsx";
|
|
5
5
|
|
|
6
6
|
import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils/focusManager";
|
|
7
|
+
import { renderWithProviders } from "@applicaster/zapp-react-native-utils/testUtils/index.tsx";
|
|
7
8
|
|
|
8
9
|
const renderWith = (props) => {
|
|
9
|
-
return
|
|
10
|
+
return renderWithProviders(<CellWithFocusable {...props} />);
|
|
10
11
|
};
|
|
11
12
|
|
|
12
13
|
describe("CellWithFocusable", () => {
|
package/Components/Cell/index.js
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import * as R from "ramda";
|
|
2
2
|
|
|
3
|
-
import { connectToStore } from "@applicaster/zapp-react-native-redux";
|
|
3
|
+
import { connectToStore } from "@applicaster/zapp-react-native-redux/utils/connectToStore";
|
|
4
4
|
import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
HorizontalScrollContext,
|
|
8
|
+
RiverOffsetContext,
|
|
9
|
+
ScreenScrollingContext,
|
|
10
|
+
} from "../../Contexts";
|
|
11
|
+
|
|
7
12
|
import { CellComponent } from "./Cell";
|
|
8
13
|
import { TvOSCellComponent } from "./TvOSCellComponent";
|
|
9
14
|
import { withConsumer } from "../../Contexts/HeaderOffsetContext";
|
|
10
|
-
import { ScreenScrollingContext } from "../../Contexts/ScreenScrollingContext";
|
|
11
15
|
|
|
12
16
|
import { ScreenLayoutContextConsumer } from "../../Contexts/ScreenLayoutContext";
|
|
13
17
|
import { createContext } from "@applicaster/zapp-react-native-utils/reactUtils/createContext";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as R from "ramda";
|
|
2
2
|
|
|
3
|
-
import { connectToStore } from "@applicaster/zapp-react-native-redux";
|
|
3
|
+
import { connectToStore } from "@applicaster/zapp-react-native-redux/utils/connectToStore";
|
|
4
4
|
|
|
5
5
|
import { ComponentResolverComponent } from "./ComponentResolver";
|
|
6
6
|
|
|
@@ -1,25 +1,16 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import * as R from "ramda";
|
|
3
|
+
import { selectZappPipes } from "@applicaster/zapp-react-native-redux";
|
|
3
4
|
|
|
4
5
|
type Props = {
|
|
5
|
-
zappPipes:
|
|
6
|
-
loadPipesData:
|
|
7
|
-
feed
|
|
8
|
-
|
|
9
|
-
clearCache: boolean;
|
|
10
|
-
meta: any;
|
|
11
|
-
loadLocalFavorites: boolean;
|
|
12
|
-
silentRefresh: boolean;
|
|
13
|
-
parentFeed: ZappFeed;
|
|
14
|
-
callback: () => void;
|
|
15
|
-
bodyParams: any;
|
|
16
|
-
riverId: string;
|
|
17
|
-
}>
|
|
18
|
-
) => void;
|
|
6
|
+
zappPipes: ReturnType<typeof selectZappPipes>;
|
|
7
|
+
loadPipesData: ReturnType<
|
|
8
|
+
typeof import("@applicaster/zapp-react-native-utils/reactHooks/feed").useLoadPipesDataDispatch
|
|
9
|
+
>;
|
|
19
10
|
feedUrl: string;
|
|
20
|
-
children: (feed: ZappFeed) => React.
|
|
11
|
+
children: (feed: ZappFeed) => React.ReactNode;
|
|
21
12
|
onFeedLoaded: (feed: ZappFeed) => {};
|
|
22
|
-
onError: (
|
|
13
|
+
onError: (error: ZappPipesData["error"]) => {};
|
|
23
14
|
refreshing: boolean;
|
|
24
15
|
refreshCallback: () => void;
|
|
25
16
|
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {
|
|
3
|
+
selectZappPipes,
|
|
4
|
+
useAppSelector,
|
|
5
|
+
} from "@applicaster/zapp-react-native-redux";
|
|
6
|
+
import { useLoadPipesDataDispatch } from "@applicaster/zapp-react-native-utils/reactHooks/feed";
|
|
7
|
+
|
|
8
|
+
export const FeedLoaderHOC = (_Component: any) => {
|
|
9
|
+
return function FeedLoaderHOC(props: any) {
|
|
10
|
+
const zappPipes = useAppSelector(selectZappPipes);
|
|
11
|
+
const loadPipesData = useLoadPipesDataDispatch();
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<_Component
|
|
15
|
+
{...props}
|
|
16
|
+
zappPipes={zappPipes}
|
|
17
|
+
loadPipesData={loadPipesData}
|
|
18
|
+
/>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
};
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
import * as R from "ramda";
|
|
2
|
-
|
|
3
|
-
import { connectToStore } from "@applicaster/zapp-react-native-redux";
|
|
4
|
-
import { loadPipesData } from "@applicaster/zapp-react-native-redux/ZappPipes";
|
|
5
|
-
|
|
6
1
|
import { FeedLoaderComponent } from "./FeedLoader";
|
|
2
|
+
import { FeedLoaderHOC } from "./FeedLoaderHOC";
|
|
7
3
|
|
|
8
|
-
export const FeedLoader =
|
|
9
|
-
loadPipesData,
|
|
10
|
-
})(FeedLoaderComponent);
|
|
4
|
+
export const FeedLoader = FeedLoaderHOC(FeedLoaderComponent);
|
|
@@ -5,6 +5,8 @@ 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 { StyleSheet, ViewStyle } from "react-native";
|
|
9
|
+
import { AccessibilityManager } from "@applicaster/zapp-react-native-utils/appUtils/accessibilityManager";
|
|
8
10
|
|
|
9
11
|
type Props = {
|
|
10
12
|
initialFocus?: boolean;
|
|
@@ -19,15 +21,16 @@ type Props = {
|
|
|
19
21
|
onPressOut?: () => void;
|
|
20
22
|
onLongPress?: () => void;
|
|
21
23
|
handleFocus?: ({ mouse }: { mouse: boolean }) => void;
|
|
22
|
-
children: (boolean, string) => React.
|
|
24
|
+
children: (boolean, string) => React.ReactNode;
|
|
23
25
|
selected?: boolean;
|
|
24
|
-
style?:
|
|
26
|
+
style?: ViewStyle[] | ViewStyle;
|
|
25
27
|
};
|
|
26
28
|
|
|
27
29
|
class Focusable extends BaseFocusable<Props> {
|
|
28
30
|
isGroup: boolean;
|
|
29
31
|
mouse: boolean;
|
|
30
32
|
longPressTimeout = null;
|
|
33
|
+
accessibilityManager: AccessibilityManager;
|
|
31
34
|
|
|
32
35
|
constructor(props) {
|
|
33
36
|
super(props);
|
|
@@ -42,6 +45,8 @@ class Focusable extends BaseFocusable<Props> {
|
|
|
42
45
|
this.resetLongPressTimeout = this.resetLongPressTimeout.bind(this);
|
|
43
46
|
this.longPress = this.longPress.bind(this);
|
|
44
47
|
this.press = this.press.bind(this);
|
|
48
|
+
|
|
49
|
+
this.accessibilityManager = AccessibilityManager.getInstance();
|
|
45
50
|
}
|
|
46
51
|
|
|
47
52
|
/**
|
|
@@ -128,6 +133,9 @@ class Focusable extends BaseFocusable<Props> {
|
|
|
128
133
|
const id = this.getId();
|
|
129
134
|
const focusableId = `focusable-${id}`;
|
|
130
135
|
|
|
136
|
+
const accessibilityProps =
|
|
137
|
+
this.accessibilityManager.getWebAccessibilityProps(this.props);
|
|
138
|
+
|
|
131
139
|
return (
|
|
132
140
|
<div
|
|
133
141
|
id={focusableId}
|
|
@@ -139,7 +147,8 @@ class Focusable extends BaseFocusable<Props> {
|
|
|
139
147
|
onMouseUp={this.pressOut}
|
|
140
148
|
data-testid={focusableId}
|
|
141
149
|
focused-teststate={focused ? "focused" : "default"}
|
|
142
|
-
style={style}
|
|
150
|
+
style={StyleSheet.flatten(style) as any as React.CSSProperties}
|
|
151
|
+
{...accessibilityProps}
|
|
143
152
|
>
|
|
144
153
|
{children(focused, { mouse: this.mouse })}
|
|
145
154
|
</div>
|
|
@@ -16,10 +16,10 @@ function noop() {}
|
|
|
16
16
|
type Props = {
|
|
17
17
|
id: string;
|
|
18
18
|
groupId: string;
|
|
19
|
-
onPress?: (nativeEvent:
|
|
20
|
-
onFocus?: (nativeEvent:
|
|
21
|
-
onBlur?: (nativeEvent:
|
|
22
|
-
children: (focused?: boolean) => React.ReactNode;
|
|
19
|
+
onPress?: (nativeEvent: any) => void;
|
|
20
|
+
onFocus?: (nativeEvent: any) => void;
|
|
21
|
+
onBlur?: (nativeEvent: any) => void;
|
|
22
|
+
children: ((focused?: boolean) => React.ReactNode) | React.ReactNode;
|
|
23
23
|
isParallaxDisabled: boolean;
|
|
24
24
|
preferredFocus?: boolean;
|
|
25
25
|
selected?: boolean;
|
|
@@ -204,7 +204,7 @@ export class Focusable extends BaseFocusable<Props> {
|
|
|
204
204
|
{...this.nextFocusableReactTags}
|
|
205
205
|
{...otherProps}
|
|
206
206
|
>
|
|
207
|
-
{
|
|
207
|
+
{typeof children === "function" ? children(focused) : children}
|
|
208
208
|
</FocusableItemNative>
|
|
209
209
|
);
|
|
210
210
|
}
|
|
@@ -2,7 +2,7 @@ import React from "react";
|
|
|
2
2
|
|
|
3
3
|
type Props = {
|
|
4
4
|
children: () => React.ReactNode;
|
|
5
|
-
}
|
|
5
|
+
} & Record<string, any>;
|
|
6
6
|
|
|
7
7
|
function FocusableiOSComponent({ children }: Props) {
|
|
8
8
|
if (typeof children === "function") {
|
|
@@ -12,4 +12,4 @@ function FocusableiOSComponent({ children }: Props) {
|
|
|
12
12
|
return children;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
export const FocusableiOS =
|
|
15
|
+
export const FocusableiOS = FocusableiOSComponent;
|
|
@@ -38,6 +38,9 @@ describe("Focusable", () => {
|
|
|
38
38
|
});
|
|
39
39
|
|
|
40
40
|
it("updates disableFocus state when disableFocus prop changes", () => {
|
|
41
|
+
const unregister = jest.fn();
|
|
42
|
+
mockFocusManager.registerFocusable.mockReturnValue(unregister);
|
|
43
|
+
|
|
41
44
|
const { rerender } = render(
|
|
42
45
|
<Focusable id="test-id" disableFocus={false}>
|
|
43
46
|
<Touchable testID="touchable" />
|
|
@@ -43,11 +43,13 @@ export const FocusableContext = React.createContext<
|
|
|
43
43
|
// eslint-disable-next-line
|
|
44
44
|
setIsFocusable: (enableFocus: boolean) => void;
|
|
45
45
|
ref: FocusManager.FocusableRef;
|
|
46
|
+
parentFocusableId: Option<string>;
|
|
46
47
|
} & ParentFocus
|
|
47
48
|
>({
|
|
48
49
|
focused: false,
|
|
49
50
|
setIsFocusable: () => {},
|
|
50
51
|
ref: { current: null },
|
|
52
|
+
parentFocusableId: undefined,
|
|
51
53
|
});
|
|
52
54
|
|
|
53
55
|
export const useFocusable = () => React.useContext(FocusableContext);
|
|
@@ -74,7 +76,7 @@ function FocusableComponent(props: Props, forwardedRef) {
|
|
|
74
76
|
|
|
75
77
|
const isRTL = useIsRTL();
|
|
76
78
|
const focusManager = useFocusManager();
|
|
77
|
-
const { ref:
|
|
79
|
+
const { ref: parentFocusableRef, parentFocusableId } = useFocusable();
|
|
78
80
|
const touchableRef = React.useRef(null);
|
|
79
81
|
|
|
80
82
|
const [focused, setFocused] = React.useState(() =>
|
|
@@ -98,13 +100,14 @@ function FocusableComponent(props: Props, forwardedRef) {
|
|
|
98
100
|
}
|
|
99
101
|
}, [disableFocus]);
|
|
100
102
|
|
|
101
|
-
React.
|
|
103
|
+
React.useLayoutEffect(() => {
|
|
102
104
|
if (id) {
|
|
103
|
-
const unregister = focusManager.registerFocusable(
|
|
105
|
+
const unregister = focusManager.registerFocusable({
|
|
104
106
|
touchableRef,
|
|
105
|
-
|
|
106
|
-
isFocusableCell
|
|
107
|
-
|
|
107
|
+
parentFocusableRef,
|
|
108
|
+
isFocusableCell,
|
|
109
|
+
parentFocusableId,
|
|
110
|
+
});
|
|
108
111
|
|
|
109
112
|
onRegister();
|
|
110
113
|
|
|
@@ -112,7 +115,7 @@ function FocusableComponent(props: Props, forwardedRef) {
|
|
|
112
115
|
unregister();
|
|
113
116
|
};
|
|
114
117
|
}
|
|
115
|
-
}, [id, onRegister, isFocusableCell]);
|
|
118
|
+
}, [id, onRegister, isFocusableCell, parentFocusableId]);
|
|
116
119
|
|
|
117
120
|
if (R.isNil(id)) {
|
|
118
121
|
// eslint-disable-next-line no-console
|
|
@@ -164,8 +167,9 @@ function FocusableComponent(props: Props, forwardedRef) {
|
|
|
164
167
|
...parentFocus,
|
|
165
168
|
ref: touchableRef,
|
|
166
169
|
setIsFocusable,
|
|
170
|
+
parentFocusableId: id,
|
|
167
171
|
};
|
|
168
|
-
}, [parentFocus, focused]);
|
|
172
|
+
}, [parentFocus, focused, id]);
|
|
169
173
|
|
|
170
174
|
return (
|
|
171
175
|
<Touchable
|
|
@@ -4,7 +4,7 @@ import { FocusableiOS } from "./FocusableiOS";
|
|
|
4
4
|
|
|
5
5
|
import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
6
6
|
|
|
7
|
-
export const Focusable = platformSelect({
|
|
7
|
+
export const Focusable: React.ComponentType<any> = platformSelect({
|
|
8
8
|
tvos: FocusableTvOS,
|
|
9
9
|
ios: FocusableiOS,
|
|
10
10
|
default: FocusableDefault,
|
|
@@ -20,11 +20,11 @@ import { FocusableScrollView } from "../FocusableScrollView";
|
|
|
20
20
|
const mapIndexed = R.addIndex(R.map);
|
|
21
21
|
|
|
22
22
|
export type IListRenderItem<ItemT> = (
|
|
23
|
-
info:
|
|
23
|
+
info: {
|
|
24
24
|
focused: boolean;
|
|
25
25
|
onLoadFinished: () => void;
|
|
26
26
|
onLoadFailed: () => void;
|
|
27
|
-
}
|
|
27
|
+
} & IListRenderItemInfo<ItemT>
|
|
28
28
|
) => React.ReactElement | null;
|
|
29
29
|
|
|
30
30
|
export const getFocusableId = (parentId, index) =>
|
|
@@ -91,6 +91,7 @@ function FocusableListComponent<ItemT>(props: Props<ItemT>, ref) {
|
|
|
91
91
|
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
92
92
|
omitPropsPropagation = [],
|
|
93
93
|
useScrollView = false,
|
|
94
|
+
onScrollToIndexFailed = noop,
|
|
94
95
|
} = props;
|
|
95
96
|
|
|
96
97
|
useCheckItemIdsForUnique({ componentId: props.id, items: data });
|
|
@@ -277,6 +278,7 @@ function FocusableListComponent<ItemT>(props: Props<ItemT>, ref) {
|
|
|
277
278
|
"withStateMemory",
|
|
278
279
|
"useSequentialLoading",
|
|
279
280
|
"useScrollView",
|
|
281
|
+
"onScrollToIndexFailed",
|
|
280
282
|
...omitPropsPropagation,
|
|
281
283
|
],
|
|
282
284
|
R.__
|
|
@@ -305,6 +307,7 @@ function FocusableListComponent<ItemT>(props: Props<ItemT>, ref) {
|
|
|
305
307
|
{...getFlatListProps(props)}
|
|
306
308
|
onEndReached={onEndReached}
|
|
307
309
|
initialNumToRender={initialNumToRender}
|
|
310
|
+
onScrollToIndexFailed={onScrollToIndexFailed}
|
|
308
311
|
renderItem={renderItem}
|
|
309
312
|
focused={focused}
|
|
310
313
|
data={data}
|
|
@@ -319,6 +322,7 @@ function FocusableListComponent<ItemT>(props: Props<ItemT>, ref) {
|
|
|
319
322
|
renderItem={renderItem}
|
|
320
323
|
onEndReached={onEndReached}
|
|
321
324
|
initialNumToRender={initialNumToRender}
|
|
325
|
+
onScrollToIndexFailed={onScrollToIndexFailed}
|
|
322
326
|
/>
|
|
323
327
|
)}
|
|
324
328
|
</ChildrenFocusDeactivatorView>
|