@applicaster/zapp-react-native-ui-components 13.0.0-rc.13 → 13.0.0-rc.130
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 +5 -9
- package/Components/AudioPlayer/AudioPlayerLayout.tsx +6 -7
- 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 -2
- package/Components/BaseFocusable/index.ios.ts +1 -1
- package/Components/BaseFocusable/index.tsx +67 -31
- package/Components/Cell/Cell.tsx +14 -14
- package/Components/Cell/CellWithFocusable.tsx +50 -59
- package/Components/Cell/CellWrapper.tsx +18 -0
- package/Components/Cell/TvOSCellComponent.tsx +20 -26
- 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/CellRendererResolver/index.ts +2 -1
- 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/GeneralContentScreen.tsx +3 -0
- package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +9 -0
- package/Components/GeneralContentScreen/utils/useCurationAPI.ts +5 -3
- package/Components/GeneralContentScreen/utils/useEventAlerts.ts +30 -0
- package/Components/HandlePlayable/HandlePlayable.tsx +21 -27
- package/Components/Layout/TV/LayoutBackground.tsx +28 -0
- package/Components/Layout/TV/NavBarContainer.tsx +19 -23
- package/Components/Layout/TV/ScreenContainer.tsx +8 -2
- 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 +15 -10
- package/Components/Layout/TV/__tests__/index.test.tsx +14 -4
- package/Components/Layout/TV/index.tsx +6 -20
- package/Components/Layout/TV/index.web.tsx +4 -1
- 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/DefaultComponents/tv/TvActionButtons/const.ts +3 -0
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/index.ts +6 -6
- 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/BottomSheetModalContent.tsx +66 -54
- package/Components/ModalComponent/Button/Item.tsx +6 -5
- package/Components/ModalComponent/Button/assets.ts +1 -1
- package/Components/ModalComponent/Button/index.tsx +45 -62
- package/Components/ModalComponent/Header/index.tsx +12 -11
- package/Components/ModalComponent/utils.ts +55 -7
- 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 +49 -29
- 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 +53 -68
- 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 +43 -3
- package/Components/River/TV/index.tsx +6 -1
- package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +121 -46
- 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/TestId.tsx +1 -5
- package/Components/RouteManager/__tests__/__snapshots__/routeManager.test.js.snap +11 -5
- package/Components/RouteManager/__tests__/routeManager.test.js +29 -14
- package/Components/RouteManager/__tests__/testId.test.js +4 -6
- package/Components/Screen/TV/__tests__/index.web.test.tsx +26 -0
- package/Components/Screen/TV/index.web.tsx +5 -6
- package/Components/Screen/__tests__/Screen.test.tsx +53 -31
- package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +6 -6
- 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/TopMarginApplicator/TopMarginApplicator.tsx +2 -3
- 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 +51 -31
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +8 -4
- package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +48 -23
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +16 -15
- package/Components/VideoModal/ModalAnimation/__tests__/getMoveUpValue.test.ts +108 -0
- package/Components/VideoModal/ModalAnimation/const.ts +5 -0
- package/Components/VideoModal/ModalAnimation/index.ts +4 -1
- package/Components/VideoModal/ModalAnimation/useModalAnimationContext.ts +6 -0
- package/Components/VideoModal/ModalAnimation/utils.ts +32 -2
- package/Components/VideoModal/OpaqueLayer.tsx +33 -0
- package/Components/VideoModal/PlayerDetails.tsx +18 -10
- package/Components/VideoModal/PlayerWrapper.tsx +51 -57
- package/Components/VideoModal/VideoModal.tsx +17 -11
- 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 +2 -40
- 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 +6 -9
- 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/ZappUIComponent/Placeholder.tsx +3 -1
- package/Components/ZappUIComponent/__tests__/{ZappUIComponent.test.js → ZappUIComponent.test.tsx} +26 -10
- package/Components/ZappUIComponent/index.tsx +4 -17
- 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 +4 -10
- package/Contexts/HeaderOffsetContext/index.tsx +4 -6
- package/Contexts/ScreenContext/index.tsx +6 -12
- package/Contexts/ScreenLayoutContext/index.tsx +5 -3
- 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
|
@@ -4,8 +4,7 @@ const defaults = {
|
|
|
4
4
|
audio_player_background_color: "black",
|
|
5
5
|
audio_player_artwork_aspect_ratio: "1:1",
|
|
6
6
|
audio_player_rtl: false,
|
|
7
|
-
|
|
8
|
-
audio_player_background_image_query: "",
|
|
7
|
+
audio_player_background_image_default_color: "",
|
|
9
8
|
};
|
|
10
9
|
|
|
11
10
|
export function getPropertyFromEntryOrConfig({ entry, plugin_configuration }) {
|
|
@@ -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,6 +12,7 @@ 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
18
|
item: ZappEntry;
|
|
@@ -61,23 +62,13 @@ type Props = {
|
|
|
61
62
|
skipFocusManagerRegistration?: boolean;
|
|
62
63
|
shouldUpdate: boolean;
|
|
63
64
|
behavior: Behavior;
|
|
65
|
+
componentsMapOffset: number;
|
|
64
66
|
};
|
|
65
67
|
|
|
66
68
|
type State = {
|
|
67
69
|
hasFocusableInside: boolean;
|
|
68
70
|
};
|
|
69
71
|
|
|
70
|
-
const baseCellStyles = {
|
|
71
|
-
height: "100%",
|
|
72
|
-
display: "flex",
|
|
73
|
-
flex: 1,
|
|
74
|
-
} as const;
|
|
75
|
-
|
|
76
|
-
const touchableStyles = {
|
|
77
|
-
flex: 1,
|
|
78
|
-
height: "100%",
|
|
79
|
-
} as const;
|
|
80
|
-
|
|
81
72
|
export class CellComponent extends React.Component<Props, State> {
|
|
82
73
|
constructor(props) {
|
|
83
74
|
super(props);
|
|
@@ -251,7 +242,7 @@ export class CellComponent extends React.Component<Props, State> {
|
|
|
251
242
|
<View
|
|
252
243
|
testID={`${component?.id}-${id}`}
|
|
253
244
|
accessible={false}
|
|
254
|
-
style={
|
|
245
|
+
style={styles.touchableCell}
|
|
255
246
|
>
|
|
256
247
|
<Focusable
|
|
257
248
|
id={focusableId}
|
|
@@ -263,7 +254,7 @@ export class CellComponent extends React.Component<Props, State> {
|
|
|
263
254
|
hasReceivedFocus={hasReceivedFocus || this.hasReceivedFocus}
|
|
264
255
|
preferredFocus={preferredFocus}
|
|
265
256
|
offsetUpdater={offsetUpdater}
|
|
266
|
-
style={
|
|
257
|
+
style={styles.baseCell}
|
|
267
258
|
isFocusable={isFocusable}
|
|
268
259
|
skipFocusManagerRegistration={skipFocusManagerRegistration}
|
|
269
260
|
>
|
|
@@ -272,7 +263,16 @@ export class CellComponent extends React.Component<Props, State> {
|
|
|
272
263
|
|
|
273
264
|
if (isFocused) {
|
|
274
265
|
const accessibilityManager = AccessibilityManager.getInstance();
|
|
275
|
-
|
|
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
|
+
});
|
|
276
276
|
}
|
|
277
277
|
|
|
278
278
|
return (
|
|
@@ -1,48 +1,12 @@
|
|
|
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;
|
|
@@ -59,6 +23,8 @@ type Props = {
|
|
|
59
23
|
focused?: boolean;
|
|
60
24
|
};
|
|
61
25
|
|
|
26
|
+
const addPrefix = (id: string) => `focusable-cell-wrapper-${id}`;
|
|
27
|
+
|
|
62
28
|
export function CellWithFocusable(props: Props) {
|
|
63
29
|
const {
|
|
64
30
|
index,
|
|
@@ -75,14 +41,10 @@ export function CellWithFocusable(props: Props) {
|
|
|
75
41
|
focused,
|
|
76
42
|
} = props;
|
|
77
43
|
|
|
78
|
-
const isFocused =
|
|
79
|
-
skipFocusManagerRegistration,
|
|
80
|
-
groupId,
|
|
81
|
-
id
|
|
82
|
-
);
|
|
44
|
+
const [isFocused, setIsFocused] = React.useState(false);
|
|
83
45
|
|
|
84
46
|
const state = useCellState({
|
|
85
|
-
|
|
47
|
+
item,
|
|
86
48
|
behavior,
|
|
87
49
|
focused: isFocused || toBooleanWithDefaultFalse(focused),
|
|
88
50
|
});
|
|
@@ -96,26 +58,55 @@ export function CellWithFocusable(props: Props) {
|
|
|
96
58
|
}
|
|
97
59
|
}, [focusedButtonId]);
|
|
98
60
|
|
|
99
|
-
const handleToggleFocus = (
|
|
100
|
-
|
|
61
|
+
const handleToggleFocus = React.useCallback(
|
|
62
|
+
(value) => {
|
|
63
|
+
setFocusedButtonId(value.focusedButtonId);
|
|
64
|
+
|
|
65
|
+
if (value.focusable) {
|
|
66
|
+
onFocus(value.focusable, value.mouse);
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
[onFocus]
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const onGroupFocus = React.useCallback(() => {
|
|
73
|
+
if (!skipFocusManagerRegistration) {
|
|
74
|
+
setIsFocused(true);
|
|
75
|
+
}
|
|
76
|
+
}, [skipFocusManagerRegistration]);
|
|
101
77
|
|
|
102
|
-
|
|
103
|
-
|
|
78
|
+
const onGroupBlur = React.useCallback(() => {
|
|
79
|
+
if (!skipFocusManagerRegistration) {
|
|
80
|
+
setIsFocused(false);
|
|
104
81
|
}
|
|
105
|
-
};
|
|
82
|
+
}, [skipFocusManagerRegistration]);
|
|
106
83
|
|
|
107
84
|
return (
|
|
108
|
-
<
|
|
109
|
-
|
|
85
|
+
<FocusableGroup
|
|
86
|
+
id={addPrefix(id)}
|
|
87
|
+
testID={"cell-with-focusable-cell-renderer-focusable-group"}
|
|
110
88
|
groupId={groupId}
|
|
111
|
-
onToggleFocus={handleToggleFocus}
|
|
112
|
-
state={state}
|
|
113
|
-
prefixId={id}
|
|
114
|
-
focusedButtonId={focusedButtonId}
|
|
115
89
|
preferredFocus={preferredFocus}
|
|
90
|
+
shouldUsePreferredFocus
|
|
91
|
+
onFocus={onGroupFocus}
|
|
92
|
+
onBlur={onGroupBlur}
|
|
116
93
|
skipFocusManagerRegistration={skipFocusManagerRegistration}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
94
|
+
>
|
|
95
|
+
<CellWrapper style={styles.cellWrapper}>
|
|
96
|
+
<CellRenderer
|
|
97
|
+
testID={"cell-with-focusable-cell-renderer"}
|
|
98
|
+
item={item}
|
|
99
|
+
groupId={addPrefix(id)}
|
|
100
|
+
onToggleFocus={handleToggleFocus}
|
|
101
|
+
state={state}
|
|
102
|
+
prefixId={id}
|
|
103
|
+
focusedButtonId={focusedButtonId}
|
|
104
|
+
preferredFocus={true}
|
|
105
|
+
skipFocusManagerRegistration={skipFocusManagerRegistration}
|
|
106
|
+
isFocusable={isFocusable}
|
|
107
|
+
focused={focused}
|
|
108
|
+
/>
|
|
109
|
+
</CellWrapper>
|
|
110
|
+
</FocusableGroup>
|
|
120
111
|
);
|
|
121
112
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { View, ViewStyle } from "react-native";
|
|
3
|
+
import { isTvOSPlatform } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
4
|
+
|
|
5
|
+
const isTvOS = isTvOSPlatform();
|
|
6
|
+
|
|
7
|
+
type Props = {
|
|
8
|
+
style: ViewStyle;
|
|
9
|
+
children: React.ReactNode;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const CellWrapper = ({ style, children }: Props) => {
|
|
13
|
+
if (isTvOS) {
|
|
14
|
+
return <View style={style}>{children}</View>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return <>{children}</>;
|
|
18
|
+
};
|
|
@@ -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;
|
|
@@ -69,6 +65,7 @@ type Props = {
|
|
|
69
65
|
isFocusable: boolean;
|
|
70
66
|
shouldUpdate: boolean;
|
|
71
67
|
behavior: Behavior;
|
|
68
|
+
componentsMapOffset: number;
|
|
72
69
|
};
|
|
73
70
|
|
|
74
71
|
type State = {
|
|
@@ -183,6 +180,7 @@ export class TvOSCellComponent extends React.Component<Props, State> {
|
|
|
183
180
|
groupId,
|
|
184
181
|
component,
|
|
185
182
|
index,
|
|
183
|
+
componentsMapOffset,
|
|
186
184
|
} = this.props;
|
|
187
185
|
|
|
188
186
|
this.setScreenLayout(componentAnchorPointY, screenLayout);
|
|
@@ -197,13 +195,11 @@ export class TvOSCellComponent extends React.Component<Props, State> {
|
|
|
197
195
|
const extraAnchorPointYOffset =
|
|
198
196
|
screenLayout?.extraAnchorPointYOffset || 0;
|
|
199
197
|
|
|
200
|
-
const marginTop = screenLayout?.screenMarginTop || 0;
|
|
201
|
-
|
|
202
198
|
const totalOffset =
|
|
203
199
|
headerOffset +
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
200
|
+
(componentAnchorPointY || 0) +
|
|
201
|
+
extraAnchorPointYOffset -
|
|
202
|
+
componentsMapOffset || 0;
|
|
207
203
|
|
|
208
204
|
mainOffsetUpdater?.(
|
|
209
205
|
{ tag: this.target },
|
|
@@ -251,7 +247,7 @@ export class TvOSCellComponent extends React.Component<Props, State> {
|
|
|
251
247
|
|
|
252
248
|
const focusableId = R.join("-", [component?.id, id, index]);
|
|
253
249
|
|
|
254
|
-
const handleFocus = (arg1: any, index
|
|
250
|
+
const handleFocus = (arg1: any, index?: number) => {
|
|
255
251
|
const focusFn = onFocus || noop;
|
|
256
252
|
focusFn(arg1, index);
|
|
257
253
|
|
|
@@ -284,7 +280,7 @@ export class TvOSCellComponent extends React.Component<Props, State> {
|
|
|
284
280
|
<View onLayout={this.onLayout} style={styles.container}>
|
|
285
281
|
<Focusable
|
|
286
282
|
id={focusableId}
|
|
287
|
-
groupId={groupId || component?.id}
|
|
283
|
+
groupId={String(groupId || component?.id)}
|
|
288
284
|
onFocus={handleFocus}
|
|
289
285
|
onBlur={onBlur || this.onBlur}
|
|
290
286
|
isParallaxDisabled={this.layout?.width > 1740}
|
|
@@ -296,20 +292,18 @@ export class TvOSCellComponent extends React.Component<Props, State> {
|
|
|
296
292
|
style={baseCellStyles}
|
|
297
293
|
isFocusable={isFocusable}
|
|
298
294
|
>
|
|
299
|
-
{(focused) =>
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
);
|
|
312
|
-
}}
|
|
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
|
+
)}
|
|
313
307
|
</Focusable>
|
|
314
308
|
</View>
|
|
315
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
|
+
});
|