@applicaster/zapp-react-native-utils 13.0.0-alpha.5771418585 → 13.0.0-alpha.5928753399

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 (37) hide show
  1. package/analyticsUtils/currentScreenProperities.ts +6 -4
  2. package/appUtils/HooksManager/index.ts +1 -1
  3. package/appUtils/focusManager/index.ts +1 -10
  4. package/appUtils/keyCodes/index.ts +11 -7
  5. package/appUtils/orientationHelper.ts +11 -13
  6. package/appUtils/playerManager/index.ts +1 -1
  7. package/appUtils/playerManager/player.ts +31 -20
  8. package/appUtils/playerManager/playerNative.ts +23 -8
  9. package/equalUtils/__tests__/isEqual/combination.test.ts +263 -0
  10. package/equalUtils/index.ts +41 -29
  11. package/focusManager/index.ts +41 -4
  12. package/functionUtils/index.ts +21 -8
  13. package/manifestUtils/defaultManifestConfigurations/player.js +8 -0
  14. package/manifestUtils/fonts/index.js +5 -6
  15. package/manifestUtils/sharedConfiguration/screenPicker/__tests__/utils.test.js +304 -0
  16. package/manifestUtils/sharedConfiguration/screenPicker/stylesFields.js +875 -0
  17. package/manifestUtils/sharedConfiguration/screenPicker/utils.js +130 -0
  18. package/numberUtils/index.ts +7 -5
  19. package/package.json +4 -10
  20. package/playerUtils/configurationGenerator.ts +8 -0
  21. package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +5 -7
  22. package/reactHooks/autoscrolling/useTrackedView.ts +12 -1
  23. package/reactHooks/navigation/__mocks__/useNavigation.ts +3 -0
  24. package/reactHooks/navigation/__tests__/index.test.tsx +6 -17
  25. package/reactHooks/navigation/index.ts +6 -4
  26. package/reactHooks/player/TVSeekControlller/TVSeekController.ts +13 -40
  27. package/reactHooks/player/TVSeekControlller/TapSeekController.ts +3 -10
  28. package/reactUtils/__tests__/reactUtils.test.js +1 -19
  29. package/reactUtils/createContext/__tests__/{index.test.js → index.test.ts} +2 -2
  30. package/reactUtils/createContext/helpers.ts +6 -1
  31. package/reactUtils/createContext/index.ts +11 -25
  32. package/reactUtils/index.ts +0 -11
  33. package/services/js2native.ts +673 -0
  34. package/time/BackgroundTimer.ts +55 -0
  35. package/time/Timer.ts +6 -6
  36. package/reactUtils/createContext/__tests__/index-no-react.test.js +0 -27
  37. /package/reactUtils/createContext/__tests__/__snapshots__/{index.test.js.snap → index.test.ts.snap} +0 -0
@@ -0,0 +1,130 @@
1
+ const defaultPlatforms = {
2
+ tvos: "tvOS",
3
+ android_tv: "Android TV",
4
+ lg_tv: "LG TV",
5
+ samsung_tv: "Samsung TV",
6
+ };
7
+
8
+ const global_defaults = {
9
+ fontSize: 20,
10
+ lineHeight: 40,
11
+ letterSpacing: 0.4,
12
+ };
13
+
14
+ const generateFontConfiguration = (platforms = defaultPlatforms) => {
15
+ const platformEntries = Object.entries(platforms);
16
+ const defaultsEntries = Object.entries(global_defaults);
17
+ const splitCamelCase = (str) => str.replace(/([a-z](?=[A-Z]))/g, "$1_");
18
+
19
+ return platformEntries.reduce((acc, [platformKey, platformValue]) => {
20
+ acc.push(
21
+ ...defaultsEntries.reduce((acc2, [valueKey, defaultValue]) => {
22
+ acc2.push({
23
+ type: "number_input",
24
+ label: `${platformValue} ${splitCamelCase(valueKey).replace(
25
+ "_",
26
+ " "
27
+ )}`,
28
+ key: `${platformKey}_${splitCamelCase(valueKey)}`.toLowerCase(),
29
+ initial_value: defaultValue,
30
+ });
31
+
32
+ return acc2;
33
+ }, [])
34
+ );
35
+
36
+ return acc;
37
+ }, []);
38
+ };
39
+
40
+ const conditional_rule = (key, condition_value) => ({
41
+ key,
42
+ condition_value,
43
+ });
44
+
45
+ const createConditionalConfig = (rules, matchAll = false) => ({
46
+ rules: matchAll ? "all_conditions" : "conditional",
47
+ conditional_fields: rules.map((field) => conditional_rule(...field)),
48
+ });
49
+
50
+ const conditional_horizontal_type = createConditionalConfig([
51
+ ["styles/screen_picker_type", "horizontal"],
52
+ ]);
53
+
54
+ const conditional_vertical_type = createConditionalConfig([
55
+ ["styles/screen_picker_type", "vertical"],
56
+ ]);
57
+
58
+ const conditional_horizontal_type_item_fixed = createConditionalConfig(
59
+ [
60
+ ["styles/screen_picker_type", "horizontal"],
61
+ ["styles/screen_picker_item_size", "fixed"],
62
+ ],
63
+ true
64
+ );
65
+
66
+ const conditional_horizontal_type_item_dynamic = createConditionalConfig(
67
+ [
68
+ ["styles/screen_picker_type", "horizontal"],
69
+ ["screen_picker_horizontal_display_type", "dynamic"],
70
+ ],
71
+ true
72
+ );
73
+
74
+ const conditional_horizontal_display_type_fixed = createConditionalConfig(
75
+ [
76
+ ["styles/screen_picker_type", "horizontal"],
77
+ ["styles/screen_picker_horizontal_display_type", "fixed"],
78
+ ],
79
+ true
80
+ );
81
+
82
+ const conditional_horizontal_asset_on = createConditionalConfig(
83
+ [
84
+ ["styles/screen_picker_type", "horizontal"],
85
+ ["styles/screen_picker_asset_switch", true],
86
+ ],
87
+ true
88
+ );
89
+
90
+ const createVariationFields = ({
91
+ prefix = "screen_picker",
92
+ key,
93
+ type = "number_input",
94
+ label = "",
95
+ variants: [a, b],
96
+ }) => {
97
+ return [
98
+ {
99
+ type,
100
+ key: `${prefix}${prefix.length > 0 ? "_" : ""}${
101
+ a?.key ?? "vertical"
102
+ }_${key}`,
103
+ label: a?.label ?? label,
104
+ initial_value: a.initial_value,
105
+ ...conditional_vertical_type,
106
+ },
107
+ {
108
+ type,
109
+ key: `${prefix}${prefix.length > 0 ? "_" : ""}${
110
+ b.key ?? "horizontal"
111
+ }_${key}`,
112
+ label: b?.label ?? label,
113
+ initial_value: b.initial_value,
114
+ ...conditional_horizontal_type,
115
+ },
116
+ ];
117
+ };
118
+
119
+ module.exports = {
120
+ generateFontConfiguration,
121
+ createVariationFields,
122
+ createConditionalConfig,
123
+ conditional_rule,
124
+ conditional_horizontal_type,
125
+ conditional_vertical_type,
126
+ conditional_horizontal_type_item_fixed,
127
+ conditional_horizontal_type_item_dynamic,
128
+ conditional_horizontal_display_type_fixed,
129
+ conditional_horizontal_asset_on,
130
+ };
@@ -3,7 +3,7 @@ import { logger } from "@applicaster/zapp-react-native-utils/logger";
3
3
 
4
4
  const numberUtilsLogger = logger?.addSubsystem("NumberUtils");
5
5
 
6
- export const toNumber = (value: any): number | undefined => {
6
+ export const toNumber = (value: unknown): number | undefined => {
7
7
  if (R.isNil(value) || R.isEmpty(value)) {
8
8
  return undefined;
9
9
  }
@@ -17,10 +17,12 @@ export const toNumber = (value: any): number | undefined => {
17
17
  return undefined;
18
18
  };
19
19
 
20
- export const toNumberWithDefault = (defaultValue: number, value: any): number =>
21
- toNumber(value) ?? defaultValue;
20
+ export const toNumberWithDefault = (
21
+ defaultValue: number,
22
+ value: unknown
23
+ ): number => toNumber(value) ?? defaultValue;
22
24
 
23
- export const toNumberWithDefaultZero = (value: any): number =>
25
+ export const toNumberWithDefaultZero = (value: unknown): number =>
24
26
  toNumberWithDefault(0, value);
25
27
 
26
28
  export const requireNumber = (obj, key: string) => {
@@ -39,7 +41,7 @@ export const requireNumber = (obj, key: string) => {
39
41
 
40
42
  export const toFiniteNumberWithDefault = (
41
43
  defaultValue: number,
42
- value: any
44
+ value: unknown
43
45
  ): number => {
44
46
  const possibleNumber = toNumberWithDefault(defaultValue, value);
45
47
 
package/package.json CHANGED
@@ -1,11 +1,10 @@
1
1
  {
2
2
  "name": "@applicaster/zapp-react-native-utils",
3
- "version": "13.0.0-alpha.5771418585",
3
+ "version": "13.0.0-alpha.5928753399",
4
4
  "description": "Applicaster Zapp React Native utilities package",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
7
7
  "scripts": {
8
- "test": "jest -w=2",
9
8
  "build": "echo skipping hybrid ts build in main packages for now"
10
9
  },
11
10
  "publishConfig": {
@@ -28,11 +27,9 @@
28
27
  },
29
28
  "homepage": "https://github.com/applicaster/quickbrick#readme",
30
29
  "dependencies": {
31
- "@applicaster/applicaster-types": "13.0.0-alpha.5771418585",
30
+ "@applicaster/applicaster-types": "13.0.0-alpha.5928753399",
32
31
  "buffer": "^5.2.1",
33
32
  "camelize": "^1.0.0",
34
- "create-react-context": "^0.2.3",
35
- "create-react-ref": "^0.1.0",
36
33
  "dayjs": "^1.11.10",
37
34
  "memoizee": "0.4.15",
38
35
  "prop-types": "^15.0.0",
@@ -42,13 +39,10 @@
42
39
  "@applicaster/zapp-pipes-v2-client": "*",
43
40
  "@react-native-community/netinfo": "*",
44
41
  "immer": "*",
45
- "react": "17.0.2",
46
- "react-native": "0.68.6",
42
+ "react": "*",
43
+ "react-native": "*",
47
44
  "uglify-js": "*",
48
45
  "validate-color": "*",
49
46
  "zustand": "*"
50
- },
51
- "devDependencies": {
52
- "@types/react-native": "0.69.6"
53
47
  }
54
48
  }
@@ -55,6 +55,14 @@ function getPlayerConfiguration({ platform }) {
55
55
  label_tooltip:
56
56
  "Set the query params which control the size of the image e.g width, height. This will help to optimize the loading time, when magic background is enabled.",
57
57
  },
58
+ {
59
+ key: "audio_player_background_image_default_color",
60
+ label: "Audio Player Background Image Default Color",
61
+ initial_value: "",
62
+ type: "text_input",
63
+ label_tooltip:
64
+ "Set the default color for the audio player background image if not image or set of gradient colors are not provided.",
65
+ },
58
66
  ],
59
67
  };
60
68
 
@@ -35,25 +35,23 @@ const Wrapper = ({ children }: { children: React.ReactChild }) => (
35
35
  const { useTrackedView } = require("../useTrackedView");
36
36
 
37
37
  describe("useTrackCurrentAutoScrollingElement", () => {
38
- it("should update position for selected component", async () => {
38
+ it("should update position for selected component - onViewportEnter", () => {
39
39
  const { result } = renderHook(() => useTrackedView("123"), {
40
40
  wrapper: Wrapper,
41
41
  });
42
42
 
43
- // Fast-forward until all timers have been executed
44
- jest.advanceTimersByTime(3000);
45
-
46
43
  expect(result.current.inViewPort).toBe(false);
47
44
 
48
45
  const mockRect = {
49
46
  rect: { left: 1, right: 1, top: 1, bottom: 1 },
50
47
  };
51
48
 
52
- act(() => {
53
- result.current.onPositionUpdated(mockRect);
49
+ act(async () => {
50
+ await result.current.onPositionUpdated(mockRect);
54
51
  });
55
52
 
56
- jest.advanceTimersByTime(3000);
53
+ // Fast-forward until all timers have been executed
54
+ jest.runAllTimers();
57
55
 
58
56
  expect(result.current.inViewPort).toBe(true);
59
57
 
@@ -2,6 +2,10 @@ import { useCallback, useEffect, useMemo, useState } from "react";
2
2
  import { useScreenTrackedViewPositionsContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenTrackedViewPositionsContext";
3
3
  import { useDimensions } from "@applicaster/zapp-react-native-utils/reactHooks/layout";
4
4
  import { findTrackedView } from "./utils/findTrackedView";
5
+ import { isNil } from "ramda";
6
+ import { withTimeout } from "@applicaster/zapp-react-native-utils/idleUtils";
7
+
8
+ const TIMEOUT_FOR_DELAY_ON_VIEWPORT_ENTER_EVENT = 500; // ms
5
9
 
6
10
  const getNormalizedRect = (rect, componentId, screenWidth, screenHeight) => {
7
11
  if (!rect) {
@@ -37,9 +41,16 @@ export const useTrackedView = (componentId: string) => {
37
41
  );
38
42
 
39
43
  const onPositionUpdated = useCallback(
40
- ({ rect }) => {
44
+ async ({ rect }) => {
41
45
  const currentPosition = normalizedRect(componentId, rect);
42
46
 
47
+ // There is an issue on the native side where they are unable to guarantee
48
+ // that the order of onViewportLeave and onViewportEnter events is always correct.
49
+ // This workaround/hack delays the onViewportEnter event to ensure it is received last.
50
+ if (!isNil(currentPosition)) {
51
+ await withTimeout(TIMEOUT_FOR_DELAY_ON_VIEWPORT_ENTER_EVENT);
52
+ }
53
+
43
54
  updateComponentsPositions(componentId, currentPosition as any);
44
55
 
45
56
  setInViewPort(!!currentPosition);
@@ -3,5 +3,8 @@ export const useNavigation = jest.fn(() => ({
3
3
  screenData: {
4
4
  name: "someName",
5
5
  },
6
+ videoModalState: {
7
+ visible: false,
8
+ },
6
9
  currentRoute: "someRoute",
7
10
  }));
@@ -310,14 +310,14 @@ describe("navigation", () => {
310
310
  expect(navBarVisible).toBe(false);
311
311
  });
312
312
 
313
- it("returns false if it's secondary nav bar and hide_secondary_level_menu is true", () => {
313
+ it("returns false if it's secondary nav bar and show_secondary_level_menu is false", () => {
314
314
  const navBarVisible = isNavBarVisible(
315
315
  "",
316
316
  {
317
317
  navigations: [
318
318
  {
319
319
  styles: {
320
- hide_secondary_level_menu: true,
320
+ show_secondary_level_menu: false,
321
321
  },
322
322
  },
323
323
  ],
@@ -329,14 +329,14 @@ describe("navigation", () => {
329
329
  expect(navBarVisible).toBe(false);
330
330
  });
331
331
 
332
- it("returns true if it's secondary nav bar and hide_secondary_level_menu is false", () => {
332
+ it("returns true if it's secondary nav bar and show_secondary_level_menu is true", () => {
333
333
  const navBarVisible = isNavBarVisible(
334
334
  "",
335
335
  {
336
336
  navigations: [
337
337
  {
338
338
  styles: {
339
- hide_secondary_level_menu: false,
339
+ show_secondary_level_menu: true,
340
340
  },
341
341
  },
342
342
  ],
@@ -348,14 +348,14 @@ describe("navigation", () => {
348
348
  expect(navBarVisible).toBe(true);
349
349
  });
350
350
 
351
- it("returns true if it's first level menu and hide_secondary_level_menu is true", () => {
351
+ it("returns true if it's first level menu and show_secondary_level_menu is false", () => {
352
352
  const navBarVisible = isNavBarVisible(
353
353
  "",
354
354
  {
355
355
  navigations: [
356
356
  {
357
357
  styles: {
358
- hide_secondary_level_menu: true,
358
+ show_secondary_level_menu: false,
359
359
  },
360
360
  },
361
361
  ],
@@ -366,16 +366,5 @@ describe("navigation", () => {
366
366
 
367
367
  expect(navBarVisible).toBe(true);
368
368
  });
369
-
370
- it("returns true otherwise", () => {
371
- const navBarVisible = isNavBarVisible(
372
- "",
373
- { navigations: [] } as any,
374
- true,
375
- true
376
- );
377
-
378
- expect(navBarVisible).toBe(true);
379
- });
380
369
  });
381
370
  });
@@ -108,11 +108,13 @@ export function isNavBarVisible(
108
108
  return false;
109
109
  }
110
110
 
111
- const hideSecondaryLevel = screenData?.navigations?.some(
112
- (navigation) => navigation.styles?.hide_secondary_level_menu
113
- );
111
+ const showSecondaryLevel =
112
+ !isTV() ||
113
+ screenData?.navigations?.some(
114
+ (navigation) => navigation.styles?.show_secondary_level_menu
115
+ );
114
116
 
115
- if (canGoBack && hideSecondaryLevel) {
117
+ if (canGoBack && !showSecondaryLevel) {
116
118
  return false;
117
119
  }
118
120
 
@@ -23,7 +23,7 @@ export enum SEEK_STRATEGY {
23
23
  }
24
24
 
25
25
  const CONFIG_TAP_SEEK = {
26
- CLICKS_BEFORE_PAUSE: 1,
26
+ CLICKS_BEFORE_PAUSE: 0,
27
27
  };
28
28
 
29
29
  const CONFIG_LONG_PRESS = {
@@ -93,8 +93,6 @@ export class TVSeekController
93
93
  this.isPlayerInitiallyPaused = this.playerController.isPaused();
94
94
  }
95
95
 
96
- log_debug(`handleStartSeek: seekType: ${seekType}, initiallyPaused: ${this.isPlayerInitiallyPaused}, isPlayerPaused: ${this.playerController.isPaused()}`);
97
-
98
96
  this.clearLongPressThresholdTimeout();
99
97
  this.clearSeekCompleteTimeout();
100
98
  this.setStrategy(SEEK_STRATEGY.TAP_SEEK);
@@ -107,36 +105,27 @@ export class TVSeekController
107
105
  };
108
106
 
109
107
  onForwardPress = (): boolean => {
110
- log_debug("onForwardPress:");
111
-
112
108
  this.handleStartSeek(SEEK_TYPE.FORWARD);
113
109
 
114
110
  return true;
115
111
  };
116
112
 
117
113
  onRewindPress = (): boolean => {
118
- log_debug("onRewindPress:");
119
-
120
114
  this.handleStartSeek(SEEK_TYPE.REWIND);
121
115
 
122
116
  return true;
123
117
  };
124
118
 
125
119
  onSeekEnd = () => {
126
- log_debug("onSeekEnd: Seek ended");
127
120
  this.clearLongPressThresholdTimeout();
128
121
  this.currentSeekController.onSeekEnd();
129
122
  };
130
123
 
131
124
  onRewindPressOut = () => {
132
- log_debug("onRewindPressOut:");
133
-
134
125
  this.onSeekEnd();
135
126
  };
136
127
 
137
128
  onForwardPressOut = () => {
138
- log_debug("onForwardPressOut:");
139
-
140
129
  this.onSeekEnd();
141
130
  };
142
131
 
@@ -149,9 +138,7 @@ export class TVSeekController
149
138
  };
150
139
 
151
140
  handleDelayedSeek = (offset: number = 0) => {
152
- if (this.delayedSeekPosition === null) {
153
- void this.handlePlayerPause();
154
- }
141
+ this.handlePlayerPause();
155
142
 
156
143
  const currentPos =
157
144
  this.delayedSeekPosition === null
@@ -187,46 +174,36 @@ export class TVSeekController
187
174
  }
188
175
  }
189
176
 
190
- log_debug(`handleDelayedSeek: currentPos: ${currentPos} targetPos:${targetPos}, initiallyPaused: ${this.isPlayerInitiallyPaused}`);
191
-
192
177
  this.delayedSeekPosition = targetPos;
193
178
  this.delayedSeekProgressSubject.next(targetPos);
194
179
  };
195
180
 
196
- handleSeekTo = async (newPosition: number) => {
197
- await this.playerController.seekTo(newPosition);
198
-
199
- log_debug(
200
- `handleSeekTo: isPlayerInitiallyPaused: ${this.isPlayerInitiallyPaused} CallPlayerPlay: ${this.isPlayerInitiallyPaused ? "NO" : "YES"}`
201
- );
181
+ handleSeekTo = (newPosition: number) => {
182
+ this.playerController.seekTo(newPosition);
202
183
 
203
184
  if (!this.isPlayerInitiallyPaused) {
204
- await this.playerController.play();
185
+ this.playerController.play();
205
186
  }
206
187
  };
207
188
 
208
- handleSeek = async (offset: number) => {
209
- await this.playerController[this.currentSeekType](offset);
210
-
211
- log_debug(
212
- `handleSeek: isPlayerInitiallyPaused: ${this.isPlayerInitiallyPaused} CallPlayerPlay: ${this.isPlayerInitiallyPaused ? "NO" : "YES"}`
213
- );
189
+ handleSeek = (offset: number) => {
190
+ this.playerController[this.currentSeekType](offset);
214
191
 
215
192
  if (!this.isPlayerInitiallyPaused) {
216
- await this.playerController.play();
193
+ this.playerController.play();
217
194
  }
218
195
  };
219
196
 
220
197
  handleSeekComplete = () => {
221
198
  this.clearSeekCompleteTimeout();
222
199
 
223
- this.seekEndTimeout = setTimeout(async () => {
200
+ this.seekEndTimeout = setTimeout(() => {
224
201
  if (this.delayedSeekPosition !== null) {
225
- await this.handleSeekTo(this.delayedSeekPosition);
202
+ this.handleSeekTo(this.delayedSeekPosition);
226
203
  }
227
204
 
228
205
  log_debug(
229
- `handleSeekComplete: Seek finished, type: ${this.currentSeekController.title}, seekPosition: ${this.delayedSeekPosition}, playerPaused: ${this.playerController.isPaused()}. Reset all states and seek position.`
206
+ `handleSeekComplete: Seek finished, type: ${this.currentSeekController.title}, seekPosition: ${this.delayedSeekPosition}. Reset all states and seek position.`
230
207
  );
231
208
 
232
209
  this.resetAll();
@@ -237,16 +214,12 @@ export class TVSeekController
237
214
  return this.delayedSeekPosition !== null;
238
215
  };
239
216
 
240
- handlePlayerPause = async () => {
241
- log_debug(
242
- `handleSeek: handlePlayerPause isPlayerPaused: ${this.playerController.isPaused()}`
243
- );
244
-
217
+ handlePlayerPause = () => {
245
218
  if (this.playerController.isPaused()) {
246
219
  return;
247
220
  }
248
221
 
249
- await this.playerController.pause();
222
+ this.playerController.pause();
250
223
  };
251
224
 
252
225
  clearSeekCompleteTimeout = () => {
@@ -12,8 +12,6 @@ interface TapPressConfig {
12
12
 
13
13
  export class TapSeekController implements ISeekController {
14
14
  readonly title = "TapSeek";
15
- private lastFastSeekExit = 0;
16
-
17
15
  constructor(
18
16
  private seekControllerDelegate: ISeekControllerDelegate,
19
17
  private seekIncrementalStrategy: SeekIncrementalBaseStrategy,
@@ -25,18 +23,13 @@ export class TapSeekController implements ISeekController {
25
23
 
26
24
  const skipTime = this.seekIncrementalStrategy.getSkipTime();
27
25
  const seekMultiplier = this.seekIncrementalStrategy.getSkipMultiplier();
28
- const cooldown = Date.now() - this.lastFastSeekExit > 1000;
29
26
 
30
27
  if (seekMultiplier > this.config.CLICKS_BEFORE_PAUSE) {
31
28
  log_debug(
32
29
  `${this.title}: handle delayed seek type:${seekType} - skipTime: ${skipTime}, seekMultiplier: ${seekMultiplier}.`
33
30
  );
34
31
 
35
- if (cooldown) {
36
- this.seekControllerDelegate.handleDelayedSeek(skipTime);
37
- } else {
38
- this.seekControllerDelegate.handleSeek(skipTime);
39
- }
32
+ this.seekControllerDelegate.handleDelayedSeek(skipTime);
40
33
  } else {
41
34
  log_debug(
42
35
  `${this.title}: handle seek type:${seekType} - skipTime: ${skipTime}.`
@@ -53,8 +46,8 @@ export class TapSeekController implements ISeekController {
53
46
  };
54
47
 
55
48
  reset = () => {
56
- log_debug(`${this.title}: Reset states`);
57
- this.lastFastSeekExit = Date.now();
49
+ log_debug("{this.title}: Reset states");
50
+
58
51
  this.seekIncrementalStrategy.reset();
59
52
  };
60
53
  }
@@ -7,7 +7,7 @@ import {
7
7
  componentDidMount,
8
8
  } from "./fixtures";
9
9
 
10
- import { attachLifeCycleMethods, createReactRef, mergeChildrenProps } from "..";
10
+ import { attachLifeCycleMethods, mergeChildrenProps } from "..";
11
11
 
12
12
  describe("attachLifeCycleMethods", () => {
13
13
  let addLifeCycleMethodsSpy;
@@ -41,24 +41,6 @@ describe("attachLifeCycleMethods", () => {
41
41
  });
42
42
  });
43
43
 
44
- describe("createReactRef", () => {
45
- it("calls the React.createRef function if it exists", () => {
46
- jest.clearAllMocks();
47
-
48
- const ref = createReactRef();
49
- expect(ref).toHaveProperty("current");
50
- });
51
-
52
- it("calls the polyfill if React.createRef doesn't exist", () => {
53
- jest.clearAllMocks();
54
- const originalCreateRef = React.createRef;
55
- React.createRef = undefined;
56
- const ref = createReactRef();
57
- expect(ref).toHaveProperty("current");
58
- React.createRef = originalCreateRef;
59
- });
60
- });
61
-
62
44
  describe("mergeChildrenProps", () => {
63
45
  it("returns the cloned children with the merged props", () => {
64
46
  const Egg = () => React.createElement("Egg");
@@ -1,3 +1,5 @@
1
+ import { createContext } from "../";
2
+
1
3
  jest.mock("react", () => ({
2
4
  ...jest.requireActual("react"),
3
5
  createContext: jest.fn(() => ({
@@ -6,8 +8,6 @@ jest.mock("react", () => ({
6
8
  })),
7
9
  }));
8
10
 
9
- const { createContext } = require("../index");
10
-
11
11
  const mockedProvider = jest.fn();
12
12
  const mockedWithConsumer = jest.fn();
13
13
  const mockedWithProvider = jest.fn();
@@ -33,7 +33,12 @@ export const getSetterName: (property: string) => string = R.compose(
33
33
  export function createContextSetters(
34
34
  properties: string[],
35
35
  component: any,
36
- options: any = {}
36
+ options: {
37
+ stateValidator?: (
38
+ obj: { property: string; value: unknown },
39
+ oldValue: unknown
40
+ ) => boolean;
41
+ } = {}
37
42
  ) {
38
43
  const { stateValidator = R.T } = options;
39
44
 
@@ -1,5 +1,4 @@
1
1
  import * as React from "react";
2
- import createReactContext from "create-react-context";
3
2
  import * as R from "ramda";
4
3
 
5
4
  import { getSetterName, NOOP } from "./helpers";
@@ -7,33 +6,20 @@ import { createProvider } from "./provider";
7
6
  import { createWithConsumerDecorator } from "./withConsumer";
8
7
  import { createWithProviderDecorator } from "./withProvider";
9
8
 
10
- const reactContextCreator = React.createContext;
11
-
12
- // Depending on the version of React used, the `createContext` function may not be available
13
- // if this is the case, we fall back to a polyfill library
14
- const contextCreatorFn =
15
- reactContextCreator && typeof reactContextCreator === "function"
16
- ? reactContextCreator
17
- : createReactContext;
18
-
19
- /**
20
- * @typedef Context
21
- * @property {Object} Context.Provider react class component to use as context provider
22
- * @property {Function} Context.Consumer react functional component to use as context consumer
23
- * @property {Function} Context.withProvider HOC to apply the context provider
24
- * @property {function} Context.withConsumer HOC to apply the context consumer. passes the context as props
25
- * @property {React.Context} Context.ReactContext React context object
26
- * to the wrapped component
27
- */
28
-
29
9
  /**
30
10
  * Creates a React Context and returns consumer & providers components & decorators to interact
31
11
  * with this context.
32
- * @param {Object} initialContext map of context properties and their initial values
33
- * @param {Function} stateValidator optional predicate to tell whether the state update is valid or not
34
- * @returns {Context} Object containing the context components & decorators {@link Context}
12
+ * @param initialContext map of context properties and their initial values
13
+ * @param stateValidator optional predicate to tell whether the state update is valid or not
14
+ * @returns Object containing the context components & decorators
35
15
  */
36
- export function createContext(initialContext, stateValidator = R.T) {
16
+ export function createContext(
17
+ initialContext: Record<string, any>,
18
+ stateValidator: (
19
+ obj: { property: string; value: unknown },
20
+ oldValue: unknown
21
+ ) => boolean = R.T
22
+ ) {
37
23
  // first we extract the properties name, and create setters name for those
38
24
  const contextPropertiesNames = R.keys(initialContext);
39
25
  const contextSettersNames = R.map(getSetterName, contextPropertiesNames);
@@ -41,7 +27,7 @@ export function createContext(initialContext, stateValidator = R.T) {
41
27
  // we create a React Context with the properties & their setters, assigning a noop function
42
28
  // temporarily (will be overriden by proper setters in the provider component)
43
29
  const ReactContext = R.compose(
44
- contextCreatorFn,
30
+ React.createContext,
45
31
  R.merge(initialContext),
46
32
  R.zipObj(contextSettersNames),
47
33
  R.map(R.always(NOOP))