@applicaster/zapp-react-native-ui-components 15.0.0-rc.99 → 15.1.0-rc.2

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 (114) hide show
  1. package/Components/BaseFocusable/index.ios.ts +2 -12
  2. package/Components/Cell/FocusableWrapper.tsx +0 -3
  3. package/Components/Cell/TvOSCellComponent.tsx +0 -5
  4. package/Components/Focusable/Focusable.tsx +2 -4
  5. package/Components/Focusable/FocusableTvOS.tsx +1 -18
  6. package/Components/Focusable/__tests__/__snapshots__/FocusableTvOS.test.tsx.snap +0 -1
  7. package/Components/FocusableGroup/FocusableTvOS.tsx +1 -30
  8. package/Components/GeneralContentScreen/GeneralContentScreen.tsx +39 -28
  9. package/Components/GeneralContentScreen/__tests__/GeneralContentScreen.test.tsx +104 -0
  10. package/Components/GeneralContentScreen/utils/__tests__/getScreenDataSource.test.ts +19 -0
  11. package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +1 -1
  12. package/Components/GeneralContentScreen/utils/getScreenDataSource.ts +9 -0
  13. package/Components/HandlePlayable/HandlePlayable.tsx +24 -42
  14. package/Components/HandlePlayable/utils.ts +31 -0
  15. package/Components/HookRenderer/HookRenderer.tsx +40 -10
  16. package/Components/HookRenderer/__tests__/HookRenderer.test.tsx +60 -0
  17. package/Components/Layout/TV/LayoutBackground.tsx +2 -5
  18. package/Components/Layout/TV/ScreenContainer.tsx +6 -2
  19. package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +5 -0
  20. package/Components/Layout/TV/index.tsx +4 -3
  21. package/Components/Layout/TV/index.web.tsx +4 -3
  22. package/Components/LinkHandler/LinkHandler.tsx +2 -2
  23. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +10 -4
  24. package/Components/MasterCell/DefaultComponents/Image/Image.android.tsx +1 -5
  25. package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +3 -11
  26. package/Components/MasterCell/DefaultComponents/Image/Image.web.tsx +1 -9
  27. package/Components/MasterCell/DefaultComponents/Image/hooks/useImage.ts +14 -15
  28. package/Components/MasterCell/DefaultComponents/LiveImage/__tests__/prepareEntry.test.ts +352 -0
  29. package/Components/MasterCell/DefaultComponents/LiveImage/executePreloadHooks.ts +136 -0
  30. package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +34 -16
  31. package/Components/MasterCell/DefaultComponents/SecondaryImage/hooks/__tests__/useGetImageDimensions.test.ts +6 -7
  32. package/Components/MasterCell/DefaultComponents/Text/index.tsx +2 -6
  33. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/index.ts +2 -6
  34. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/__tests__/getPluginIdentifier.test.ts +11 -233
  35. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/index.ts +15 -19
  36. package/Components/Navigator/StackNavigator.tsx +6 -0
  37. package/Components/OfflineHandler/NotificationView/NotificationView.tsx +2 -2
  38. package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +18 -17
  39. package/Components/OfflineHandler/__tests__/index.test.tsx +18 -27
  40. package/Components/PlayerContainer/PlayerContainer.tsx +14 -32
  41. package/Components/PreloaderWrapper/__tests__/index.test.tsx +26 -0
  42. package/Components/PreloaderWrapper/index.tsx +15 -0
  43. package/Components/River/ComponentsMap/ComponentsMap.tsx +3 -4
  44. package/Components/River/ComponentsMap/hooks/__tests__/useLoadingState.test.ts +1 -1
  45. package/Components/River/RefreshControl.tsx +9 -3
  46. package/Components/River/RiverItem.tsx +26 -20
  47. package/Components/River/TV/River.tsx +14 -31
  48. package/Components/River/TV/index.tsx +4 -8
  49. package/Components/River/TV/withTVEventHandler.tsx +36 -0
  50. package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +0 -1
  51. package/Components/River/__tests__/componentsMap.test.js +0 -38
  52. package/Components/Screen/TV/index.web.tsx +2 -4
  53. package/Components/Screen/__tests__/Screen.test.tsx +43 -65
  54. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +44 -68
  55. package/Components/Screen/hooks.ts +76 -5
  56. package/Components/Screen/index.tsx +10 -3
  57. package/Components/Screen/orientationHandler.ts +3 -3
  58. package/Components/ScreenFeedLoader/ScreenFeedLoader.tsx +46 -0
  59. package/Components/ScreenFeedLoader/__tests__/ScreenFeedLoader.test.tsx +94 -0
  60. package/Components/ScreenFeedLoader/index.ts +1 -0
  61. package/Components/ScreenResolver/__tests__/screenResolver.test.js +24 -0
  62. package/Components/ScreenResolver/hooks/index.ts +3 -0
  63. package/Components/ScreenResolver/hooks/useGetComponent.ts +15 -0
  64. package/Components/ScreenResolver/hooks/useScreenComponentResolver.tsx +90 -0
  65. package/Components/ScreenResolver/index.tsx +9 -115
  66. package/Components/ScreenResolver/utils/__tests__/getScreenTypeProps.test.ts +45 -0
  67. package/Components/ScreenResolver/utils/getScreenTypeProps.ts +43 -0
  68. package/Components/ScreenResolver/utils/index.ts +1 -0
  69. package/Components/ScreenResolver/withDefaultScreenContext.tsx +16 -0
  70. package/Components/ScreenResolverFeedProvider/ScreenResolverFeedProvider.tsx +25 -0
  71. package/Components/ScreenResolverFeedProvider/__tests__/ScreenResolverFeedProvider.test.tsx +44 -0
  72. package/Components/ScreenResolverFeedProvider/index.ts +1 -0
  73. package/Components/ScreenRevealManager/ScreenRevealManager.ts +8 -40
  74. package/Components/ScreenRevealManager/__tests__/ScreenRevealManager.test.ts +69 -86
  75. package/Components/ScreenRevealManager/withScreenRevealManager.tsx +4 -1
  76. package/Components/Tabs/TabContent.tsx +4 -7
  77. package/Components/Transitioner/Scene.tsx +9 -15
  78. package/Components/Transitioner/index.js +3 -3
  79. package/Components/VideoLive/LiveImageManager.ts +199 -54
  80. package/Components/VideoLive/PlayerLiveImageComponent.tsx +31 -33
  81. package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +2 -17
  82. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +5 -5
  83. package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +7 -15
  84. package/Components/VideoModal/utils.ts +9 -12
  85. package/Components/Viewport/ViewportEvents/__tests__/viewportEvents.test.js +1 -1
  86. package/Components/ZappFrameworkComponents/BarView/BarView.tsx +6 -4
  87. package/Components/ZappFrameworkComponents/BarView/__tests__/BarView.test.tsx +2 -2
  88. package/Components/ZappUIComponent/index.tsx +12 -6
  89. package/Components/index.js +1 -1
  90. package/Contexts/ScreenContext/__tests__/index.test.tsx +57 -0
  91. package/Contexts/ScreenContext/index.tsx +64 -26
  92. package/Contexts/ScreenTrackedViewPositionsContext/__tests__/index.test.tsx +1 -1
  93. package/Contexts/ZappPipesContext/ZappPipesContextFactory.tsx +18 -7
  94. package/Decorators/Analytics/index.tsx +5 -6
  95. package/Decorators/ConfigurationWrapper/__tests__/__snapshots__/withConfigurationProvider.test.tsx.snap +0 -1
  96. package/Decorators/ConfigurationWrapper/const.ts +0 -1
  97. package/Decorators/ZappPipesDataConnector/ResolverSelector.tsx +25 -7
  98. package/Decorators/ZappPipesDataConnector/__tests__/ResolverSelector.test.tsx +212 -5
  99. package/Decorators/ZappPipesDataConnector/__tests__/zappPipesDataConnector.test.js +1 -1
  100. package/Decorators/ZappPipesDataConnector/index.tsx +2 -2
  101. package/Decorators/ZappPipesDataConnector/resolvers/StaticFeedResolver.tsx +1 -1
  102. package/Helpers/DataSourceHelper/index.js +19 -0
  103. package/package.json +5 -5
  104. package/Components/MasterCell/DefaultComponents/Text/utils/__tests__/withAdjustedLineHeight.test.ts +0 -46
  105. package/Components/MasterCell/DefaultComponents/Text/utils/index.ts +0 -21
  106. package/Components/PlayerContainer/ErrorDisplay/ErrorDisplay.tsx +0 -57
  107. package/Components/PlayerContainer/ErrorDisplay/index.ts +0 -9
  108. package/Components/PlayerContainer/useRestrictMobilePlayback.tsx +0 -101
  109. package/Components/River/TV/utils/__tests__/toStringOrEmpty.test.ts +0 -30
  110. package/Components/River/TV/utils/index.ts +0 -4
  111. package/Components/River/TV/withFocusableGroupForContent.tsx +0 -71
  112. package/Helpers/DataSourceHelper/__tests__/itemLimitForData.test.ts +0 -80
  113. package/Helpers/DataSourceHelper/index.ts +0 -19
  114. /package/Components/HookRenderer/{index.tsx → index.ts} +0 -0
@@ -1,35 +1,32 @@
1
1
  import { mergeRight } from "ramda";
2
2
  import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
3
- import {
4
- useAppSelector,
5
- useContentTypes,
6
- } from "@applicaster/zapp-react-native-redux/hooks";
3
+ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
7
4
  import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useNavigation";
8
5
  import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks/device/useIsTablet";
9
6
  import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
10
7
  import { create } from "zustand";
11
- import { useRivers } from "@applicaster/zapp-react-native-utils/reactHooks";
12
- import { selectPluginConfigurationsByPluginId } from "@applicaster/zapp-react-native-redux";
13
8
 
14
9
  export const useConfiguration = () => {
15
10
  const {
16
11
  videoModalState: { item },
17
12
  } = useNavigation();
18
13
 
19
- const rivers = useRivers();
20
- const contentTypes = useContentTypes();
14
+ const { rivers, contentTypes, pluginConfigurations } = usePickFromState([
15
+ "rivers",
16
+ "contentTypes",
17
+ "pluginConfigurations",
18
+ ]);
21
19
 
22
20
  const targetScreenId = contentTypes?.[item?.type?.value]?.screen_id;
23
21
  const targetScreenConfiguration = rivers?.[targetScreenId];
24
22
 
25
- const { configuration_json } = useAppSelector((state) =>
26
- selectPluginConfigurationsByPluginId(state, targetScreenConfiguration?.type)
27
- );
23
+ const pluginConfiguration =
24
+ pluginConfigurations[targetScreenConfiguration?.type]?.configuration_json;
28
25
 
29
26
  const playerPluginConfig = playerManager.getPluginConfiguration();
30
27
 
31
28
  const config = mergeRight(playerPluginConfig, {
32
- ...configuration_json,
29
+ ...pluginConfiguration,
33
30
  ...targetScreenConfiguration?.general,
34
31
  ...targetScreenConfiguration?.styles,
35
32
  });
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import { renderHook } from "@testing-library/react-native";
2
+ import { renderHook } from "@testing-library/react-hooks";
3
3
  import {
4
4
  ViewportEvents,
5
5
  useViewportEventsContext,
@@ -1,5 +1,6 @@
1
1
  import React from "react";
2
- import { StyleSheet, View } from "react-native";
2
+ import { StyleSheet } from "react-native";
3
+ import { SafeAreaView } from "react-native-safe-area-context";
3
4
 
4
5
  import { useIsRTL } from "@applicaster/zapp-react-native-utils/localizationUtils";
5
6
  import CloseButton from "./Buttons/CloseButton";
@@ -44,14 +45,15 @@ const BarView = ({ screenStyles, barState = defaultState }: Props) => {
44
45
  );
45
46
 
46
47
  return (
47
- <View
48
+ <SafeAreaView
49
+ edges={["top", "left", "right"]}
48
50
  style={[style.view, isRTL ? style.rtlStyle : {}]}
49
- testID="BarView-Container"
51
+ testID="BarView-safeAreaView"
50
52
  >
51
53
  {backButton}
52
54
  <BarTitle title={barState.title} screenStyles={screenStyles} />
53
55
  {closeButton}
54
- </View>
56
+ </SafeAreaView>
55
57
  );
56
58
  };
57
59
 
@@ -46,7 +46,7 @@ describe("BarView", () => {
46
46
  <BarView screenStyles={screenStyles} barState={barState} />
47
47
  );
48
48
 
49
- expect(getByTestId("BarView-Container").props.style).toContainEqual({
49
+ expect(getByTestId("BarView-safeAreaView").props.style).toContainEqual({
50
50
  transform: [{ scaleX: -1 }],
51
51
  });
52
52
  });
@@ -58,7 +58,7 @@ describe("BarView", () => {
58
58
  <BarView screenStyles={screenStyles} barState={barState} />
59
59
  );
60
60
 
61
- expect(getByTestId("BarView-Container").props.style).not.toContainEqual({
61
+ expect(getByTestId("BarView-safeAreaView").props.style).not.toContainEqual({
62
62
  transform: [{ scaleX: -1 }],
63
63
  });
64
64
  });
@@ -144,12 +144,23 @@ New signature: {Component, ErrorComponent, LoadingComponent, options}`
144
144
  [props, parent]
145
145
  );
146
146
 
147
+ const hasError = !!zappPipesData?.error;
148
+
147
149
  React.useEffect(() => {
148
150
  if (!skipOnLoadFinished && !isLoading) {
149
151
  onLoadFinished();
150
152
  }
151
153
  }, [isLoading]);
152
154
 
155
+ React.useEffect(() => {
156
+ if (hasError) {
157
+ onLoadFailed?.({
158
+ error: zappPipesData.error,
159
+ index: componentIndex,
160
+ });
161
+ }
162
+ }, [hasError, componentIndex, onLoadFailed, zappPipesData?.error]);
163
+
153
164
  if (isDataSourceEmpty(props) && allowsEmptyDataSource) {
154
165
  return RenderComponent(Component, componentProps);
155
166
  }
@@ -158,12 +169,7 @@ New signature: {Component, ErrorComponent, LoadingComponent, options}`
158
169
  return RenderComponent(LoadingComponent || Placeholder, componentProps);
159
170
  }
160
171
 
161
- if (zappPipesData?.error) {
162
- onLoadFailed?.({
163
- error: zappPipesData.error,
164
- index: componentIndex,
165
- });
166
-
172
+ if (hasError) {
167
173
  return RenderComponent(ErrorComponent, componentProps);
168
174
  }
169
175
 
@@ -10,7 +10,7 @@ export { ContentScreen } from "./ContentScreen";
10
10
 
11
11
  export { TextInputTv } from "./TextInputTv";
12
12
 
13
- export { HookRenderer } from "./HookRenderer";
13
+ export { HookRenderer } from "./HookRenderer/HookRenderer";
14
14
 
15
15
  export { Touchable } from "./Touchable";
16
16
 
@@ -2,6 +2,32 @@ import { render } from "@testing-library/react-native";
2
2
  import { ScreenContext, ScreenContextProvider, withScreenContext } from "../";
3
3
  import React from "react";
4
4
 
5
+ jest.mock("@applicaster/zapp-react-native-utils/reactHooks", () => ({
6
+ useCurrentScreenData: jest.fn(() => ({})),
7
+ useNavigation: jest.fn(() => ({
8
+ data: {},
9
+ modalData: null,
10
+ videoModalState: {},
11
+ canGoBack: jest.fn(() => false),
12
+ })),
13
+ useRoute: jest.fn(() => ({ screenData: null })),
14
+ isNavBarVisible: jest.fn(() => true),
15
+ }));
16
+
17
+ jest.mock(
18
+ "@applicaster/zapp-react-native-ui-components/Contexts/ModalNavigationContext",
19
+ () => ({
20
+ useModalNavigationContext: jest.fn(() => false),
21
+ })
22
+ );
23
+
24
+ jest.mock(
25
+ "@applicaster/zapp-react-native-ui-components/Contexts/NestedNavigationContext",
26
+ () => ({
27
+ useNestedNavigationContext: jest.fn(() => false),
28
+ })
29
+ );
30
+
5
31
  describe("ScreenContext", () => {
6
32
  describe("ScreneContext context", () => {
7
33
  it("should return the context", () => {
@@ -13,6 +39,37 @@ describe("ScreenContext", () => {
13
39
  it("should return the provider", () => {
14
40
  expect(ScreenContextProvider).toBeDefined();
15
41
  });
42
+
43
+ it("recreates _feedStore when pathname changes", () => {
44
+ const contexts = [];
45
+
46
+ const CaptureContext = () => {
47
+ const context = React.useContext(ScreenContext);
48
+ contexts.push(context);
49
+
50
+ return null;
51
+ };
52
+
53
+ const { rerender } = render(
54
+ <ScreenContextProvider pathname="/screen-a">
55
+ <CaptureContext />
56
+ </ScreenContextProvider>
57
+ );
58
+
59
+ const first = contexts[contexts.length - 1];
60
+ first._feedStore.setState({ screenFeed: "screen-a" });
61
+
62
+ rerender(
63
+ <ScreenContextProvider pathname="/screen-b">
64
+ <CaptureContext />
65
+ </ScreenContextProvider>
66
+ );
67
+
68
+ const second = contexts[contexts.length - 1];
69
+
70
+ expect(second._feedStore).not.toBe(first._feedStore);
71
+ expect(second._feedStore.getState()).toEqual({});
72
+ });
16
73
  });
17
74
 
18
75
  describe("withScreenContext", () => {
@@ -16,7 +16,6 @@ import { useNestedNavigationContext } from "@applicaster/zapp-react-native-ui-co
16
16
  import { create } from "zustand";
17
17
  import { subscribeWithSelector } from "zustand/middleware";
18
18
  import { useShallow } from "zustand/react/shallow";
19
-
20
19
  import { Animated } from "react-native";
21
20
 
22
21
  interface NavBarStoreState {
@@ -30,8 +29,6 @@ interface NavBarStoreState {
30
29
  scrollState: number;
31
30
  contentPosition: string;
32
31
  scrollYAnimated: Animated.Value;
33
- hideOnScrollAnimated: Animated.Value;
34
- hideOnScroll: boolean;
35
32
  }
36
33
 
37
34
  interface NavBarState {
@@ -65,39 +62,58 @@ const createStateStore = () =>
65
62
  );
66
63
 
67
64
  const createStore = () =>
68
- create(
69
- subscribeWithSelector<NavBarStoreState>((set) => ({
70
- title: "",
71
- summary: "",
72
- visible: true,
73
- height: 0,
74
- scrollState: 0,
75
- contentPosition: "",
76
- scrollYAnimated: new Animated.Value(0),
77
- hideOnScrollAnimated: new Animated.Value(0),
78
- hideOnScroll: false,
79
- setTitle(title) {
80
- set({ title });
81
- },
82
- setSummary(summary) {
83
- set({ summary });
84
- },
85
- setVisible(visible) {
86
- set({ visible });
87
- },
88
- }))
89
- );
65
+ create<NavBarStoreState>((set) => ({
66
+ title: "",
67
+ summary: "",
68
+ visible: true,
69
+ height: 0,
70
+ scrollState: 0,
71
+ contentPosition: "",
72
+ scrollYAnimated: new Animated.Value(0),
73
+ setTitle(title) {
74
+ set({ title });
75
+ },
76
+ setSummary(summary) {
77
+ set({ summary });
78
+ },
79
+ setVisible(visible) {
80
+ set({ visible });
81
+ },
82
+ }));
83
+
84
+ const createScreenComponentsStore = () =>
85
+ create(subscribeWithSelector<Record<string, unknown>>((_) => ({})));
86
+
87
+ const createFeedStore = () =>
88
+ create(subscribeWithSelector<Record<string, unknown>>((_) => ({})));
90
89
 
91
90
  type ScreenContextType = {
92
91
  _navBarStore: ReturnType<typeof createStore>;
93
92
  _stateStore: ReturnType<typeof createStateStore>;
93
+ _feedStore: ReturnType<typeof createFeedStore>;
94
94
  navBar: NavBarState;
95
95
  legacyFormatScreenData: LegacyNavigationScreenData | null;
96
+ /**
97
+ * Zustand store for component-level state within a screen.
98
+ *
99
+ * **Purpose:** Persists state across component mount/unmount cycles (e.g., during virtualization)
100
+ * and enables state sharing between components using the same key within the same screen.
101
+ *
102
+ * **Lifecycle:** Tied to the screen/route — recreated on each route change.
103
+ *
104
+ * @example
105
+ * // Used by useComponentScreenState hook:
106
+ * const store = useScreenContextV2()._componentStateStore;
107
+ * store.setState({ 'my-key': value });
108
+ * const value = store.getState()['my-key'];
109
+ */
110
+ _componentStateStore: ReturnType<typeof createScreenComponentsStore>;
96
111
  };
97
112
 
98
113
  export const ScreenContext = createContext<ScreenContextType>({
99
114
  _stateStore: createStateStore(),
100
115
  _navBarStore: createStore(),
116
+ _feedStore: createFeedStore(),
101
117
  navBar: {
102
118
  visible: true,
103
119
  title: "",
@@ -107,6 +123,7 @@ export const ScreenContext = createContext<ScreenContextType>({
107
123
  setSummary: (_subtitle) => void 0,
108
124
  },
109
125
  legacyFormatScreenData: {} as LegacyNavigationScreenData,
126
+ _componentStateStore: createScreenComponentsStore(),
110
127
  });
111
128
 
112
129
  export function ScreenContextProvider({
@@ -138,6 +155,10 @@ export function ScreenContextProvider({
138
155
  null
139
156
  );
140
157
 
158
+ const screenFeedStoreRef = useRef<null | ReturnType<typeof createFeedStore>>(
159
+ null
160
+ );
161
+
141
162
  const getScreenState = useCallback(() => {
142
163
  if (screenStateRef.current !== null) {
143
164
  return screenStateRef.current;
@@ -160,6 +181,21 @@ export function ScreenContextProvider({
160
181
  return navBarState;
161
182
  }, []);
162
183
 
184
+ // Assign feed store to ref to persist it across re-renders, but recreate on pathname change
185
+ const screenFeedStore = useMemo(() => createFeedStore(), [pathname]);
186
+
187
+ if (screenFeedStoreRef.current !== screenFeedStore) {
188
+ screenFeedStoreRef.current = screenFeedStore;
189
+ }
190
+
191
+ // Component state store - recreated when pathname changes (route change).
192
+ // Unlike _navBarStore and _stateStore (cached via refs), this store
193
+ // resets only when pathname changes to provide a clean state for the new route.
194
+ const componentStateStore = useMemo(
195
+ () => createScreenComponentsStore(),
196
+ [pathname]
197
+ );
198
+
163
199
  const screenNavBarState = getScreenNavBarState()(
164
200
  useShallow((state) => ({
165
201
  visible: state.visible,
@@ -210,10 +246,12 @@ export function ScreenContextProvider({
210
246
  () => ({
211
247
  _navBarStore: getScreenNavBarState(),
212
248
  _stateStore: getScreenState(),
249
+ _feedStore: screenFeedStoreRef.current,
213
250
  navBar: navBarState,
214
251
  legacyFormatScreenData: routeScreenData,
252
+ _componentStateStore: componentStateStore,
215
253
  }),
216
- [navBarState, screenData, routeScreenData]
254
+ [navBarState, screenData, routeScreenData, componentStateStore]
217
255
  )}
218
256
  >
219
257
  {children}
@@ -1,4 +1,4 @@
1
- import { renderHook } from "@testing-library/react-native";
1
+ import { renderHook } from "@testing-library/react-hooks";
2
2
  import {
3
3
  useScreenTrackedViewPositionsContext,
4
4
  ScreenTrackedViewPositionsContext,
@@ -5,10 +5,10 @@ import React, {
5
5
  useMemo,
6
6
  useState,
7
7
  } from "react";
8
- import * as R from "ramda";
9
8
 
10
- type ProviderProps = {
9
+ type ProviderProps<S> = {
11
10
  children: React.ReactChild;
11
+ initialContextValue?: S;
12
12
  };
13
13
 
14
14
  type ContextType<T> = {
@@ -27,21 +27,29 @@ export function createZappPipesContext<T, S = T>(
27
27
  ) {
28
28
  const Context = createContext<ContextType<S>>(initialContext);
29
29
 
30
- const { selector = R.identity, prepareContext = R.identity } = options || {};
30
+ const defaultSelector = (c: any) => c;
31
+ const defaultPrepareContext = (n: any) => n;
32
+ const joinArgs = (args: any[]) => args.join("-");
33
+
34
+ const { selector = defaultSelector, prepareContext = defaultPrepareContext } =
35
+ options || {};
31
36
 
32
37
  function useZappPipesContext(...hookArgs: any[]): [T, (T) => void] {
33
38
  const { context, setContext } = useContext(Context);
39
+ const joinedArgs = joinArgs(hookArgs);
34
40
 
35
41
  const contextValue = useMemo(
36
42
  () => selector(context, ...hookArgs),
37
- [context, R.join("-", hookArgs)]
43
+ // eslint-disable-next-line @wogns3623/better-exhaustive-deps/exhaustive-deps
44
+ [context, joinedArgs]
38
45
  );
39
46
 
40
47
  const contextSetter = useCallback(
41
48
  (newContext: T) => {
42
49
  setContext(prepareContext(newContext, context, ...hookArgs));
43
50
  },
44
- [context, setContext, R.join("-", hookArgs)]
51
+ // eslint-disable-next-line @wogns3623/better-exhaustive-deps/exhaustive-deps
52
+ [context, joinedArgs]
45
53
  );
46
54
 
47
55
  return useMemo(
@@ -50,8 +58,11 @@ export function createZappPipesContext<T, S = T>(
50
58
  );
51
59
  }
52
60
 
53
- function Provider({ children }: ProviderProps) {
54
- const [context, setContext] = useState<S>(initialContext.context);
61
+ /** Provider accepts `initialContextValue` prop to set the initial context value */
62
+ function Provider({ children, initialContextValue }: ProviderProps<S>) {
63
+ const [context, setContext] = useState<S>(
64
+ initialContextValue ?? initialContext.context
65
+ );
55
66
 
56
67
  return (
57
68
  <Context.Provider value={{ context, setContext }}>
@@ -1,6 +1,7 @@
1
1
  import React from "react";
2
2
 
3
3
  import { getAnalyticsFunctions } from "@applicaster/zapp-react-native-utils/analyticsUtils";
4
+ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
4
5
 
5
6
  type ComponentProps = {
6
7
  component: {
@@ -20,13 +21,11 @@ type ComponentProps = {
20
21
 
21
22
  function withAnalytics(Component) {
22
23
  return function WithAnalytics(props: ComponentProps) {
24
+ const { appData } = usePickFromState(["appData"]);
25
+
23
26
  const analyticsFunctions = React.useMemo(
24
- () =>
25
- getAnalyticsFunctions({
26
- component: props.component,
27
- zappPipesData: props.zappPipesData,
28
- } as any),
29
- [props.component, props.zappPipesData]
27
+ () => getAnalyticsFunctions({ props, appData }),
28
+ [props, appData]
30
29
  );
31
30
 
32
31
  return (
@@ -88,7 +88,6 @@ exports[`withConfigurationProvider correctly passes all the configuration keys c
88
88
  tab_cell_padding_right={10}
89
89
  tab_cell_padding_top={14}
90
90
  tablet_theme={false}
91
- tabs_screen_background_color="transparent"
92
91
  target={false}
93
92
  target_screen_switch={false}
94
93
  text_label_active_font_color="rgba(239, 239, 239, 0.5)"
@@ -208,5 +208,4 @@ export const keysMap: Record<string, Function> = {
208
208
  tab_bar_item_margin_right: castOrDefaultValue(Number, 0),
209
209
  tab_bar_item_margin_bottom: castOrDefaultValue(Number, 0),
210
210
  tab_bar_item_margin_left: castOrDefaultValue(Number, 0),
211
- tabs_screen_background_color: castOrDefaultValue(R.identity, "transparent"),
212
211
  };
@@ -1,4 +1,3 @@
1
- // ResolverSelector.tsx
2
1
  import React from "react";
3
2
  import { ComponentDataSourceContext, ZappPipesDataProps } from "./types";
4
3
  import { StaticFeedResolver } from "./resolvers/StaticFeedResolver";
@@ -12,14 +11,33 @@ type ResolverSelectorProps = ComponentDataSourceContext & {
12
11
  export function ResolverSelector(props: ResolverSelectorProps) {
13
12
  const { getStaticComponentFeed, component, feedUrl, children } = props;
14
13
 
15
- // Determine which resolver to use
14
+ const renderDefaultResolver = (
15
+ fallbackChildren: (dataProps: ZappPipesDataProps) => React.ReactNode
16
+ ) => {
17
+ if (feedUrl || component?.data?.source) {
18
+ return <UrlFeedResolver {...props}>{fallbackChildren}</UrlFeedResolver>;
19
+ }
20
+
21
+ return <NullFeedResolver>{fallbackChildren}</NullFeedResolver>;
22
+ };
23
+
16
24
  if (getStaticComponentFeed) {
17
- return <StaticFeedResolver {...props}>{children}</StaticFeedResolver>;
18
- }
25
+ return (
26
+ <StaticFeedResolver {...props}>
27
+ {(zappPipesDataProps) => {
28
+ const { data, loading, error } = zappPipesDataProps.zappPipesData;
29
+
30
+ const shouldFallback = !loading && data === null && !error;
31
+
32
+ if (shouldFallback) {
33
+ return renderDefaultResolver(children);
34
+ }
19
35
 
20
- if (feedUrl || component?.data?.source) {
21
- return <UrlFeedResolver {...props}>{children}</UrlFeedResolver>;
36
+ return children(zappPipesDataProps);
37
+ }}
38
+ </StaticFeedResolver>
39
+ );
22
40
  }
23
41
 
24
- return <NullFeedResolver>{children}</NullFeedResolver>;
42
+ return renderDefaultResolver(children);
25
43
  }