@applicaster/zapp-react-native-utils 12.0.0-alpha.4043183114 → 12.0.0-alpha.4081044014

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 (63) hide show
  1. package/analyticsUtils/AnalyticPlayerListener.ts +141 -0
  2. package/analyticsUtils/PlayerAnalyticsManager.ts +90 -0
  3. package/analyticsUtils/{analyticsTracker.ts → playerAnalyticsTracker.ts} +19 -10
  4. package/appUtils/HooksManager/{Hook.ts → Hook.js} +11 -17
  5. package/appUtils/HooksManager/{constants.ts → constants.js} +1 -1
  6. package/appUtils/HooksManager/{index.ts → index.js} +109 -98
  7. package/appUtils/RiverFocusManager/index.js +12 -17
  8. package/appUtils/accessibilityManager/hooks.ts +16 -7
  9. package/appUtils/accessibilityManager/index.ts +33 -28
  10. package/appUtils/focusManager/treeDataStructure/Tree/index.js +3 -2
  11. package/appUtils/focusManager/treeDataStructure/Utils/index.js +3 -1
  12. package/appUtils/{index.ts → index.js} +1 -1
  13. package/appUtils/keyCodes/{index.ts → index.js} +0 -2
  14. package/appUtils/keyCodes/{keys/keyEventMapper.ts → keys.android.js} +19 -0
  15. package/appUtils/keyCodes/keys.ios.js +46 -0
  16. package/appUtils/platform/platformUtils.ts +49 -2
  17. package/appUtils/playerManager/index.ts +9 -27
  18. package/appUtils/playerManager/playerHooks/usePlayerCurrentTime.tsx +57 -0
  19. package/appUtils/playerManager/playerNative.ts +1 -1
  20. package/appUtils/playerManager/usePlayerControllerSetup.tsx +1 -1
  21. package/appUtils/playerManager/usePlayerState.tsx +19 -34
  22. package/arrayUtils/index.ts +11 -0
  23. package/cellUtils/index.ts +38 -5
  24. package/domUtils/{cookieManager.ts → cookieManager.js} +2 -1
  25. package/focusManager/FocusManager.ts +20 -5
  26. package/focusManager/__tests__/FocusManager.test.ts +0 -1
  27. package/functionUtils/index.ts +49 -15
  28. package/index.d.ts +15 -0
  29. package/manifestUtils/defaultManifestConfigurations/player.js +121 -0
  30. package/manifestUtils/keys.js +2 -1
  31. package/modalState/index.ts +5 -1
  32. package/navigationUtils/index.ts +6 -15
  33. package/numberUtils/__tests__/toNumber.test.ts +2 -2
  34. package/numberUtils/__tests__/toPositiveNumberWithDefault.test.ts +66 -0
  35. package/numberUtils/__tests__/toPositiveNumberWithDefaultZero.test.ts +66 -0
  36. package/numberUtils/index.ts +20 -0
  37. package/package.json +2 -2
  38. package/playerUtils/configurationGenerator.ts +120 -0
  39. package/playerUtils/imaScriptDom.ts +59 -0
  40. package/reactHooks/cell-click/index.ts +17 -3
  41. package/reactHooks/debugging/__tests__/index.test.js +81 -11
  42. package/reactHooks/feed/__tests__/useBatchLoading.test.tsx +69 -6
  43. package/reactHooks/feed/useBatchLoading.ts +52 -28
  44. package/reactHooks/layout/useDimensions/__tests__/useDimensions.test.ts +134 -0
  45. package/reactHooks/layout/useDimensions/useDimensions.ts +2 -0
  46. package/reactHooks/navigation/index.ts +5 -8
  47. package/reactHooks/player/useAutoSeek.tsx +9 -7
  48. package/reactHooks/resolvers/useCellResolver.ts +5 -1
  49. package/reactHooks/useConfiguration.ts +2 -2
  50. package/reactUtils/index.ts +15 -2
  51. package/testUtils/index.tsx +42 -9
  52. package/appUtils/HooksManager/types.ts +0 -93
  53. package/appUtils/keyCodes/keys/index.ts +0 -3
  54. package/appUtils/keyCodes/keys/keys.android.ts +0 -18
  55. package/appUtils/keyCodes/keys/keys.ios.ts +0 -25
  56. package/appUtils/keyCodes/keys/keys.ts +0 -15
  57. /package/appUtils/HooksManager/{logger.ts → logger.js} +0 -0
  58. /package/appUtils/{directionHelper.ts → directionHelper.js} +0 -0
  59. /package/appUtils/keyCodes/{androidTVKeys.ts → androidTVKeys.js} +0 -0
  60. /package/appUtils/keyCodes/{keys/keys.web.ts → keys.web.js} +0 -0
  61. /package/appUtils/keyCodes/{keys/keysByPlatform.ts → keysByPlatform.js} +0 -0
  62. /package/appUtils/{localizationsHelper.ts → localizationsHelper.js} +0 -0
  63. /package/domUtils/{logger.ts → logger.js} +0 -0
@@ -31,13 +31,12 @@ export const getKeyForLabel = (dataKey, customKey) => {
31
31
  * This method will return true if the argument passed to it is either empty or nil
32
32
  * The method prevents zero from being evaluated as falsey in an || condition
33
33
  * i.e. - NaN, null, {}, "", [], should all return true
34
- * @param {*} argument - argument passed to it could be any type
35
34
  * @returns {Boolean} returns true if empty or nil
35
+ * @param value
36
36
  */
37
- export const isEmptyOrNil = R.either(
38
- R.equals(NaN),
39
- R.either(R.isEmpty, R.isNil)
40
- );
37
+
38
+ export const isEmptyOrNil = (value: any): boolean =>
39
+ Number.isNaN(value) || value == null || R.isEmpty(value);
41
40
 
42
41
  /**
43
42
  * This method is used to find the appropriate label for any given text field.
@@ -320,6 +319,7 @@ export const ifElseFocusedSelected = (
320
319
  * @param {Object} stylesObj styles object with keys from zapp { button_icon_width: "10" }
321
320
  * @returns {*} value, returns any type that can be used as styles
322
321
  */
322
+
323
323
  export const getValue = (stylesObj) => (key) => {
324
324
  return R.propOr(null, key, stylesObj);
325
325
  };
@@ -468,3 +468,36 @@ export const getColorFromData = ({
468
468
 
469
469
  return valueFromLayout;
470
470
  };
471
+
472
+ export const getImageStyles = ({
473
+ image,
474
+ value,
475
+ }: {
476
+ image: any;
477
+ value: any;
478
+ }) => {
479
+ return {
480
+ width: image.imageContentWidth,
481
+ height: image.imageContentHeight,
482
+ aspectRatio: image.aspectRatio,
483
+ borderRadius: toNumberWithDefaultZero(value("image_corner_radius")),
484
+ };
485
+ };
486
+
487
+ export const getImageContainerPaddingStyles = ({ value }: { value: any }) => {
488
+ return {
489
+ paddingTop: value("image_padding_top"),
490
+ paddingBottom: value("image_padding_bottom"),
491
+ paddingLeft: value("image_padding_left"),
492
+ paddingRight: value("image_padding_right"),
493
+ };
494
+ };
495
+
496
+ export const getImageContainerMarginStyles = ({ value }: { value: any }) => {
497
+ return {
498
+ marginTop: value("image_margin_top"),
499
+ marginBottom: value("image_margin_bottom"),
500
+ marginLeft: value("image_margin_left"),
501
+ marginRight: value("image_margin_right"),
502
+ };
503
+ };
@@ -2,6 +2,7 @@ import { domUtilsLogger } from "./logger";
2
2
 
3
3
  /**
4
4
  * Gets an object of cookies and sets them on the DOM.
5
+ * @param {Object} cookies selected data key for label.
5
6
  */
6
7
  export function setCookies(cookies): void {
7
8
  const cookieKeys = Object.keys(cookies);
@@ -24,7 +25,7 @@ export function setCookies(cookies): void {
24
25
  /**
25
26
  * Gets cookies set on DOM
26
27
  */
27
- export function getCookies(): typeof document.cookie {
28
+ export function getCookies(): Object {
28
29
  try {
29
30
  if (document) {
30
31
  return document.cookie;
@@ -18,6 +18,7 @@ class FocusManager {
18
18
  private static instance: FocusManager;
19
19
 
20
20
  private _focusedId: string | null = null;
21
+ private _prevFocusedId: string | null = null;
21
22
  public previousNavigationDirection: FocusManager.Android.NavDir = null;
22
23
 
23
24
  /**
@@ -47,10 +48,22 @@ class FocusManager {
47
48
  return focusedRef?.current;
48
49
  }
49
50
 
51
+ get prevFocused() {
52
+ const focusedRef = this.prevFocusedId
53
+ ? FocusManager.findFocusable(this.prevFocusedId)
54
+ : { current: null };
55
+
56
+ return focusedRef?.current;
57
+ }
58
+
50
59
  get focusedId() {
51
60
  return FocusManager.instance._focusedId;
52
61
  }
53
62
 
63
+ get prevFocusedId() {
64
+ return FocusManager.instance._prevFocusedId;
65
+ }
66
+
54
67
  public static getInstance(): FocusManager {
55
68
  if (!FocusManager.instance) {
56
69
  FocusManager.instance = new FocusManager();
@@ -151,9 +164,8 @@ class FocusManager {
151
164
  }
152
165
 
153
166
  private setFocusLocal(nextFocus: FocusManager.TouchableReactRef) {
167
+ FocusManager.instance._prevFocusedId = FocusManager.instance._focusedId;
154
168
  FocusManager.instance._focusedId = nextFocus?.current?.props?.id ?? null;
155
-
156
- this.eventHandler?.invokeHandler?.(FOCUS_EVENTS.FOCUS, nextFocus);
157
169
  }
158
170
 
159
171
  private setPreviousNavigationDirection(
@@ -217,8 +229,11 @@ class FocusManager {
217
229
 
218
230
  FocusManager.instance.setFocus(nextNextFocus, options);
219
231
  } else {
220
- FocusManager.instance.blurPrevious(options);
221
232
  FocusManager.instance.setFocusLocal(nextFocus);
233
+
234
+ FocusManager.instance.blurPrevious(options);
235
+ this.eventHandler?.invokeHandler?.(FOCUS_EVENTS.FOCUS, nextFocus);
236
+
222
237
  FocusManager.instance.setPreviousNavigationDirection(options ?? null);
223
238
 
224
239
  nextFocus?.current?.onFocus?.(nextFocus.current, options ?? {});
@@ -227,8 +242,8 @@ class FocusManager {
227
242
 
228
243
  blurPrevious(options?: FocusManager.Android.CallbackOptions) {
229
244
  if (options) {
230
- FocusManager.instance.focused?.onBlur?.(
231
- FocusManager.instance.focused,
245
+ FocusManager.instance.prevFocused?.onBlur?.(
246
+ FocusManager.instance.prevFocused,
232
247
  options
233
248
  );
234
249
  }
@@ -156,7 +156,6 @@ describe("FocusManager", () => {
156
156
  child1.current.onBlur.mockClear();
157
157
  focusManager.setFocus(child1.current.props.id);
158
158
  focusManager.blurPrevious({ direction: "down" });
159
- expect(child1.current.onBlur).toBeCalled();
160
159
  });
161
160
 
162
161
  it("focusManager - focus shouldn't change if nextFocus has blockFocus", () => {
@@ -1,4 +1,42 @@
1
1
  import * as R from "ramda";
2
+ import { useRef } from "react";
3
+
4
+ /**
5
+ *
6
+ * @param callback - The function to throttle.
7
+ * @param delay - The delay in milliseconds.
8
+ * @returns A throttled version of the callback.
9
+ */
10
+ export const useThrottle = (callback: () => void, delay: number) => {
11
+ const lastCallRef = useRef<number>(0);
12
+ const timeoutRef = useRef<any | null>(null);
13
+
14
+ const throttledFunction = () => {
15
+ const now = Date.now();
16
+
17
+ if (now - lastCallRef.current >= delay) {
18
+ callback();
19
+ lastCallRef.current = now;
20
+ } else if (!timeoutRef.current) {
21
+ const remainingTime = delay - (now - lastCallRef.current);
22
+
23
+ timeoutRef.current = setTimeout(() => {
24
+ callback();
25
+ lastCallRef.current = Date.now();
26
+ timeoutRef.current = null;
27
+ }, remainingTime);
28
+ }
29
+ };
30
+
31
+ const cancel = () => {
32
+ if (timeoutRef.current) {
33
+ clearTimeout(timeoutRef.current);
34
+ timeoutRef.current = null;
35
+ }
36
+ };
37
+
38
+ return { throttledFunction, cancel };
39
+ };
2
40
 
3
41
  /**
4
42
  * standard debounce function.
@@ -73,12 +111,12 @@ type SubscriberFn<T> = (
73
111
 
74
112
  export type EventHandlerFn<T> = (event: string, ...args: unknown[]) => T;
75
113
 
76
- export type SubscriberObj<T extends {} = {}> = {
77
- on: SubscriberFn<SubscriberObj<T>>;
78
- invokeHandler: EventHandlerFn<SubscriberObj<T>>;
79
- removeHandler: EventHandlerFn<SubscriberObj<T>>;
80
- handlers: Record<string, SubscriberFn<SubscriberObj<T>>[] | []>;
81
- } & T;
114
+ type SubscriberObj = Partial<{
115
+ on?: SubscriberFn<SubscriberObj>;
116
+ invokeHandler: EventHandlerFn<SubscriberObj>;
117
+ removeHandler: EventHandlerFn<SubscriberObj>;
118
+ handlers: Record<string, SubscriberFn<SubscriberObj>[] | []>;
119
+ }>;
82
120
 
83
121
  export const clearObject = (object: { [key: string]: unknown }) =>
84
122
  Object.keys(object).forEach((key) => delete object[key]);
@@ -88,11 +126,7 @@ export const clearObject = (object: { [key: string]: unknown }) =>
88
126
  * @param {Object} obj to add the subscription feature on
89
127
  * @returns {Object} subscriber object
90
128
  */
91
- export function subscriber<T extends Partial<SubscriberObj> = {}>(
92
- _obj: T = {} as T
93
- ): SubscriberObj {
94
- const obj: T = _obj;
95
-
129
+ export function subscriber(obj: SubscriberObj = {}): SubscriberObj {
96
130
  if (!obj.handlers) {
97
131
  obj.handlers = {};
98
132
  }
@@ -138,7 +172,7 @@ export function subscriber<T extends Partial<SubscriberObj> = {}>(
138
172
  | SubscriberFn<SubscriberObj>[]
139
173
  | [];
140
174
 
141
- return obj as SubscriberObj;
175
+ return obj;
142
176
  };
143
177
 
144
178
  /**
@@ -154,16 +188,16 @@ export function subscriber<T extends Partial<SubscriberObj> = {}>(
154
188
 
155
189
  R.compose(R.forEach(callHandlerWithDispose), R.propOr([], event))(handlers);
156
190
 
157
- return obj as SubscriberObj;
191
+ return obj;
158
192
  };
159
193
 
160
194
  obj.removeHandler = function (event, handler) {
161
195
  handlers[event] = R.reject(R.equals(handler), handlers[event]);
162
196
 
163
- return obj as SubscriberObj;
197
+ return obj;
164
198
  };
165
199
 
166
- return obj as SubscriberObj;
200
+ return obj;
167
201
  }
168
202
 
169
203
  /**
package/index.d.ts CHANGED
@@ -143,3 +143,18 @@ declare type BuilderData = {
143
143
  river?: ZappRiver;
144
144
  method?: string;
145
145
  };
146
+
147
+ declare type AccessibilityState = {
148
+ screenReaderEnabled: boolean;
149
+ reduceMotionEnabled: boolean;
150
+ boldTextEnabled: boolean;
151
+ };
152
+
153
+ declare type AccessibilityProps = {
154
+ accessibilityLabel?: string;
155
+ accessibilityHint?: string;
156
+ "aria-label"?: string;
157
+ "aria-description"?: string;
158
+ accessibilityRole?: string;
159
+ "aria-role"?: string;
160
+ };
@@ -18,6 +18,7 @@ function getDevice(platform) {
18
18
  case "lg_tv":
19
19
  case "samsung_tv":
20
20
  case "web":
21
+ case "vizio":
21
22
  return "tv";
22
23
  }
23
24
  }
@@ -1795,6 +1796,30 @@ function getPlayerConfiguration({ platform }) {
1795
1796
  key: "menu_header_samsung_letter_spacing",
1796
1797
  initial_value: 0,
1797
1798
  },
1799
+ {
1800
+ type: "vizio_font_selector",
1801
+ label: "Vizio Font Family",
1802
+ key: "menu_header_vizio_font_family",
1803
+ initial_value: "SmsungOneUI-Bold",
1804
+ },
1805
+ {
1806
+ type: "number_input",
1807
+ label: "Vizio Font Size",
1808
+ key: "menu_header_vizio_font_size",
1809
+ initial_value: 30,
1810
+ },
1811
+ {
1812
+ type: "number_input",
1813
+ label: "Vizio Line Height",
1814
+ key: "menu_header_vizio_line_height",
1815
+ initial_value: 60,
1816
+ },
1817
+ {
1818
+ type: "number_input",
1819
+ label: "Vizio Letter Spacing",
1820
+ key: "menu_header_vizio_letter_spacing",
1821
+ initial_value: 0,
1822
+ },
1798
1823
  ]
1799
1824
  ),
1800
1825
  // Captions Menu - Item Text Label
@@ -1874,6 +1899,30 @@ function getPlayerConfiguration({ platform }) {
1874
1899
  key: "menu_item_samsung_letter_spacing",
1875
1900
  initial_value: 0,
1876
1901
  },
1902
+ {
1903
+ type: "vizio_font_selector",
1904
+ label: "Vizio Font Family",
1905
+ key: "menu_item_vizio_font_family",
1906
+ initial_value: "SmsungOneUI-Bold",
1907
+ },
1908
+ {
1909
+ type: "number_input",
1910
+ label: "Vizio Font Size",
1911
+ key: "menu_item_vizio_font_size",
1912
+ initial_value: 25,
1913
+ },
1914
+ {
1915
+ type: "number_input",
1916
+ label: "Vizio Line Height",
1917
+ key: "menu_item_vizio_line_height",
1918
+ initial_value: 40,
1919
+ },
1920
+ {
1921
+ type: "number_input",
1922
+ label: "Vizio Letter Spacing",
1923
+ key: "menu_item_vizio_letter_spacing",
1924
+ initial_value: 0,
1925
+ },
1877
1926
  ]
1878
1927
  ),
1879
1928
  // Captions Menu - Item Border
@@ -2017,6 +2066,18 @@ function getPlayerConfiguration({ platform }) {
2017
2066
  key: "samsung_tv_video_player_title_font_size",
2018
2067
  initial_value: 64,
2019
2068
  },
2069
+ {
2070
+ type: "vizio_font_selector",
2071
+ label: "Vizio Font Family",
2072
+ key: "vizio_video_player_title_font_family",
2073
+ initial_value: "Ubuntu-Bold",
2074
+ },
2075
+ {
2076
+ type: "number_input",
2077
+ label: "Vizio Font Size",
2078
+ key: "vizio_video_player_title_font_size",
2079
+ initial_value: 64,
2080
+ },
2020
2081
  {
2021
2082
  type: "tvos_font_selector",
2022
2083
  label: "tvOS Font Family",
@@ -2090,6 +2151,18 @@ function getPlayerConfiguration({ platform }) {
2090
2151
  key: "samsung_tv_video_player_summary_font_size",
2091
2152
  initial_value: 30,
2092
2153
  },
2154
+ {
2155
+ type: "vizio_font_selector",
2156
+ label: "Vizio Font Family",
2157
+ key: "vizio_video_player_summary_font_family",
2158
+ initial_value: "Ubuntu-Bold",
2159
+ },
2160
+ {
2161
+ type: "number_input",
2162
+ label: "Vizio Font Size",
2163
+ key: "vizio_video_player_summary_font_size",
2164
+ initial_value: 30,
2165
+ },
2093
2166
  {
2094
2167
  type: "tvos_font_selector",
2095
2168
  label: "tvOS Font Family",
@@ -2157,6 +2230,18 @@ function getPlayerConfiguration({ platform }) {
2157
2230
  key: "samsung_tv_audio_player_title_font_size",
2158
2231
  initial_value: 38,
2159
2232
  },
2233
+ {
2234
+ type: "vizio_font_selector",
2235
+ label: "Vizio Font Family",
2236
+ key: "vizio_tv_audio_player_title_font_family",
2237
+ initial_value: "Ubuntu-Bold",
2238
+ },
2239
+ {
2240
+ type: "number_input",
2241
+ label: "Vizio Font Size",
2242
+ key: "vizio_audio_player_title_font_size",
2243
+ initial_value: 38,
2244
+ },
2160
2245
  {
2161
2246
  type: "tvos_font_selector",
2162
2247
  label: "tvOS Font Family",
@@ -2212,6 +2297,18 @@ function getPlayerConfiguration({ platform }) {
2212
2297
  key: "samsung_tv_audio_player_summary_font_size",
2213
2298
  initial_value: 20,
2214
2299
  },
2300
+ {
2301
+ type: "vizio_font_selector",
2302
+ label: "Vizio Font Family",
2303
+ key: "vizio_audio_player_summary_font_family",
2304
+ initial_value: "Ubuntu-Bold",
2305
+ },
2306
+ {
2307
+ type: "number_input",
2308
+ label: "Vizio Font Size",
2309
+ key: "vizio_audio_player_summary_font_size",
2310
+ initial_value: 20,
2311
+ },
2215
2312
  {
2216
2313
  type: "tvos_font_selector",
2217
2314
  label: "tvOS Font Family",
@@ -2267,6 +2364,18 @@ function getPlayerConfiguration({ platform }) {
2267
2364
  key: "samsung_tv_player_time_font_size",
2268
2365
  initial_value: 20,
2269
2366
  },
2367
+ {
2368
+ type: "vizio_font_selector",
2369
+ label: "Vizio Font Family",
2370
+ key: "vizio_player_time_font_family",
2371
+ initial_value: "Ubuntu-Bold",
2372
+ },
2373
+ {
2374
+ type: "number_input",
2375
+ label: "Vizio Font Size",
2376
+ key: "vizio_player_time_font_size",
2377
+ initial_value: 20,
2378
+ },
2270
2379
  {
2271
2380
  type: "android_font_selector",
2272
2381
  label: "Android TV Font Family",
@@ -2322,6 +2431,18 @@ function getPlayerConfiguration({ platform }) {
2322
2431
  key: "samsung_tv_audio_player_run_time_font_size",
2323
2432
  initial_value: 20,
2324
2433
  },
2434
+ {
2435
+ type: "vizio_font_selector",
2436
+ label: "Vizio Font Family",
2437
+ key: "vizio_audio_player_run_time_font_family",
2438
+ initial_value: "Ubuntu-Bold",
2439
+ },
2440
+ {
2441
+ type: "number_input",
2442
+ label: "Vizio Font Size",
2443
+ key: "vizio_audio_player_run_time_font_size",
2444
+ initial_value: 20,
2445
+ },
2325
2446
  {
2326
2447
  type: "tvos_font_selector",
2327
2448
  label: "tvOS Font Family",
@@ -17,10 +17,11 @@ const ZAPPIFEST_FIELDS = {
17
17
  lg: "lg_tv_font_selector",
18
18
  samsung: "samsung_font_selector",
19
19
  roku: "roku_font_selector",
20
+ vizio: "vizio_font_selector",
20
21
  },
21
22
  };
22
23
 
23
- const TV_PLATFORMS = ["tvOS", "android", "LG", "samsung", "roku"];
24
+ const TV_PLATFORMS = ["tvOS", "android", "LG", "samsung", "roku", "vizio"];
24
25
 
25
26
  const FontPropsForTVPlatform = (platform) => ({
26
27
  [`${R.toLower(platform)}FontFamily`]: {
@@ -31,7 +31,11 @@ export const useModalStore = create<ModalStore>((set) => ({
31
31
  set((state) => ({
32
32
  modalState: { ...state.modalState, ...newState },
33
33
  })),
34
- openModal: ({ item, options = {}, props }: OpenModalArg) =>
34
+ openModal: ({
35
+ item,
36
+ options = {},
37
+ props = { screenData: {} },
38
+ }: OpenModalArg) =>
35
39
  set({
36
40
  modalState: {
37
41
  visible: true,
@@ -263,7 +263,7 @@ export function getTargetRoute(
263
263
  pathname = "",
264
264
  {
265
265
  contentTypes = undefined,
266
- layoutVersion = undefined,
266
+ layoutVersion = "v2",
267
267
  rivers = {},
268
268
  }: {
269
269
  contentTypes?: ZappContentTypes | null;
@@ -324,13 +324,7 @@ export function getPathAttributes({
324
324
  * @param {object} rivers
325
325
  * @returns {object}
326
326
  */
327
- export function getRiverFromRoute({
328
- route,
329
- rivers,
330
- }: {
331
- route: string;
332
- rivers: Record<string, ZappRiver>;
333
- }) {
327
+ export function getRiverFromRoute({ route, rivers }) {
334
328
  if (!route) {
335
329
  return null;
336
330
  }
@@ -443,7 +437,7 @@ export const runZappHooksForEntry = async (
443
437
 
444
438
  let success;
445
439
  let payload;
446
- const rivers: Record<string, ZappRiver> = appStore.get("rivers");
440
+ const rivers = appStore.get("rivers");
447
441
  const plugins = appStore.get("plugins");
448
442
  const appData = appStore.get("appData");
449
443
 
@@ -498,16 +492,13 @@ export const runZappHooksForEntry = async (
498
492
  payload = _payload;
499
493
  };
500
494
 
501
- const hooksManager = HooksManager(hooksOptions);
502
-
503
- hooksManager.subscriber
495
+ HooksManager(hooksOptions)
504
496
  .on(HOOKS_EVENTS.PRESENT_SCREEN_HOOK, handleHookPresent)
505
497
  .on(HOOKS_EVENTS.START_BACKGROUND_HOOK, handleBackgroundHook)
506
498
  .on(HOOKS_EVENTS.ERROR, onFinished(false))
507
499
  .on(HOOKS_EVENTS.CANCEL, onFinished(false))
508
- .on(HOOKS_EVENTS.COMPLETE, onFinished(true));
509
-
510
- hooksManager.handleHooks(entry);
500
+ .on(HOOKS_EVENTS.COMPLETE, onFinished(true))
501
+ .handleHooks(entry);
511
502
 
512
503
  // eslint-disable-next-line no-unmodified-loop-condition
513
504
  while (success === undefined) {
@@ -2,7 +2,7 @@ import { toNumber } from "..";
2
2
 
3
3
  describe("toNumber", () => {
4
4
  it("return number if input is number", () => {
5
- const inputs = [-1, 0, 1, 100];
5
+ const inputs = [-1, 0, 1, 100, 0.2];
6
6
  expect.assertions(inputs.length);
7
7
 
8
8
  inputs.forEach((input) => {
@@ -12,7 +12,7 @@ describe("toNumber", () => {
12
12
  });
13
13
 
14
14
  it("return number if input is string as number", () => {
15
- const inputs = ["-1", "0", "1", "100"];
15
+ const inputs = ["-1", "0", "1", "100", "0.2"];
16
16
  expect.assertions(inputs.length);
17
17
 
18
18
  inputs.forEach((input) => {
@@ -0,0 +1,66 @@
1
+ import { toPositiveNumberWithDefault } from "..";
2
+
3
+ describe("toNumber", () => {
4
+ const DEFAULT = 5;
5
+
6
+ it("return number if input is positive number", () => {
7
+ const inputs = [0, 1, 2, 100, 200.12, Infinity];
8
+ expect.assertions(inputs.length);
9
+
10
+ inputs.forEach((input) => {
11
+ const output = toPositiveNumberWithDefault(DEFAULT, input);
12
+ expect(output).toBe(input);
13
+ });
14
+ });
15
+
16
+ it("return number if input is positive number as string", () => {
17
+ const inputs = ["0", "1", "2", "100", "200.12"];
18
+ expect.assertions(inputs.length);
19
+
20
+ inputs.forEach((input) => {
21
+ const output = toPositiveNumberWithDefault(DEFAULT, input);
22
+ expect(output).toBe(Number(input));
23
+ });
24
+ });
25
+
26
+ it("return default number if input is negative number", () => {
27
+ const inputs = [-1, -2, -100, -Infinity];
28
+ expect.assertions(inputs.length);
29
+
30
+ inputs.forEach((input) => {
31
+ const output = toPositiveNumberWithDefault(DEFAULT, input);
32
+ expect(output).toBe(DEFAULT);
33
+ });
34
+ });
35
+
36
+ it("return default number if input is negative number as string", () => {
37
+ const inputs = ["-1", "-2", "-100"];
38
+ expect.assertions(inputs.length);
39
+
40
+ inputs.forEach((input) => {
41
+ const output = toPositiveNumberWithDefault(DEFAULT, input);
42
+ expect(output).toBe(DEFAULT);
43
+ });
44
+ });
45
+
46
+ it("return default if input is not a number or infinite", () => {
47
+ const inputs = [
48
+ "vfdvf",
49
+ null,
50
+ undefined,
51
+ NaN,
52
+ "",
53
+ {},
54
+ { test: 1 },
55
+ [],
56
+ [1],
57
+ ];
58
+
59
+ expect.assertions(inputs.length);
60
+
61
+ inputs.forEach((input) => {
62
+ const output = toPositiveNumberWithDefault(DEFAULT, input);
63
+ expect(output).toBe(DEFAULT);
64
+ });
65
+ });
66
+ });
@@ -0,0 +1,66 @@
1
+ import { toPositiveNumberWithDefaultZero } from "..";
2
+
3
+ const DEFAULT = 0;
4
+
5
+ describe("toNumber", () => {
6
+ it("return number if input is positive number", () => {
7
+ const inputs = [0, 1, 2, 100, 200.12];
8
+ expect.assertions(inputs.length);
9
+
10
+ inputs.forEach((input) => {
11
+ const output = toPositiveNumberWithDefaultZero(input);
12
+ expect(output).toBe(input);
13
+ });
14
+ });
15
+
16
+ it("return number if input is positive number as string", () => {
17
+ const inputs = ["0", "1", "2", "100", "200.12"];
18
+ expect.assertions(inputs.length);
19
+
20
+ inputs.forEach((input) => {
21
+ const output = toPositiveNumberWithDefaultZero(input);
22
+ expect(output).toBe(Number(input));
23
+ });
24
+ });
25
+
26
+ it("return default number if input is negative number", () => {
27
+ const inputs = [-1, -2, -100];
28
+ expect.assertions(inputs.length);
29
+
30
+ inputs.forEach((input) => {
31
+ const output = toPositiveNumberWithDefaultZero(input);
32
+ expect(output).toBe(DEFAULT);
33
+ });
34
+ });
35
+
36
+ it("return default number if input is negative number as string", () => {
37
+ const inputs = ["-1", "-2", "-100"];
38
+ expect.assertions(inputs.length);
39
+
40
+ inputs.forEach((input) => {
41
+ const output = toPositiveNumberWithDefaultZero(input);
42
+ expect(output).toBe(DEFAULT);
43
+ });
44
+ });
45
+
46
+ it("return default if input is not a number or infinite", () => {
47
+ const inputs = [
48
+ "vfdvf",
49
+ null,
50
+ undefined,
51
+ NaN,
52
+ "",
53
+ {},
54
+ { test: 1 },
55
+ [],
56
+ [1],
57
+ ];
58
+
59
+ expect.assertions(inputs.length);
60
+
61
+ inputs.forEach((input) => {
62
+ const output = toPositiveNumberWithDefaultZero(input);
63
+ expect(output).toBe(DEFAULT);
64
+ });
65
+ });
66
+ });