@applicaster/zapp-react-native-utils 15.0.0-rc.5 → 15.0.0-rc.52

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 (64) hide show
  1. package/actionsExecutor/ActionExecutorContext.tsx +3 -6
  2. package/actionsExecutor/feedDecorator.ts +6 -6
  3. package/adsUtils/index.ts +2 -2
  4. package/analyticsUtils/AnalyticPlayerListener.ts +5 -2
  5. package/analyticsUtils/README.md +1 -1
  6. package/appUtils/HooksManager/index.ts +10 -10
  7. package/appUtils/accessibilityManager/const.ts +4 -0
  8. package/appUtils/accessibilityManager/hooks.ts +20 -13
  9. package/appUtils/accessibilityManager/index.ts +28 -1
  10. package/appUtils/accessibilityManager/utils.ts +36 -5
  11. package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +1 -0
  12. package/appUtils/focusManager/index.ios.ts +18 -1
  13. package/appUtils/focusManagerAux/utils/index.ts +18 -0
  14. package/appUtils/focusManagerAux/utils/utils.ios.ts +35 -0
  15. package/appUtils/keyCodes/keys/keys.web.ts +1 -4
  16. package/appUtils/orientationHelper.ts +2 -4
  17. package/appUtils/platform/platformUtils.ts +117 -18
  18. package/appUtils/playerManager/OverlayObserver/OverlaysObserver.ts +94 -4
  19. package/appUtils/playerManager/OverlayObserver/utils.ts +32 -20
  20. package/appUtils/playerManager/conts.ts +21 -0
  21. package/appUtils/playerManager/player.ts +4 -0
  22. package/appUtils/playerManager/playerNative.ts +29 -16
  23. package/appUtils/playerManager/usePlayerState.tsx +14 -2
  24. package/arrayUtils/__tests__/allTruthy.test.ts +24 -0
  25. package/arrayUtils/__tests__/anyThruthy.test.ts +24 -0
  26. package/arrayUtils/index.ts +5 -0
  27. package/cellUtils/index.ts +32 -0
  28. package/configurationUtils/__tests__/manifestKeyParser.test.ts +26 -26
  29. package/manifestUtils/defaultManifestConfigurations/player.js +75 -1
  30. package/manifestUtils/keys.js +21 -0
  31. package/manifestUtils/sharedConfiguration/screenPicker/utils.js +1 -0
  32. package/manifestUtils/tvAction/container/index.js +1 -1
  33. package/navigationUtils/index.ts +19 -16
  34. package/package.json +2 -2
  35. package/playerUtils/usePlayerTTS.ts +8 -3
  36. package/pluginUtils/index.ts +4 -0
  37. package/reactHooks/advertising/index.ts +2 -2
  38. package/reactHooks/debugging/__tests__/index.test.js +4 -4
  39. package/reactHooks/device/useMemoizedIsTablet.ts +3 -3
  40. package/reactHooks/feed/__tests__/useEntryScreenId.test.tsx +3 -0
  41. package/reactHooks/feed/useBatchLoading.ts +7 -1
  42. package/reactHooks/feed/useEntryScreenId.ts +2 -2
  43. package/reactHooks/feed/usePipesCacheReset.ts +3 -1
  44. package/reactHooks/flatList/useLoadNextPageIfNeeded.ts +13 -16
  45. package/reactHooks/layout/index.ts +1 -1
  46. package/reactHooks/layout/useDimensions/__tests__/{useDimensions.test.ts → useDimensions.test.tsx} +105 -25
  47. package/reactHooks/layout/useDimensions/useDimensions.ts +2 -2
  48. package/reactHooks/navigation/index.ts +7 -6
  49. package/reactHooks/navigation/useRoute.ts +8 -6
  50. package/reactHooks/player/TVSeekControlller/TVSeekController.ts +27 -10
  51. package/reactHooks/resolvers/useCellResolver.ts +6 -2
  52. package/reactHooks/resolvers/useComponentResolver.ts +8 -2
  53. package/reactHooks/screen/__tests__/useTargetScreenData.test.tsx +10 -2
  54. package/reactHooks/screen/useTargetScreenData.ts +4 -2
  55. package/reactHooks/state/useRivers.ts +1 -1
  56. package/reactHooks/usePluginConfiguration.ts +2 -2
  57. package/testUtils/index.tsx +29 -20
  58. package/utils/__tests__/mapAccum.test.ts +73 -0
  59. package/utils/__tests__/selectors.test.ts +124 -0
  60. package/utils/index.ts +10 -0
  61. package/utils/mapAccum.ts +23 -0
  62. package/utils/selectors.ts +46 -0
  63. package/zappFrameworkUtils/HookCallback/callbackNavigationAction.ts +49 -12
  64. package/zappFrameworkUtils/HookCallback/hookCallbackManifestExtensions.config.js +1 -1
@@ -1,10 +1,8 @@
1
1
  import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
2
2
  import React from "react";
3
3
 
4
- type Return = (index: number) => void;
5
-
6
4
  type Predicate = (
7
- entry: ZappUIComponentProps["zappPipesData"]["data"]["entry"],
5
+ entryLength: number,
8
6
  index: number,
9
7
  numberOfColumns: number
10
8
  ) => boolean;
@@ -12,19 +10,15 @@ type Predicate = (
12
10
  type Props = {
13
11
  ifNeeded: Predicate;
14
12
  loadNextData: () => void;
15
- entry: ZappUIComponentProps["zappPipesData"]["data"]["entry"];
13
+ entryLength: number;
16
14
  numberOfColumns?: number;
17
15
  };
18
16
 
19
17
  const handleLoadNextPage =
20
18
  (
21
- ifNeeded: (
22
- entry: ZappEntry[],
23
- index: number,
24
- numberOfColumns?: number
25
- ) => boolean,
19
+ ifNeeded: Predicate,
26
20
  loadNextData: () => void,
27
- entry: ZappEntry[],
21
+ entryLength: number,
28
22
  numberOfColumns
29
23
  ) =>
30
24
  (index: number) => {
@@ -32,7 +26,7 @@ const handleLoadNextPage =
32
26
  * Lazy-Loading, invoke nextLoadData if we reach the end of the List
33
27
  */
34
28
 
35
- if (ifNeeded(entry, index, numberOfColumns)) {
29
+ if (ifNeeded(entryLength, index, numberOfColumns)) {
36
30
  loadNextData();
37
31
  }
38
32
  };
@@ -40,11 +34,14 @@ const handleLoadNextPage =
40
34
  export const useLoadNextPageIfNeeded = ({
41
35
  ifNeeded,
42
36
  loadNextData = noop,
43
- entry,
37
+ entryLength,
44
38
  numberOfColumns = 0,
45
- }: Props): Return => {
46
- return React.useCallback(
47
- handleLoadNextPage(ifNeeded, loadNextData, entry, numberOfColumns),
48
- [ifNeeded, loadNextData, entry, numberOfColumns]
39
+ }: Props) => {
40
+ const memoFn = React.useMemo(
41
+ () =>
42
+ handleLoadNextPage(ifNeeded, loadNextData, entryLength, numberOfColumns),
43
+ [ifNeeded, loadNextData, entryLength, numberOfColumns]
49
44
  );
45
+
46
+ return memoFn;
50
47
  };
@@ -44,7 +44,7 @@ export function useStatusBarHeight() {
44
44
 
45
45
  return platformSelect({
46
46
  ios: StatusBarHeight,
47
- android: StatusBar.currentHeight,
47
+ android: StatusBar.currentHeight ?? 0,
48
48
  default: 0,
49
49
  });
50
50
  }
@@ -1,16 +1,10 @@
1
- import { renderHook } from "@testing-library/react-hooks";
1
+ import React from "react";
2
+ import { renderHook } from "@testing-library/react-native";
2
3
  import { Dimensions, StatusBar } from "react-native";
3
4
  import { useDimensions } from "../useDimensions";
4
- import { usePickFromState } from "@applicaster/zapp-react-native-redux";
5
5
 
6
6
  import { useIsScreenActive } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useIsScreenActive";
7
-
8
- jest.mock("@applicaster/zapp-react-native-redux/hooks", () => {
9
- return {
10
- ...jest.requireActual("@applicaster/zapp-react-native-redux/hooks"),
11
- usePickFromState: jest.fn(),
12
- };
13
- });
7
+ import { WrappedWithProviders } from "@applicaster/zapp-react-native-utils/testUtils";
14
8
 
15
9
  jest.mock(
16
10
  "@applicaster/zapp-react-native-utils/reactHooks/navigation/useIsScreenActive",
@@ -42,12 +36,22 @@ describe("useDimensions", () => {
42
36
 
43
37
  beforeEach(() => {
44
38
  StatusBar.currentHeight = 20;
45
- (usePickFromState as jest.Mock).mockReturnValue({ appData: mockAppData });
46
39
  });
47
40
 
48
41
  it("returns correct initial dimensions", () => {
49
- const { result } = renderHook(() =>
50
- useDimensions("window", { fullDimensions: false })
42
+ const { result } = renderHook(
43
+ () => useDimensions("window", { fullDimensions: false }),
44
+ {
45
+ wrapper: ({ children }) => (
46
+ <WrappedWithProviders
47
+ store={{
48
+ appData: mockAppData,
49
+ }}
50
+ >
51
+ {children}
52
+ </WrappedWithProviders>
53
+ ),
54
+ }
51
55
  );
52
56
 
53
57
  expect(result.current).toMatchObject({
@@ -56,7 +60,17 @@ describe("useDimensions", () => {
56
60
  });
57
61
 
58
62
  it("calls handler on mount", () => {
59
- renderHook(() => useDimensions("window", { fullDimensions: false }));
63
+ renderHook(() => useDimensions("window", { fullDimensions: false }), {
64
+ wrapper: ({ children }) => (
65
+ <WrappedWithProviders
66
+ store={{
67
+ appData: mockAppData,
68
+ }}
69
+ >
70
+ {children}
71
+ </WrappedWithProviders>
72
+ ),
73
+ });
60
74
 
61
75
  expect(Dimensions.addEventListener).toHaveBeenCalledWith(
62
76
  "change",
@@ -65,12 +79,23 @@ describe("useDimensions", () => {
65
79
  });
66
80
 
67
81
  it("calls handler on isActive change", () => {
68
- const { rerender } = renderHook(() =>
69
- useDimensions("window", { fullDimensions: false })
82
+ const { rerender } = renderHook(
83
+ () => useDimensions("window", { fullDimensions: false }),
84
+ {
85
+ wrapper: ({ children }) => (
86
+ <WrappedWithProviders
87
+ store={{
88
+ appData: mockAppData,
89
+ }}
90
+ >
91
+ {children}
92
+ </WrappedWithProviders>
93
+ ),
94
+ }
70
95
  );
71
96
 
72
97
  (useIsScreenActive as jest.Mock).mockReturnValue(false);
73
- rerender();
98
+ rerender({});
74
99
 
75
100
  expect(Dimensions.addEventListener).toHaveBeenCalledWith(
76
101
  "change",
@@ -79,8 +104,19 @@ describe("useDimensions", () => {
79
104
  });
80
105
 
81
106
  it("handles fullDimensions option", () => {
82
- const { result } = renderHook(() =>
83
- useDimensions("window", { fullDimensions: true })
107
+ const { result } = renderHook(
108
+ () => useDimensions("window", { fullDimensions: true }),
109
+ {
110
+ wrapper: ({ children }) => (
111
+ <WrappedWithProviders
112
+ store={{
113
+ appData: mockAppData,
114
+ }}
115
+ >
116
+ {children}
117
+ </WrappedWithProviders>
118
+ ),
119
+ }
84
120
  );
85
121
 
86
122
  expect(result.current).toMatchObject({
@@ -91,8 +127,19 @@ describe("useDimensions", () => {
91
127
  });
92
128
 
93
129
  it("handles excludeStatusBar option", () => {
94
- const { result } = renderHook(() =>
95
- useDimensions("window", { excludeStatusBar: true })
130
+ const { result } = renderHook(
131
+ () => useDimensions("window", { excludeStatusBar: true }),
132
+ {
133
+ wrapper: ({ children }) => (
134
+ <WrappedWithProviders
135
+ store={{
136
+ appData: mockAppData,
137
+ }}
138
+ >
139
+ {children}
140
+ </WrappedWithProviders>
141
+ ),
142
+ }
96
143
  );
97
144
 
98
145
  expect(result.current.height).toBe(
@@ -101,8 +148,19 @@ describe("useDimensions", () => {
101
148
  });
102
149
 
103
150
  it("handles rounded option", () => {
104
- const { result } = renderHook(() =>
105
- useDimensions("window", { rounded: true })
151
+ const { result } = renderHook(
152
+ () => useDimensions("window", { rounded: true }),
153
+ {
154
+ wrapper: ({ children }) => (
155
+ <WrappedWithProviders
156
+ store={{
157
+ appData: mockAppData,
158
+ }}
159
+ >
160
+ {children}
161
+ </WrappedWithProviders>
162
+ ),
163
+ }
106
164
  );
107
165
 
108
166
  expect(result.current.width).toBe(Math.ceil(mockDimensions.width));
@@ -110,8 +168,19 @@ describe("useDimensions", () => {
110
168
  });
111
169
 
112
170
  it("handles deviceInfo option", () => {
113
- const { result } = renderHook(() =>
114
- useDimensions("window", { deviceInfo: true })
171
+ const { result } = renderHook(
172
+ () => useDimensions("window", { deviceInfo: true }),
173
+ {
174
+ wrapper: ({ children }) => (
175
+ <WrappedWithProviders
176
+ store={{
177
+ appData: mockAppData,
178
+ }}
179
+ >
180
+ {children}
181
+ </WrappedWithProviders>
182
+ ),
183
+ }
115
184
  );
116
185
 
117
186
  expect(result.current.deviceInfo).toMatchObject({
@@ -121,7 +190,18 @@ describe("useDimensions", () => {
121
190
 
122
191
  it("logs deprecation warning when fullDimensions is boolean", () => {
123
192
  const consoleWarnSpy = jest.spyOn(console, "warn").mockImplementation();
124
- renderHook(() => useDimensions("window", true));
193
+
194
+ renderHook(() => useDimensions("window", true), {
195
+ wrapper: ({ children }) => (
196
+ <WrappedWithProviders
197
+ store={{
198
+ appData: mockAppData,
199
+ }}
200
+ >
201
+ {children}
202
+ </WrappedWithProviders>
203
+ ),
204
+ });
125
205
 
126
206
  expect(consoleWarnSpy).toHaveBeenCalledWith(
127
207
  "Deprecation Warning\nSecond argument is now the options object. {fullDimensions: boolean, ...}"
@@ -3,7 +3,7 @@ import { useLayoutEffect, useMemo, useRef, useState } from "react";
3
3
  import * as R from "ramda";
4
4
 
5
5
  import { Dimensions, Platform, StatusBar } from "react-native";
6
- import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
6
+ import { useAppData } from "@applicaster/zapp-react-native-redux/hooks";
7
7
 
8
8
  import { isTV } from "../../../reactUtils";
9
9
 
@@ -37,7 +37,7 @@ export const useDimensions: UseDimensions = (
37
37
  ) => {
38
38
  const statusBarHeight = StatusBar?.currentHeight;
39
39
  const isActive = useIsScreenActive();
40
- const { appData } = usePickFromState(["appData"]);
40
+ const appData = useAppData();
41
41
 
42
42
  if (typeof fullDimensions === "boolean") {
43
43
  // eslint-disable-next-line no-console
@@ -3,7 +3,7 @@ import { BackHandler } from "react-native";
3
3
 
4
4
  import {
5
5
  useContentTypes,
6
- usePickFromState,
6
+ usePlugins,
7
7
  } from "@applicaster/zapp-react-native-redux/hooks";
8
8
  import { HooksManager } from "@applicaster/zapp-react-native-utils/appUtils/HooksManager";
9
9
 
@@ -16,6 +16,8 @@ import { useConnectionInfo } from "../connection";
16
16
 
17
17
  import { isTV, isWeb } from "@applicaster/zapp-react-native-utils/reactUtils";
18
18
  import { useNavbarState } from "../screen";
19
+ import { useRivers } from "../state";
20
+ import { useLayoutVersion } from "../layout";
19
21
 
20
22
  export { useNavigation } from "./useNavigation";
21
23
 
@@ -164,11 +166,10 @@ export const useZappHooksForEntry = (
164
166
  setIsRunningInBackground,
165
167
  }: HookModalContextT = useContext(ZappHookModalContext.ReactContext);
166
168
 
167
- const {
168
- appData: { layoutVersion },
169
- rivers,
170
- plugins,
171
- } = usePickFromState(["appData", "rivers", "plugins"]);
169
+ const plugins = usePlugins();
170
+ const rivers = useRivers();
171
+
172
+ const layoutVersion = useLayoutVersion();
172
173
 
173
174
  const contentTypes = useContentTypes();
174
175
 
@@ -3,7 +3,10 @@
3
3
 
4
4
  import { useContext } from "react";
5
5
 
6
- import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
6
+ import {
7
+ useContentTypes,
8
+ usePlugins,
9
+ } from "@applicaster/zapp-react-native-redux/hooks";
7
10
 
8
11
  import { legacyScreenData } from "@applicaster/quick-brick-core/App/NavigationProvider/utils";
9
12
 
@@ -14,6 +17,7 @@ import { useNavigation } from "./useNavigation";
14
17
  import { useModalStoreState } from "../../modalState";
15
18
  import { ScreenDataContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenDataContext";
16
19
  import { usePathname } from "./usePathname";
20
+ import { useRivers } from "../state";
17
21
 
18
22
  // starts with modal/
19
23
  const isModalPathname = (pathname: string) => /^modal\//.test(pathname);
@@ -42,11 +46,9 @@ export const useRoute = (
42
46
  ? legacyScreenData(screenContext)
43
47
  : screenContext;
44
48
 
45
- const { plugins, contentTypes, rivers } = usePickFromState([
46
- "plugins",
47
- "rivers",
48
- "contentTypes",
49
- ]);
49
+ const plugins = usePlugins();
50
+ const rivers = useRivers();
51
+ const contentTypes = useContentTypes();
50
52
 
51
53
  const modalState = useModalStoreState();
52
54
 
@@ -147,17 +147,34 @@ export class TVSeekController
147
147
 
148
148
  let targetPos = currentPos;
149
149
 
150
- if (this.currentSeekType === SEEK_TYPE.FORWARD) {
151
- targetPos = Math.min(
152
- currentPos + offset,
153
- this.playerController.getSeekableDuration()
154
- );
155
- } else if (this.currentSeekType === SEEK_TYPE.REWIND) {
156
- targetPos = Math.max(0, currentPos - offset);
150
+ const isLive = this.playerController.isLive();
151
+
152
+ if (isLive) {
153
+ if (this.currentSeekType === SEEK_TYPE.REWIND) {
154
+ targetPos = Math.min(
155
+ currentPos + offset,
156
+ this.playerController.getSeekableDuration()
157
+ );
158
+ } else if (this.currentSeekType === SEEK_TYPE.FORWARD) {
159
+ targetPos = Math.max(0, currentPos - offset);
160
+ } else {
161
+ log_warning(
162
+ `TVSeekController: handleDelayedSeek - invalid seek type: ${this.currentSeekType}`
163
+ );
164
+ }
157
165
  } else {
158
- log_warning(
159
- `TVSeekController: handleDelayedSeek - invalid seek type: ${this.currentSeekType}`
160
- );
166
+ if (this.currentSeekType === SEEK_TYPE.FORWARD) {
167
+ targetPos = Math.min(
168
+ currentPos + offset,
169
+ this.playerController.getSeekableDuration()
170
+ );
171
+ } else if (this.currentSeekType === SEEK_TYPE.REWIND) {
172
+ targetPos = Math.max(0, currentPos - offset);
173
+ } else {
174
+ log_warning(
175
+ `TVSeekController: handleDelayedSeek - invalid seek type: ${this.currentSeekType}`
176
+ );
177
+ }
161
178
  }
162
179
 
163
180
  log_debug(
@@ -3,7 +3,10 @@ import memoizee from "memoizee";
3
3
  import * as R from "ramda";
4
4
 
5
5
  import { CellRendererResolver } from "@applicaster/zapp-react-native-ui-components/Components/CellRendererResolver";
6
- import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
6
+ import {
7
+ usePlugins,
8
+ useCellStyles,
9
+ } from "@applicaster/zapp-react-native-redux";
7
10
  import { useDimensions } from "../layout";
8
11
  import { useIsRTL } from "../../localizationUtils";
9
12
 
@@ -53,7 +56,8 @@ export function useCellResolver({
53
56
  updateForInactiveScreens: false,
54
57
  });
55
58
 
56
- const { plugins, cellStyles } = usePickFromState(["plugins", "cellStyles"]);
59
+ const plugins = usePlugins();
60
+ const cellStyles = useCellStyles();
57
61
  const isRTL = useIsRTL();
58
62
 
59
63
  const options = {
@@ -2,7 +2,11 @@
2
2
  import * as React from "react";
3
3
 
4
4
  import { findComponentByType } from "@applicaster/zapp-react-native-utils/pluginUtils";
5
- import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
5
+ import {
6
+ usePlugins,
7
+ useAppSelector,
8
+ selectComponents,
9
+ } from "@applicaster/zapp-react-native-redux";
6
10
 
7
11
  type Decorator = (component: React.Component<any>) => React.Component<any>;
8
12
  type Watcher = Array<any>;
@@ -15,7 +19,9 @@ export function useComponentResolver(
15
19
  { componentType, decorators }: Props,
16
20
  watchers?: Watcher
17
21
  ): React.ComponentType<any> {
18
- const { plugins, components } = usePickFromState(["plugins", "components"]);
22
+ const plugins = usePlugins();
23
+
24
+ const components = useAppSelector(selectComponents);
19
25
 
20
26
  return React.useMemo(
21
27
  () =>
@@ -9,8 +9,16 @@ const mockStore = configureStore([thunk]);
9
9
  import { useTargetScreenData } from "../useTargetScreenData";
10
10
 
11
11
  describe("useTargetScreenData", function () {
12
- const river_id_2 = {};
13
- const river_id_1 = {};
12
+ const river_id_2 = {
13
+ id: "river_id_2",
14
+ type: "any",
15
+ };
16
+
17
+ const river_id_1 = {
18
+ id: "river_id_1",
19
+ type: "any",
20
+ };
21
+
14
22
  const screenId = "river_id_2";
15
23
  const entry = { id: "test", type: { value: "video" } };
16
24
 
@@ -1,7 +1,8 @@
1
1
  import React from "react";
2
- import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
2
+ import { useContentTypes } from "@applicaster/zapp-react-native-redux/hooks";
3
3
  import * as R from "ramda";
4
4
  import { appStore } from "@applicaster/zapp-react-native-redux/AppStore";
5
+ import { useRivers } from "../state";
5
6
 
6
7
  export function getTargetScreenData(
7
8
  entry: ZappEntry,
@@ -43,7 +44,8 @@ export function getTargetScreenDataFromEntry(entry: ZappEntry): ZappRiver {
43
44
  }
44
45
 
45
46
  export const useTargetScreenData = (entry: ZappEntry) => {
46
- const { rivers, contentTypes } = usePickFromState(["rivers", "contentTypes"]);
47
+ const rivers = useRivers();
48
+ const contentTypes = useContentTypes();
47
49
 
48
50
  return React.useMemo(
49
51
  () => getTargetScreenData(entry, rivers, contentTypes),
@@ -3,6 +3,6 @@ import {
3
3
  selectRivers,
4
4
  } from "@applicaster/zapp-react-native-redux";
5
5
 
6
- export function useRivers(): Record<string, ZappRiver> {
6
+ export function useRivers() {
7
7
  return useAppSelector(selectRivers);
8
8
  }
@@ -1,7 +1,7 @@
1
1
  import * as R from "ramda";
2
2
  import { useMemo } from "react";
3
3
 
4
- import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
4
+ import { usePlugins } from "@applicaster/zapp-react-native-redux/hooks";
5
5
 
6
6
  // importing this way prevents typescript packages importing from this
7
7
  // file to go crazy reporting errors on JS
@@ -25,7 +25,7 @@ export function parsePluginConfiguration(plugin, manifest) {
25
25
  }
26
26
 
27
27
  export function usePluginConfiguration<T, S>(identifier, manifest) {
28
- const { plugins } = usePickFromState(["plugins"]);
28
+ const plugins = usePlugins();
29
29
 
30
30
  const plugin = useMemo(
31
31
  () => R.find(R.propEq("identifier", identifier), plugins),
@@ -56,9 +56,29 @@ const initialState = {
56
56
  contentTypes: null,
57
57
  };
58
58
 
59
+ const themeObjDefault = {
60
+ component_margin_top: 0,
61
+ component_margin_bottom: 0,
62
+ component_margin_left: 0,
63
+ component_margin_right: 0,
64
+ component_padding_top: 0,
65
+ component_padding_bottom: 0,
66
+ component_padding_left: 0,
67
+ component_padding_right: 0,
68
+ component_gutter_vertical: 0,
69
+ component_gutter_horizontal: 0,
70
+ component_corner_radius: 0,
71
+ app_background_color: "rgba(0,0,0,0)",
72
+ screen_margin_top: 0,
73
+ screen_margin_bottom: 0,
74
+ component_anchor_point_y: 0,
75
+ assets: "",
76
+ };
77
+
59
78
  export const WrappedWithProviders = ({
60
79
  children,
61
80
  store: storeObj = {},
81
+ theme: themeObj = themeObjDefault,
62
82
  }: any) => {
63
83
  const _store = configureStore([thunk])(
64
84
  R.mergeDeepRight(initialState, { ...storeObj })
@@ -70,24 +90,7 @@ export const WrappedWithProviders = ({
70
90
  <ThemeContext.Provider
71
91
  value={{
72
92
  themes: {
73
- light: {
74
- component_margin_top: 0,
75
- component_margin_bottom: 0,
76
- component_margin_left: 0,
77
- component_margin_right: 0,
78
- component_padding_top: 0,
79
- component_padding_bottom: 0,
80
- component_padding_left: 0,
81
- component_padding_right: 0,
82
- component_gutter_vertical: 0,
83
- component_gutter_horizontal: 0,
84
- component_corner_radius: 0,
85
- app_background_color: "rgba(0,0,0,0)",
86
- screen_margin_top: 0,
87
- screen_margin_bottom: 0,
88
- component_anchor_point_y: 0,
89
- assets: "",
90
- },
93
+ light: themeObj,
91
94
  },
92
95
  selectedThemeId: "light",
93
96
  setSelectedThemeId: () => {},
@@ -113,11 +116,17 @@ export const WrappedWithProviders = ({
113
116
  * @param store optional store to pass to the provider
114
117
  * @returns
115
118
  */
116
- export const renderWithProviders = (component, storeObj?: unknown) => {
119
+ export const renderWithProviders = (
120
+ component,
121
+ storeObj?: unknown,
122
+ themeObj?: unknown
123
+ ) => {
117
124
  return render(component, {
118
125
  wrapper: function TestWrapper({ children }: PropsWithChildren<any>) {
119
126
  return (
120
- <WrappedWithProviders store={storeObj}>{children}</WrappedWithProviders>
127
+ <WrappedWithProviders store={storeObj} theme={themeObj}>
128
+ {children}
129
+ </WrappedWithProviders>
121
130
  );
122
131
  },
123
132
  });
@@ -0,0 +1,73 @@
1
+ import { mapAccum } from "../mapAccum";
2
+
3
+ describe("mapAccum", () => {
4
+ it("using standard ramda test", () => {
5
+ const digits = ["1", "2", "3", "4"];
6
+ const appender = (a, b) => [a + b, a + b];
7
+
8
+ const [acc, result] = mapAccum(appender, 0, digits); //= > ['01234', ['01', '012', '0123', '01234']]
9
+ expect(acc).toBe("01234");
10
+ expect(result).toEqual(["01", "012", "0123", "01234"]);
11
+ });
12
+
13
+ it("maps and accumulates over an array", () => {
14
+ const fn = (acc, x) => [acc + x, x * 2];
15
+ const [acc, result] = mapAccum(fn, 0, [1, 2, 3]);
16
+
17
+ expect(acc).toBe(6); // final accumulator (0 + 1 + 2 + 3)
18
+ expect(result).toEqual([2, 4, 6]); // mapped values (acc + x*2 at each step)
19
+ });
20
+
21
+ it("returns initial accumulator for empty array", () => {
22
+ const fn = (acc, x) => [acc + x, acc * x];
23
+ const [acc, result] = mapAccum(fn, 10, []);
24
+
25
+ expect(acc).toBe(10);
26
+ expect(result).toEqual([]);
27
+ });
28
+
29
+ it("accumulates strings correctly", () => {
30
+ const fn = (acc, x) => [acc + x, acc + x];
31
+ const [acc, result] = mapAccum(fn, "A", ["B", "C", "D"]);
32
+
33
+ expect(acc).toBe("ABCD");
34
+ expect(result).toEqual(["AB", "ABC", "ABCD"]);
35
+ });
36
+
37
+ it("works with objects as accumulator", () => {
38
+ const fn = (acc, x) => {
39
+ const newAcc = { sum: acc.sum + x };
40
+
41
+ return [newAcc, newAcc.sum];
42
+ };
43
+
44
+ const [acc, result] = mapAccum(fn, { sum: 0 }, [1, 2, 3]);
45
+
46
+ expect(acc).toEqual({ sum: 6 });
47
+ expect(result).toEqual([1, 3, 6]);
48
+ });
49
+
50
+ it("is curried", () => {
51
+ const fn = (acc, x) => [acc + x, x * 2];
52
+ const mapWithFn = mapAccum(fn);
53
+ const withInit = mapWithFn(2);
54
+ const [acc, result] = withInit([1, 2, 3]);
55
+
56
+ expect(acc).toBe(8);
57
+ expect(result).toEqual([2, 4, 6]);
58
+ });
59
+
60
+ it("does not mutate the original array", () => {
61
+ const arr = [1, 2, 3];
62
+ mapAccum((acc, x) => [acc + x, acc + x], 0, arr);
63
+ expect(arr).toEqual([1, 2, 3]);
64
+ });
65
+
66
+ it("handles mixed types in accumulator and result", () => {
67
+ const fn = (acc, x) => [acc + x.length, acc + "-" + x];
68
+ const [acc, result] = mapAccum(fn, 0, ["a", "bb", "ccc"]);
69
+
70
+ expect(acc).toBe(6);
71
+ expect(result).toEqual(["0-a", "1-bb", "3-ccc"]);
72
+ });
73
+ });