@applicaster/zapp-react-native-ui-components 15.0.0-rc.12 → 15.0.0-rc.120

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/Components/AnimatedInOut/index.tsx +69 -26
  2. package/Components/BaseFocusable/index.ios.ts +12 -2
  3. package/Components/Cell/Cell.tsx +14 -3
  4. package/Components/Cell/CellWithFocusable.tsx +9 -0
  5. package/Components/Cell/FocusableWrapper.tsx +47 -0
  6. package/Components/Cell/TvOSCellComponent.tsx +106 -19
  7. package/Components/Focusable/Focusable.tsx +4 -2
  8. package/Components/Focusable/FocusableTvOS.tsx +18 -1
  9. package/Components/Focusable/__tests__/__snapshots__/FocusableTvOS.test.tsx.snap +1 -0
  10. package/Components/FocusableGroup/FocusableTvOS.tsx +32 -1
  11. package/Components/GeneralContentScreen/GeneralContentScreen.tsx +39 -28
  12. package/Components/GeneralContentScreen/__tests__/GeneralContentScreen.test.tsx +104 -0
  13. package/Components/GeneralContentScreen/utils/__tests__/getScreenDataSource.test.ts +19 -0
  14. package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +1 -1
  15. package/Components/GeneralContentScreen/utils/getScreenDataSource.ts +9 -0
  16. package/Components/GeneralContentScreen/utils/useCurationAPI.ts +22 -6
  17. package/Components/HandlePlayable/HandlePlayable.tsx +33 -94
  18. package/Components/HandlePlayable/const.ts +3 -0
  19. package/Components/HandlePlayable/utils.ts +105 -0
  20. package/Components/HookRenderer/HookRenderer.tsx +40 -10
  21. package/Components/HookRenderer/__tests__/HookRenderer.test.tsx +60 -0
  22. package/Components/Layout/TV/LayoutBackground.tsx +5 -2
  23. package/Components/Layout/TV/NavBarContainer.tsx +1 -10
  24. package/Components/Layout/TV/ScreenContainer.tsx +2 -6
  25. package/Components/Layout/TV/__tests__/__snapshots__/NavBarContainer.test.tsx.snap +7 -12
  26. package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +7 -12
  27. package/Components/Layout/TV/index.tsx +3 -4
  28. package/Components/Layout/TV/index.web.tsx +3 -4
  29. package/Components/LinkHandler/LinkHandler.tsx +2 -2
  30. package/Components/MasterCell/DefaultComponents/BorderContainerView/__tests__/index.test.tsx +16 -1
  31. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +30 -2
  32. package/Components/MasterCell/DefaultComponents/Image/Image.android.tsx +5 -1
  33. package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +11 -3
  34. package/Components/MasterCell/DefaultComponents/Image/Image.web.tsx +9 -1
  35. package/Components/MasterCell/DefaultComponents/Image/hooks/useImage.ts +15 -14
  36. package/Components/MasterCell/DefaultComponents/LiveImage/__tests__/prepareEntry.test.ts +352 -0
  37. package/Components/MasterCell/DefaultComponents/LiveImage/executePreloadHooks.ts +136 -0
  38. package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +43 -22
  39. package/Components/MasterCell/DefaultComponents/SecondaryImage/Image.tsx +40 -39
  40. package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/Image.test.tsx +95 -0
  41. package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/__snapshots__/Image.test.tsx.snap +86 -0
  42. package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/index.test.ts +141 -0
  43. package/Components/MasterCell/DefaultComponents/SecondaryImage/hooks/__tests__/useGetImageDimensions.test.ts +7 -6
  44. package/Components/MasterCell/DefaultComponents/SecondaryImage/index.ts +1 -1
  45. package/Components/MasterCell/DefaultComponents/Text/index.tsx +8 -8
  46. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/index.ts +6 -2
  47. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/__tests__/getPluginIdentifier.test.ts +233 -11
  48. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/index.ts +19 -15
  49. package/Components/MasterCell/hoc/__tests__/withAsyncRender.test.tsx +219 -0
  50. package/Components/MasterCell/hoc/withAsyncRender.tsx +9 -7
  51. package/Components/MasterCell/index.tsx +2 -0
  52. package/Components/MasterCell/utils/__tests__/resolveColor.test.js +82 -3
  53. package/Components/MasterCell/utils/index.ts +61 -31
  54. package/Components/MeasurmentsPortal/MeasurementsPortal.tsx +102 -87
  55. package/Components/MeasurmentsPortal/__tests__/MeasurementsPortal.test.tsx +355 -0
  56. package/Components/OfflineHandler/NotificationView/NotificationView.lg.tsx +17 -9
  57. package/Components/OfflineHandler/NotificationView/NotificationView.samsung.tsx +16 -8
  58. package/Components/OfflineHandler/NotificationView/NotificationView.tsx +2 -2
  59. package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +17 -18
  60. package/Components/OfflineHandler/NotificationView/utils.ts +34 -0
  61. package/Components/OfflineHandler/__tests__/index.test.tsx +27 -18
  62. package/Components/PlayerContainer/PlayerContainer.tsx +43 -64
  63. package/Components/PlayerImageBackground/index.tsx +3 -22
  64. package/Components/PreloaderWrapper/__tests__/index.test.tsx +26 -0
  65. package/Components/PreloaderWrapper/index.tsx +15 -0
  66. package/Components/River/ComponentsMap/ComponentsMap.tsx +16 -0
  67. package/Components/River/ComponentsMap/hooks/__tests__/useLoadingState.test.ts +1 -1
  68. package/Components/River/RefreshControl.tsx +9 -3
  69. package/Components/River/RiverItem.tsx +26 -20
  70. package/Components/River/TV/River.tsx +31 -14
  71. package/Components/River/TV/index.tsx +8 -4
  72. package/Components/River/TV/utils/__tests__/toStringOrEmpty.test.ts +30 -0
  73. package/Components/River/TV/utils/index.ts +4 -0
  74. package/Components/River/TV/withFocusableGroupForContent.tsx +71 -0
  75. package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +2 -0
  76. package/Components/River/__tests__/componentsMap.test.js +38 -0
  77. package/Components/Screen/TV/index.web.tsx +4 -2
  78. package/Components/Screen/__tests__/Screen.test.tsx +66 -42
  79. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +68 -44
  80. package/Components/Screen/hooks.ts +75 -6
  81. package/Components/Screen/index.tsx +9 -4
  82. package/Components/Screen/navigationHandler.ts +49 -24
  83. package/Components/Screen/orientationHandler.ts +10 -13
  84. package/Components/ScreenFeedLoader/ScreenFeedLoader.tsx +46 -0
  85. package/Components/ScreenFeedLoader/__tests__/ScreenFeedLoader.test.tsx +94 -0
  86. package/Components/ScreenFeedLoader/index.ts +1 -0
  87. package/Components/ScreenResolver/__tests__/screenResolver.test.js +24 -0
  88. package/Components/ScreenResolver/hooks/index.ts +3 -0
  89. package/Components/ScreenResolver/hooks/useGetComponent.ts +15 -0
  90. package/Components/ScreenResolver/hooks/useScreenComponentResolver.tsx +90 -0
  91. package/Components/ScreenResolver/index.tsx +15 -111
  92. package/Components/ScreenResolver/utils/__tests__/getScreenTypeProps.test.ts +45 -0
  93. package/Components/ScreenResolver/utils/getScreenTypeProps.ts +43 -0
  94. package/Components/ScreenResolver/utils/index.ts +1 -0
  95. package/Components/ScreenResolver/withDefaultScreenContext.tsx +16 -0
  96. package/Components/ScreenResolverFeedProvider/ScreenResolverFeedProvider.tsx +25 -0
  97. package/Components/ScreenResolverFeedProvider/__tests__/ScreenResolverFeedProvider.test.tsx +44 -0
  98. package/Components/ScreenResolverFeedProvider/index.ts +1 -0
  99. package/Components/ScreenRevealManager/ScreenRevealManager.ts +40 -8
  100. package/Components/ScreenRevealManager/__tests__/ScreenRevealManager.test.ts +86 -69
  101. package/Components/ScreenRevealManager/withScreenRevealManager.tsx +44 -26
  102. package/Components/Tabs/TV/Tabs.tsx +20 -3
  103. package/Components/Tabs/TabContent.tsx +7 -4
  104. package/Components/Transitioner/Scene.tsx +10 -3
  105. package/Components/Transitioner/index.js +3 -3
  106. package/Components/VideoLive/LiveImageManager.ts +199 -54
  107. package/Components/VideoLive/PlayerLiveImageComponent.tsx +31 -33
  108. package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +2 -17
  109. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +1 -0
  110. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +118 -171
  111. package/Components/VideoModal/ModalAnimation/index.ts +2 -13
  112. package/Components/VideoModal/ModalAnimation/utils.ts +1 -327
  113. package/Components/VideoModal/PlayerWrapper.tsx +14 -88
  114. package/Components/VideoModal/VideoModal.tsx +1 -5
  115. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +1 -0
  116. package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +15 -7
  117. package/Components/VideoModal/hooks/useModalSize.ts +10 -5
  118. package/Components/VideoModal/playerWrapperStyle.ts +70 -0
  119. package/Components/VideoModal/playerWrapperUtils.ts +91 -0
  120. package/Components/VideoModal/utils.ts +19 -9
  121. package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +0 -2
  122. package/Components/Viewport/ViewportAware/index.tsx +16 -7
  123. package/Components/Viewport/ViewportEvents/__tests__/viewportEvents.test.js +1 -1
  124. package/Components/ZappUIComponent/index.tsx +12 -6
  125. package/Components/index.js +1 -1
  126. package/Contexts/ScreenContext/__tests__/index.test.tsx +57 -0
  127. package/Contexts/ScreenContext/index.tsx +71 -19
  128. package/Contexts/ScreenTrackedViewPositionsContext/__tests__/index.test.tsx +1 -1
  129. package/Contexts/ZappHookModalContext/index.tsx +37 -61
  130. package/Contexts/ZappPipesContext/ZappPipesContextFactory.tsx +18 -7
  131. package/Contexts/index.ts +0 -2
  132. package/Decorators/Analytics/index.tsx +6 -5
  133. package/Decorators/ConfigurationWrapper/__tests__/__snapshots__/withConfigurationProvider.test.tsx.snap +1 -0
  134. package/Decorators/ConfigurationWrapper/const.ts +1 -0
  135. package/Decorators/ZappPipesDataConnector/ResolverSelector.tsx +25 -7
  136. package/Decorators/ZappPipesDataConnector/__tests__/ResolverSelector.test.tsx +212 -5
  137. package/Decorators/ZappPipesDataConnector/__tests__/UrlFeedResolver.test.tsx +39 -21
  138. package/Decorators/ZappPipesDataConnector/__tests__/zappPipesDataConnector.test.js +1 -1
  139. package/Decorators/ZappPipesDataConnector/index.tsx +2 -2
  140. package/Decorators/ZappPipesDataConnector/resolvers/StaticFeedResolver.tsx +1 -1
  141. package/Decorators/ZappPipesDataConnector/resolvers/UrlFeedResolver.tsx +18 -7
  142. package/Helpers/DataSourceHelper/__tests__/itemLimitForData.test.ts +80 -0
  143. package/Helpers/DataSourceHelper/index.ts +19 -0
  144. package/events/index.ts +3 -0
  145. package/events/scrollEndReached.ts +15 -0
  146. package/index.d.ts +7 -0
  147. package/package.json +6 -5
  148. package/Components/PlayerContainer/ErrorDisplay/ErrorDisplay.tsx +0 -57
  149. package/Components/PlayerContainer/ErrorDisplay/index.ts +0 -9
  150. package/Components/River/TV/withTVEventHandler.tsx +0 -27
  151. package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +0 -60
  152. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +0 -417
  153. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.web.tsx +0 -294
  154. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +0 -176
  155. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.web.tsx +0 -93
  156. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +0 -500
  157. package/Components/VideoModal/ModalAnimation/__tests__/getMoveUpValue.test.ts +0 -108
  158. package/Helpers/DataSourceHelper/index.js +0 -19
  159. /package/Components/HookRenderer/{index.tsx → index.ts} +0 -0
@@ -0,0 +1,60 @@
1
+ import React from "react";
2
+ import { View } from "react-native";
3
+ import { render } from "@testing-library/react-native";
4
+ import { HookRenderer } from "..";
5
+
6
+ jest.mock("@applicaster/zapp-react-native-utils/reactUtils", () => ({
7
+ isTV: jest.fn(() => false),
8
+ }));
9
+
10
+ jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation", () => ({
11
+ useBackHandler: jest.fn(),
12
+ useIsNavBarVisible: jest.fn(() => true),
13
+ }));
14
+
15
+ jest.mock(
16
+ "@applicaster/zapp-react-native-utils/analyticsUtils/helpers/hooks",
17
+ () => ({
18
+ useHookAnalytics: jest.fn(),
19
+ })
20
+ );
21
+
22
+ jest.mock("@applicaster/zapp-react-native-utils/reactHooks", () => ({
23
+ useSetNavbarState: jest.fn(() => ({
24
+ setVisible: jest.fn(),
25
+ })),
26
+ }));
27
+
28
+ describe("HookRenderer", () => {
29
+ it("returns null when hookPlugin is missing", () => {
30
+ const { toJSON } = render(
31
+ <HookRenderer callback={jest.fn()} screenData={{ payload: {} } as any} />
32
+ );
33
+
34
+ expect(toJSON()).toBeNull();
35
+ });
36
+
37
+ it("passes Hook presentationType to rendered hook component", () => {
38
+ const HookComponent = (props) => (
39
+ <View testID="hook-component" {...props} />
40
+ );
41
+
42
+ const { getByTestId } = render(
43
+ <HookRenderer
44
+ callback={jest.fn()}
45
+ screenData={{
46
+ payload: { foo: "bar" },
47
+ hookPlugin: {
48
+ module: {
49
+ Component: HookComponent,
50
+ presentFullScreen: false,
51
+ },
52
+ configuration: {},
53
+ },
54
+ }}
55
+ />
56
+ );
57
+
58
+ expect(getByTestId("hook-component").props.presentationType).toBe("Hook");
59
+ });
60
+ });
@@ -1,7 +1,10 @@
1
1
  import React from "react";
2
- import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
3
2
  import { getBackgroundImageUrl } from "../utils";
4
3
  import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
4
+ import {
5
+ selectRemoteConfigurations,
6
+ useAppSelector,
7
+ } from "@applicaster/zapp-react-native-redux";
5
8
 
6
9
  export const LayoutBackground = ({
7
10
  Background,
@@ -12,7 +15,7 @@ export const LayoutBackground = ({
12
15
  }) => {
13
16
  const theme = useTheme();
14
17
 
15
- const { remoteConfigurations } = usePickFromState(["remoteConfigurations"]);
18
+ const remoteConfigurations = useAppSelector(selectRemoteConfigurations);
16
19
 
17
20
  const backgroundColor = theme.app_background_color;
18
21
  const backgroundImageUrl = getBackgroundImageUrl(remoteConfigurations);
@@ -15,12 +15,6 @@ const styles = StyleSheet.create({
15
15
  flex: 1,
16
16
  width: "100%",
17
17
  },
18
- themeStyles: {
19
- // limits the height of the focusable container of the TopMenuBarTV component
20
- // to prevent it from being overlapped by the screen content,
21
- // as it makes TopMenuBarTV unfocusable on tvOS
22
- maxHeight: 1,
23
- },
24
18
  });
25
19
 
26
20
  export const NavBarContainer = ({ children, isVisible, onReady }: Props) => {
@@ -31,10 +25,7 @@ export const NavBarContainer = ({ children, isVisible, onReady }: Props) => {
31
25
  }, [onReady]);
32
26
 
33
27
  return isVisible ? (
34
- <View
35
- testID="nav-bar-container"
36
- style={[styles.container, styles.themeStyles]}
37
- >
28
+ <View testID="nav-bar-container" style={styles.container}>
38
29
  {children}
39
30
  </View>
40
31
  ) : null;
@@ -18,7 +18,7 @@ import {
18
18
  routeIsPlayerScreen,
19
19
  } from "@applicaster/zapp-react-native-utils/navigationUtils";
20
20
  import { isApplePlatform } from "@applicaster/zapp-react-native-utils/reactUtils";
21
- import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
21
+ import { usePlugins } from "@applicaster/zapp-react-native-redux/hooks";
22
22
  import { NavBarContainer } from "./NavBarContainer";
23
23
 
24
24
  type ComponentsExtraProps = {
@@ -111,11 +111,7 @@ export const ScreenContainer = React.memo(function ScreenContainer({
111
111
  const { activeRiver } = navigator;
112
112
  const { title, visible } = useNavbarState();
113
113
 
114
- const { plugins = [] } = usePickFromState([
115
- "appState",
116
- "remoteConfigurations",
117
- "plugins",
118
- ]);
114
+ const plugins = usePlugins();
119
115
 
120
116
  const navigationProps = getNavigationProps({
121
117
  navigator,
@@ -3,18 +3,13 @@
3
3
  exports[`NavBarContainer renders 1`] = `
4
4
  <View
5
5
  style={
6
- [
7
- {
8
- "flex": 1,
9
- "position": "absolute",
10
- "top": 0,
11
- "width": "100%",
12
- "zIndex": 10,
13
- },
14
- {
15
- "maxHeight": 1,
16
- },
17
- ]
6
+ {
7
+ "flex": 1,
8
+ "position": "absolute",
9
+ "top": 0,
10
+ "width": "100%",
11
+ "zIndex": 10,
12
+ }
18
13
  }
19
14
  testID="nav-bar-container"
20
15
  >
@@ -14,18 +14,13 @@ exports[`ScreenContainer renders 1`] = `
14
14
  >
15
15
  <View
16
16
  style={
17
- [
18
- {
19
- "flex": 1,
20
- "position": "absolute",
21
- "top": 0,
22
- "width": "100%",
23
- "zIndex": 10,
24
- },
25
- {
26
- "maxHeight": 1,
27
- },
28
- ]
17
+ {
18
+ "flex": 1,
19
+ "position": "absolute",
20
+ "top": 0,
21
+ "width": "100%",
22
+ "zIndex": 10,
23
+ }
29
24
  }
30
25
  testID="nav-bar-container"
31
26
  >
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
2
+ import { useAppSelector } from "@applicaster/zapp-react-native-redux/hooks";
3
3
  import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
4
4
 
5
5
  import { LayoutContainer } from "./LayoutContainer";
@@ -10,6 +10,7 @@ import { PathnameContext } from "../../../Contexts/PathnameContext";
10
10
  import { ScreenDataContext } from "../../../Contexts/ScreenDataContext";
11
11
  import { ScreenContextProvider } from "../../../Contexts/ScreenContext";
12
12
  import { LayoutBackground } from "./LayoutBackground";
13
+ import { selectAppReady } from "@applicaster/zapp-react-native-redux";
13
14
 
14
15
  type Components = {
15
16
  NavBar: React.ComponentType<any>;
@@ -29,9 +30,7 @@ type Props = {
29
30
  const Layout = ({ Components, ComponentsExtraProps, children }: Props) => {
30
31
  const navigator = useNavigation();
31
32
 
32
- const { appState: { appReady = false } = {} } = usePickFromState([
33
- "appState",
34
- ]);
33
+ const appReady = useAppSelector(selectAppReady);
35
34
 
36
35
  if (!appReady) {
37
36
  return null;
@@ -1,11 +1,11 @@
1
1
  import * as React from "react";
2
- import { pathOr } from "ramda";
3
2
 
4
- import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
3
+ import { useAppSelector } from "@applicaster/zapp-react-native-redux/hooks";
5
4
 
6
5
  import { ScreenLayoutContextProvider } from "./ScreenLayoutContextProvider";
7
6
  import { StackNavigator } from "../../Navigator";
8
7
  import { LayoutBackground } from "./LayoutBackground";
8
+ import { selectAppReady } from "@applicaster/zapp-react-native-redux";
9
9
 
10
10
  type Components = {
11
11
  NavBar: React.ComponentType<any>;
@@ -17,8 +17,7 @@ type Props = {
17
17
  };
18
18
 
19
19
  const Layout = ({ Components }: Props) => {
20
- const { appState } = usePickFromState(["appState"]);
21
- const appReady = pathOr(false, ["appReady"], appState);
20
+ const appReady = useAppSelector(selectAppReady);
22
21
 
23
22
  if (!appReady) {
24
23
  return null;
@@ -2,7 +2,7 @@ import * as React from "react";
2
2
  import * as R from "ramda";
3
3
 
4
4
  import { findPluginByIdentifier } from "@applicaster/zapp-react-native-utils/pluginUtils";
5
- import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
5
+ import { usePlugins } from "@applicaster/zapp-react-native-redux/hooks";
6
6
  import {
7
7
  inflateString,
8
8
  objectToReadableString,
@@ -40,7 +40,7 @@ export async function inflateUrl(url) {
40
40
 
41
41
  export function LinkHandler(props: Props) {
42
42
  const screenData = props?.screenData;
43
- const { plugins } = usePickFromState(["rivers", "plugins"]);
43
+ const plugins = usePlugins();
44
44
 
45
45
  const ScreenPlugin = findPluginByIdentifier(
46
46
  WEBVIEW_SCREEN_IDENTIFIER,
@@ -1,8 +1,8 @@
1
+ import * as React from "react";
1
2
  import {
2
3
  BorderContainerView,
3
4
  getBorderPadding, // Export for testing (using a double underscore prefix is a common convention)
4
5
  } from "../index";
5
- import * as React from "react";
6
6
  import { render } from "@testing-library/react-native";
7
7
  import { toNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/numberUtils";
8
8
  import { View } from "react-native";
@@ -11,6 +11,15 @@ jest.mock("@applicaster/zapp-react-native-utils/numberUtils", () => ({
11
11
  toNumberWithDefaultZero: jest.fn((value) => Number(value) || 0),
12
12
  }));
13
13
 
14
+ jest.mock(
15
+ "@applicaster/zapp-react-native-utils/appUtils/accessibilityManager/hooks",
16
+ () => ({
17
+ useAccessibilityManager: jest.fn(() => ({
18
+ addHeading: jest.fn(),
19
+ })),
20
+ })
21
+ );
22
+
14
23
  describe("BorderContainerView", () => {
15
24
  describe("getBorderPadding", () => {
16
25
  it("returns 0 for inside", () => {
@@ -42,6 +51,8 @@ describe("BorderContainerView", () => {
42
51
  };
43
52
 
44
53
  const borderPosition = null;
54
+ const mockEntry = { id: "test-entry" } as ZappEntry;
55
+ const mockHasFocusableInside = jest.fn(() => false);
45
56
 
46
57
  const { queryByTestId } = render(
47
58
  <BorderContainerView
@@ -52,6 +63,10 @@ describe("BorderContainerView", () => {
52
63
  borderPaddingRight={toNumberWithDefaultZero(padding.paddingRight)}
53
64
  borderPaddingBottom={toNumberWithDefaultZero(padding.paddingBottom)}
54
65
  borderPaddingLeft={toNumberWithDefaultZero(padding.paddingLeft)}
66
+ hasFocusableInside={mockHasFocusableInside}
67
+ entry={mockEntry}
68
+ state="focused"
69
+ hasTextLabels={false}
55
70
  >
56
71
  <View testID="child" />
57
72
  </BorderContainerView>
@@ -1,10 +1,16 @@
1
- import { toNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/numberUtils";
2
- import * as React from "react";
1
+ import React, { useMemo, useContext, useEffect } from "react";
3
2
  import { ImageStyle, StyleSheet, View, ViewStyle } from "react-native";
3
+ import { useAccessibilityManager } from "@applicaster/zapp-react-native-utils/appUtils/accessibilityManager/hooks";
4
+ import { toNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/numberUtils";
5
+ import { MeasurementPortalContext } from "../../../MeasurmentsPortal/MeasurementsPortal";
4
6
 
5
7
  type BorderPosition = "inside" | "outside" | "center";
6
8
 
7
9
  interface Props {
10
+ hasFocusableInside: (entry: ZappEntry) => boolean;
11
+ entry: ZappEntry;
12
+ state: CellState;
13
+ hasTextLabels: boolean;
8
14
  style: ImageStyle | ViewStyle;
9
15
  borderPosition: BorderPosition;
10
16
  borderPaddingTop: number;
@@ -118,8 +124,30 @@ export const BorderContainerView = (props: Props) => {
118
124
  borderPaddingLeft,
119
125
  style,
120
126
  children,
127
+ hasFocusableInside,
128
+ entry,
129
+ state,
130
+ hasTextLabels,
121
131
  } = props;
122
132
 
133
+ const accessibilityManager = useAccessibilityManager();
134
+ const isMeasurement = useContext(MeasurementPortalContext);
135
+
136
+ const isImageOnlyCell = useMemo(
137
+ () =>
138
+ state === "focused" &&
139
+ !hasTextLabels &&
140
+ !isMeasurement?.measuringInProgress &&
141
+ !hasFocusableInside(entry),
142
+ [entry, hasTextLabels, state, isMeasurement?.measuringInProgress]
143
+ );
144
+
145
+ useEffect(() => {
146
+ if (isImageOnlyCell && entry?.title) {
147
+ accessibilityManager.addHeading(String(entry.title));
148
+ }
149
+ }, [isImageOnlyCell, entry?.title]);
150
+
123
151
  const padding =
124
152
  borderPosition === "outside"
125
153
  ? {
@@ -32,6 +32,7 @@ export default function Image({
32
32
  placeholderImage,
33
33
  entry,
34
34
  withDimensions,
35
+ source: sourceProp,
35
36
  ...otherProps
36
37
  }: Props) {
37
38
  const [showDefault, setShowDefault] = React.useState(false);
@@ -48,7 +49,10 @@ export default function Image({
48
49
  entry,
49
50
  showDefault,
50
51
  placeholderImage: placeholderImage || "",
51
- otherProps,
52
+ otherProps: {
53
+ source: sourceProp,
54
+ state: otherProps.state,
55
+ },
52
56
  });
53
57
 
54
58
  const onError = React.useCallback(() => {
@@ -1,8 +1,8 @@
1
1
  import * as React from "react";
2
2
  import { Image as RnImage, ImageStyle } from "react-native";
3
- import { equals, omit } from "ramda";
4
3
 
5
4
  import { useImageSource } from "./hooks";
5
+ import { equals } from "@applicaster/zapp-react-native-utils/utils";
6
6
 
7
7
  type Source = {
8
8
  uri: string;
@@ -25,11 +25,19 @@ function Image({
25
25
  placeholderImage,
26
26
  entry,
27
27
  withDimensions,
28
+ source: sourceProp,
28
29
  ...otherProps
29
30
  }: Props) {
30
31
  const [error, setErrorState] = React.useState(null);
31
32
 
32
- const source = useImageSource({ uri, entry, otherProps });
33
+ const source = useImageSource({
34
+ uri,
35
+ entry,
36
+ otherProps: {
37
+ source: sourceProp,
38
+ state: otherProps.state,
39
+ },
40
+ });
33
41
 
34
42
  React.useEffect(() => {
35
43
  // reset error state on URI change as the error is referencing previous uri
@@ -49,7 +57,7 @@ function Image({
49
57
  onError={React.useCallback(() => setErrorState(true), [])}
50
58
  // as we have defaults as "" for placeholder image, we need to pass undefined to source to not throw warnings
51
59
  source={_source?.uri ? _source : undefined}
52
- {...omit(["source"], otherProps)}
60
+ {...otherProps}
53
61
  />
54
62
  );
55
63
  }
@@ -23,9 +23,17 @@ function Image({
23
23
  placeholderImage,
24
24
  entry,
25
25
  withDimensions,
26
+ source: sourceProp,
26
27
  ...otherProps
27
28
  }: Props) {
28
- const source = useImageSource({ uri, entry, otherProps });
29
+ const source = useImageSource({
30
+ uri,
31
+ entry,
32
+ otherProps: {
33
+ source: sourceProp,
34
+ state: otherProps.state,
35
+ },
36
+ });
29
37
 
30
38
  const updatedSource = source ? withDimensions(source) : { uri: "" };
31
39
 
@@ -1,19 +1,21 @@
1
1
  import * as React from "react";
2
- import { path } from "ramda";
3
2
 
4
3
  import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
5
4
  import { useActions } from "@applicaster/zapp-react-native-utils/reactHooks/actions";
6
5
  import { extractAsset } from "./utils";
7
6
 
8
7
  type Return = { uri: string } | null;
8
+ type Source = { context?: string; uri?: string } | null | undefined;
9
9
 
10
- const getSourceContext = path(["source", "context"]);
11
- const getSourceUri = path(["source", "uri"]);
12
- const getState = path(["state"]);
10
+ const getSourceContext = (source: Source) => source?.context;
11
+ const getSourceUri = (source: Source) => source?.uri;
13
12
 
14
- export const useImageSource = ({ uri, entry, otherProps }): Return => {
15
- const uriContext = getSourceContext(otherProps);
16
- const uriState = getState(otherProps);
13
+ export const useImageSource = ({
14
+ uri,
15
+ entry,
16
+ otherProps: { source, state: uriState },
17
+ }): Return => {
18
+ const uriContext = getSourceContext(source);
17
19
 
18
20
  const action = useActions(uriContext);
19
21
 
@@ -38,7 +40,7 @@ export const useImageSource = ({ uri, entry, otherProps }): Return => {
38
40
  return { uri };
39
41
  }
40
42
 
41
- const uriFromSource = getSourceUri(otherProps);
43
+ const uriFromSource = getSourceUri(source);
42
44
 
43
45
  if (uriFromSource) {
44
46
  return { uri: uriFromSource };
@@ -47,7 +49,7 @@ export const useImageSource = ({ uri, entry, otherProps }): Return => {
47
49
  return null;
48
50
  };
49
51
 
50
- const getSource = (uri, showDefault, placeholderImage, otherProps) => {
52
+ const getSource = (uri, showDefault, placeholderImage, source) => {
51
53
  const placeholderName = placeholderImage || "";
52
54
 
53
55
  const defaultPath = {
@@ -60,7 +62,7 @@ const getSource = (uri, showDefault, placeholderImage, otherProps) => {
60
62
  return { uri };
61
63
  }
62
64
 
63
- const uriFromSource = getSourceUri(otherProps);
65
+ const uriFromSource = getSourceUri(source);
64
66
 
65
67
  if (uriFromSource) {
66
68
  return { uri: uriFromSource };
@@ -74,10 +76,9 @@ export const useImageSourceWithDefault = ({
74
76
  entry,
75
77
  showDefault,
76
78
  placeholderImage,
77
- otherProps,
79
+ otherProps: { state: uriState, source },
78
80
  }): Return => {
79
- const uriContext = getSourceContext(otherProps);
80
- const uriState = getState(otherProps);
81
+ const uriContext = getSourceContext(source);
81
82
 
82
83
  const action = useActions(uriContext);
83
84
 
@@ -98,5 +99,5 @@ export const useImageSourceWithDefault = ({
98
99
  return extractAsset(!isTV(), entryStateLocal.asset, uriState);
99
100
  }
100
101
 
101
- return getSource(uri, showDefault, placeholderImage, otherProps);
102
+ return getSource(uri, showDefault, placeholderImage, source);
102
103
  };