@applicaster/zapp-react-native-ui-components 15.1.4 → 16.0.0-alpha.1042942411

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 (202) hide show
  1. package/Components/BackgroundImage/index.ts +1 -8
  2. package/Components/BaseFocusable/index.ios.ts +12 -2
  3. package/Components/Cell/FocusableWrapper.tsx +3 -0
  4. package/Components/Cell/TvOSCellComponent.tsx +6 -3
  5. package/Components/CellRendererResolver/index.ts +1 -1
  6. package/Components/Focusable/Focusable.tsx +4 -2
  7. package/Components/Focusable/FocusableTvOS.tsx +18 -1
  8. package/Components/Focusable/__tests__/__snapshots__/FocusableTvOS.test.tsx.snap +1 -0
  9. package/Components/FocusableGroup/FocusableTvOS.tsx +30 -1
  10. package/Components/GeneralContentScreen/GeneralContentScreenHookAdapter.tsx +39 -0
  11. package/Components/GeneralContentScreen/__tests__/GeneralContentScreenHookAdapter.test.tsx +64 -0
  12. package/Components/GeneralContentScreen/__tests__/HookContentFocusGroup.web.test.tsx +91 -0
  13. package/Components/GeneralContentScreen/hookAdapter/__tests__/networkService.test.ts +74 -0
  14. package/Components/GeneralContentScreen/hookAdapter/__tests__/runInBackground.test.ts +139 -0
  15. package/Components/GeneralContentScreen/hookAdapter/__tests__/validationHelper.test.ts +124 -0
  16. package/Components/GeneralContentScreen/hookAdapter/logger.ts +6 -0
  17. package/Components/GeneralContentScreen/hookAdapter/networkService.ts +53 -0
  18. package/Components/GeneralContentScreen/hookAdapter/runInBackground.ts +48 -0
  19. package/Components/GeneralContentScreen/hookAdapter/validationHelper.ts +72 -0
  20. package/Components/GeneralContentScreen/hookFocus/index.tsx +13 -0
  21. package/Components/GeneralContentScreen/hookFocus/index.web.tsx +69 -0
  22. package/Components/GeneralContentScreen/index.ts +2 -0
  23. package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +1 -1
  24. package/Components/HandlePlayable/HandlePlayable.tsx +13 -8
  25. package/Components/Layout/TV/NavBarContainer.tsx +1 -10
  26. package/Components/Layout/TV/ScreenContainer.tsx +2 -6
  27. package/Components/Layout/TV/__tests__/__snapshots__/NavBarContainer.test.tsx.snap +7 -12
  28. package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +7 -12
  29. package/Components/Layout/TV/index.tsx +3 -4
  30. package/Components/Layout/TV/index.web.tsx +3 -4
  31. package/Components/LinkHandler/LinkHandler.tsx +2 -2
  32. package/Components/MasterCell/CONFIG_BUILDER_TO_REACT_COMPONENT.md +144 -0
  33. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +27 -48
  34. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/model.test.ts +80 -0
  35. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/placement.test.ts +213 -0
  36. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/selectors.test.ts +45 -0
  37. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/style.test.ts +49 -0
  38. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/components/ActionButtonController.tsx +165 -0
  39. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/components/__tests__/ActionButtonController.test.tsx +405 -0
  40. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/components/index.ts +1 -0
  41. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/model.ts +47 -0
  42. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/placement.ts +198 -0
  43. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/selectors.ts +26 -0
  44. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/style.ts +29 -0
  45. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/types.ts +37 -0
  46. package/Components/MasterCell/DefaultComponents/BorderContainerView/__tests__/index.test.tsx +217 -46
  47. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +50 -119
  48. package/Components/MasterCell/DefaultComponents/Button.tsx +50 -58
  49. package/Components/MasterCell/DefaultComponents/ButtonContainerView/components/HorizontalSeparator.tsx +8 -0
  50. package/Components/MasterCell/DefaultComponents/ButtonContainerView/index.android.tv.tsx +58 -0
  51. package/Components/MasterCell/DefaultComponents/ButtonContainerView/index.tsx +15 -0
  52. package/Components/MasterCell/DefaultComponents/{tv/ButtonContainerView/index.tsx → ButtonContainerView/index.tv.tsx} +3 -11
  53. package/Components/MasterCell/DefaultComponents/ButtonContainerView/index.web.ts +1 -0
  54. package/Components/MasterCell/DefaultComponents/ButtonContainerView/types.ts +40 -0
  55. package/Components/MasterCell/DefaultComponents/CellBadge/__tests__/__snapshots__/index.test.tsx.snap +18 -0
  56. package/Components/MasterCell/DefaultComponents/CellBadge/__tests__/index.test.tsx +90 -0
  57. package/Components/MasterCell/DefaultComponents/CellBadge/index.tsx +13 -14
  58. package/Components/MasterCell/DefaultComponents/DataProvider/index.tsx +163 -0
  59. package/Components/MasterCell/DefaultComponents/FocusableView/index.android.tsx +2 -23
  60. package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +4 -22
  61. package/Components/MasterCell/DefaultComponents/Image/Image.android.tsx +8 -2
  62. package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +11 -3
  63. package/Components/MasterCell/DefaultComponents/Image/Image.web.tsx +9 -1
  64. package/Components/MasterCell/DefaultComponents/Image/hooks/useImage.ts +15 -14
  65. package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +5 -3
  66. package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +1 -2
  67. package/Components/MasterCell/DefaultComponents/PressableView.tsx +54 -0
  68. package/Components/MasterCell/DefaultComponents/SecondaryImage/Image.tsx +46 -50
  69. package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/__snapshots__/Image.test.tsx.snap +47 -39
  70. package/Components/MasterCell/DefaultComponents/SecondaryImage/hooks/__tests__/useGetImageDimensions.test.ts +7 -6
  71. package/Components/MasterCell/DefaultComponents/SecondaryImage/utils.ts +19 -6
  72. package/Components/MasterCell/DefaultComponents/Text/hooks/useText.ts +15 -0
  73. package/Components/MasterCell/DefaultComponents/Text/index.tsx +45 -15
  74. package/Components/MasterCell/DefaultComponents/UIKitAdapters/Badge.tsx +49 -0
  75. package/Components/MasterCell/DefaultComponents/__tests__/ActionButton.test.tsx +122 -0
  76. package/Components/MasterCell/DefaultComponents/__tests__/Button.test.tsx +186 -0
  77. package/Components/MasterCell/DefaultComponents/__tests__/DataProvider.test.tsx +141 -0
  78. package/Components/MasterCell/DefaultComponents/__tests__/DynamicBadge.test.tsx +156 -0
  79. package/Components/MasterCell/DefaultComponents/__tests__/__snapshots__/ActionButton.test.tsx.snap +60 -0
  80. package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +196 -67
  81. package/Components/MasterCell/DefaultComponents/index.ts +13 -3
  82. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/ActionButton.tsx +189 -0
  83. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Asset.ts +33 -0
  84. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/AssetComponent.tsx +33 -0
  85. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Button.ts +159 -0
  86. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Spacer.ts +18 -0
  87. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/TextLabel.ts +67 -0
  88. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/TextLabelsContainer.ts +39 -0
  89. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/PressableView.test.tsx +402 -0
  90. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/builders.test.ts +141 -0
  91. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/index.test.ts +354 -0
  92. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/helpers.ts +105 -0
  93. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/index.ts +129 -0
  94. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/utils/__tests__/insertButtons.test.ts +123 -0
  95. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/utils/index.ts +238 -0
  96. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/Asset.ts +4 -18
  97. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/Button.ts +24 -73
  98. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/TextLabelsContainer.ts +37 -18
  99. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/TvActionButton.tsx +27 -0
  100. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/__tests__/index.test.ts +89 -0
  101. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/__tests__/renderedTree.test.tsx +231 -0
  102. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/index.ts +47 -48
  103. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/__tests__/getPluginIdentifier.test.ts +115 -29
  104. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/__tests__/insertButtonsBetweenLabels.test.ts +45 -13
  105. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/index.ts +101 -144
  106. package/Components/MasterCell/MappingFunctions/index.js +3 -2
  107. package/Components/MasterCell/README.md +4 -0
  108. package/Components/MasterCell/__tests__/__snapshots__/dataAdapter.test.js.snap +24 -0
  109. package/Components/MasterCell/__tests__/configInflater.test.js +1 -0
  110. package/Components/MasterCell/__tests__/elementMapper.test.js +46 -0
  111. package/Components/MasterCell/contexts/PressedStateContext.ts +3 -0
  112. package/Components/MasterCell/dataAdapter.ts +4 -1
  113. package/Components/MasterCell/elementMapper.tsx +54 -7
  114. package/Components/MasterCell/hooks/index.ts +2 -0
  115. package/Components/MasterCell/hooks/usePressedState.ts +4 -0
  116. package/Components/MasterCell/index.tsx +20 -4
  117. package/Components/MasterCell/utils/__tests__/cloneChildrenWithIds.test.tsx +43 -0
  118. package/Components/MasterCell/utils/__tests__/useFilterChildren.test.tsx +80 -0
  119. package/Components/MasterCell/utils/index.ts +82 -16
  120. package/Components/ModalComponent/AudioPlayer/Components/Action.tsx +33 -69
  121. package/Components/ModalComponent/AudioPlayer/Components/Button.tsx +25 -47
  122. package/Components/ModalComponent/AudioPlayer/Components/Header.tsx +122 -39
  123. package/Components/ModalComponent/AudioPlayer/Components/Input.tsx +671 -0
  124. package/Components/ModalComponent/AudioPlayer/Components/Item.tsx +257 -88
  125. package/Components/ModalComponent/AudioPlayer/Components/index.ts +6 -4
  126. package/Components/ModalComponent/BottomSheetDragArea.tsx +33 -0
  127. package/Components/ModalComponent/BottomSheetModalContent.tsx +17 -10
  128. package/Components/ModalComponent/__tests__/BottomSheetDragArea.test.tsx +74 -0
  129. package/Components/OfflineHandler/__tests__/__snapshots__/index.test.tsx.snap +4 -85
  130. package/Components/OfflineHandler/__tests__/index.test.tsx +101 -32
  131. package/Components/OfflineHandler/hooks.ts +123 -0
  132. package/Components/OfflineHandler/index.tsx +51 -73
  133. package/Components/OfflineHandler/utils/index.ts +1 -13
  134. package/Components/PlayerContainer/PlayerContainer.tsx +6 -5
  135. package/Components/PlayerContainer/__tests__/PlayerContainer.test.tsx +2 -4
  136. package/Components/PreloaderWrapper/index.tsx +1 -1
  137. package/Components/River/ComponentsMap/ComponentsMap.tsx +8 -21
  138. package/Components/River/ComponentsMap/hooks/__tests__/useLoadingState.test.ts +1 -1
  139. package/Components/River/RefreshControl.tsx +19 -105
  140. package/Components/River/River.tsx +9 -82
  141. package/Components/River/TV/River.tsx +31 -14
  142. package/Components/River/TV/index.tsx +8 -4
  143. package/Components/River/TV/utils/__tests__/toStringOrEmpty.test.ts +30 -0
  144. package/Components/River/TV/utils/index.ts +4 -0
  145. package/Components/River/TV/withFocusableGroupForContent.tsx +71 -0
  146. package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +4 -0
  147. package/Components/River/__tests__/componentsMap.test.js +38 -0
  148. package/Components/River/hooks/__tests__/usePullToRefresh.test.ts +132 -0
  149. package/Components/River/hooks/index.ts +1 -0
  150. package/Components/River/hooks/usePullToRefresh.ts +51 -0
  151. package/Components/Screen/TV/index.web.tsx +4 -2
  152. package/Components/Screen/__tests__/Screen.test.tsx +65 -42
  153. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +68 -44
  154. package/Components/Screen/hooks.ts +2 -3
  155. package/Components/Screen/index.tsx +2 -3
  156. package/Components/Screen/orientationHandler.ts +3 -3
  157. package/Components/ScreenFeedLoader/ScreenFeedLoader.tsx +5 -3
  158. package/Components/ScreenResolver/index.tsx +9 -5
  159. package/Components/ScreenResolverFeedProvider/ScreenResolverFeedProvider.tsx +1 -1
  160. package/Components/ScreenRevealManager/ScreenRevealManager.ts +40 -8
  161. package/Components/ScreenRevealManager/__tests__/ScreenRevealManager.test.ts +86 -69
  162. package/Components/ScreenRevealManager/withScreenRevealManager.tsx +1 -1
  163. package/Components/Tabs/TabContent.tsx +7 -4
  164. package/Components/TopCutoffOverlay/__tests__/TopCutoffOverlay.test.tsx +201 -0
  165. package/Components/TopCutoffOverlay/hooks/__tests__/useMarginTop.test.ts +130 -0
  166. package/Components/TopCutoffOverlay/hooks/index.ts +1 -0
  167. package/Components/TopCutoffOverlay/hooks/useMarginTop.ts +59 -0
  168. package/Components/TopCutoffOverlay/index.tsx +55 -0
  169. package/Components/Transitioner/index.js +3 -3
  170. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +5 -5
  171. package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +15 -7
  172. package/Components/VideoModal/utils.ts +12 -10
  173. package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +0 -2
  174. package/Components/Viewport/ViewportAware/index.tsx +16 -7
  175. package/Components/Viewport/ViewportEvents/__tests__/viewportEvents.test.js +1 -1
  176. package/Components/default-cell-renderer/viewTrees/mobile/index.ts +0 -3
  177. package/Contexts/CachedDimensionsContext/__tests__/index.test.ts +154 -0
  178. package/Contexts/ScreenContext/index.tsx +25 -18
  179. package/Contexts/ScreenTrackedViewPositionsContext/__tests__/index.test.tsx +1 -1
  180. package/Decorators/Analytics/index.tsx +6 -5
  181. package/Decorators/ConfigurationWrapper/__tests__/__snapshots__/withConfigurationProvider.test.tsx.snap +1 -0
  182. package/Decorators/ConfigurationWrapper/const.ts +1 -0
  183. package/Decorators/ZappPipesDataConnector/__tests__/UrlFeedResolver.test.tsx +39 -21
  184. package/Decorators/ZappPipesDataConnector/__tests__/zappPipesDataConnector.test.js +1 -1
  185. package/Decorators/ZappPipesDataConnector/index.tsx +2 -2
  186. package/Decorators/ZappPipesDataConnector/resolvers/StaticFeedResolver.tsx +1 -1
  187. package/Decorators/ZappPipesDataConnector/resolvers/UrlFeedResolver.tsx +18 -7
  188. package/Helpers/DataSourceHelper/__tests__/itemLimitForData.test.ts +80 -0
  189. package/Helpers/DataSourceHelper/index.ts +19 -0
  190. package/package.json +5 -5
  191. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.android.tsx +0 -135
  192. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/types.ts +0 -25
  193. package/Components/OfflineHandler/NotificationView/NotificationView.lg.tsx +0 -112
  194. package/Components/OfflineHandler/NotificationView/NotificationView.samsung.tsx +0 -107
  195. package/Components/OfflineHandler/NotificationView/NotificationView.tsx +0 -153
  196. package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +0 -67
  197. package/Components/OfflineHandler/NotificationView/utils.ts +0 -34
  198. package/Components/River/TV/withTVEventHandler.tsx +0 -36
  199. package/Helpers/DataSourceHelper/index.js +0 -19
  200. /package/Components/BackgroundImage/{BackgroundImage.tv.android.tsx → BackgroundImage.android.tv.tsx} +0 -0
  201. /package/Components/BackgroundImage/{BackgroundImage.tv.ios.tsx → BackgroundImage.ios.tv.tsx} +0 -0
  202. /package/Components/BackgroundImage/{BackgroundImage.tv.web.tsx → BackgroundImage.tsx} +0 -0
@@ -7,6 +7,7 @@ exports[`dataAdapter creates a tree of nodes 1`] = `
7
7
  {
8
8
  "elements": undefined,
9
9
  "props": {
10
+ "_dataKey": "uri",
10
11
  "numberOfLines": 1,
11
12
  "uri": "http://urlOfTheImage.net/img.png",
12
13
  },
@@ -23,6 +24,7 @@ exports[`dataAdapter creates a tree of nodes 1`] = `
23
24
  {
24
25
  "elements": undefined,
25
26
  "props": {
27
+ "_dataKey": "label",
26
28
  "label": "Test Entry",
27
29
  "numberOfLines": 1,
28
30
  },
@@ -49,6 +51,7 @@ exports[`dataAdapter creates a tree of nodes 1`] = `
49
51
  {
50
52
  "elements": undefined,
51
53
  "props": {
54
+ "_dataKey": "label",
52
55
  "label": "Summary of the test entry",
53
56
  "numberOfLines": 2,
54
57
  },
@@ -76,6 +79,7 @@ exports[`dataAdapter creates a tree of nodes 1`] = `
76
79
  {
77
80
  "elements": undefined,
78
81
  "props": {
82
+ "_dataKey": "uri",
79
83
  "uri": "http://urlOfTheImage.net/channelLogo.png",
80
84
  },
81
85
  "style": {
@@ -119,6 +123,7 @@ exports[`dataAdapter returns a tree view for a specific content type fallback to
119
123
  {
120
124
  "elements": undefined,
121
125
  "props": {
126
+ "_dataKey": "uri",
122
127
  "numberOfLines": 1,
123
128
  "uri": "http://urlOfTheImage.net/img.png",
124
129
  },
@@ -135,6 +140,7 @@ exports[`dataAdapter returns a tree view for a specific content type fallback to
135
140
  {
136
141
  "elements": undefined,
137
142
  "props": {
143
+ "_dataKey": "label",
138
144
  "label": "Test Entry",
139
145
  "numberOfLines": 1,
140
146
  },
@@ -161,6 +167,7 @@ exports[`dataAdapter returns a tree view for a specific content type fallback to
161
167
  {
162
168
  "elements": undefined,
163
169
  "props": {
170
+ "_dataKey": "label",
164
171
  "label": "Summary of the test entry",
165
172
  "numberOfLines": 2,
166
173
  },
@@ -188,6 +195,7 @@ exports[`dataAdapter returns a tree view for a specific content type fallback to
188
195
  {
189
196
  "elements": undefined,
190
197
  "props": {
198
+ "_dataKey": "uri",
191
199
  "uri": "http://urlOfTheImage.net/channelLogo.png",
192
200
  },
193
201
  "style": {
@@ -231,6 +239,7 @@ exports[`dataAdapter returns a tree view for a specific content type if the cont
231
239
  {
232
240
  "elements": undefined,
233
241
  "props": {
242
+ "_dataKey": "uri",
234
243
  "numberOfLines": 1,
235
244
  "uri": "http://urlOfTheImage.net/img.png",
236
245
  },
@@ -247,6 +256,7 @@ exports[`dataAdapter returns a tree view for a specific content type if the cont
247
256
  {
248
257
  "elements": undefined,
249
258
  "props": {
259
+ "_dataKey": "label",
250
260
  "label": "Test Entry",
251
261
  "numberOfLines": 1,
252
262
  },
@@ -273,6 +283,7 @@ exports[`dataAdapter returns a tree view for a specific content type if the cont
273
283
  {
274
284
  "elements": undefined,
275
285
  "props": {
286
+ "_dataKey": "label",
276
287
  "label": "Summary of the test entry",
277
288
  "numberOfLines": 2,
278
289
  },
@@ -300,6 +311,7 @@ exports[`dataAdapter returns a tree view for a specific content type if the cont
300
311
  {
301
312
  "elements": undefined,
302
313
  "props": {
314
+ "_dataKey": "uri",
303
315
  "uri": "http://urlOfTheImage.net/channelLogo.png",
304
316
  },
305
317
  "style": {
@@ -343,6 +355,7 @@ exports[`dataAdapter returns a tree view for state fallback to the default if th
343
355
  {
344
356
  "elements": undefined,
345
357
  "props": {
358
+ "_dataKey": "uri",
346
359
  "numberOfLines": 1,
347
360
  "uri": "http://urlOfTheImage.net/img.png",
348
361
  },
@@ -359,6 +372,7 @@ exports[`dataAdapter returns a tree view for state fallback to the default if th
359
372
  {
360
373
  "elements": undefined,
361
374
  "props": {
375
+ "_dataKey": "label",
362
376
  "label": "Test Entry",
363
377
  "numberOfLines": 1,
364
378
  },
@@ -385,6 +399,7 @@ exports[`dataAdapter returns a tree view for state fallback to the default if th
385
399
  {
386
400
  "elements": undefined,
387
401
  "props": {
402
+ "_dataKey": "label",
388
403
  "label": "Summary of the test entry",
389
404
  "numberOfLines": 2,
390
405
  },
@@ -412,6 +427,7 @@ exports[`dataAdapter returns a tree view for state fallback to the default if th
412
427
  {
413
428
  "elements": undefined,
414
429
  "props": {
430
+ "_dataKey": "uri",
415
431
  "uri": "http://urlOfTheImage.net/channelLogo.png",
416
432
  },
417
433
  "style": {
@@ -455,6 +471,7 @@ exports[`dataAdapter returns a tree view for state fallback to the default if th
455
471
  {
456
472
  "elements": undefined,
457
473
  "props": {
474
+ "_dataKey": "uri",
458
475
  "numberOfLines": 1,
459
476
  "uri": "http://urlOfTheImage.net/img.png",
460
477
  },
@@ -471,6 +488,7 @@ exports[`dataAdapter returns a tree view for state fallback to the default if th
471
488
  {
472
489
  "elements": undefined,
473
490
  "props": {
491
+ "_dataKey": "label",
474
492
  "label": "Test Entry",
475
493
  "numberOfLines": 1,
476
494
  },
@@ -497,6 +515,7 @@ exports[`dataAdapter returns a tree view for state fallback to the default if th
497
515
  {
498
516
  "elements": undefined,
499
517
  "props": {
518
+ "_dataKey": "label",
500
519
  "label": "Summary of the test entry",
501
520
  "numberOfLines": 2,
502
521
  },
@@ -524,6 +543,7 @@ exports[`dataAdapter returns a tree view for state fallback to the default if th
524
543
  {
525
544
  "elements": undefined,
526
545
  "props": {
546
+ "_dataKey": "uri",
527
547
  "uri": "http://urlOfTheImage.net/channelLogo.png",
528
548
  },
529
549
  "style": {
@@ -567,6 +587,7 @@ exports[`dataAdapter returns a tree view for state matching the state if it exis
567
587
  {
568
588
  "elements": undefined,
569
589
  "props": {
590
+ "_dataKey": "uri",
570
591
  "numberOfLines": 1,
571
592
  "uri": "http://urlOfTheImage.net/img.png",
572
593
  },
@@ -583,6 +604,7 @@ exports[`dataAdapter returns a tree view for state matching the state if it exis
583
604
  {
584
605
  "elements": undefined,
585
606
  "props": {
607
+ "_dataKey": "label",
586
608
  "label": "Test Entry",
587
609
  "numberOfLines": 1,
588
610
  },
@@ -609,6 +631,7 @@ exports[`dataAdapter returns a tree view for state matching the state if it exis
609
631
  {
610
632
  "elements": undefined,
611
633
  "props": {
634
+ "_dataKey": "label",
612
635
  "label": "Summary of the test entry",
613
636
  "numberOfLines": 2,
614
637
  },
@@ -636,6 +659,7 @@ exports[`dataAdapter returns a tree view for state matching the state if it exis
636
659
  {
637
660
  "elements": undefined,
638
661
  "props": {
662
+ "_dataKey": "uri",
639
663
  "uri": "http://urlOfTheImage.net/channelLogo.png",
640
664
  },
641
665
  "style": {
@@ -32,6 +32,7 @@ describe("configInflater", () => {
32
32
  },
33
33
  type: "testType",
34
34
  props: {
35
+ _dataKey: "uri",
35
36
  uri: {
36
37
  extensions: {
37
38
  color: "red",
@@ -30,4 +30,50 @@ describe("elementMapper", () => {
30
30
 
31
31
  expect(wrapper.toJSON()).toMatchSnapshot();
32
32
  });
33
+
34
+ it("renders inline ReactComponent nodes", () => {
35
+ const InlineComponent = jest.fn(({ testID, children }) => (
36
+ <View testID={testID}>{children}</View>
37
+ ));
38
+
39
+ const node = {
40
+ type: "ReactComponent",
41
+ style: { marginTop: 8 },
42
+ props: {
43
+ component: InlineComponent,
44
+ testID: "inline-react-component",
45
+ requiresCellUUID: true,
46
+ },
47
+ elements: [
48
+ {
49
+ type: "View",
50
+ style: { width: 10 },
51
+ props: {
52
+ testID: "inline-react-child",
53
+ },
54
+ },
55
+ ],
56
+ };
57
+
58
+ const wrapper = render(
59
+ <View>
60
+ {elementMapper({ View }, { cellUUID: "cell-uuid-test" })(node)}
61
+ </View>
62
+ );
63
+
64
+ expect(wrapper.getByTestId("inline-react-component")).toBeTruthy();
65
+ expect(wrapper.getByTestId("inline-react-child")).toBeTruthy();
66
+
67
+ expect(InlineComponent).toHaveBeenCalledWith(
68
+ expect.objectContaining({
69
+ testID: "inline-react-component",
70
+ style: { marginTop: 8 },
71
+ cellUUID: "cell-uuid-test",
72
+ }),
73
+ expect.anything()
74
+ );
75
+
76
+ expect(InlineComponent.mock.calls[0][0].component).toBeUndefined();
77
+ expect(InlineComponent.mock.calls[0][0].requiresCellUUID).toBeUndefined();
78
+ });
33
79
  });
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+
3
+ export const PressedStateContext = React.createContext<boolean>(false);
@@ -32,7 +32,9 @@ function retrieveData(entry, func, args) {
32
32
  * @param {String} masterCellConfig.type of the component
33
33
  * @param {Object} masterCellConfig.style default style object for the component
34
34
  * @param {?Object} masterCellConfig.data func/args/propName that indicates how to extract
35
- * the data from the entry and to which prop it should be injected after manipulation
35
+ * the data from the entry and to which prop it should be injected after manipulation.
36
+ * The last mapped propName is also stored as `_dataKey` so DataProvider can
37
+ * mirror the resolved value into both direct props and `dataProviderProps`.
36
38
  * @param {?[Object]} element.elements Optional array of nested elements to render within the current node
37
39
  * @returns {Object} inflated configuration, ready to be rendered by the master cell's element mapper
38
40
  */
@@ -56,6 +58,7 @@ export function configInflater(
56
58
  ) {
57
59
  const props = data.reduce(
58
60
  (acc, curr) => {
61
+ acc._dataKey = curr.propName;
59
62
  acc[curr.propName] = retrieveData(entry, curr.func, curr.args);
60
63
 
61
64
  return acc;
@@ -8,6 +8,8 @@ type ElementProps = {
8
8
  key: string;
9
9
  };
10
10
 
11
+ const REACT_COMPONENT_TYPE = "ReactComponent";
12
+
11
13
  export function mapElementWithKey(fn) {
12
14
  return function (element, key) {
13
15
  return fn({ ...element, key });
@@ -18,9 +20,23 @@ export function mapElementWithKey(fn) {
18
20
  const focusableTypes = new Set([
19
21
  "View",
20
22
  "ButtonContainerView",
21
- "FocusableView",
23
+ "TvActionButton",
24
+ "PressableView",
22
25
  "CollapsibleTextContainer",
23
26
  "BorderContainerView",
27
+ "UIKitBadge",
28
+ ]);
29
+
30
+ const childrenRenderingTypes = new Set([
31
+ "View",
32
+ "ButtonContainerView",
33
+ "PressableView",
34
+ "CollapsibleTextContainer",
35
+ "BorderContainerView",
36
+ "DataProvider",
37
+ "TvActionButton",
38
+ "MobileActionButton",
39
+ "UIKitBadge",
24
40
  ]);
25
41
 
26
42
  const cellPlayerTypes = new Set([
@@ -30,6 +46,23 @@ const cellPlayerTypes = new Set([
30
46
  "DynamicBadge",
31
47
  ]);
32
48
 
49
+ const resolveComponent = (type, props, components) => {
50
+ if (type === REACT_COMPONENT_TYPE) {
51
+ return props?.component;
52
+ }
53
+
54
+ return components[type];
55
+ };
56
+
57
+ const shouldInjectCellUUID = (type, props) =>
58
+ cellPlayerTypes.has(type) ||
59
+ (type === REACT_COMPONENT_TYPE && Boolean(props?.requiresCellUUID));
60
+
61
+ const shouldRenderChildren = (type, props) =>
62
+ type === REACT_COMPONENT_TYPE
63
+ ? props?.renderChildren !== false
64
+ : childrenRenderingTypes.has(type);
65
+
33
66
  /**
34
67
  * Maps a provided node in a master cell configuration to a React Component tree with appropriate props & styles
35
68
  * Curried function of the form elementMapper(components)(element)
@@ -58,7 +91,7 @@ export function elementMapper(
58
91
  elements = [],
59
92
  key,
60
93
  }: ElementProps) {
61
- const propsForCellPlayer = cellPlayerTypes.has(type)
94
+ const propsForCellPlayer = shouldInjectCellUUID(type, props)
62
95
  ? {
63
96
  cellUUID: otherProps?.cellUUID,
64
97
  }
@@ -86,14 +119,28 @@ export function elementMapper(
86
119
 
87
120
  if (hidden) return null;
88
121
 
89
- const Component = components[type];
122
+ const Component = resolveComponent(type, componentProps, components);
123
+
124
+ if (!Component) return null;
125
+
126
+ const componentPropsToRender =
127
+ type === REACT_COMPONENT_TYPE
128
+ ? (({
129
+ component: _component,
130
+ renderChildren: _renderChildren,
131
+ requiresCellUUID: _requiresCellUUID,
132
+ ...rest
133
+ }: Record<string, any>) => rest)(componentProps)
134
+ : componentProps;
135
+
136
+ const canRenderChildren =
137
+ elements.length > 0 && shouldRenderChildren(type, componentProps);
138
+
90
139
  const fn = mapElementWithKey(elementMapper(components, otherProps));
91
140
 
92
141
  return (
93
- <Component key={key} {...componentProps}>
94
- {focusableTypes.has(type) && elements.length > 0
95
- ? elements.map(fn)
96
- : null}
142
+ <Component key={key} {...componentPropsToRender}>
143
+ {canRenderChildren ? elements.map(fn) : null}
97
144
  </Component>
98
145
  );
99
146
  };
@@ -1 +1,3 @@
1
1
  export { useAsyncRendering } from "./useAsyncRendering";
2
+
3
+ export { usePressedState } from "./usePressedState";
@@ -0,0 +1,4 @@
1
+ import React from "react";
2
+ import { PressedStateContext } from "../contexts/PressedStateContext";
3
+
4
+ export const usePressedState = () => React.useContext(PressedStateContext);
@@ -2,6 +2,8 @@ import * as R from "ramda";
2
2
  import * as React from "react";
3
3
  import { v4 as uuid } from "uuid";
4
4
 
5
+ import { isHorizontalList } from "@applicaster/zapp-react-native-utils/componentsUtils";
6
+ import { isVideoPreviewEnabled } from "@applicaster/zapp-react-native-ui-components/Components/MasterCell/utils";
5
7
  import { useRoute } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
6
8
  import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
7
9
  import { useScreenState } from "@applicaster/zapp-react-native-utils/screenState";
@@ -35,8 +37,8 @@ type MasterCellBuilderOptions = {
35
37
  containerStyle: any;
36
38
  cellOptions?: {
37
39
  isRTL?: boolean;
38
- generateId?: () => string;
39
40
  skipButtons?: boolean;
41
+ component?: ZappComponent;
40
42
  };
41
43
  };
42
44
 
@@ -47,7 +49,7 @@ export function masterCellBuilder({
47
49
  containerStyle = defaultContainerStyle,
48
50
  cellOptions = {},
49
51
  }: MasterCellBuilderOptions) {
50
- const { generateId = uuid, skipButtons = false } = cellOptions;
52
+ const { skipButtons = false, component } = cellOptions;
51
53
 
52
54
  const componentsMap = R.merge(defaultComponents, components);
53
55
  const { View } = componentsMap;
@@ -100,8 +102,22 @@ export function masterCellBuilder({
100
102
 
101
103
  const wrapperRef = React.useRef(null);
102
104
 
103
- const cellUUID = React.useMemo<string>(generateId, [
104
- generateId,
105
+ const cellUUID = React.useMemo<string>(() => {
106
+ const isLiveImage = isVideoPreviewEnabled({
107
+ enable_video_preview: component?.rules?.enable_video_preview,
108
+ player_screen_id: component?.rules?.player_screen_id,
109
+ });
110
+
111
+ const isHL = isHorizontalList(component);
112
+
113
+ return isHL && isLiveImage
114
+ ? `${component?.id}-${component?.styles?.cell_plugin_configuration_id}`
115
+ : uuid();
116
+ }, [
117
+ component?.id,
118
+ component?.styles?.cell_plugin_configuration_id,
119
+ component?.rules?.enable_video_preview,
120
+ component?.rules?.player_screen_id,
105
121
  screenId,
106
122
  item?.id,
107
123
  ]);
@@ -0,0 +1,43 @@
1
+ import React from "react";
2
+
3
+ import { DataProvider } from "../../DefaultComponents/DataProvider";
4
+ import { cloneChildrenWithIds } from "..";
5
+
6
+ const Probe = () => null;
7
+
8
+ describe("cloneChildrenWithIds", () => {
9
+ it("injects next focus props into plain children", () => {
10
+ const children = [
11
+ <Probe key="one" />,
12
+ <Probe key="two" />,
13
+ <Probe key="three" />,
14
+ ];
15
+
16
+ const result = cloneChildrenWithIds(["id-1", "id-2", "id-3"], children);
17
+
18
+ expect(result[0].props.nextFocusLeft).toBeUndefined();
19
+ expect(result[0].props.nextFocusRight).toBe("id-2");
20
+ expect(result[1].props.nextFocusLeft).toBe("id-1");
21
+ expect(result[1].props.nextFocusRight).toBe("id-3");
22
+ expect(result[2].props.nextFocusLeft).toBe("id-2");
23
+ expect(result[2].props.nextFocusRight).toBeUndefined();
24
+ });
25
+
26
+ it("injects next focus props into DataProvider-wrapped children", () => {
27
+ const children = [
28
+ <DataProvider key="one" entry={{ id: "entry-1" }}>
29
+ <Probe suffixId="button_1" />
30
+ </DataProvider>,
31
+ <DataProvider key="two" entry={{ id: "entry-2" }}>
32
+ <Probe suffixId="button_2" />
33
+ </DataProvider>,
34
+ ];
35
+
36
+ const result = cloneChildrenWithIds(["id-1", "id-2"], children);
37
+
38
+ expect(result[0].props.children.props.nextFocusLeft).toBeUndefined();
39
+ expect(result[0].props.children.props.nextFocusRight).toBe("id-2");
40
+ expect(result[1].props.children.props.nextFocusLeft).toBe("id-1");
41
+ expect(result[1].props.children.props.nextFocusRight).toBeUndefined();
42
+ });
43
+ });
@@ -0,0 +1,80 @@
1
+ import React from "react";
2
+ import { renderHook } from "@testing-library/react-native";
3
+ import { useActions } from "@applicaster/zapp-react-native-utils/reactHooks/actions";
4
+
5
+ import { DataProvider } from "../../DefaultComponents/DataProvider";
6
+ import { useFilterChildren } from "..";
7
+
8
+ jest.mock("@applicaster/zapp-react-native-utils/reactHooks/actions", () => ({
9
+ useActions: jest.fn(),
10
+ }));
11
+
12
+ const mockUseActions = useActions as jest.Mock;
13
+ const Probe = () => null;
14
+
15
+ describe("useFilterChildren", () => {
16
+ beforeEach(() => {
17
+ jest.clearAllMocks();
18
+ });
19
+
20
+ it("filters DataProvider-wrapped button children using the wrapped button props", () => {
21
+ const available = jest.fn(() => true);
22
+ const unavailable = jest.fn(() => false);
23
+
24
+ mockUseActions.mockReturnValue({
25
+ actions: {
26
+ available_action: {
27
+ module: {
28
+ context: {
29
+ _currentValue: {
30
+ isActionAvailable: available,
31
+ },
32
+ },
33
+ },
34
+ },
35
+ unavailable_action: {
36
+ module: {
37
+ context: {
38
+ _currentValue: {
39
+ isActionAvailable: unavailable,
40
+ },
41
+ },
42
+ },
43
+ },
44
+ },
45
+ });
46
+
47
+ const availableItem = { id: "entry-1" };
48
+ const unavailableItem = { id: "entry-2" };
49
+
50
+ const children = [
51
+ <DataProvider key="available" entry={availableItem}>
52
+ <Probe
53
+ entry={availableItem}
54
+ pluginIdentifier="available_action"
55
+ suffixId="button_1"
56
+ cellUUID="cell-1"
57
+ />
58
+ </DataProvider>,
59
+ <DataProvider key="unavailable" entry={unavailableItem}>
60
+ <Probe
61
+ entry={unavailableItem}
62
+ pluginIdentifier="unavailable_action"
63
+ suffixId="button_2"
64
+ cellUUID="cell-1"
65
+ />
66
+ </DataProvider>,
67
+ ];
68
+
69
+ const { result } = renderHook(() => useFilterChildren(children));
70
+
71
+ expect(result.current).toHaveLength(1);
72
+
73
+ expect(result.current[0].props.children.props.pluginIdentifier).toBe(
74
+ "available_action"
75
+ );
76
+
77
+ expect(available).toHaveBeenCalledWith(availableItem);
78
+ expect(unavailable).toHaveBeenCalledWith(unavailableItem);
79
+ });
80
+ });