@applicaster/zapp-react-native-ui-components 13.0.0-alpha.6525006318 → 13.0.0-alpha.6651373134
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/AppContainer/__tests__/AppContainer.test.js +4 -6
- package/Components/AppContainer/__tests__/__snapshots__/AppContainer.test.js.snap +1 -1
- package/Components/AudioPlayer/AudioPlayer.tsx +7 -0
- package/Components/AudioPlayer/__tests__/Runtime.test.js +5 -8
- package/Components/AudioPlayer/__tests__/__snapshots__/Runtime.test.js.snap +4 -4
- package/Components/AudioPlayer/__tests__/__snapshots__/artWork.test.js.snap +3 -3
- package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayer.test.js.snap +56 -113
- package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayerLayout.test.js.snap +39 -23
- package/Components/AudioPlayer/__tests__/__snapshots__/channel.test.js.snap +3 -3
- package/Components/AudioPlayer/__tests__/__snapshots__/summary.test.js.snap +2 -2
- package/Components/AudioPlayer/__tests__/__snapshots__/title.test.js.snap +2 -2
- package/Components/AudioPlayer/__tests__/artWork.test.js +3 -5
- package/Components/AudioPlayer/__tests__/audioPlayer.test.js +3 -5
- package/Components/AudioPlayer/__tests__/audioPlayerLayout.test.js +7 -8
- package/Components/AudioPlayer/__tests__/channel.test.js +3 -5
- package/Components/AudioPlayer/__tests__/summary.test.js +3 -5
- package/Components/AudioPlayer/__tests__/title.test.js +3 -5
- package/Components/AudioPlayer/helpers.tsx +1 -0
- package/Components/BaseFocusable/index.ios.ts +1 -1
- package/Components/BaseFocusable/index.tsx +67 -31
- package/Components/Cell/Cell.tsx +18 -22
- package/Components/Cell/CellWithFocusable.tsx +49 -60
- package/Components/Cell/CellWrapper.ts +5 -0
- package/Components/Cell/TvOSCellComponent.tsx +23 -30
- package/Components/Cell/__tests__/CellWIthFocusable.test.js +13 -6
- package/Components/Cell/index.js +3 -1
- package/Components/Cell/styles.ts +17 -0
- package/Components/CellRendererResolver/__tests__/cellRendererResolver.test.js +50 -50
- package/Components/ComponentResolver/__tests__/__snapshots__/componentResolver.test.js.snap +1 -42
- package/Components/ComponentResolver/__tests__/componentResolver.test.js +26 -30
- package/Components/ContentScreen/__tests__/contentScreen.test.js +3 -3
- package/Components/DisplayState/__tests__/__snapshots__/displayState.test.js.snap +2 -2
- package/Components/ErrorScreen/index.tsx +14 -6
- package/Components/Focusable/Focusable.tsx +1 -54
- package/Components/Focusable/FocusableTvOS.tsx +6 -2
- package/Components/Focusable/Touchable.tsx +19 -20
- package/Components/Focusable/index.android.tsx +10 -3
- package/Components/FocusableCell/index.tsx +1 -1
- package/Components/FocusableGroup/FocusableTvOS.tsx +34 -86
- package/Components/FocusableGroup/index.tsx +0 -3
- package/Components/FocusableList/index.tsx +26 -10
- package/Components/FocusableScrollView/index.tsx +43 -13
- package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +76 -7
- package/Components/GeneralContentScreen/utils/useCurationAPI.ts +53 -9
- package/Components/HandlePlayable/HandlePlayable.tsx +14 -27
- package/Components/Layout/TV/NavBarContainer.tsx +19 -23
- package/Components/Layout/TV/ScreenContainer.tsx +8 -1
- package/Components/Layout/TV/ScreenLayoutContextProvider.tsx +5 -0
- package/Components/Layout/TV/__tests__/ScreenContainer.test.tsx +3 -1
- package/Components/Layout/TV/__tests__/__snapshots__/LayoutContainer.test.tsx.snap +1 -1
- package/Components/Layout/TV/__tests__/__snapshots__/NavBarContainer.test.tsx.snap +6 -5
- package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +12 -11
- package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +1 -1
- package/Components/Layout/TV/__tests__/index.test.tsx +7 -3
- package/Components/MasterCell/DefaultComponents/ActionButton.tsx +2 -3
- package/Components/MasterCell/DefaultComponents/BorderContainerView/__tests__/index.test.tsx +66 -0
- package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +4 -1
- package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +10 -15
- package/Components/MasterCell/DefaultComponents/Image/hooks/useImage.ts +11 -7
- package/Components/MasterCell/DefaultComponents/ImageBorderContainer/__tests__/index.test.ts +93 -0
- package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +2 -2
- package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/__snapshots__/Image.test.tsx.snap +3 -3
- package/Components/MasterCell/DefaultComponents/SecondaryImage/utils.ts +1 -1
- package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
- package/Components/MasterCell/SharedUI/CollapsibleTextContainer/__tests__/__snapshots__/index.test.tsx.snap +1 -1
- package/Components/MasterCell/SharedUI/ProgressBar/hooks/useFillInPercent.ts +2 -8
- package/Components/MasterCell/__tests__/__snapshots__/dataAdapter.test.js.snap +180 -180
- package/Components/MasterCell/__tests__/__snapshots__/elementMapper.test.js.snap +11 -19
- package/Components/MasterCell/__tests__/__snapshots__/masterCell.test.js.snap +6 -235
- package/Components/MasterCell/__tests__/elementMapper.test.js +18 -5
- package/Components/MasterCell/__tests__/masterCell.test.js +26 -26
- package/Components/MasterCell/hooks/useAsyncRendering/MasterCellAsyncRenderManager.ts +2 -2
- package/Components/MasterCell/hooks/useAsyncRendering/index.ts +2 -2
- package/Components/MasterCell/utils/behaviorProvider.ts +136 -0
- package/Components/MasterCell/utils/index.ts +9 -135
- package/Components/ModalComponent/Button/assets.ts +1 -1
- package/Components/ModalComponent/Button/index.tsx +6 -6
- package/Components/ModalComponent/Header/index.tsx +3 -3
- package/Components/NativeFocusables/{index.js → index.ts} +4 -2
- package/Components/OfflineHandler/NotificationView/NotificationView.lg.tsx +2 -2
- package/Components/OfflineHandler/NotificationView/NotificationView.samsung.tsx +2 -2
- package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +0 -5
- package/Components/OfflineHandler/__tests__/__snapshots__/index.test.tsx.snap +7 -7
- package/Components/OfflineHandler/__tests__/index.test.tsx +28 -25
- package/Components/OfflineHandler/utils/index.ts +1 -1
- package/Components/PlayerContainer/PlayerContainer.tsx +22 -24
- package/Components/PlayerContainer/PlayerContainerContext.tsx +9 -0
- package/Components/PlayerContainer/ProgramInfo/index.tsx +2 -2
- package/Components/PlayerImageBackground/index.tsx +1 -1
- package/Components/River/ComponentsMap/ComponentsMap.tsx +42 -65
- package/Components/River/ComponentsMap/hooks/useLoadingState.ts +78 -51
- package/Components/River/RefreshControl.tsx +1 -1
- package/Components/River/RiverFooter.tsx +39 -9
- package/Components/River/RiverItem.tsx +37 -2
- package/Components/River/TV/index.tsx +6 -1
- package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +114 -45
- package/Components/River/__tests__/__snapshots__/river.test.js.snap +21 -83
- package/Components/River/__tests__/componentsMap.test.js +64 -17
- package/Components/River/__tests__/river.test.js +75 -40
- package/Components/RouteManager/__tests__/__snapshots__/routeManager.test.js.snap +12 -5
- package/Components/RouteManager/__tests__/routeManager.test.js +29 -14
- package/Components/RouteManager/__tests__/testId.test.js +8 -6
- package/Components/Screen/TV/index.web.tsx +5 -6
- package/Components/Screen/__tests__/Screen.test.tsx +41 -27
- package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +4 -4
- package/Components/Screen/hooks.ts +53 -0
- package/Components/Screen/index.tsx +16 -42
- package/Components/ScreenResolver/__tests__/screenResolver.test.js +95 -70
- package/Components/Tabs/Tab.tsx +12 -9
- package/Components/TextInputTv/__tests__/TextInputTv.test.js +42 -42
- package/Components/TextInputTv/__tests__/__snapshots__/TextInputTv.test.js.snap +7 -0
- package/Components/TextInputTv/index.tsx +6 -5
- package/Components/Touchable/__tests__/__snapshots__/touchable.test.tsx.snap +2 -2
- package/Components/TrackedView/index.tsx +1 -0
- package/Components/Transitioner/AnimationManager.js +15 -15
- package/Components/Transitioner/Scene.tsx +53 -24
- package/Components/Transitioner/Transitioner.tsx +3 -3
- package/Components/Transitioner/__tests__/Scene.test.js +25 -14
- package/Components/Transitioner/__tests__/__snapshots__/AnimationManager.test.js.snap +26 -26
- package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +10 -50
- package/Components/Transitioner/__tests__/__snapshots__/config.test.js.snap +20 -20
- package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +4 -4
- package/Components/Transitioner/__tests__/transitioner.test.js +13 -4
- package/Components/Transitioner/index.js +8 -4
- package/Components/VideoLive/LiveImageManager.ts +27 -1
- package/Components/VideoLive/PlayerLiveImageComponent.tsx +36 -24
- package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +63 -8
- package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +6 -10
- package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +1 -1
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +49 -31
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +8 -4
- package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +32 -18
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +8 -15
- package/Components/VideoModal/ModalAnimation/index.ts +2 -1
- package/Components/VideoModal/ModalAnimation/useModalAnimationContext.ts +6 -0
- package/Components/VideoModal/ModalAnimation/utils.ts +2 -2
- package/Components/VideoModal/OpaqueLayer.tsx +33 -0
- package/Components/VideoModal/PlayerDetails.tsx +9 -6
- package/Components/VideoModal/PlayerWrapper.tsx +43 -39
- package/Components/VideoModal/VideoModal.tsx +16 -25
- package/Components/VideoModal/__tests__/PlayerDetails.test.tsx +5 -2
- package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +13 -10
- package/Components/VideoModal/__tests__/__snapshots__/PlayerDetails.test.tsx.snap +4 -4
- package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +66 -156
- package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +89 -0
- package/Components/VideoModal/hooks/index.ts +7 -0
- package/Components/VideoModal/hooks/useDelayedPlayerDetails.ts +49 -0
- package/Components/VideoModal/hooks/utils/__tests__/showDetails.test.ts +91 -0
- package/Components/VideoModal/hooks/utils/index.ts +33 -0
- package/Components/VideoModal/utils.ts +3 -5
- package/Components/Viewport/ViewportAware/__tests__/__snapshots__/viewportAware.test.js.snap +24 -36
- package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +12 -18
- package/Components/Viewport/ViewportTracker/__tests__/__snapshots__/viewportTracker.test.js.snap +1 -1
- package/Components/Viewport/__tests__/utils.test.js +5 -4
- package/Components/ZappFrameworkComponents/BarView/BarView.tsx +1 -0
- package/Components/ZappUIComponent/Placeholder.tsx +3 -1
- package/Components/ZappUIComponent/__tests__/{ZappUIComponent.test.js → ZappUIComponent.test.tsx} +26 -10
- package/Components/ZappUIComponent/index.tsx +3 -16
- package/Components/default-cell-renderer/__tests__/defaultCellRenderer.test.tsx +20 -17
- package/Components/default-cell-renderer/viewTrees/tv/DefaultCell/__tests__/DefaultCell.test.tsx +15 -11
- package/Contexts/ComponentsMapOffsetContext/index.tsx +49 -0
- package/Contexts/ConfigutaionContext/__tests__/__snapshots__/ConfigurationProvider.test.tsx.snap +1 -1
- package/Contexts/FocusableGroupContext/withFocusableContext.tsx +12 -11
- package/Contexts/HeaderOffsetContext/index.tsx +4 -6
- package/Contexts/ScreenContext/index.tsx +6 -12
- package/Contexts/ScreenLayoutContext/index.tsx +5 -3
- package/Decorators/Analytics/{index.js → index.tsx} +11 -11
- package/Decorators/Navigator/__tests__/navigator.test.js +16 -16
- package/Decorators/Navigator/index.tsx +1 -1
- package/Decorators/RiverFeedLoader/__tests__/__snapshots__/riverFeedLoader.test.tsx.snap +77 -77
- package/Decorators/RiverFeedLoader/__tests__/riverFeedLoader.test.tsx +34 -39
- package/Decorators/RiverFeedLoader/__tests__/utils.test.ts +0 -9
- package/Decorators/RiverFeedLoader/index.tsx +1 -1
- package/Decorators/RiverFeedLoader/utils/getDatasourceUrl.ts +39 -0
- package/Decorators/RiverFeedLoader/utils/index.ts +29 -0
- package/Decorators/RiverFeedLoader/utils/usePipesContexts.ts +40 -0
- package/Decorators/RiverResolver/__tests__/riverResolver.test.tsx +27 -27
- package/Decorators/RiverResolver/index.tsx +6 -8
- package/Decorators/ZappPipesDataConnector/__tests__/Hero.js +1 -1
- package/Decorators/ZappPipesDataConnector/__tests__/zappPipesDataConnector.test.js +29 -22
- package/Decorators/ZappPipesDataConnector/index.tsx +7 -3
- package/package.json +13 -11
- package/tsconfig.json +2 -3
- package/.babelrc +0 -8
- package/Components/Cell/CellStyles/FallbackCellStyle/index.js +0 -157
- package/Components/Cell/CellStyles/Hero/index.js +0 -111
- package/Components/Cell/CellStyles/ScreenSelector/index.js +0 -68
- package/Components/Cell/CellStyles/cellStylesResolver.ts +0 -19
- package/Components/Cell/CellStyles/colors.js +0 -40
- package/Components/Cell/CellStyles/index.js +0 -15
- package/Components/CellRendererResolver/__tests__/__snapshots__/cellRendererResolver.test.js.snap +0 -53
- package/Components/RouteManager/__tests__/__snapshots__/testId.test.js.snap +0 -17
- package/Components/ScreenResolver/__tests__/__snapshots__/screenResolver.test.js.snap +0 -17
- package/Components/ZappUIComponent/__tests__/__snapshots__/ZappUIComponent.test.js.snap +0 -91
- package/Components/default-cell-renderer/__tests__/__snapshots__/defaultCellRenderer.test.tsx.snap +0 -338
- package/Decorators/Navigator/__tests__/__snapshots__/navigator.test.js.snap +0 -18
- package/Decorators/RiverFeedLoader/utils.ts +0 -100
- package/Decorators/RiverResolver/__tests__/__snapshots__/riverResolver.test.tsx.snap +0 -28
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
+
import * as R from "ramda";
|
|
2
3
|
|
|
3
4
|
import {
|
|
4
5
|
BaseFocusable as BaseFocusableInterface,
|
|
5
6
|
BoundingRect,
|
|
6
7
|
} from "./BaseFocusable.interface";
|
|
7
8
|
|
|
8
|
-
import { createReactRef } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
9
9
|
import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils/focusManager";
|
|
10
|
-
import * as FOCUS_EVENTS from "@applicaster/zapp-react-native-utils/appUtils/focusManager/events";
|
|
11
10
|
import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
12
11
|
|
|
13
12
|
type ScrollDirection = FocusManager.IOS.Direction | FocusManager.Web.Direction;
|
|
@@ -35,7 +34,7 @@ type Props = {
|
|
|
35
34
|
};
|
|
36
35
|
|
|
37
36
|
export class BaseFocusable<
|
|
38
|
-
T extends Props = Props
|
|
37
|
+
T extends Props = Props,
|
|
39
38
|
> extends BaseFocusableInterface<T> {
|
|
40
39
|
constructor(props) {
|
|
41
40
|
super(props);
|
|
@@ -45,7 +44,7 @@ export class BaseFocusable<
|
|
|
45
44
|
focused: initialFocus || false,
|
|
46
45
|
};
|
|
47
46
|
|
|
48
|
-
this.ref =
|
|
47
|
+
this.ref = React.createRef();
|
|
49
48
|
}
|
|
50
49
|
|
|
51
50
|
componentDidMount() {
|
|
@@ -131,12 +130,6 @@ export class BaseFocusable<
|
|
|
131
130
|
willLoseFocus: FocusManager.FocusEventCB = (focusable, scrollDirection) => {
|
|
132
131
|
const { willLoseFocus = noop } = this.props;
|
|
133
132
|
willLoseFocus(focusable, scrollDirection);
|
|
134
|
-
|
|
135
|
-
focusManager.invokeHandler?.(
|
|
136
|
-
FOCUS_EVENTS.WILL_LOSE_FOCUS,
|
|
137
|
-
this,
|
|
138
|
-
scrollDirection
|
|
139
|
-
);
|
|
140
133
|
};
|
|
141
134
|
|
|
142
135
|
willReceiveFocus: FocusManager.FocusEventCB = (
|
|
@@ -145,12 +138,6 @@ export class BaseFocusable<
|
|
|
145
138
|
) => {
|
|
146
139
|
const { willReceiveFocus = noop } = this.props;
|
|
147
140
|
willReceiveFocus(focusable, scrollDirection);
|
|
148
|
-
|
|
149
|
-
focusManager.invokeHandler?.(
|
|
150
|
-
FOCUS_EVENTS.WILL_RECEIVE_FOCUS,
|
|
151
|
-
this,
|
|
152
|
-
scrollDirection
|
|
153
|
-
);
|
|
154
141
|
};
|
|
155
142
|
|
|
156
143
|
/**
|
|
@@ -163,8 +150,6 @@ export class BaseFocusable<
|
|
|
163
150
|
const { onFocus = noop } = this.props;
|
|
164
151
|
this.setFocusedState(true);
|
|
165
152
|
onFocus(focusable, scrollDirection);
|
|
166
|
-
|
|
167
|
-
focusManager.invokeHandler?.(FOCUS_EVENTS.FOCUS, this, scrollDirection);
|
|
168
153
|
};
|
|
169
154
|
|
|
170
155
|
/**
|
|
@@ -179,12 +164,6 @@ export class BaseFocusable<
|
|
|
179
164
|
) => {
|
|
180
165
|
const { hasReceivedFocus = noop } = this.props;
|
|
181
166
|
hasReceivedFocus(focusable, scrollDirection);
|
|
182
|
-
|
|
183
|
-
focusManager.invokeHandler?.(
|
|
184
|
-
FOCUS_EVENTS.HAS_RECEIVED_FOCUS,
|
|
185
|
-
this,
|
|
186
|
-
scrollDirection
|
|
187
|
-
);
|
|
188
167
|
};
|
|
189
168
|
|
|
190
169
|
/**
|
|
@@ -196,12 +175,6 @@ export class BaseFocusable<
|
|
|
196
175
|
hasLostFocus: FocusManager.FocusEventCB = (focusable, scrollDirection) => {
|
|
197
176
|
const { hasLostFocus = noop } = this.props;
|
|
198
177
|
hasLostFocus(focusable, scrollDirection);
|
|
199
|
-
|
|
200
|
-
focusManager.invokeHandler?.(
|
|
201
|
-
FOCUS_EVENTS.HAS_LOST_FOCUS,
|
|
202
|
-
this,
|
|
203
|
-
scrollDirection
|
|
204
|
-
);
|
|
205
178
|
};
|
|
206
179
|
|
|
207
180
|
/**
|
|
@@ -228,7 +201,6 @@ export class BaseFocusable<
|
|
|
228
201
|
const { onBlur = noop } = this.props;
|
|
229
202
|
this.setFocusedState(false);
|
|
230
203
|
onBlur(focusable, scrollDirection);
|
|
231
|
-
focusManager.invokeHandler?.(FOCUS_EVENTS.BLUR, this, scrollDirection);
|
|
232
204
|
};
|
|
233
205
|
|
|
234
206
|
onPress = (keyEvent?: Nullable<React.MouseEvent>) => {
|
|
@@ -269,4 +241,68 @@ export class BaseFocusable<
|
|
|
269
241
|
this.setState({ focused });
|
|
270
242
|
}
|
|
271
243
|
};
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* will invoke the underlying component's focus method
|
|
247
|
+
* @param {Object} scrollDirection
|
|
248
|
+
* @returns {Promise}
|
|
249
|
+
*/
|
|
250
|
+
focus(_, scrollDirection) {
|
|
251
|
+
return this.onFocus(this, scrollDirection); // invokeComponentMethod(this, "onFocus", scrollDirection);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* will invoke the underlying component's blur method
|
|
256
|
+
* @param {Object} scrollDirection
|
|
257
|
+
* @returns {Promise}
|
|
258
|
+
*/
|
|
259
|
+
blur(
|
|
260
|
+
_,
|
|
261
|
+
scrollDirection?: FocusManager.Web.Direction | FocusManager.IOS.Direction
|
|
262
|
+
) {
|
|
263
|
+
return this.onBlur(this, scrollDirection);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Sets the focus on this item. Will trigger sequentially a sequence of
|
|
268
|
+
* functions (willReceiveFocus, focus, hasReceivedFocus). If these functions (defined in the Focusable
|
|
269
|
+
* Item underlying component) return promises, execution will wait before it proceeds to the next. This
|
|
270
|
+
* is useful for triggering sequential operations that specifically require to fully run before or after
|
|
271
|
+
* focus is actually set on that item.
|
|
272
|
+
* @param {string} scrollDirection string representation of the direction of the navigation which landed
|
|
273
|
+
* to this item being focused
|
|
274
|
+
*/
|
|
275
|
+
_executeFocusSequence(methodNames, scrollDirection) {
|
|
276
|
+
return R.reduce(
|
|
277
|
+
(sequence, methodName) => {
|
|
278
|
+
const method = this[methodName]; // Access the method by name
|
|
279
|
+
|
|
280
|
+
if (typeof method !== "function") {
|
|
281
|
+
throw new Error(
|
|
282
|
+
`Method '${methodName}' not found or not a function.`
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
return sequence
|
|
287
|
+
.then(() => method.call(this, scrollDirection))
|
|
288
|
+
.catch((e) => {
|
|
289
|
+
throw e; // Re-throw for consistent error handling
|
|
290
|
+
});
|
|
291
|
+
},
|
|
292
|
+
Promise.resolve(),
|
|
293
|
+
methodNames
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
setFocus(scrollDirection) {
|
|
298
|
+
const focusMethods = ["willReceiveFocus", "focus", "hasReceivedFocus"];
|
|
299
|
+
|
|
300
|
+
return this._executeFocusSequence(focusMethods, scrollDirection);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
setBlur(scrollDirection) {
|
|
304
|
+
const blurMethods = ["willLoseFocus", "blur", "hasLostFocus"];
|
|
305
|
+
|
|
306
|
+
return this._executeFocusSequence(blurMethods, scrollDirection);
|
|
307
|
+
}
|
|
272
308
|
}
|
package/Components/Cell/Cell.tsx
CHANGED
|
@@ -12,12 +12,10 @@ import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
|
12
12
|
import { CellWithFocusable } from "./CellWithFocusable";
|
|
13
13
|
import { BaseFocusable } from "../BaseFocusable";
|
|
14
14
|
import { AccessibilityManager } from "@applicaster/zapp-react-native-utils/appUtils/accessibilityManager";
|
|
15
|
+
import { styles } from "./styles";
|
|
15
16
|
|
|
16
17
|
type Props = {
|
|
17
|
-
item:
|
|
18
|
-
id: string;
|
|
19
|
-
title: string;
|
|
20
|
-
};
|
|
18
|
+
item: ZappEntry;
|
|
21
19
|
index: number;
|
|
22
20
|
shouldScrollHorizontally: (arg1: [any]) => boolean | null | undefined;
|
|
23
21
|
shouldScrollVertically: (...args: any) => boolean | null | undefined;
|
|
@@ -33,10 +31,9 @@ type Props = {
|
|
|
33
31
|
id: string;
|
|
34
32
|
};
|
|
35
33
|
selected?: boolean;
|
|
36
|
-
CellRenderer: React.
|
|
37
|
-
item:
|
|
38
|
-
|
|
39
|
-
}> & { hasFocusableInside: (item: Record<string, string>) => boolean };
|
|
34
|
+
CellRenderer: React.FunctionComponent<any> & {
|
|
35
|
+
hasFocusableInside: (item: ZappEntry) => boolean;
|
|
36
|
+
};
|
|
40
37
|
preferredFocus: boolean;
|
|
41
38
|
navigator: {
|
|
42
39
|
push: (arg1: Record<any, any>) => void;
|
|
@@ -65,23 +62,13 @@ type Props = {
|
|
|
65
62
|
skipFocusManagerRegistration?: boolean;
|
|
66
63
|
shouldUpdate: boolean;
|
|
67
64
|
behavior: Behavior;
|
|
65
|
+
componentsMapOffset: number;
|
|
68
66
|
};
|
|
69
67
|
|
|
70
68
|
type State = {
|
|
71
69
|
hasFocusableInside: boolean;
|
|
72
70
|
};
|
|
73
71
|
|
|
74
|
-
const baseCellStyles = {
|
|
75
|
-
height: "100%",
|
|
76
|
-
display: "flex",
|
|
77
|
-
flex: 1,
|
|
78
|
-
} as const;
|
|
79
|
-
|
|
80
|
-
const touchableStyles = {
|
|
81
|
-
flex: 1,
|
|
82
|
-
height: "100%",
|
|
83
|
-
} as const;
|
|
84
|
-
|
|
85
72
|
export class CellComponent extends React.Component<Props, State> {
|
|
86
73
|
constructor(props) {
|
|
87
74
|
super(props);
|
|
@@ -255,7 +242,7 @@ export class CellComponent extends React.Component<Props, State> {
|
|
|
255
242
|
<View
|
|
256
243
|
testID={`${component?.id}-${id}`}
|
|
257
244
|
accessible={false}
|
|
258
|
-
style={
|
|
245
|
+
style={styles.touchableCell}
|
|
259
246
|
>
|
|
260
247
|
<Focusable
|
|
261
248
|
id={focusableId}
|
|
@@ -267,7 +254,7 @@ export class CellComponent extends React.Component<Props, State> {
|
|
|
267
254
|
hasReceivedFocus={hasReceivedFocus || this.hasReceivedFocus}
|
|
268
255
|
preferredFocus={preferredFocus}
|
|
269
256
|
offsetUpdater={offsetUpdater}
|
|
270
|
-
style={
|
|
257
|
+
style={styles.baseCell}
|
|
271
258
|
isFocusable={isFocusable}
|
|
272
259
|
skipFocusManagerRegistration={skipFocusManagerRegistration}
|
|
273
260
|
>
|
|
@@ -276,7 +263,16 @@ export class CellComponent extends React.Component<Props, State> {
|
|
|
276
263
|
|
|
277
264
|
if (isFocused) {
|
|
278
265
|
const accessibilityManager = AccessibilityManager.getInstance();
|
|
279
|
-
|
|
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
|
+
});
|
|
280
276
|
}
|
|
281
277
|
|
|
282
278
|
return (
|
|
@@ -1,52 +1,16 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
|
|
3
|
-
import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils/focusManager";
|
|
4
|
-
import * as FOCUS_EVENTS from "@applicaster/zapp-react-native-utils/appUtils/focusManager/events";
|
|
5
3
|
import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
6
4
|
import { toBooleanWithDefaultFalse } from "@applicaster/zapp-react-native-utils/booleanUtils";
|
|
7
5
|
|
|
8
|
-
import { isAppleTV } from "../../Helpers/Platform";
|
|
9
6
|
import { useCellState } from "../MasterCell/utils";
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
groupId: string,
|
|
14
|
-
id: string
|
|
15
|
-
) => {
|
|
16
|
-
const [currentCellFocused, setCurrentCellFocused] = React.useState(false);
|
|
17
|
-
|
|
18
|
-
React.useEffect(() => {
|
|
19
|
-
const isGroupItemFocused = () => {
|
|
20
|
-
if (!skipFocusManagerRegistration) {
|
|
21
|
-
const isFocused = focusManager.isGroupItemFocused(groupId, id);
|
|
22
|
-
setCurrentCellFocused(isFocused);
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
const handler = () => {
|
|
27
|
-
// tvOS hack for properly checking focus
|
|
28
|
-
if (isAppleTV()) {
|
|
29
|
-
setTimeout(() => {
|
|
30
|
-
isGroupItemFocused();
|
|
31
|
-
}, 0);
|
|
32
|
-
} else {
|
|
33
|
-
isGroupItemFocused();
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
focusManager.on(FOCUS_EVENTS.FOCUS, handler);
|
|
38
|
-
|
|
39
|
-
return () => {
|
|
40
|
-
focusManager.removeHandler(FOCUS_EVENTS.FOCUS, handler);
|
|
41
|
-
};
|
|
42
|
-
}, [groupId, skipFocusManagerRegistration]);
|
|
43
|
-
|
|
44
|
-
return currentCellFocused;
|
|
45
|
-
};
|
|
7
|
+
import { FocusableGroup } from "../FocusableGroup";
|
|
8
|
+
import { CellWrapper } from "./CellWrapper";
|
|
9
|
+
import { styles } from "./styles";
|
|
46
10
|
|
|
47
11
|
type Props = {
|
|
48
12
|
item: ZappEntry;
|
|
49
|
-
CellRenderer: React.
|
|
13
|
+
CellRenderer: React.FunctionComponent<any>;
|
|
50
14
|
id: string;
|
|
51
15
|
groupId: string;
|
|
52
16
|
onFocus: Function;
|
|
@@ -75,14 +39,10 @@ export function CellWithFocusable(props: Props) {
|
|
|
75
39
|
focused,
|
|
76
40
|
} = props;
|
|
77
41
|
|
|
78
|
-
const isFocused =
|
|
79
|
-
skipFocusManagerRegistration,
|
|
80
|
-
groupId,
|
|
81
|
-
id
|
|
82
|
-
);
|
|
42
|
+
const [isFocused, setIsFocused] = React.useState(false);
|
|
83
43
|
|
|
84
44
|
const state = useCellState({
|
|
85
|
-
|
|
45
|
+
item,
|
|
86
46
|
behavior,
|
|
87
47
|
focused: isFocused || toBooleanWithDefaultFalse(focused),
|
|
88
48
|
});
|
|
@@ -96,26 +56,55 @@ export function CellWithFocusable(props: Props) {
|
|
|
96
56
|
}
|
|
97
57
|
}, [focusedButtonId]);
|
|
98
58
|
|
|
99
|
-
const handleToggleFocus = (
|
|
100
|
-
|
|
59
|
+
const handleToggleFocus = React.useCallback(
|
|
60
|
+
(value) => {
|
|
61
|
+
setFocusedButtonId(value.focusedButtonId);
|
|
62
|
+
|
|
63
|
+
if (value.focusable) {
|
|
64
|
+
onFocus(value.focusable, value.mouse);
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
[onFocus]
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
const onGroupFocus = React.useCallback(() => {
|
|
71
|
+
if (!skipFocusManagerRegistration) {
|
|
72
|
+
setIsFocused(true);
|
|
73
|
+
}
|
|
74
|
+
}, [skipFocusManagerRegistration]);
|
|
101
75
|
|
|
102
|
-
|
|
103
|
-
|
|
76
|
+
const onGroupBlur = React.useCallback(() => {
|
|
77
|
+
if (!skipFocusManagerRegistration) {
|
|
78
|
+
setIsFocused(false);
|
|
104
79
|
}
|
|
105
|
-
};
|
|
80
|
+
}, [skipFocusManagerRegistration]);
|
|
106
81
|
|
|
107
82
|
return (
|
|
108
|
-
<
|
|
109
|
-
|
|
83
|
+
<FocusableGroup
|
|
84
|
+
id={`focusable-cell-wrapper-${id}`}
|
|
85
|
+
testID={"cell-with-focusable-cell-renderer-focusable-group"}
|
|
110
86
|
groupId={groupId}
|
|
111
|
-
onToggleFocus={handleToggleFocus}
|
|
112
|
-
state={state}
|
|
113
|
-
prefixId={id}
|
|
114
|
-
focusedButtonId={focusedButtonId}
|
|
115
87
|
preferredFocus={preferredFocus}
|
|
88
|
+
shouldUsePreferredFocus
|
|
89
|
+
onFocus={onGroupFocus}
|
|
90
|
+
onBlur={onGroupBlur}
|
|
116
91
|
skipFocusManagerRegistration={skipFocusManagerRegistration}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
92
|
+
>
|
|
93
|
+
<CellWrapper style={styles.cellWrapper}>
|
|
94
|
+
<CellRenderer
|
|
95
|
+
testID={"cell-with-focusable-cell-renderer"}
|
|
96
|
+
item={item}
|
|
97
|
+
groupId={`focusable-cell-wrapper-${id}`}
|
|
98
|
+
onToggleFocus={handleToggleFocus}
|
|
99
|
+
state={state}
|
|
100
|
+
prefixId={id}
|
|
101
|
+
focusedButtonId={focusedButtonId}
|
|
102
|
+
preferredFocus={true}
|
|
103
|
+
skipFocusManagerRegistration={skipFocusManagerRegistration}
|
|
104
|
+
isFocusable={isFocusable}
|
|
105
|
+
focused={focused}
|
|
106
|
+
/>
|
|
107
|
+
</CellWrapper>
|
|
108
|
+
</FocusableGroup>
|
|
120
109
|
);
|
|
121
110
|
}
|
|
@@ -2,7 +2,7 @@ import * as React from "react";
|
|
|
2
2
|
import * as R from "ramda";
|
|
3
3
|
import { View, StyleSheet } from "react-native";
|
|
4
4
|
|
|
5
|
-
import { Focusable } from "@applicaster/zapp-react-native-ui-components/Components/Focusable";
|
|
5
|
+
import { Focusable } from "@applicaster/zapp-react-native-ui-components/Components/Focusable/FocusableTvOS";
|
|
6
6
|
import { FocusableCell } from "@applicaster/zapp-react-native-ui-components/Components/FocusableCell";
|
|
7
7
|
import { getItemType } from "@applicaster/zapp-react-native-utils/navigationUtils";
|
|
8
8
|
import { SCREEN_TYPES } from "@applicaster/zapp-react-native-utils/navigationUtils/itemTypes";
|
|
@@ -10,10 +10,6 @@ import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils/focu
|
|
|
10
10
|
import { sendSelectCellEvent } from "@applicaster/zapp-react-native-utils/analyticsUtils";
|
|
11
11
|
import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
12
12
|
import { CellWithFocusable } from "./CellWithFocusable";
|
|
13
|
-
import { getCellState } from "./utils";
|
|
14
|
-
|
|
15
|
-
const _getCellState = (focused, selected) =>
|
|
16
|
-
getCellState({ focused, selected });
|
|
17
13
|
|
|
18
14
|
type Props = {
|
|
19
15
|
item: ZappEntry;
|
|
@@ -36,10 +32,9 @@ type Props = {
|
|
|
36
32
|
component_type: string;
|
|
37
33
|
};
|
|
38
34
|
selected: boolean;
|
|
39
|
-
CellRenderer: React.
|
|
40
|
-
item: any;
|
|
41
|
-
|
|
42
|
-
}> & { hasFocusableInside: (item: any) => boolean };
|
|
35
|
+
CellRenderer: React.FunctionComponent<any> & {
|
|
36
|
+
hasFocusableInside: (item: any) => boolean;
|
|
37
|
+
};
|
|
43
38
|
preferredFocus: boolean;
|
|
44
39
|
navigator: {
|
|
45
40
|
push: (arg1: Record<any, any>) => void;
|
|
@@ -70,6 +65,7 @@ type Props = {
|
|
|
70
65
|
isFocusable: boolean;
|
|
71
66
|
shouldUpdate: boolean;
|
|
72
67
|
behavior: Behavior;
|
|
68
|
+
componentsMapOffset: number;
|
|
73
69
|
};
|
|
74
70
|
|
|
75
71
|
type State = {
|
|
@@ -184,6 +180,7 @@ export class TvOSCellComponent extends React.Component<Props, State> {
|
|
|
184
180
|
groupId,
|
|
185
181
|
component,
|
|
186
182
|
index,
|
|
183
|
+
componentsMapOffset,
|
|
187
184
|
} = this.props;
|
|
188
185
|
|
|
189
186
|
this.setScreenLayout(componentAnchorPointY, screenLayout);
|
|
@@ -198,13 +195,11 @@ export class TvOSCellComponent extends React.Component<Props, State> {
|
|
|
198
195
|
const extraAnchorPointYOffset =
|
|
199
196
|
screenLayout?.extraAnchorPointYOffset || 0;
|
|
200
197
|
|
|
201
|
-
const marginTop = screenLayout?.screenMarginTop || 0;
|
|
202
|
-
|
|
203
198
|
const totalOffset =
|
|
204
199
|
headerOffset +
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
200
|
+
(componentAnchorPointY || 0) +
|
|
201
|
+
extraAnchorPointYOffset -
|
|
202
|
+
componentsMapOffset || 0;
|
|
208
203
|
|
|
209
204
|
mainOffsetUpdater?.(
|
|
210
205
|
{ tag: this.target },
|
|
@@ -252,7 +247,7 @@ export class TvOSCellComponent extends React.Component<Props, State> {
|
|
|
252
247
|
|
|
253
248
|
const focusableId = R.join("-", [component?.id, id, index]);
|
|
254
249
|
|
|
255
|
-
const handleFocus = (arg1: any, index
|
|
250
|
+
const handleFocus = (arg1: any, index?: number) => {
|
|
256
251
|
const focusFn = onFocus || noop;
|
|
257
252
|
focusFn(arg1, index);
|
|
258
253
|
|
|
@@ -285,7 +280,7 @@ export class TvOSCellComponent extends React.Component<Props, State> {
|
|
|
285
280
|
<View onLayout={this.onLayout} style={styles.container}>
|
|
286
281
|
<Focusable
|
|
287
282
|
id={focusableId}
|
|
288
|
-
groupId={groupId || component?.id}
|
|
283
|
+
groupId={String(groupId || component?.id)}
|
|
289
284
|
onFocus={handleFocus}
|
|
290
285
|
onBlur={onBlur || this.onBlur}
|
|
291
286
|
isParallaxDisabled={this.layout?.width > 1740}
|
|
@@ -297,20 +292,18 @@ export class TvOSCellComponent extends React.Component<Props, State> {
|
|
|
297
292
|
style={baseCellStyles}
|
|
298
293
|
isFocusable={isFocusable}
|
|
299
294
|
>
|
|
300
|
-
{(focused) =>
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
);
|
|
313
|
-
}}
|
|
295
|
+
{(focused) => (
|
|
296
|
+
<FocusableCell
|
|
297
|
+
{...{
|
|
298
|
+
index,
|
|
299
|
+
CellRenderer,
|
|
300
|
+
item,
|
|
301
|
+
focused: !!(this.props.focused || selectedCell || focused),
|
|
302
|
+
scrollTo: this.scrollTo,
|
|
303
|
+
behavior,
|
|
304
|
+
}}
|
|
305
|
+
/>
|
|
306
|
+
)}
|
|
314
307
|
</Focusable>
|
|
315
308
|
</View>
|
|
316
309
|
);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { View } from "react-native";
|
|
2
2
|
import React from "react";
|
|
3
3
|
import { act, render } from "@testing-library/react-native";
|
|
4
|
-
import { CellWithFocusable } from "../CellWithFocusable";
|
|
4
|
+
import { CellWithFocusable } from "../CellWithFocusable.tsx";
|
|
5
5
|
|
|
6
6
|
import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils/focusManager";
|
|
7
7
|
|
|
@@ -23,7 +23,9 @@ describe("CellWithFocusable", () => {
|
|
|
23
23
|
|
|
24
24
|
const wrapper = renderWith(props);
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
const element = wrapper.getByTestId("cell-with-focusable-cell-renderer");
|
|
27
|
+
|
|
28
|
+
expect(element.props.state).toBe("default");
|
|
27
29
|
});
|
|
28
30
|
|
|
29
31
|
it("should render in default state", () => {
|
|
@@ -40,8 +42,9 @@ describe("CellWithFocusable", () => {
|
|
|
40
42
|
focusManager.isGroupItemFocused = jest.fn(() => true);
|
|
41
43
|
|
|
42
44
|
const wrapper = renderWith(props);
|
|
45
|
+
const element = wrapper.getByTestId("cell-with-focusable-cell-renderer");
|
|
43
46
|
|
|
44
|
-
expect(
|
|
47
|
+
expect(element.props.state).toBe("default");
|
|
45
48
|
});
|
|
46
49
|
|
|
47
50
|
it("should render in focused state", () => {
|
|
@@ -55,13 +58,17 @@ describe("CellWithFocusable", () => {
|
|
|
55
58
|
scrollTo: jest.fn(),
|
|
56
59
|
};
|
|
57
60
|
|
|
58
|
-
focusManager.isGroupItemFocused = jest.fn(() => true);
|
|
59
61
|
const wrapper = renderWith(props);
|
|
60
62
|
|
|
63
|
+
const focusableGroupComponent = wrapper.getByTestId(
|
|
64
|
+
"cell-with-focusable-cell-renderer-focusable-group"
|
|
65
|
+
);
|
|
66
|
+
|
|
61
67
|
act(() => {
|
|
62
|
-
|
|
68
|
+
focusableGroupComponent.props.onFocus();
|
|
63
69
|
});
|
|
64
70
|
|
|
65
|
-
|
|
71
|
+
const element = wrapper.getByTestId("cell-with-focusable-cell-renderer");
|
|
72
|
+
expect(element.props.state).toBe("focused");
|
|
66
73
|
});
|
|
67
74
|
});
|
package/Components/Cell/index.js
CHANGED
|
@@ -11,6 +11,7 @@ import { ScreenScrollingContext } from "../../Contexts/ScreenScrollingContext";
|
|
|
11
11
|
|
|
12
12
|
import { ScreenLayoutContextConsumer } from "../../Contexts/ScreenLayoutContext";
|
|
13
13
|
import { createContext } from "@applicaster/zapp-react-native-utils/reactUtils/createContext";
|
|
14
|
+
import { withComponentsMapOffsetContextConsumer } from "../../Contexts/ComponentsMapOffsetContext";
|
|
14
15
|
|
|
15
16
|
// TODO | Gallery QB | Extract this
|
|
16
17
|
export const ScrollInterceptorContext = createContext(
|
|
@@ -30,5 +31,6 @@ export const Cell = R.compose(
|
|
|
30
31
|
RiverOffsetContext.withConsumer,
|
|
31
32
|
HorizontalScrollContext.withConsumer,
|
|
32
33
|
withConsumer,
|
|
33
|
-
ScreenLayoutContextConsumer
|
|
34
|
+
ScreenLayoutContextConsumer,
|
|
35
|
+
withComponentsMapOffsetContextConsumer
|
|
34
36
|
)(Component);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { StyleSheet } from "react-native";
|
|
2
|
+
|
|
3
|
+
export const styles = StyleSheet.create({
|
|
4
|
+
cellWrapper: {
|
|
5
|
+
flex: 0,
|
|
6
|
+
height: "100%",
|
|
7
|
+
},
|
|
8
|
+
baseCell: {
|
|
9
|
+
height: "100%",
|
|
10
|
+
display: "flex",
|
|
11
|
+
flex: 1,
|
|
12
|
+
},
|
|
13
|
+
touchableCell: {
|
|
14
|
+
flex: 1,
|
|
15
|
+
height: "100%",
|
|
16
|
+
},
|
|
17
|
+
});
|