@applicaster/zapp-react-native-ui-components 13.0.0-alpha.1436249127 → 13.0.0-alpha.1442750538

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 (122) hide show
  1. package/Components/AppContainer/__tests__/__snapshots__/AppContainer.test.js.snap +1 -1
  2. package/Components/AudioPlayer/__tests__/__snapshots__/Runtime.test.js.snap +4 -4
  3. package/Components/AudioPlayer/__tests__/__snapshots__/artWork.test.js.snap +3 -3
  4. package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayer.test.js.snap +6 -6
  5. package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayerLayout.test.js.snap +7 -7
  6. package/Components/AudioPlayer/__tests__/__snapshots__/channel.test.js.snap +3 -3
  7. package/Components/AudioPlayer/__tests__/__snapshots__/summary.test.js.snap +2 -2
  8. package/Components/AudioPlayer/__tests__/__snapshots__/title.test.js.snap +2 -2
  9. package/Components/BaseFocusable/index.ios.ts +1 -1
  10. package/Components/BaseFocusable/index.tsx +1 -1
  11. package/Components/Cell/Cell.tsx +7 -3
  12. package/Components/Cell/CellWithFocusable.ios.tsx +126 -0
  13. package/Components/Cell/CellWithFocusable.tsx +43 -59
  14. package/Components/Cell/TvOSCellComponent.tsx +0 -4
  15. package/Components/Cell/__tests__/CellWIthFocusable.test.js +13 -6
  16. package/Components/CellRendererResolver/__tests__/__snapshots__/cellRendererResolver.test.js.snap +20 -20
  17. package/Components/CellRendererResolver/__tests__/cellRendererResolver.test.js +5 -3
  18. package/Components/ComponentResolver/__tests__/__snapshots__/componentResolver.test.js.snap +5 -5
  19. package/Components/ComponentResolver/__tests__/componentResolver.test.js +11 -9
  20. package/Components/DisplayState/__tests__/__snapshots__/displayState.test.js.snap +2 -2
  21. package/Components/Focusable/FocusableTvOS.tsx +1 -1
  22. package/Components/Focusable/Touchable.tsx +19 -20
  23. package/Components/FocusableList/index.tsx +0 -1
  24. package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +9 -0
  25. package/Components/GeneralContentScreen/utils/useCurationAPI.ts +1 -1
  26. package/Components/Layout/TV/__tests__/ScreenContainer.test.tsx +1 -0
  27. package/Components/Layout/TV/__tests__/__snapshots__/LayoutContainer.test.tsx.snap +1 -1
  28. package/Components/Layout/TV/__tests__/__snapshots__/NavBarContainer.test.tsx.snap +3 -3
  29. package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +9 -9
  30. package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +1 -1
  31. package/Components/Layout/TV/__tests__/index.test.tsx +7 -3
  32. package/Components/MasterCell/DefaultComponents/BorderContainerView/__tests__/index.test.tsx +66 -0
  33. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +4 -1
  34. package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +6 -12
  35. package/Components/MasterCell/DefaultComponents/ImageBorderContainer/__tests__/index.test.ts +93 -0
  36. package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/__snapshots__/Image.test.tsx.snap +3 -3
  37. package/Components/MasterCell/DefaultComponents/SecondaryImage/utils.ts +1 -1
  38. package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
  39. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/__tests__/__snapshots__/index.test.tsx.snap +1 -1
  40. package/Components/MasterCell/__tests__/__snapshots__/dataAdapter.test.js.snap +180 -180
  41. package/Components/MasterCell/__tests__/__snapshots__/elementMapper.test.js.snap +7 -7
  42. package/Components/MasterCell/__tests__/__snapshots__/masterCell.test.js.snap +34 -34
  43. package/Components/MasterCell/hooks/useAsyncRendering/MasterCellAsyncRenderManager.ts +2 -2
  44. package/Components/MasterCell/hooks/useAsyncRendering/index.ts +2 -2
  45. package/Components/MasterCell/utils/index.ts +1 -1
  46. package/Components/ModalComponent/Header/index.tsx +3 -3
  47. package/Components/OfflineHandler/__tests__/__snapshots__/index.test.tsx.snap +7 -7
  48. package/Components/OfflineHandler/__tests__/index.test.tsx +28 -25
  49. package/Components/PlayerContainer/PlayerContainer.tsx +5 -11
  50. package/Components/PlayerContainer/PlayerContainerContext.tsx +9 -0
  51. package/Components/River/ComponentsMap/ComponentsMap.tsx +39 -65
  52. package/Components/River/ComponentsMap/hooks/useLoadingState.ts +78 -51
  53. package/Components/River/RefreshControl.tsx +1 -1
  54. package/Components/River/RiverFooter.tsx +39 -9
  55. package/Components/River/RiverItem.tsx +37 -2
  56. package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +114 -45
  57. package/Components/River/__tests__/__snapshots__/river.test.js.snap +12 -12
  58. package/Components/River/__tests__/componentsMap.test.js +64 -17
  59. package/Components/RouteManager/__tests__/__snapshots__/routeManager.test.js.snap +1 -1
  60. package/Components/RouteManager/__tests__/__snapshots__/testId.test.js.snap +1 -1
  61. package/Components/Screen/__tests__/Screen.test.tsx +41 -27
  62. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +4 -4
  63. package/Components/Screen/hooks.ts +56 -0
  64. package/Components/Screen/index.tsx +13 -39
  65. package/Components/ScreenResolver/__tests__/__snapshots__/screenResolver.test.js.snap +2 -2
  66. package/Components/ScreenResolver/__tests__/screenResolver.test.js +31 -27
  67. package/Components/Tabs/Tab.tsx +7 -6
  68. package/Components/TextInputTv/__tests__/TextInputTv.test.js +42 -42
  69. package/Components/TextInputTv/__tests__/__snapshots__/TextInputTv.test.js.snap +7 -0
  70. package/Components/TextInputTv/index.tsx +4 -4
  71. package/Components/Touchable/__tests__/__snapshots__/touchable.test.tsx.snap +2 -2
  72. package/Components/Transitioner/AnimationManager.js +8 -8
  73. package/Components/Transitioner/Scene.tsx +52 -23
  74. package/Components/Transitioner/__tests__/__snapshots__/AnimationManager.test.js.snap +26 -26
  75. package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +62 -46
  76. package/Components/Transitioner/__tests__/__snapshots__/config.test.js.snap +20 -20
  77. package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +4 -4
  78. package/Components/Transitioner/index.js +8 -4
  79. package/Components/VideoLive/LiveImageManager.ts +27 -1
  80. package/Components/VideoLive/PlayerLiveImageComponent.tsx +29 -21
  81. package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +63 -8
  82. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +5 -10
  83. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +5 -1
  84. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +5 -1
  85. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +8 -7
  86. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +6 -13
  87. package/Components/VideoModal/ModalAnimation/index.ts +2 -1
  88. package/Components/VideoModal/ModalAnimation/useModalAnimationContext.ts +6 -0
  89. package/Components/VideoModal/ModalAnimation/utils.ts +2 -2
  90. package/Components/VideoModal/OpaqueLayer.tsx +33 -0
  91. package/Components/VideoModal/PlayerWrapper.tsx +16 -35
  92. package/Components/VideoModal/VideoModal.tsx +14 -23
  93. package/Components/VideoModal/__tests__/PlayerDetails.test.tsx +5 -2
  94. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +13 -10
  95. package/Components/VideoModal/__tests__/__snapshots__/PlayerDetails.test.tsx.snap +4 -4
  96. package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +66 -156
  97. package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +89 -0
  98. package/Components/VideoModal/hooks/index.ts +7 -0
  99. package/Components/VideoModal/hooks/useDelayedPlayerDetails.ts +49 -0
  100. package/Components/VideoModal/hooks/utils/__tests__/showDetails.test.ts +91 -0
  101. package/Components/VideoModal/hooks/utils/index.ts +33 -0
  102. package/Components/VideoModal/utils.ts +3 -5
  103. package/Components/Viewport/ViewportAware/__tests__/__snapshots__/viewportAware.test.js.snap +2 -2
  104. package/Components/Viewport/ViewportTracker/__tests__/__snapshots__/viewportTracker.test.js.snap +1 -1
  105. package/Components/ZappUIComponent/__tests__/__snapshots__/ZappUIComponent.test.js.snap +11 -11
  106. package/Components/default-cell-renderer/__tests__/__snapshots__/defaultCellRenderer.test.tsx.snap +30 -30
  107. package/Contexts/ConfigutaionContext/__tests__/__snapshots__/ConfigurationProvider.test.tsx.snap +1 -1
  108. package/Contexts/ScreenContext/index.tsx +3 -2
  109. package/Decorators/Navigator/__tests__/__snapshots__/navigator.test.js.snap +2 -2
  110. package/Decorators/RiverFeedLoader/__tests__/__snapshots__/riverFeedLoader.test.tsx.snap +77 -77
  111. package/Decorators/RiverFeedLoader/__tests__/riverFeedLoader.test.tsx +34 -39
  112. package/Decorators/RiverFeedLoader/__tests__/utils.test.ts +0 -9
  113. package/Decorators/RiverFeedLoader/index.tsx +1 -1
  114. package/Decorators/RiverFeedLoader/utils/getDatasourceUrl.ts +39 -0
  115. package/Decorators/RiverFeedLoader/utils/index.ts +29 -0
  116. package/Decorators/RiverFeedLoader/utils/usePipesContexts.ts +40 -0
  117. package/Decorators/RiverResolver/__tests__/__snapshots__/riverResolver.test.tsx.snap +5 -5
  118. package/Decorators/RiverResolver/__tests__/riverResolver.test.tsx +16 -10
  119. package/Decorators/ZappPipesDataConnector/__tests__/Hero.js +1 -1
  120. package/Decorators/ZappPipesDataConnector/index.tsx +32 -2
  121. package/package.json +12 -6
  122. package/Decorators/RiverFeedLoader/utils.ts +0 -100
@@ -3,7 +3,7 @@
3
3
  exports[`<AppContainer /> renders correctly 1`] = `
4
4
  <View
5
5
  style={
6
- Object {
6
+ {
7
7
  "backgroundColor": "rgba(255, 255, 255, 1)",
8
8
  "flex": 1,
9
9
  }
@@ -3,7 +3,7 @@
3
3
  exports[`<Runtime /> LTR renders correctly 1`] = `
4
4
  <View
5
5
  style={
6
- Object {
6
+ {
7
7
  "height": 40,
8
8
  "justifyContent": "flex-start",
9
9
  "width": 600,
@@ -12,7 +12,7 @@ exports[`<Runtime /> LTR renders correctly 1`] = `
12
12
  >
13
13
  <Text
14
14
  style={
15
- Object {
15
+ {
16
16
  "alignItems": "flex-end",
17
17
  "color": "white",
18
18
  "flexDirection": "row",
@@ -32,7 +32,7 @@ exports[`<Runtime /> LTR renders correctly 1`] = `
32
32
  exports[`<Runtime /> RTL renders correctly 1`] = `
33
33
  <View
34
34
  style={
35
- Object {
35
+ {
36
36
  "height": 40,
37
37
  "justifyContent": "flex-end",
38
38
  "width": 600,
@@ -41,7 +41,7 @@ exports[`<Runtime /> RTL renders correctly 1`] = `
41
41
  >
42
42
  <Text
43
43
  style={
44
- Object {
44
+ {
45
45
  "alignItems": "flex-start",
46
46
  "color": "white",
47
47
  "flexDirection": "row-reverse",
@@ -3,7 +3,7 @@
3
3
  exports[`<Artwork /> renders correctly 1`] = `
4
4
  <View
5
5
  style={
6
- Object {
6
+ {
7
7
  "marginHorizontal": 24,
8
8
  }
9
9
  }
@@ -12,12 +12,12 @@ exports[`<Artwork /> renders correctly 1`] = `
12
12
  fadeDuration={0}
13
13
  resizeMode="cover"
14
14
  source={
15
- Object {
15
+ {
16
16
  "uri": "https://example.com",
17
17
  }
18
18
  }
19
19
  style={
20
- Object {
20
+ {
21
21
  "height": 400,
22
22
  "width": 400,
23
23
  }
@@ -3,7 +3,7 @@
3
3
  exports[`<AudioPlayer /> renders correctly 1`] = `
4
4
  <AudioPlayerLayout
5
5
  config={
6
- Object {
6
+ {
7
7
  "artworkAspectRatio": "1:1",
8
8
  "audioPlayerBackgroundImageQuery": "",
9
9
  "backgroundColor": "black",
@@ -21,11 +21,11 @@ exports[`<AudioPlayer /> renders correctly 1`] = `
21
21
  "titleFontSize": undefined,
22
22
  }
23
23
  }
24
- style={Object {}}
24
+ style={{}}
25
25
  >
26
26
  <Channel
27
27
  config={
28
- Object {
28
+ {
29
29
  "artworkAspectRatio": "1:1",
30
30
  "audioPlayerBackgroundImageQuery": "",
31
31
  "backgroundColor": "black",
@@ -47,7 +47,7 @@ exports[`<AudioPlayer /> renders correctly 1`] = `
47
47
  />
48
48
  <Title
49
49
  config={
50
- Object {
50
+ {
51
51
  "artworkAspectRatio": "1:1",
52
52
  "audioPlayerBackgroundImageQuery": "",
53
53
  "backgroundColor": "black",
@@ -69,7 +69,7 @@ exports[`<AudioPlayer /> renders correctly 1`] = `
69
69
  />
70
70
  <Summary
71
71
  config={
72
- Object {
72
+ {
73
73
  "artworkAspectRatio": "1:1",
74
74
  "audioPlayerBackgroundImageQuery": "",
75
75
  "backgroundColor": "black",
@@ -98,7 +98,7 @@ exports[`<AudioPlayer /> renders correctly 1`] = `
98
98
  audio_player_summary_color="white"
99
99
  audio_player_title_color="white"
100
100
  config={
101
- Object {
101
+ {
102
102
  "artworkAspectRatio": "1:1",
103
103
  "audioPlayerBackgroundImageQuery": "",
104
104
  "backgroundColor": "black",
@@ -4,7 +4,7 @@ exports[`<AudioPlayerLayout /> renders correctly 1`] = `
4
4
  <View
5
5
  pointerEvents="none"
6
6
  style={
7
- Object {
7
+ {
8
8
  "backgroundColor": "transparent",
9
9
  "overflow": "hidden",
10
10
  }
@@ -12,12 +12,12 @@ exports[`<AudioPlayerLayout /> renders correctly 1`] = `
12
12
  >
13
13
  <ForwardRef(AnimatedComponentWrapper)
14
14
  style={
15
- Array [
16
- Object {
15
+ [
16
+ {
17
17
  "backgroundColor": "transparent",
18
18
  "overflow": "hidden",
19
19
  },
20
- Object {
20
+ {
21
21
  "opacity": 0,
22
22
  },
23
23
  ]
@@ -26,19 +26,19 @@ exports[`<AudioPlayerLayout /> renders correctly 1`] = `
26
26
  <ImageBackground
27
27
  resizeMode="cover"
28
28
  source={
29
- Object {
29
+ {
30
30
  "uri": "https://example.com",
31
31
  }
32
32
  }
33
33
  style={
34
- Object {
34
+ {
35
35
  "flex": 1,
36
36
  }
37
37
  }
38
38
  >
39
39
  <View
40
40
  style={
41
- Object {
41
+ {
42
42
  "backgroundColor": "transparent",
43
43
  "overflow": "hidden",
44
44
  }
@@ -3,7 +3,7 @@
3
3
  exports[`<Channel /> renders correctly 1`] = `
4
4
  <View
5
5
  style={
6
- Object {
6
+ {
7
7
  "height": 72,
8
8
  "marginBottom": 30,
9
9
  "width": 128,
@@ -13,12 +13,12 @@ exports[`<Channel /> renders correctly 1`] = `
13
13
  <Image
14
14
  fadeDuration={0}
15
15
  source={
16
- Object {
16
+ {
17
17
  "uri": "https://example.com",
18
18
  }
19
19
  }
20
20
  style={
21
- Object {
21
+ {
22
22
  "height": 72,
23
23
  "width": 128,
24
24
  }
@@ -3,7 +3,7 @@
3
3
  exports[`<Summary /> renders correctly 1`] = `
4
4
  <View
5
5
  style={
6
- Object {
6
+ {
7
7
  "height": 80,
8
8
  "marginBottom": 30,
9
9
  "width": 600,
@@ -13,7 +13,7 @@ exports[`<Summary /> renders correctly 1`] = `
13
13
  <Text
14
14
  numberOfLines={2}
15
15
  style={
16
- Object {
16
+ {
17
17
  "color": "white",
18
18
  "fontFamily": null,
19
19
  "fontSize": 20,
@@ -3,7 +3,7 @@
3
3
  exports[`<Title /> renders correctly 1`] = `
4
4
  <View
5
5
  style={
6
- Object {
6
+ {
7
7
  "height": 100,
8
8
  "marginBottom": 12,
9
9
  "width": 600,
@@ -13,7 +13,7 @@ exports[`<Title /> renders correctly 1`] = `
13
13
  <Text
14
14
  numberOfLines={2}
15
15
  style={
16
- Object {
16
+ {
17
17
  "color": "white",
18
18
  "fontFamily": null,
19
19
  "fontSize": 38,
@@ -25,7 +25,7 @@ type Props = {
25
25
  };
26
26
 
27
27
  export class BaseFocusable<
28
- T extends Props = Props
28
+ T extends Props = Props,
29
29
  > extends BaseFocusableInterface<T> {
30
30
  constructor(props) {
31
31
  super(props);
@@ -35,7 +35,7 @@ type Props = {
35
35
  };
36
36
 
37
37
  export class BaseFocusable<
38
- T extends Props = Props
38
+ T extends Props = Props,
39
39
  > extends BaseFocusableInterface<T> {
40
40
  constructor(props) {
41
41
  super(props);
@@ -273,10 +273,14 @@ export class CellComponent extends React.Component<Props, State> {
273
273
  if (isFocused) {
274
274
  const accessibilityManager = AccessibilityManager.getInstance();
275
275
 
276
+ const accessibilityTitle =
277
+ item?.extensions?.accessibility?.label || item?.title || "";
278
+
279
+ const accessibilityHint =
280
+ item?.extensions?.accessibility?.hint || "";
281
+
276
282
  accessibilityManager.readText({
277
- text: String(
278
- item.extensions?.accessibility?.label || item.title
279
- ),
283
+ text: `${accessibilityTitle} ${accessibilityHint}`,
280
284
  });
281
285
  }
282
286
 
@@ -0,0 +1,126 @@
1
+ /** TODO: Remove this file when tvos FocusableGroup
2
+ * behaviour is aligned to the web one
3
+ * FocusableGroup should only send onFocus and onBlur events when
4
+ * Focus enters and leaves the Focusables inside the branch
5
+ */
6
+ import * as React from "react";
7
+
8
+ import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils/focusManager";
9
+ import * as FOCUS_EVENTS from "@applicaster/zapp-react-native-utils/appUtils/focusManager/events";
10
+ import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
11
+ import { toBooleanWithDefaultFalse } from "@applicaster/zapp-react-native-utils/booleanUtils";
12
+
13
+ import { isAppleTV } from "../../Helpers/Platform";
14
+ import { useCellState } from "../MasterCell/utils";
15
+
16
+ const useCellFocusedState = (
17
+ skipFocusManagerRegistration: boolean,
18
+ groupId: string,
19
+ id: string
20
+ ) => {
21
+ const [currentCellFocused, setCurrentCellFocused] = React.useState(false);
22
+
23
+ React.useEffect(() => {
24
+ const isGroupItemFocused = () => {
25
+ if (!skipFocusManagerRegistration) {
26
+ const isFocused = focusManager.isGroupItemFocused(groupId, id);
27
+ setCurrentCellFocused(isFocused);
28
+ }
29
+ };
30
+
31
+ const handler = () => {
32
+ // tvOS hack for properly checking focus
33
+ if (isAppleTV()) {
34
+ setTimeout(() => {
35
+ isGroupItemFocused();
36
+ }, 0);
37
+ } else {
38
+ isGroupItemFocused();
39
+ }
40
+ };
41
+
42
+ focusManager.on(FOCUS_EVENTS.FOCUS, handler);
43
+
44
+ return () => {
45
+ focusManager.removeHandler(FOCUS_EVENTS.FOCUS, handler);
46
+ };
47
+ }, [groupId, skipFocusManagerRegistration]);
48
+
49
+ return currentCellFocused;
50
+ };
51
+
52
+ type Props = {
53
+ item: ZappEntry;
54
+ CellRenderer: React.FunctionComponent<any>;
55
+ id: string;
56
+ groupId: string;
57
+ onFocus: Function;
58
+ index: number;
59
+ scrollTo: Function;
60
+ preferredFocus?: boolean;
61
+ skipFocusManagerRegistration?: boolean;
62
+ isFocusable?: boolean;
63
+ behavior: Behavior;
64
+ focused?: boolean;
65
+ };
66
+
67
+ export function CellWithFocusable(props: Props) {
68
+ const {
69
+ index,
70
+ item,
71
+ CellRenderer,
72
+ id,
73
+ groupId,
74
+ onFocus,
75
+ scrollTo = noop,
76
+ preferredFocus,
77
+ skipFocusManagerRegistration,
78
+ isFocusable,
79
+ behavior,
80
+ focused,
81
+ } = props;
82
+
83
+ const isFocused = useCellFocusedState(
84
+ skipFocusManagerRegistration,
85
+ groupId,
86
+ id
87
+ );
88
+
89
+ const state = useCellState({
90
+ id: item.id,
91
+ behavior,
92
+ focused: isFocused || toBooleanWithDefaultFalse(focused),
93
+ });
94
+
95
+ const [focusedButtonId, setFocusedButtonId] = React.useState(undefined);
96
+
97
+ // for horizontal scrolling
98
+ React.useEffect(() => {
99
+ if (focusedButtonId) {
100
+ scrollTo(index);
101
+ }
102
+ }, [focusedButtonId]);
103
+
104
+ const handleToggleFocus = (value) => {
105
+ setFocusedButtonId(value.focusedButtonId);
106
+
107
+ if (value.focusable) {
108
+ onFocus(value.focusable, value.mouse);
109
+ }
110
+ };
111
+
112
+ return (
113
+ <CellRenderer
114
+ item={item}
115
+ groupId={groupId}
116
+ onToggleFocus={handleToggleFocus}
117
+ state={state}
118
+ prefixId={id}
119
+ focusedButtonId={focusedButtonId}
120
+ preferredFocus={preferredFocus}
121
+ skipFocusManagerRegistration={skipFocusManagerRegistration}
122
+ isFocusable={isFocusable}
123
+ focused={focused}
124
+ />
125
+ );
126
+ }
@@ -1,48 +1,10 @@
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
- const useCellFocusedState = (
12
- skipFocusManagerRegistration: boolean,
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";
46
8
 
47
9
  type Props = {
48
10
  item: ZappEntry;
@@ -75,11 +37,7 @@ export function CellWithFocusable(props: Props) {
75
37
  focused,
76
38
  } = props;
77
39
 
78
- const isFocused = useCellFocusedState(
79
- skipFocusManagerRegistration,
80
- groupId,
81
- id
82
- );
40
+ const [isFocused, setIsFocused] = React.useState(false);
83
41
 
84
42
  const state = useCellState({
85
43
  id: item.id,
@@ -96,26 +54,52 @@ export function CellWithFocusable(props: Props) {
96
54
  }
97
55
  }, [focusedButtonId]);
98
56
 
99
- const handleToggleFocus = (value) => {
100
- setFocusedButtonId(value.focusedButtonId);
57
+ const handleToggleFocus = React.useCallback(
58
+ (value) => {
59
+ setFocusedButtonId(value.focusedButtonId);
60
+
61
+ if (value.focusable) {
62
+ onFocus(value.focusable, value.mouse);
63
+ }
64
+ },
65
+ [onFocus]
66
+ );
67
+
68
+ const onGroupFocus = React.useCallback(() => {
69
+ if (!skipFocusManagerRegistration) {
70
+ setIsFocused(true);
71
+ }
72
+ }, [skipFocusManagerRegistration]);
101
73
 
102
- if (value.focusable) {
103
- onFocus(value.focusable, value.mouse);
74
+ const onGroupBlur = React.useCallback(() => {
75
+ if (!skipFocusManagerRegistration) {
76
+ setIsFocused(false);
104
77
  }
105
- };
78
+ }, [skipFocusManagerRegistration]);
106
79
 
107
80
  return (
108
- <CellRenderer
109
- item={item}
81
+ <FocusableGroup
82
+ id={`focusable-cell-wrapper-${id}`}
83
+ testID={"cell-with-focusable-cell-renderer-focusable-group"}
110
84
  groupId={groupId}
111
- onToggleFocus={handleToggleFocus}
112
- state={state}
113
- prefixId={id}
114
- focusedButtonId={focusedButtonId}
115
85
  preferredFocus={preferredFocus}
116
- skipFocusManagerRegistration={skipFocusManagerRegistration}
117
- isFocusable={isFocusable}
118
- focused={focused}
119
- />
86
+ shouldUsePreferredFocus
87
+ onFocus={onGroupFocus}
88
+ onBlur={onGroupBlur}
89
+ >
90
+ <CellRenderer
91
+ testID={"cell-with-focusable-cell-renderer"}
92
+ item={item}
93
+ groupId={`focusable-cell-wrapper-${id}`}
94
+ onToggleFocus={handleToggleFocus}
95
+ state={state}
96
+ prefixId={id}
97
+ focusedButtonId={focusedButtonId}
98
+ preferredFocus={true}
99
+ skipFocusManagerRegistration={skipFocusManagerRegistration}
100
+ isFocusable={isFocusable}
101
+ focused={focused}
102
+ />
103
+ </FocusableGroup>
120
104
  );
121
105
  }
@@ -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;
@@ -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
- expect(wrapper.UNSAFE_getByType("View").props.state).toBe("default");
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(wrapper.UNSAFE_getByType("View").props.state).toBe("default");
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
- focusManager.on.mock.calls[focusManager.on.mock.calls.length - 1][1]();
68
+ focusableGroupComponent.props.onFocus();
63
69
  });
64
70
 
65
- expect(wrapper.UNSAFE_getByType("View").props.state).toBe("focused");
71
+ const element = wrapper.getByTestId("cell-with-focusable-cell-renderer");
72
+ expect(element.props.state).toBe("focused");
66
73
  });
67
74
  });
@@ -3,24 +3,24 @@
3
3
  exports[`CellRendererResolver renders correctly 1`] = `
4
4
  <View
5
5
  someProp={
6
- Object {
7
- "cellOptions": Object {},
8
- "cellStyles": Object {
9
- "ABCDE-123456": Object {
10
- "configuration": Object {},
6
+ {
7
+ "cellOptions": {},
8
+ "cellStyles": {
9
+ "ABCDE-123456": {
10
+ "configuration": {},
11
11
  "plugin_identifier": "custom_renderer_plugin",
12
12
  },
13
- "FGHIJ-123456": Object {
14
- "configuration": Object {},
13
+ "FGHIJ-123456": {
14
+ "configuration": {},
15
15
  "plugin_identifier": "unknown_plugin",
16
16
  },
17
17
  },
18
- "component": Object {
19
- "styles": Object {
18
+ "component": {
19
+ "styles": {
20
20
  "cell_plugin_configuration_id": "ABCDE-123456",
21
21
  },
22
22
  },
23
- "styles": Object {},
23
+ "styles": {},
24
24
  }
25
25
  }
26
26
  />
@@ -29,24 +29,24 @@ exports[`CellRendererResolver renders correctly 1`] = `
29
29
  exports[`CellRendererResolver with a default renderer plugin renders correctly 1`] = `
30
30
  <View
31
31
  someProp={
32
- Object {
33
- "cellOptions": Object {},
34
- "cellStyles": Object {
35
- "ABCDE-123456": Object {
36
- "configuration": Object {},
32
+ {
33
+ "cellOptions": {},
34
+ "cellStyles": {
35
+ "ABCDE-123456": {
36
+ "configuration": {},
37
37
  "plugin_identifier": "custom_renderer_plugin",
38
38
  },
39
- "FGHIJ-123456": Object {
40
- "configuration": Object {},
39
+ "FGHIJ-123456": {
40
+ "configuration": {},
41
41
  "plugin_identifier": "unknown_plugin",
42
42
  },
43
43
  },
44
- "component": Object {
45
- "styles": Object {
44
+ "component": {
45
+ "styles": {
46
46
  "cell_plugin_configuration_id": "ABCDE-123456",
47
47
  },
48
48
  },
49
- "styles": Object {},
49
+ "styles": {},
50
50
  }
51
51
  }
52
52
  />
@@ -2,9 +2,11 @@ import * as React from "react";
2
2
  import { View } from "react-native";
3
3
  import { shallow } from "enzyme";
4
4
 
5
- jest.mock("../../default-cell-renderer", () =>
6
- jest.fn((prop) => <View whoAmI="default renderer" someProp={prop} />)
7
- );
5
+ jest.mock("../../default-cell-renderer", () => {
6
+ const View = jest.requireActual("react-native").View;
7
+
8
+ return jest.fn((prop) => <View whoAmI="default renderer" someProp={prop} />);
9
+ });
8
10
 
9
11
  const { CellRendererResolver } = require("../index");
10
12