@applicaster/zapp-react-native-ui-components 13.0.0-rc.14 → 13.0.0-rc.140

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 (226) hide show
  1. package/Components/AppContainer/__tests__/AppContainer.test.js +4 -6
  2. package/Components/AppContainer/__tests__/__snapshots__/AppContainer.test.js.snap +1 -1
  3. package/Components/AudioPlayer/index.tsx +15 -0
  4. package/Components/AudioPlayer/mobile/Layout.tsx +63 -0
  5. package/Components/AudioPlayer/mobile/__tests__/__snapshots__/audioPlayerMobileLayout.test.js.snap +66 -0
  6. package/Components/AudioPlayer/mobile/__tests__/audioPlayerMobileLayout.test.js +18 -0
  7. package/Components/AudioPlayer/mobile/index.tsx +23 -0
  8. package/Components/AudioPlayer/tv/Artwork.tsx +40 -0
  9. package/Components/AudioPlayer/{AudioPlayerLayout.tsx → tv/Layout.tsx} +37 -79
  10. package/Components/AudioPlayer/{Runtime.tsx → tv/Runtime.tsx} +2 -1
  11. package/Components/AudioPlayer/{Summary.tsx → tv/Summary.tsx} +12 -9
  12. package/Components/AudioPlayer/{Title.tsx → tv/Title.tsx} +12 -9
  13. package/Components/AudioPlayer/{__tests__ → tv/__tests__}/Runtime.test.js +5 -8
  14. package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/Runtime.test.js.snap +6 -6
  15. package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/artWork.test.js.snap +11 -6
  16. package/Components/AudioPlayer/tv/__tests__/__snapshots__/audioPlayer.test.js.snap +170 -0
  17. package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/channel.test.js.snap +3 -3
  18. package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/summary.test.js.snap +3 -3
  19. package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/title.test.js.snap +3 -3
  20. package/Components/AudioPlayer/{__tests__ → tv/__tests__}/artWork.test.js +3 -5
  21. package/Components/AudioPlayer/{__tests__ → tv/__tests__}/audioPlayer.test.js +5 -7
  22. package/Components/AudioPlayer/{__tests__ → tv/__tests__}/channel.test.js +3 -5
  23. package/Components/AudioPlayer/{__tests__ → tv/__tests__}/summary.test.js +3 -5
  24. package/Components/AudioPlayer/{__tests__ → tv/__tests__}/title.test.js +3 -5
  25. package/Components/AudioPlayer/{helpers.tsx → tv/helpers.tsx} +3 -5
  26. package/Components/AudioPlayer/{AudioPlayer.tsx → tv/index.tsx} +21 -62
  27. package/Components/AudioPlayer/types.ts +40 -0
  28. package/Components/BaseFocusable/index.ios.ts +1 -1
  29. package/Components/BaseFocusable/index.tsx +67 -31
  30. package/Components/Cell/Cell.tsx +14 -14
  31. package/Components/Cell/CellWithFocusable.tsx +50 -59
  32. package/Components/Cell/CellWrapper.tsx +18 -0
  33. package/Components/Cell/TvOSCellComponent.tsx +20 -26
  34. package/Components/Cell/__tests__/CellWIthFocusable.test.js +13 -6
  35. package/Components/Cell/index.js +3 -1
  36. package/Components/Cell/styles.ts +17 -0
  37. package/Components/CellRendererResolver/__tests__/cellRendererResolver.test.js +50 -50
  38. package/Components/CellRendererResolver/index.ts +2 -1
  39. package/Components/ComponentResolver/__tests__/__snapshots__/componentResolver.test.js.snap +1 -42
  40. package/Components/ComponentResolver/__tests__/componentResolver.test.js +26 -30
  41. package/Components/ContentScreen/__tests__/contentScreen.test.js +3 -3
  42. package/Components/DisplayState/__tests__/__snapshots__/displayState.test.js.snap +2 -2
  43. package/Components/ErrorScreen/index.tsx +14 -6
  44. package/Components/Focusable/Focusable.tsx +1 -54
  45. package/Components/Focusable/FocusableTvOS.tsx +6 -2
  46. package/Components/Focusable/Touchable.tsx +19 -20
  47. package/Components/Focusable/index.android.tsx +10 -3
  48. package/Components/FocusableCell/index.tsx +1 -1
  49. package/Components/FocusableGroup/FocusableTvOS.tsx +34 -86
  50. package/Components/FocusableGroup/index.tsx +0 -3
  51. package/Components/FocusableList/index.tsx +26 -10
  52. package/Components/FocusableScrollView/index.tsx +43 -13
  53. package/Components/GeneralContentScreen/GeneralContentScreen.tsx +3 -0
  54. package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +9 -0
  55. package/Components/GeneralContentScreen/utils/useCurationAPI.ts +5 -3
  56. package/Components/GeneralContentScreen/utils/useEventAlerts.ts +30 -0
  57. package/Components/HandlePlayable/HandlePlayable.tsx +21 -27
  58. package/Components/Layout/TV/LayoutBackground.tsx +28 -0
  59. package/Components/Layout/TV/NavBarContainer.tsx +19 -23
  60. package/Components/Layout/TV/ScreenContainer.tsx +8 -2
  61. package/Components/Layout/TV/ScreenLayoutContextProvider.tsx +5 -0
  62. package/Components/Layout/TV/__tests__/ScreenContainer.test.tsx +3 -1
  63. package/Components/Layout/TV/__tests__/__snapshots__/LayoutContainer.test.tsx.snap +1 -1
  64. package/Components/Layout/TV/__tests__/__snapshots__/NavBarContainer.test.tsx.snap +6 -5
  65. package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +12 -11
  66. package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +15 -10
  67. package/Components/Layout/TV/__tests__/index.test.tsx +14 -4
  68. package/Components/Layout/TV/index.tsx +6 -20
  69. package/Components/Layout/TV/index.web.tsx +4 -1
  70. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +2 -3
  71. package/Components/MasterCell/DefaultComponents/BorderContainerView/__tests__/index.test.tsx +66 -0
  72. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +4 -1
  73. package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +10 -15
  74. package/Components/MasterCell/DefaultComponents/Image/hooks/useImage.ts +11 -7
  75. package/Components/MasterCell/DefaultComponents/ImageBorderContainer/__tests__/index.test.ts +93 -0
  76. package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +2 -2
  77. package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/__snapshots__/Image.test.tsx.snap +3 -3
  78. package/Components/MasterCell/DefaultComponents/SecondaryImage/utils.ts +1 -1
  79. package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
  80. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/const.ts +3 -0
  81. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/index.ts +6 -6
  82. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/__tests__/__snapshots__/index.test.tsx.snap +1 -1
  83. package/Components/MasterCell/SharedUI/ProgressBar/hooks/useFillInPercent.ts +2 -8
  84. package/Components/MasterCell/__tests__/__snapshots__/dataAdapter.test.js.snap +180 -180
  85. package/Components/MasterCell/__tests__/__snapshots__/elementMapper.test.js.snap +11 -19
  86. package/Components/MasterCell/__tests__/__snapshots__/masterCell.test.js.snap +6 -235
  87. package/Components/MasterCell/__tests__/elementMapper.test.js +18 -5
  88. package/Components/MasterCell/__tests__/masterCell.test.js +26 -26
  89. package/Components/MasterCell/hooks/useAsyncRendering/MasterCellAsyncRenderManager.ts +2 -2
  90. package/Components/MasterCell/hooks/useAsyncRendering/index.ts +2 -2
  91. package/Components/MasterCell/utils/behaviorProvider.ts +136 -0
  92. package/Components/MasterCell/utils/index.ts +9 -135
  93. package/Components/ModalComponent/BottomSheetModalContent.tsx +66 -54
  94. package/Components/ModalComponent/Button/Item.tsx +6 -5
  95. package/Components/ModalComponent/Button/assets.ts +1 -1
  96. package/Components/ModalComponent/Button/index.tsx +45 -62
  97. package/Components/ModalComponent/Header/index.tsx +12 -11
  98. package/Components/ModalComponent/utils.ts +55 -7
  99. package/Components/OfflineHandler/NotificationView/NotificationView.lg.tsx +2 -2
  100. package/Components/OfflineHandler/NotificationView/NotificationView.samsung.tsx +2 -2
  101. package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +0 -5
  102. package/Components/OfflineHandler/__tests__/__snapshots__/index.test.tsx.snap +7 -7
  103. package/Components/OfflineHandler/__tests__/index.test.tsx +28 -25
  104. package/Components/OfflineHandler/utils/index.ts +1 -1
  105. package/Components/PlayerContainer/PlayerContainer.tsx +76 -66
  106. package/Components/PlayerContainer/PlayerContainerContext.tsx +9 -0
  107. package/Components/PlayerContainer/ProgramInfo/index.tsx +2 -2
  108. package/Components/PlayerImageBackground/index.tsx +2 -2
  109. package/Components/River/ComponentsMap/ComponentsMap.tsx +49 -68
  110. package/Components/River/ComponentsMap/hooks/useLoadingState.ts +78 -51
  111. package/Components/River/RefreshControl.tsx +1 -1
  112. package/Components/River/RiverFooter.tsx +39 -9
  113. package/Components/River/RiverItem.tsx +44 -4
  114. package/Components/River/TV/index.tsx +6 -1
  115. package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +115 -46
  116. package/Components/River/__tests__/__snapshots__/river.test.js.snap +21 -83
  117. package/Components/River/__tests__/componentsMap.test.js +64 -17
  118. package/Components/River/__tests__/river.test.js +75 -40
  119. package/Components/RouteManager/TestId.tsx +1 -5
  120. package/Components/RouteManager/__tests__/__snapshots__/routeManager.test.js.snap +11 -5
  121. package/Components/RouteManager/__tests__/routeManager.test.js +29 -14
  122. package/Components/RouteManager/__tests__/testId.test.js +4 -6
  123. package/Components/Screen/TV/__tests__/index.web.test.tsx +26 -0
  124. package/Components/Screen/TV/index.web.tsx +5 -6
  125. package/Components/Screen/__tests__/Screen.test.tsx +53 -31
  126. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +6 -6
  127. package/Components/Screen/hooks.ts +53 -0
  128. package/Components/Screen/index.tsx +16 -42
  129. package/Components/ScreenResolver/__tests__/screenResolver.test.js +95 -70
  130. package/Components/Tabs/Tab.tsx +12 -9
  131. package/Components/TextInputTv/__tests__/TextInputTv.test.js +42 -42
  132. package/Components/TextInputTv/__tests__/__snapshots__/TextInputTv.test.js.snap +7 -0
  133. package/Components/TextInputTv/index.tsx +6 -5
  134. package/Components/TopMarginApplicator/TopMarginApplicator.tsx +2 -3
  135. package/Components/Touchable/__tests__/__snapshots__/touchable.test.tsx.snap +2 -2
  136. package/Components/TrackedView/index.tsx +1 -0
  137. package/Components/Transitioner/AnimationManager.js +15 -15
  138. package/Components/Transitioner/Scene.tsx +53 -24
  139. package/Components/Transitioner/Transitioner.tsx +3 -3
  140. package/Components/Transitioner/__tests__/Scene.test.js +25 -14
  141. package/Components/Transitioner/__tests__/__snapshots__/AnimationManager.test.js.snap +26 -26
  142. package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +10 -50
  143. package/Components/Transitioner/__tests__/__snapshots__/config.test.js.snap +20 -20
  144. package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +4 -4
  145. package/Components/Transitioner/__tests__/transitioner.test.js +13 -4
  146. package/Components/Transitioner/index.js +8 -4
  147. package/Components/VideoLive/LiveImageManager.ts +27 -1
  148. package/Components/VideoLive/PlayerLiveImageComponent.tsx +36 -24
  149. package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +63 -8
  150. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +6 -10
  151. package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +1 -1
  152. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +51 -31
  153. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +8 -4
  154. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +48 -23
  155. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +16 -15
  156. package/Components/VideoModal/ModalAnimation/__tests__/getMoveUpValue.test.ts +108 -0
  157. package/Components/VideoModal/ModalAnimation/const.ts +5 -0
  158. package/Components/VideoModal/ModalAnimation/index.ts +4 -1
  159. package/Components/VideoModal/ModalAnimation/useModalAnimationContext.ts +6 -0
  160. package/Components/VideoModal/ModalAnimation/utils.ts +32 -2
  161. package/Components/VideoModal/OpaqueLayer.tsx +33 -0
  162. package/Components/VideoModal/PlayerDetails.tsx +18 -10
  163. package/Components/VideoModal/PlayerWrapper.tsx +51 -57
  164. package/Components/VideoModal/VideoModal.tsx +17 -11
  165. package/Components/VideoModal/__tests__/PlayerDetails.test.tsx +5 -2
  166. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +13 -10
  167. package/Components/VideoModal/__tests__/__snapshots__/PlayerDetails.test.tsx.snap +2 -40
  168. package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +74 -104
  169. package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +51 -0
  170. package/Components/VideoModal/hooks/index.ts +7 -0
  171. package/Components/VideoModal/hooks/useDelayedPlayerDetails.ts +38 -0
  172. package/Components/VideoModal/hooks/utils/__tests__/showDetails.test.ts +91 -0
  173. package/Components/VideoModal/hooks/utils/index.ts +33 -0
  174. package/Components/VideoModal/utils.ts +6 -9
  175. package/Components/Viewport/ViewportAware/__tests__/__snapshots__/viewportAware.test.js.snap +24 -36
  176. package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +12 -18
  177. package/Components/Viewport/ViewportTracker/__tests__/__snapshots__/viewportTracker.test.js.snap +1 -1
  178. package/Components/Viewport/__tests__/utils.test.js +5 -4
  179. package/Components/ZappUIComponent/Placeholder.tsx +3 -1
  180. package/Components/ZappUIComponent/__tests__/{ZappUIComponent.test.js → ZappUIComponent.test.tsx} +26 -10
  181. package/Components/ZappUIComponent/index.tsx +4 -17
  182. package/Components/default-cell-renderer/__tests__/defaultCellRenderer.test.tsx +20 -17
  183. package/Components/default-cell-renderer/viewTrees/tv/DefaultCell/__tests__/DefaultCell.test.tsx +15 -11
  184. package/Contexts/ComponentsMapOffsetContext/index.tsx +49 -0
  185. package/Contexts/ConfigutaionContext/__tests__/__snapshots__/ConfigurationProvider.test.tsx.snap +1 -1
  186. package/Contexts/FocusableGroupContext/withFocusableContext.tsx +4 -10
  187. package/Contexts/HeaderOffsetContext/index.tsx +4 -6
  188. package/Contexts/ScreenContext/index.tsx +6 -12
  189. package/Contexts/ScreenLayoutContext/index.tsx +5 -3
  190. package/Decorators/Navigator/__tests__/navigator.test.js +16 -16
  191. package/Decorators/Navigator/index.tsx +1 -1
  192. package/Decorators/RiverFeedLoader/__tests__/__snapshots__/riverFeedLoader.test.tsx.snap +77 -77
  193. package/Decorators/RiverFeedLoader/__tests__/riverFeedLoader.test.tsx +34 -39
  194. package/Decorators/RiverFeedLoader/__tests__/utils.test.ts +0 -9
  195. package/Decorators/RiverFeedLoader/index.tsx +1 -1
  196. package/Decorators/RiverFeedLoader/utils/getDatasourceUrl.ts +39 -0
  197. package/Decorators/RiverFeedLoader/utils/index.ts +29 -0
  198. package/Decorators/RiverFeedLoader/utils/usePipesContexts.ts +40 -0
  199. package/Decorators/RiverResolver/__tests__/riverResolver.test.tsx +27 -27
  200. package/Decorators/RiverResolver/index.tsx +6 -8
  201. package/Decorators/ZappPipesDataConnector/__tests__/Hero.js +1 -1
  202. package/Decorators/ZappPipesDataConnector/__tests__/zappPipesDataConnector.test.js +29 -22
  203. package/Decorators/ZappPipesDataConnector/index.tsx +7 -3
  204. package/package.json +13 -11
  205. package/tsconfig.json +2 -3
  206. package/.babelrc +0 -8
  207. package/Components/AudioPlayer/Artwork.tsx +0 -35
  208. package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayer.test.js.snap +0 -123
  209. package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayerLayout.test.js.snap +0 -50
  210. package/Components/AudioPlayer/__tests__/audioPlayerLayout.test.js +0 -27
  211. package/Components/AudioPlayer/index.ts +0 -1
  212. package/Components/Cell/CellStyles/FallbackCellStyle/index.js +0 -157
  213. package/Components/Cell/CellStyles/Hero/index.js +0 -111
  214. package/Components/Cell/CellStyles/ScreenSelector/index.js +0 -68
  215. package/Components/Cell/CellStyles/cellStylesResolver.ts +0 -19
  216. package/Components/Cell/CellStyles/colors.js +0 -40
  217. package/Components/Cell/CellStyles/index.js +0 -15
  218. package/Components/CellRendererResolver/__tests__/__snapshots__/cellRendererResolver.test.js.snap +0 -53
  219. package/Components/RouteManager/__tests__/__snapshots__/testId.test.js.snap +0 -17
  220. package/Components/ScreenResolver/__tests__/__snapshots__/screenResolver.test.js.snap +0 -17
  221. package/Components/ZappUIComponent/__tests__/__snapshots__/ZappUIComponent.test.js.snap +0 -91
  222. package/Components/default-cell-renderer/__tests__/__snapshots__/defaultCellRenderer.test.tsx.snap +0 -338
  223. package/Decorators/Navigator/__tests__/__snapshots__/navigator.test.js.snap +0 -18
  224. package/Decorators/RiverFeedLoader/utils.ts +0 -100
  225. package/Decorators/RiverResolver/__tests__/__snapshots__/riverResolver.test.tsx.snap +0 -28
  226. /package/Components/AudioPlayer/{Channel.tsx → tv/Channel.tsx} +0 -0
@@ -1,16 +1,13 @@
1
- import React, { useEffect, useMemo } from "react";
1
+ import React, { useMemo } from "react";
2
2
  import * as R from "ramda";
3
3
  import validateColor from "validate-color";
4
4
  import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
5
5
  import { useActions } from "@applicaster/zapp-react-native-utils/reactHooks/actions";
6
6
 
7
7
  import { masterCellLogger } from "../logger";
8
- import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
9
- import { usePlayer } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayer";
10
- import { PushTopicManager } from "@applicaster/zapp-react-native-bridge/PushNotifications/PushTopicManager";
11
- import { StorageMultiSelectProvider } from "@applicaster/zapp-react-native-bridge/ZappStorage/StorageMultiSelectProvider";
12
8
  import { getCellState } from "../../Cell/utils";
13
9
  import { getColorFromData } from "@applicaster/zapp-react-native-utils/cellUtils";
10
+ import { isCellSelected, useBehaviorUpdate } from "./behaviorProvider";
14
11
 
15
12
  const hasElementSpecificViewType = (viewType) => (element) => {
16
13
  if (R.isNil(element)) {
@@ -103,7 +100,7 @@ export const useFilterChildren = <
103
100
  item: any;
104
101
  pluginIdentifier: string;
105
102
  };
106
- }
103
+ },
107
104
  >(
108
105
  children: T[]
109
106
  ): T[] => {
@@ -193,147 +190,24 @@ export const getFocusedButtonId = (focusable) => {
193
190
  });
194
191
  };
195
192
 
196
- export const isSelected = (id: string | number, behavior?: Behavior) => {
197
- if (!behavior) {
198
- return false;
199
- }
200
-
201
- if (behavior?.selection_source === "now_playing") {
202
- const player = playerManager.getActivePlayer();
203
-
204
- if (player?.entry?.id === id) {
205
- return true;
206
- }
207
- }
208
-
209
- if (behavior?.select_mode === "single") {
210
- return behavior.current_selection === id;
211
- }
212
-
213
- if (behavior?.select_mode === "multi") {
214
- // TODO: Use generic resolver source
215
-
216
- if (behavior.selection_source === "@{push/topics}") {
217
- const tags = PushTopicManager.getInstance().getRegisteredTags();
218
-
219
- return tags.includes(String(id));
220
- }
221
-
222
- if (Array.isArray(behavior.current_selection)) {
223
- return behavior.current_selection.includes(id);
224
- }
225
-
226
- const currentSelection = String(behavior.current_selection);
227
-
228
- if (currentSelection?.startsWith("@{ctx/")) {
229
- const keyWithoutCtx = currentSelection.substring(
230
- "@{ctx/".length,
231
- currentSelection.length - 1
232
- );
233
-
234
- const selectedItems =
235
- StorageMultiSelectProvider.getProvider(
236
- keyWithoutCtx
237
- )?.getSelectedItems();
238
-
239
- return selectedItems?.includes(String(id));
240
- }
241
- }
242
-
243
- return false;
244
- };
245
-
246
- export const useBehaviorUpdate = (behavior: Behavior) => {
247
- const [lastUpdate, setLastUpdate] = React.useState(null);
248
-
249
- const player = usePlayer();
250
-
251
- const triggerUpdate = () => {
252
- setLastUpdate(Date.now());
253
- };
254
-
255
- // TODO: Create generic RX to state update
256
- useEffect(() => {
257
- // TODO: Use generic resolver source
258
- if (!behavior) {
259
- return;
260
- }
261
-
262
- const currentSelection = String(behavior.current_selection);
263
-
264
- if (currentSelection?.startsWith("@{ctx/")) {
265
- const keyWithoutCtx = currentSelection.substring(
266
- "@{ctx/".length,
267
- currentSelection.length - 1
268
- );
269
-
270
- if (keyWithoutCtx) {
271
- const subscription = StorageMultiSelectProvider.getProvider(
272
- keyWithoutCtx
273
- )
274
- .getObservable()
275
- .subscribe(() => {
276
- triggerUpdate();
277
- });
278
-
279
- return () => {
280
- subscription.unsubscribe();
281
- };
282
- }
283
- }
284
- }, [behavior]);
285
-
286
- useEffect(() => {
287
- if (!behavior) {
288
- return;
289
- }
290
-
291
- if (behavior?.selection_source === "@{push/topics}") {
292
- const subscription = PushTopicManager.getInstance()
293
- .getEntryObservable()
294
- .subscribe(() => {
295
- triggerUpdate();
296
- });
297
-
298
- return () => {
299
- subscription.unsubscribe();
300
- };
301
- }
302
- }, [behavior]);
303
-
304
- useEffect(() => {
305
- if (!behavior) {
306
- return;
307
- }
308
-
309
- if (behavior?.selection_source === "now_playing" && player) {
310
- const subscription = player.getEntryObservable().subscribe(() => {
311
- triggerUpdate();
312
- });
313
-
314
- return () => {
315
- subscription.unsubscribe();
316
- };
317
- }
318
- }, [behavior, player]);
319
-
320
- return lastUpdate;
193
+ export const isSelected = (item: ZappEntry, behavior?: Behavior) => {
194
+ return isCellSelected(item, behavior);
321
195
  };
322
196
 
323
197
  export const useCellState = ({
324
- id,
198
+ item,
325
199
  behavior,
326
200
  focused,
327
201
  }: {
328
- id: string | number;
202
+ item: ZappEntry;
329
203
  behavior: Behavior;
330
204
  focused: boolean;
331
205
  }): CellState => {
332
206
  const lastUpdate = useBehaviorUpdate(behavior);
333
207
 
334
208
  const _isSelected = useMemo(
335
- () => isSelected(id, behavior),
336
- [behavior, id, lastUpdate]
209
+ () => isSelected(item, behavior),
210
+ [behavior, item, lastUpdate]
337
211
  );
338
212
 
339
213
  return getCellState({ focused, selected: _isSelected });
@@ -1,23 +1,16 @@
1
- import React, {
2
- useCallback,
3
- useEffect,
4
- useMemo,
5
- useRef,
6
- useState,
7
- } from "react";
8
- import { View, LayoutChangeEvent, ScrollView } from "react-native";
1
+ import React, { useCallback, useEffect, useMemo, useRef } from "react";
2
+ import { View, ScrollView } from "react-native";
9
3
  import { Button } from "./Button";
10
4
  import { ItemIconProps } from "./Button/ItemIcon";
11
5
  import { ItemProps } from "./Button/Item";
12
6
  import { ItemLabelProps } from "./Button/ItemLabel";
13
- import {
14
- defaultItemIconProps,
15
- defaultItemLabelProps,
16
- defaultItemProps,
17
- } from "./utils";
7
+ import { getItemIconProps, getItemLabelProps, getItemProps } from "./utils";
18
8
  import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
19
9
 
20
- import { ModalHeader } from "./Header";
10
+ import type { PluginConfiguration } from "./";
11
+
12
+ import { ModalHeader as DefaultModalHeader } from "./Header";
13
+ import { useSafeAreaInsets } from "react-native-safe-area-context";
21
14
 
22
15
  type ModalComponentProps = {
23
16
  items: any[];
@@ -29,33 +22,46 @@ type ModalComponentProps = {
29
22
  title?: string;
30
23
  maxHeight?: number;
31
24
  dismiss: () => void;
25
+ headerComponent?: React.ComponentType;
32
26
  buttonComponent?: React.ComponentType;
27
+ iconProps?: ItemIconProps | ((theme: PluginConfiguration) => ItemIconProps);
28
+ itemProps?:
29
+ | ItemProps
30
+ | ((theme: PluginConfiguration, width: number) => ItemProps);
31
+ labelProps?:
32
+ | ItemLabelProps
33
+ | ((theme: PluginConfiguration, width: number) => ItemLabelProps);
34
+ getSelectedItemIcon: (
35
+ theme: PluginConfiguration
36
+ ) => ItemIconProps["asset"] | null;
37
+ getDefaultItemIcon: (
38
+ theme: PluginConfiguration
39
+ ) => ItemIconProps["asset"] | null;
40
+ iconPlacement?: "left" | "right";
33
41
  };
34
42
 
35
43
  export function BottomSheetModalContent(props: ModalComponentProps) {
36
44
  const {
37
45
  items,
38
46
  currentRoute,
39
- maxHeight,
40
47
  current_selection = null,
41
48
  onPress,
42
49
  dismiss,
43
50
  summary,
44
51
  title,
52
+ headerComponent: ModalHeader = DefaultModalHeader,
45
53
  buttonComponent: ButtonComponent = Button,
54
+ getSelectedItemIcon = ({
55
+ modal_bottom_sheet_item_selected_icon,
56
+ }: BaseThemePropertiesMobile) => modal_bottom_sheet_item_selected_icon,
57
+ getDefaultItemIcon = () => null,
58
+ iconPlacement,
46
59
  } = props;
47
60
 
48
- const [headerHeight, setHeaderHeight] = useState(0);
49
61
  const route = useRef(currentRoute);
50
62
  const theme = useTheme<BaseThemePropertiesMobile>();
51
-
52
- const maxContentHeight = maxHeight
53
- ? maxHeight - headerHeight - Number(theme.modal_bottom_sheet_padding_top)
54
- : undefined;
55
-
56
- const onHeaderLayout = useCallback((event: LayoutChangeEvent) => {
57
- setHeaderHeight(event.nativeEvent.layout.height);
58
- }, []);
63
+ const paddingTop = Number(theme.modal_bottom_sheet_padding_top);
64
+ const paddingBottom = Number(theme.modal_bottom_sheet_padding_bottom);
59
65
 
60
66
  useEffect(() => {
61
67
  if (currentRoute !== route.current) {
@@ -64,57 +70,63 @@ export function BottomSheetModalContent(props: ModalComponentProps) {
64
70
  }, [currentRoute]);
65
71
 
66
72
  const iconBaseProps = useMemo<ItemIconProps>(() => {
67
- return defaultItemIconProps(theme);
68
- }, [theme]);
73
+ return getItemIconProps(theme, props.iconProps);
74
+ }, [theme, props.iconProps]);
69
75
 
70
76
  const itemBaseProps = useMemo<ItemProps>(() => {
71
- return defaultItemProps(theme, props.width);
72
- }, [theme, props.width]);
77
+ return getItemProps(theme, props.width, props.itemProps);
78
+ }, [theme, props.width, props.itemProps]);
73
79
 
74
80
  const labelBaseProps = useMemo<ItemLabelProps>(() => {
75
- return defaultItemLabelProps(theme, props.width);
76
- }, [theme, props.width]);
81
+ return getItemLabelProps(theme, props.width, props.labelProps);
82
+ }, [theme, props.width, props.labelProps]);
83
+
84
+ const handlePress = useCallback(
85
+ (item: any) => {
86
+ onPress(item);
87
+ dismiss();
88
+ },
89
+ [onPress, dismiss]
90
+ );
77
91
 
78
- const handlePress = (item: any) => {
79
- onPress(item);
80
- dismiss();
81
- };
92
+ const bottomInset = useSafeAreaInsets().bottom;
82
93
 
83
94
  return (
84
95
  <View
85
96
  style={{
86
- paddingTop: Number(theme.modal_bottom_sheet_padding_top),
97
+ maxHeight: props.maxHeight,
98
+ paddingTop: paddingTop,
87
99
  }}
88
100
  >
89
101
  <ModalHeader
90
- width={props.width}
91
102
  dismiss={dismiss}
92
103
  configuration={theme}
93
- onLayout={onHeaderLayout}
94
104
  summary={summary}
95
105
  title={title}
96
106
  />
97
107
  <ScrollView
98
- bounces={false}
99
- style={{ maxHeight: maxContentHeight }}
100
108
  contentContainerStyle={{
101
- paddingBottom: Number(theme.modal_bottom_sheet_padding_bottom),
102
- paddingTop: Number(theme.modal_bottom_sheet_padding_top),
109
+ paddingBottom: paddingBottom + bottomInset,
103
110
  }}
104
111
  >
105
- {items.map((item, index) => (
106
- <ButtonComponent
107
- key={index}
108
- width={props.width}
109
- configuration={theme}
110
- selectedItem={current_selection}
111
- item={item}
112
- onPress={handlePress}
113
- iconBaseProps={iconBaseProps}
114
- itemBaseProps={itemBaseProps}
115
- labelBaseProps={labelBaseProps}
116
- />
117
- ))}
112
+ {items.map((item, index) =>
113
+ item ? (
114
+ <ButtonComponent
115
+ key={index}
116
+ configuration={theme}
117
+ selectedItem={current_selection}
118
+ item={item}
119
+ onPress={handlePress}
120
+ label={theme[item?.label] ?? item?.label}
121
+ iconBaseProps={iconBaseProps}
122
+ itemBaseProps={itemBaseProps}
123
+ labelBaseProps={labelBaseProps}
124
+ selectedItemIcon={getSelectedItemIcon(theme)}
125
+ defaultItemIcon={getDefaultItemIcon(theme)}
126
+ iconPlacement={iconPlacement}
127
+ />
128
+ ) : null
129
+ )}
118
130
  </ScrollView>
119
131
  </View>
120
132
  );
@@ -5,7 +5,7 @@ export type ItemProps = {
5
5
  backgroundColor: string;
6
6
  focusedBackgroundColor: string;
7
7
  selectedBackgroundColor?: string;
8
- focusectedBackgroundColor?: string;
8
+ focusedSelectedBackgroundColor?: string;
9
9
  borderRadius: number;
10
10
  marginBottom: number;
11
11
  marginLeft: number;
@@ -15,6 +15,7 @@ export type ItemProps = {
15
15
  paddingBottom: number;
16
16
  paddingRight: number;
17
17
  paddingLeft: number;
18
+ maxWidth: number;
18
19
  focused?: boolean;
19
20
  selected?: boolean;
20
21
  children?: ReactChild[];
@@ -33,11 +34,11 @@ function getBackgroundColor({
33
34
  backgroundColor,
34
35
  focusedBackgroundColor,
35
36
  selectedBackgroundColor,
36
- focusectedBackgroundColor,
37
+ focusedSelectedBackgroundColor,
37
38
  }) {
38
39
  switch (true) {
39
40
  case selected && focused:
40
- return focusectedBackgroundColor;
41
+ return focusedSelectedBackgroundColor;
41
42
  case selected && !focused:
42
43
  return selectedBackgroundColor;
43
44
  case !selected && focused:
@@ -51,7 +52,7 @@ export function Item(props: ItemProps) {
51
52
  const {
52
53
  backgroundColor,
53
54
  focusedBackgroundColor,
54
- focusectedBackgroundColor,
55
+ focusedSelectedBackgroundColor,
55
56
  selectedBackgroundColor,
56
57
  children,
57
58
  focused,
@@ -68,7 +69,7 @@ export function Item(props: ItemProps) {
68
69
  backgroundColor: getBackgroundColor({
69
70
  selected,
70
71
  focused,
71
- focusectedBackgroundColor,
72
+ focusedSelectedBackgroundColor,
72
73
  focusedBackgroundColor,
73
74
  selectedBackgroundColor,
74
75
  backgroundColor,
@@ -1,4 +1,4 @@
1
1
  /* eslint-disable max-len */
2
2
 
3
3
  export const defaultSelectedAsset: string =
4
- "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAYAAABV7bNHAAAACXBIWXMAACE4AAAhOAFFljFgAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAGsSURBVHgB7drdaYRAFIbhk2yuBTuwlXSQDrKdrOnErSSlpATBe0nOBxEMEXV+nDnjfg8MwiK4vKjMDIoQERERERERERHRY+j7vtHxJvTfb5wvHd/DMLyLpyc5IcTRw6eOZvrtcrlcq6q6i6PTBVqKM/GJdKpAa3EmrpGe5ST2xIFxHF/FwSnuoL1x1L2u66s4KD7QkXGg6EBHx4FiA6WIA0UGShUHiguUMg4UFSh1HCgmUI44UESgXHEgaCatf/wWslLeeY1GMsWBF/GEOHpodeouGkl8Vso7rtFIxjjg9YhNcea/+W4nrFyjkcxxwDnQUpxJrEhW4oBToLU4k9BIluKA60t6M6i+kzrfF7e1OODziLV6uG2d53onWYwDvi/pViJGshoHvCeKsSJZjgNBM+nQSNbjQPBSwzdSCXEgylrMNVIpcSDaYnVvJPWhA9OAZuO87HEg6mreIdIWE3Eg+nZHhEhm4sAh+0EBkUzFgcM2zDwimYsDh+4oOkQyGQcO33LdEclsHEiyJ70SyXScpBAJX3vNRif01yxSJ7SMH1USEREREREREREV7Ad//SBSU+GIIAAAAABJRU5ErkJggg==";
4
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAYAAABV7bNHAAAACXBIWXMAACE4AAAhOAFFljFgAAAA+0lEQVR4nO3a3QnCQBBF4ZRiSXZgKVqKnVnCQBpQwb0QJA752ZjszPlg3/JwOU8b2K4DAAAAAAAAkIOZnczsvPeOQypxHmb27Pv+sveeQxnG0SFSMRaHSIUXJ32kKXHKue+99e+I4yCOgzgO4jiI4yCOgzgO4jiajfMedd366t50nK3/b0LE2SpSqDi1I4WMUytSs3G6z/jbhOGLIzUdR7aKFCKO1I4UKo7UihQyjqyNFDqOLI2UIo7MjZQqjkyNVL7LFUdmRMoXRypEihtHVkSKH0cWRMoTR2ZEyhdHJkTKG0ecSMSRkUjE+TaIRJxfeFQJAAAAAAAANOwFT0Mt2UgcaMoAAAAASUVORK5CYII=";
@@ -4,11 +4,9 @@ import { Item, ItemProps } from "./Item";
4
4
  import { ItemIcon, ItemIconProps } from "./ItemIcon";
5
5
  import { ItemLabel, ItemLabelProps } from "./ItemLabel";
6
6
  import { defaultSelectedAsset } from "./assets";
7
- import * as assets from "./assets";
8
7
 
9
8
  type ButtonProps = {
10
9
  configuration: any;
11
- width: number;
12
10
  selectedItem?: any;
13
11
  item: any; // Adjust type as needed
14
12
  onPress: (item: any) => void; // Adjust type as needed
@@ -17,6 +15,9 @@ type ButtonProps = {
17
15
  labelBaseProps?: ItemLabelProps;
18
16
  disabled?: boolean;
19
17
  label?: string | Record<string, string>;
18
+ iconPlacement?: "left" | "right";
19
+ selectedItemIcon?: ItemIconProps["asset"];
20
+ defaultItemIcon?: ItemIconProps["asset"];
20
21
  };
21
22
 
22
23
  const styles = StyleSheet.create({
@@ -31,81 +32,63 @@ export function Button({
31
32
  item,
32
33
  onPress,
33
34
  configuration,
34
- width,
35
35
  iconBaseProps,
36
- itemBaseProps,
36
+ itemBaseProps: itemProps,
37
37
  labelBaseProps,
38
38
  label,
39
+ iconPlacement = "left",
40
+ defaultItemIcon,
41
+ selectedItemIcon,
39
42
  disabled = false,
40
43
  }: ButtonProps) {
41
44
  const [focused, setFocused] = useState(false);
42
45
 
43
- const selected = useMemo(
44
- () => selectedItem && item.value === selectedItem?.value,
45
- [selectedItem, selectedItem]
46
- );
47
-
48
- const itemProps = useMemo<ItemProps>(
49
- () => ({
50
- ...itemBaseProps,
51
- width,
52
- }),
53
- [configuration, width]
54
- );
46
+ const selected = selectedItem && item.value === selectedItem?.value;
55
47
 
56
- const itemIconProps = useMemo<ItemIconProps>(
57
- () => ({
58
- ...iconBaseProps,
59
- asset: configuration[item.asset] ?? assets[item.asset] ?? item.asset,
60
- }),
61
- [configuration, item.asset]
48
+ const itemIconPropsAssets = useMemo<ItemIconProps["asset"]>(
49
+ () => configuration[item.asset] ?? item.asset ?? defaultItemIcon,
50
+ [item.asset, defaultItemIcon]
62
51
  );
63
52
 
64
- const selectedItemIconProps = useMemo<ItemIconProps>(
65
- () => ({
66
- ...iconBaseProps,
67
- asset:
68
- configuration["modal_bottom_sheet_item_selected_icon"] ||
69
- defaultSelectedAsset,
70
- marginRight: 10,
71
- }),
72
- [configuration]
53
+ const selectedItemIconPropsAssets = useMemo<ItemIconProps["asset"]>(
54
+ () => selectedItemIcon || defaultSelectedAsset,
55
+ [selectedItemIcon]
73
56
  );
74
57
 
75
- const itemLabelProps = useMemo<ItemLabelProps>(
76
- () => ({
77
- ...labelBaseProps,
78
- label: label ?? configuration[item?.label] ?? item?.label ?? null,
79
- }),
80
- [configuration, item?.label]
81
- );
58
+ const renderItemIcon =
59
+ itemIconPropsAssets && itemIconPropsAssets.length > 0 ? (
60
+ <ItemIcon {...iconBaseProps} asset={itemIconPropsAssets} />
61
+ ) : null;
82
62
 
83
63
  if (disabled) return null;
84
64
 
85
65
  return (
86
- <View style={{ maxWidth: width }}>
87
- <TouchableOpacity
88
- activeOpacity={1}
89
- onPress={() => onPress(item)}
90
- onPressIn={() => setFocused(true)}
91
- onPressOut={() => setFocused(false)}
92
- >
93
- <Item {...itemProps} focused={focused} selected={selected}>
94
- <View style={styles.label_icon_container}>
95
- {itemIconProps.asset && itemIconProps.asset.length > 0 && (
96
- <ItemIcon {...itemIconProps} />
97
- )}
98
- {itemLabelProps.label && (
99
- <ItemLabel
100
- {...itemLabelProps}
101
- focused={focused}
102
- selected={selected}
103
- />
104
- )}
105
- </View>
106
- {selected && <ItemIcon {...selectedItemIconProps} />}
107
- </Item>
108
- </TouchableOpacity>
109
- </View>
66
+ <TouchableOpacity
67
+ activeOpacity={1}
68
+ onPress={() => onPress(item)}
69
+ onPressIn={() => setFocused(true)}
70
+ onPressOut={() => setFocused(false)}
71
+ >
72
+ <Item {...itemProps} focused={focused} selected={selected}>
73
+ <View style={styles.label_icon_container}>
74
+ {iconPlacement === "left" && renderItemIcon}
75
+
76
+ {label ? (
77
+ <ItemLabel
78
+ {...labelBaseProps}
79
+ label={label ?? null}
80
+ focused={focused}
81
+ selected={selected}
82
+ />
83
+ ) : null}
84
+ </View>
85
+
86
+ {selected ? (
87
+ <ItemIcon {...iconBaseProps} asset={selectedItemIconPropsAssets} />
88
+ ) : (
89
+ iconPlacement === "right" && renderItemIcon
90
+ )}
91
+ </Item>
92
+ </TouchableOpacity>
110
93
  );
111
94
  }
@@ -1,5 +1,5 @@
1
1
  import React, { useMemo } from "react";
2
- import { View, StyleSheet, LayoutChangeEvent } from "react-native";
2
+ import { LayoutChangeEvent, StyleSheet, View } from "react-native";
3
3
  import { Title, TitleProps } from "./Title";
4
4
  import { CloseButton, CloseButtonProps } from "./CloseButton";
5
5
  import { getCloseButtonProps, getTitleProps } from "./utils";
@@ -8,13 +8,18 @@ import { PluginConfiguration } from "../index";
8
8
  type Props = {
9
9
  dismiss: () => void;
10
10
  configuration: PluginConfiguration;
11
- width: number;
12
11
  onLayout?: (event: LayoutChangeEvent) => void;
13
12
  summary?: string;
14
13
  title?: string;
15
14
  };
16
15
 
17
16
  const styles = StyleSheet.create({
17
+ noFlex: {
18
+ flex: 0,
19
+ },
20
+ flex: {
21
+ flex: 1,
22
+ },
18
23
  container: {
19
24
  flexDirection: "row",
20
25
  alignItems: "center",
@@ -22,7 +27,7 @@ const styles = StyleSheet.create({
22
27
  });
23
28
 
24
29
  export function ModalHeader(props: Props) {
25
- const { configuration, dismiss, width, onLayout, summary, title } = props;
30
+ const { configuration, dismiss, onLayout, summary, title } = props;
26
31
 
27
32
  const closeButtonProps = useMemo<CloseButtonProps>(
28
33
  () => ({
@@ -55,15 +60,11 @@ export function ModalHeader(props: Props) {
55
60
 
56
61
  return (
57
62
  <View onLayout={onLayout} style={styles.container}>
58
- <View
59
- style={{
60
- width: width - buttonsContainerWidth,
61
- }}
62
- >
63
- {title && <Title {...titleProps} />}
64
- {summary && <Title {...summaryProps} />}
63
+ <View style={styles.flex}>
64
+ {title ? <Title {...titleProps} /> : null}
65
+ {summary ? <Title {...summaryProps} /> : null}
65
66
  </View>
66
- <View style={{ width: buttonsContainerWidth }}>
67
+ <View style={[styles.noFlex, { width: buttonsContainerWidth }]}>
67
68
  <CloseButton {...closeButtonProps} />
68
69
  </View>
69
70
  </View>