@applicaster/zapp-react-native-ui-components 12.0.0-alpha.4400210593 → 12.0.0-alpha.4408649484

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 (95) hide show
  1. package/Components/BaseFocusable/index.tsx +3 -3
  2. package/Components/Cell/Cell.tsx +10 -5
  3. package/Components/Cell/CellWithFocusable.tsx +23 -9
  4. package/Components/Cell/TvOSCellComponent.tsx +3 -7
  5. package/Components/Focusable/Focusable.tsx +6 -1
  6. package/Components/FocusableGroup/index.tsx +11 -2
  7. package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +13 -6
  8. package/Components/GeneralContentScreen/utils/useCurationAPI.ts +1 -1
  9. package/Components/HandlePlayable/HandlePlayable.tsx +3 -0
  10. package/Components/Layout/TV/ScreenContainer.tsx +84 -5
  11. package/Components/Layout/TV/ScreenLayoutContextProvider.tsx +2 -2
  12. package/Components/Layout/TV/__tests__/ScreenContainer.test.tsx +38 -28
  13. package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +25 -13
  14. package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +10 -50
  15. package/Components/Layout/TV/__tests__/index.test.tsx +20 -75
  16. package/Components/Layout/TV/index.tsx +14 -67
  17. package/Components/Layout/TV/index.web.tsx +33 -0
  18. package/Components/Layout/index.tsx +15 -11
  19. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +2 -0
  20. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +88 -112
  21. package/Components/MasterCell/DefaultComponents/DynamicBadge.tsx +4 -2
  22. package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +4 -1
  23. package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +5 -3
  24. package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +5 -1
  25. package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +14 -1
  26. package/Components/MasterCell/DefaultComponents/Text/index.tsx +14 -2
  27. package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
  28. package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +24 -9
  29. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.android.tsx +4 -1
  30. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.tsx +10 -2
  31. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/index.ts +1 -3
  32. package/Components/MasterCell/hooks/useAsyncRendering/index.ts +1 -1
  33. package/Components/MasterCell/utils/__tests__/insertBetween.test.js +9 -0
  34. package/Components/MasterCell/utils/index.ts +33 -35
  35. package/Components/MeasurmentsPortal/BasicMeasurementsPortal.tsx +11 -7
  36. package/Components/MeasurmentsPortal/MeasurementsPortal.tsx +10 -1
  37. package/Components/Navigator/StackNavigator.tsx +57 -0
  38. package/Components/Navigator/index.ts +1 -0
  39. package/Components/PlayerContainer/PlayerContainer.tsx +23 -3
  40. package/Components/PlayerImageBackground/index.tsx +34 -8
  41. package/Components/River/ComponentsMap/ComponentsMap.tsx +92 -22
  42. package/Components/River/RefreshControl.tsx +55 -1
  43. package/Components/River/TV/River.tsx +0 -23
  44. package/Components/River/__tests__/componentsMap.test.js +6 -0
  45. package/Components/RouteManager/index.tsx +2 -2
  46. package/Components/Screen/TV/hooks/index.ts +3 -0
  47. package/Components/Screen/TV/hooks/useInitialFocus.ts +70 -0
  48. package/Components/Screen/TV/hooks/useRestoreFocus.ts +22 -0
  49. package/Components/Screen/TV/index.web.tsx +169 -0
  50. package/Components/Screen/__tests__/Screen.test.tsx +3 -0
  51. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +4 -0
  52. package/Components/Screen/index.tsx +64 -25
  53. package/Components/ScreenResolver/index.tsx +3 -1
  54. package/Components/Transitioner/Scene.tsx +24 -19
  55. package/Components/Transitioner/Transitioner.tsx +21 -28
  56. package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +6 -2
  57. package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +1 -0
  58. package/Components/VideoLive/LiveImageManager.ts +28 -1
  59. package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +20 -5
  60. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +0 -5
  61. package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +78 -0
  62. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +352 -0
  63. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +158 -0
  64. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +455 -0
  65. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +162 -0
  66. package/Components/VideoModal/ModalAnimation/index.ts +15 -0
  67. package/Components/VideoModal/ModalAnimation/utils.ts +301 -0
  68. package/Components/VideoModal/PlayerDetails.tsx +3 -3
  69. package/Components/VideoModal/PlayerWrapper.tsx +77 -47
  70. package/Components/VideoModal/VideoModal.tsx +23 -40
  71. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +13 -1
  72. package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +157 -105
  73. package/Components/VideoModal/utils.ts +8 -5
  74. package/Components/Viewport/ViewportTracker/ViewportTracker.tsx +31 -40
  75. package/Components/Viewport/ViewportTracker/index.tsx +1 -0
  76. package/Components/Viewport/utils.js +1 -1
  77. package/Contexts/FocusableGroupContext/FocusableGroupContext.ts +3 -0
  78. package/Contexts/FocusableGroupContext/FocusableGroupContextProvider.tsx +16 -0
  79. package/Contexts/FocusableGroupContext/__tests__/FocusableGroupContextProvider.test.tsx +22 -0
  80. package/Contexts/FocusableGroupContext/__tests__/withFocusableContext.test.tsx +26 -0
  81. package/Contexts/FocusableGroupContext/index.ts +7 -0
  82. package/Contexts/FocusableGroupContext/withFocusableContext.tsx +17 -0
  83. package/Contexts/MenuToggleContext/{index.js → index.ts} +16 -0
  84. package/Contexts/ScreenContext/__tests__/__snapshots__/index.test.tsx.snap +3 -0
  85. package/Contexts/ScreenContext/__tests__/index.test.tsx +27 -0
  86. package/Contexts/ScreenContext/index.tsx +94 -25
  87. package/Contexts/ScreenDataContext/index.tsx +20 -0
  88. package/Contexts/ZappPipesContext/ZappPipesEntryContext.ts +1 -1
  89. package/events/index.ts +1 -0
  90. package/package.json +5 -5
  91. package/Components/Layout/TV/TransitionOverlay.tsx +0 -64
  92. package/Components/VideoModal/hooks/usePosition.ts +0 -50
  93. /package/Components/FocusableGroup/{index.android.js → index.android.ts} +0 -0
  94. /package/Components/FocusableGroup/{index.ios.js → index.ios.ts} +0 -0
  95. /package/Contexts/{index.js → index.ts} +0 -0
@@ -23,9 +23,6 @@ exports[`PlayerWrapper renders inline 1`] = `
23
23
  }
24
24
  style={
25
25
  Array [
26
- Object {
27
- "flexDirection": "column",
28
- },
29
26
  Object {
30
27
  "backgroundColor": "transparent",
31
28
  },
@@ -38,44 +35,50 @@ exports[`PlayerWrapper renders inline 1`] = `
38
35
  }
39
36
  >
40
37
  <View
38
+ additionalData={
39
+ Object {
40
+ "saveArea": true,
41
+ }
42
+ }
43
+ animationType="moveUpComponent"
41
44
  style={
42
45
  Array [
43
46
  Object {
44
- "alignSelf": "center",
45
- "position": "relative",
46
- "zIndex": 200,
47
+ "flexDirection": "column",
47
48
  },
48
49
  Object {
49
- "aspectRatio": 1.7777777777777777,
50
- "height": undefined,
51
- "width": "100%",
50
+ "flex": 1,
52
51
  },
53
- Object {},
54
- Object {},
55
52
  ]
56
53
  }
57
- testID="test-player-container"
58
- />
59
- <View
60
- configuration={
61
- Object {
62
- "tablet_landscape_player_container_background_color": "red",
63
- "tablet_landscape_sidebar_width": "35%",
64
- }
65
- }
66
- entry={
67
- Object {
68
- "id": "test",
54
+ >
55
+ <View
56
+ style={
57
+ Array [
58
+ Object {
59
+ "alignSelf": "center",
60
+ "position": "relative",
61
+ "zIndex": 200,
62
+ },
63
+ Object {
64
+ "aspectRatio": 1.7777777777777777,
65
+ "height": undefined,
66
+ "width": "100%",
67
+ },
68
+ Object {},
69
+ Object {},
70
+ ]
69
71
  }
70
- }
71
- isTabletLandscape={false}
72
- style={
73
- Object {
74
- "flex": 1,
75
- "paddingTop": 20,
72
+ testID="test-player-container"
73
+ />
74
+ <View
75
+ style={
76
+ Object {
77
+ "flex": 1,
78
+ }
76
79
  }
77
- }
78
- />
80
+ />
81
+ </View>
79
82
  </RNCSafeAreaView>
80
83
  </RNCSafeAreaProvider>
81
84
  `;
@@ -95,22 +98,19 @@ exports[`PlayerWrapper renders inline and docked 1`] = `
95
98
  <RNCSafeAreaView
96
99
  edges={
97
100
  Object {
98
- "bottom": "additive",
101
+ "bottom": "off",
99
102
  "left": "off",
100
103
  "right": "off",
101
- "top": "off",
104
+ "top": "additive",
102
105
  }
103
106
  }
104
107
  style={
105
108
  Array [
106
- Object {
107
- "flexDirection": "column",
108
- },
109
109
  Object {
110
110
  "backgroundColor": "transparent",
111
111
  },
112
112
  Object {
113
- "height": 50,
113
+ "height": undefined,
114
114
  "width": 300,
115
115
  },
116
116
  Object {},
@@ -118,32 +118,50 @@ exports[`PlayerWrapper renders inline and docked 1`] = `
118
118
  }
119
119
  >
120
120
  <View
121
+ additionalData={
122
+ Object {
123
+ "saveArea": true,
124
+ }
125
+ }
126
+ animationType="moveUpComponent"
121
127
  style={
122
128
  Array [
123
129
  Object {
124
- "alignSelf": "center",
125
- "position": "relative",
126
- "zIndex": 200,
130
+ "flexDirection": "column",
127
131
  },
128
132
  Object {
129
- "aspectRatio": undefined,
130
- "height": 50,
131
- "width": "100%",
133
+ "flex": 1,
132
134
  },
133
- Object {},
134
- Object {},
135
135
  ]
136
136
  }
137
- testID="test-player-container"
138
- />
139
- <View
140
- style={
141
- Object {
142
- "flex": 1,
143
- "paddingTop": 20,
137
+ >
138
+ <View
139
+ style={
140
+ Array [
141
+ Object {
142
+ "alignSelf": "center",
143
+ "position": "relative",
144
+ "zIndex": 200,
145
+ },
146
+ Object {
147
+ "aspectRatio": undefined,
148
+ "height": undefined,
149
+ "width": "100%",
150
+ },
151
+ Object {},
152
+ Object {},
153
+ ]
144
154
  }
145
- }
146
- />
155
+ testID="test-player-container"
156
+ />
157
+ <View
158
+ style={
159
+ Object {
160
+ "flex": 1,
161
+ }
162
+ }
163
+ />
164
+ </View>
147
165
  </RNCSafeAreaView>
148
166
  </RNCSafeAreaProvider>
149
167
  `;
@@ -171,9 +189,6 @@ exports[`PlayerWrapper renders inline on tablet in landscape orientation 1`] = `
171
189
  }
172
190
  style={
173
191
  Array [
174
- Object {
175
- "flexDirection": "row",
176
- },
177
192
  Object {
178
193
  "backgroundColor": "red",
179
194
  },
@@ -186,44 +201,66 @@ exports[`PlayerWrapper renders inline on tablet in landscape orientation 1`] = `
186
201
  }
187
202
  >
188
203
  <View
204
+ additionalData={
205
+ Object {
206
+ "saveArea": true,
207
+ }
208
+ }
209
+ animationType="moveUpComponent"
189
210
  style={
190
211
  Array [
191
212
  Object {
192
- "alignSelf": "center",
193
- "position": "relative",
194
- "zIndex": 200,
213
+ "flexDirection": "row",
195
214
  },
196
215
  Object {
197
- "aspectRatio": 1.7777777777777777,
198
- "height": undefined,
199
- "width": 195,
216
+ "flex": 1,
200
217
  },
201
- Object {},
202
- Object {},
203
218
  ]
204
219
  }
205
- testID="test-player-container"
206
- />
207
- <View
208
- configuration={
209
- Object {
210
- "tablet_landscape_player_container_background_color": "red",
211
- "tablet_landscape_sidebar_width": "35%",
212
- }
213
- }
214
- entry={
215
- Object {
216
- "id": "test",
220
+ >
221
+ <View
222
+ style={
223
+ Array [
224
+ Object {
225
+ "alignSelf": "center",
226
+ "position": "relative",
227
+ "zIndex": 200,
228
+ },
229
+ Object {
230
+ "aspectRatio": 1.7777777777777777,
231
+ "height": undefined,
232
+ "width": 195,
233
+ },
234
+ Object {},
235
+ Object {},
236
+ ]
217
237
  }
218
- }
219
- isTabletLandscape={true}
220
- style={
221
- Object {
222
- "flex": 1,
223
- "paddingTop": 20,
238
+ testID="test-player-container"
239
+ >
240
+ <View
241
+ additionalData={
242
+ Object {
243
+ "disableAnimatedComponent": false,
244
+ "resetAnimationValue": undefined,
245
+ "useLayoutMeasure": true,
246
+ }
247
+ }
248
+ animationType="moveUpComponent"
249
+ style={
250
+ Object {
251
+ "flex": 1,
252
+ }
253
+ }
254
+ />
255
+ </View>
256
+ <View
257
+ style={
258
+ Object {
259
+ "flex": 1,
260
+ }
224
261
  }
225
- }
226
- />
262
+ />
263
+ </View>
227
264
  </RNCSafeAreaView>
228
265
  </RNCSafeAreaProvider>
229
266
  `;
@@ -251,9 +288,6 @@ exports[`PlayerWrapper renders properly 1`] = `
251
288
  }
252
289
  style={
253
290
  Array [
254
- Object {
255
- "flexDirection": "column",
256
- },
257
291
  Object {
258
292
  "backgroundColor": "transparent",
259
293
  },
@@ -266,32 +300,50 @@ exports[`PlayerWrapper renders properly 1`] = `
266
300
  }
267
301
  >
268
302
  <View
303
+ additionalData={
304
+ Object {
305
+ "saveArea": true,
306
+ }
307
+ }
308
+ animationType="moveUpComponent"
269
309
  style={
270
310
  Array [
271
311
  Object {
272
- "alignSelf": "center",
273
- "position": "relative",
274
- "zIndex": 200,
312
+ "flexDirection": "column",
275
313
  },
276
314
  Object {
277
- "aspectRatio": 1.7786666666666666,
278
- "height": undefined,
279
- "width": "100%",
315
+ "flex": 1,
280
316
  },
281
- Object {},
282
- Object {},
283
317
  ]
284
318
  }
285
- testID="test-player-container"
286
- />
287
- <View
288
- style={
289
- Object {
290
- "flex": 1,
291
- "paddingTop": 20,
319
+ >
320
+ <View
321
+ style={
322
+ Array [
323
+ Object {
324
+ "alignSelf": "center",
325
+ "position": "relative",
326
+ "zIndex": 200,
327
+ },
328
+ Object {
329
+ "aspectRatio": 1.7786666666666666,
330
+ "height": undefined,
331
+ "width": "100%",
332
+ },
333
+ Object {},
334
+ Object {},
335
+ ]
292
336
  }
293
- }
294
- />
337
+ testID="test-player-container"
338
+ />
339
+ <View
340
+ style={
341
+ Object {
342
+ "flex": 1,
343
+ }
344
+ }
345
+ />
346
+ </View>
295
347
  </RNCSafeAreaView>
296
348
  </RNCSafeAreaProvider>
297
349
  `;
@@ -23,18 +23,21 @@ export const useConfiguration = () => {
23
23
  const targetScreenConfiguration = rivers?.[targetScreenId];
24
24
 
25
25
  const pluginConfiguration =
26
- pluginConfigurations[targetScreenConfiguration.type].configuration_json;
26
+ pluginConfigurations[targetScreenConfiguration?.type]?.configuration_json;
27
27
 
28
28
  const playerPluginConfig = playerManager.getPluginConfiguration();
29
29
 
30
30
  const config = R.mergeRight(playerPluginConfig, {
31
- ...targetScreenConfiguration.general,
32
- ...targetScreenConfiguration.styles,
31
+ ...targetScreenConfiguration?.general,
32
+ ...targetScreenConfiguration?.styles,
33
33
  ...pluginConfiguration,
34
34
  });
35
35
 
36
- const { minimised_height, minimised_height_tablet, modal_background_color } =
37
- config;
36
+ const {
37
+ minimised_height = 0,
38
+ minimised_height_tablet = 0,
39
+ modal_background_color,
40
+ } = config;
38
41
 
39
42
  const minimisedHeight = useIsTablet()
40
43
  ? minimised_height_tablet
@@ -6,23 +6,23 @@ import { callOnChildren } from "../utils";
6
6
 
7
7
  export function ViewportTracker(props) {
8
8
  const viewportEvents = useViewportEventsContext();
9
- const { children } = props;
10
- const [width, setWidth] = React.useState(0);
11
- const [height, setHeight] = React.useState(0);
12
- const [offsetX, setOffsetX] = React.useState(0);
13
- const [offsetY, setOffsetY] = React.useState(0);
14
9
  const [nodeHandle, setNodeHandle] = React.useState(null);
15
10
 
16
- const assignRef = React.useCallback(
17
- (ref) => {
18
- callOnChildren(children, "ref", ref);
19
- setNodeHandle(findNodeHandle(ref));
20
- },
21
- [children]
22
- );
11
+ const childrenRef = React.useRef(props.children);
12
+
13
+ const dimensionsRef = React.useRef({ width: 0, height: 0 });
14
+ const offsetRef = React.useRef({ offsetX: 0, offsetY: 0 });
15
+
16
+ const assignRef = React.useCallback((ref) => {
17
+ childrenRef.current?.ref?.(ref);
18
+ setNodeHandle(findNodeHandle(ref));
19
+ }, []);
23
20
 
24
21
  const onViewportChange = React.useCallback(
25
- (event, shouldMeasureLayout = true) => {
22
+ ({
23
+ event = { ...dimensionsRef.current, ...offsetRef.current },
24
+ shouldMeasureLayout = true,
25
+ } = {}) => {
26
26
  if (nodeHandle && event?.width > 0 && event?.height > 0) {
27
27
  viewportEvents?.notify?.({
28
28
  parentHandle: nodeHandle,
@@ -36,54 +36,45 @@ export function ViewportTracker(props) {
36
36
 
37
37
  const onLayout = React.useCallback(
38
38
  (event) => {
39
- callOnChildren(children, "onLayout", event);
40
- setWidth(event?.nativeEvent?.layout?.width);
41
- setHeight(event?.nativeEvent?.layout?.height);
39
+ callOnChildren(childrenRef.current, "onLayout", event);
40
+ dimensionsRef.current = event?.nativeEvent?.layout;
42
41
 
43
- onViewportChange({
44
- width: event?.nativeEvent?.layout?.width,
45
- height: event?.nativeEvent?.layout?.height,
46
- offsetX,
47
- offsetY,
48
- });
42
+ onViewportChange();
49
43
  },
50
- [offsetX, offsetY, children, onViewportChange]
44
+ [onViewportChange]
51
45
  );
52
46
 
53
47
  const onContentSizeChange = React.useCallback(
54
48
  (contentWidth, contentHeight) => {
55
49
  callOnChildren(
56
- children,
50
+ childrenRef.current,
57
51
  "onContentSizeChange",
58
52
  contentWidth,
59
53
  contentHeight
60
54
  );
61
55
 
62
- onViewportChange({ width, height, offsetX, offsetY });
56
+ onViewportChange();
63
57
  },
64
- [onViewportChange, children, width, height, offsetX, offsetY]
58
+ [onViewportChange]
65
59
  );
66
60
 
67
61
  const onScroll = React.useCallback(
68
62
  (event) => {
69
- callOnChildren(children, "onScroll", event);
70
- setOffsetX(event?.nativeEvent?.contentOffset?.x);
71
- setOffsetY(event?.nativeEvent?.contentOffset?.y);
63
+ callOnChildren(childrenRef.current, "onScroll", event);
64
+ offsetRef.current = event?.nativeEvent?.contentOffset;
72
65
 
73
- onViewportChange(
74
- {
75
- width,
76
- height,
77
- offsetX: event?.nativeEvent?.contentOffset?.x,
78
- offsetY: event?.nativeEvent?.contentOffset?.y,
79
- },
80
- false
81
- );
66
+ onViewportChange({
67
+ shouldMeasureLayout: false,
68
+ });
82
69
  },
83
- [onViewportChange, width, height, children]
70
+ [onViewportChange]
84
71
  );
85
72
 
86
- return React.cloneElement(React.Children.only(children), {
73
+ React.useEffect(() => {
74
+ childrenRef.current = props.children;
75
+ }, [props.children]);
76
+
77
+ return React.cloneElement(React.Children.only(props.children), {
87
78
  ref: assignRef,
88
79
  onLayout,
89
80
  onContentSizeChange,
@@ -6,6 +6,7 @@ import { ViewportEventContext, ViewportEvents } from "../ViewportEvents";
6
6
  type Props = {
7
7
  viewportEventsManager?: any;
8
8
  children: React.ReactNode;
9
+ flatListRef?: any; // this ref is used to bind to children component
9
10
  };
10
11
 
11
12
  export function ViewportTracker(props: Props) {
@@ -2,7 +2,7 @@ import * as React from "react";
2
2
 
3
3
  export function callOnChildren(children, method, ...args) {
4
4
  const childMethod = React.Children.only(children).props[method];
5
- childMethod && childMethod(...args);
5
+ typeof childMethod === "function" && childMethod?.(...args);
6
6
  }
7
7
 
8
8
  export function isInViewport(
@@ -0,0 +1,3 @@
1
+ import * as React from "react";
2
+
3
+ export const FocusableGroupContext = React.createContext<string | null>(null);
@@ -0,0 +1,16 @@
1
+ import * as React from "react";
2
+ import { FocusableGroupContext } from "./FocusableGroupContext";
3
+
4
+ type ProviderArgs = {
5
+ id: string;
6
+ children: React.ReactNode;
7
+ };
8
+
9
+ export const FocusableGroupContextProvider = ({
10
+ id,
11
+ children,
12
+ }: ProviderArgs) => (
13
+ <FocusableGroupContext.Provider value={id}>
14
+ {children}
15
+ </FocusableGroupContext.Provider>
16
+ );
@@ -0,0 +1,22 @@
1
+ import React, { useContext } from "react";
2
+ import { Text } from "react-native";
3
+ import { render } from "@testing-library/react-native";
4
+ import { FocusableGroupContextProvider, FocusableGroupContext } from "../";
5
+
6
+ const MockComponent = () => {
7
+ const focusableContext = useContext(FocusableGroupContext) || "default";
8
+
9
+ return <Text testID={focusableContext} />;
10
+ };
11
+
12
+ describe("FocusableGroupContextProvider", () => {
13
+ it("should provide focusable context to the wrapped component", () => {
14
+ const { getByTestId } = render(
15
+ <FocusableGroupContextProvider id="testId">
16
+ <MockComponent />
17
+ </FocusableGroupContextProvider>
18
+ );
19
+
20
+ expect(getByTestId("testId")).toBeTruthy();
21
+ });
22
+ });
@@ -0,0 +1,26 @@
1
+ import React from "react";
2
+ import { Text } from "react-native";
3
+ import { render } from "@testing-library/react-native";
4
+ import { withFocusableContext } from "../withFocusableContext";
5
+ import { FocusableGroupContext } from "../FocusableGroupContext";
6
+
7
+ const MockComponent = ({ groupId }: { groupId: string }) => (
8
+ <Text testID={groupId} />
9
+ );
10
+
11
+ const WrappedComponent = withFocusableContext(MockComponent);
12
+
13
+ describe("withFocusableContext HOC", () => {
14
+ it("should provide focusable context to the wrapped component", () => {
15
+ const { getByTestId } = render(<WrappedComponent />, {
16
+ // eslint-disable-next-line react/display-name
17
+ wrapper: ({ children }: { children: React.ReactElement }) => (
18
+ <FocusableGroupContext.Provider value="test">
19
+ {children}
20
+ </FocusableGroupContext.Provider>
21
+ ),
22
+ });
23
+
24
+ expect(getByTestId("test")).toBeTruthy();
25
+ });
26
+ });
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+ import { FocusableGroupContext } from "./FocusableGroupContext";
3
+ import { FocusableGroupContextProvider } from "./FocusableGroupContextProvider";
4
+
5
+ export { FocusableGroupContext, FocusableGroupContextProvider };
6
+
7
+ export const useGroupId = () => React.useContext(FocusableGroupContext);
@@ -0,0 +1,17 @@
1
+ import React from "react";
2
+ import { FocusableGroupContext } from "./FocusableGroupContext";
3
+
4
+ export const withFocusableContext = (Component) => {
5
+ // eslint-disable-next-line react/display-name
6
+ return ({ groupId, ...props }: Record<string, any>) => (
7
+ <FocusableGroupContext.Consumer>
8
+ {(groupIdContext: string) => {
9
+ // eslint-disable-next-line react/display-name
10
+ const propsGroupId = groupId || null;
11
+ const providedGroupId = propsGroupId || groupIdContext;
12
+
13
+ return <Component {...props} groupId={providedGroupId} />;
14
+ }}
15
+ </FocusableGroupContext.Consumer>
16
+ );
17
+ };
@@ -1,4 +1,5 @@
1
1
  import { createContext } from "@applicaster/zapp-react-native-utils/reactUtils/createContext";
2
+ import React from "react";
2
3
 
3
4
  const initialContext = { toggleMenu: {}, closeMenu: {}, openMenu: {} };
4
5
 
@@ -16,3 +17,18 @@ const stateValidator = ({ property }) =>
16
17
  property === "openMenu";
17
18
 
18
19
  export const MenuToggleContext = createContext(initialContext, stateValidator);
20
+
21
+ export type MenuToggleContextType = {
22
+ toggleMenu: any;
23
+ setToggleMenu: () => void;
24
+ openMenu: any;
25
+ setOpenMenu: () => void;
26
+ closeMenu: any;
27
+ setCloseMenu: () => void;
28
+ };
29
+
30
+ export const useMenuToggleContext = () => {
31
+ return React.useContext<MenuToggleContextType>(
32
+ MenuToggleContext.ReactContext
33
+ );
34
+ };
@@ -0,0 +1,3 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`ScreenContext withScreenContext should return the context 1`] = `null`;
@@ -0,0 +1,27 @@
1
+ import { render } from "@testing-library/react-native";
2
+ import { ScreenContext, ScreenContextProvider, withScreenContext } from "../";
3
+ import React from "react";
4
+
5
+ describe("ScreenContext", () => {
6
+ describe("ScreneContext context", () => {
7
+ it("should return the context", () => {
8
+ expect(ScreenContext).toBeDefined();
9
+ });
10
+ });
11
+
12
+ describe("ScreenContextProvider", () => {
13
+ it("should return the provider", () => {
14
+ expect(ScreenContextProvider).toBeDefined();
15
+ });
16
+ });
17
+
18
+ describe("withScreenContext", () => {
19
+ it("should return the context", () => {
20
+ const Component = () => null;
21
+ const WrappedComponent = withScreenContext(Component);
22
+ const { toJSON } = render(<WrappedComponent />);
23
+
24
+ expect(toJSON()).toMatchSnapshot();
25
+ });
26
+ });
27
+ });