@applicaster/zapp-react-native-ui-components 14.0.0-alpha.2175196485 → 14.0.0-alpha.2292190333

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 (74) hide show
  1. package/Components/AudioPlayer/mobile/Layout.tsx +1 -1
  2. package/Components/AudioPlayer/tv/helpers.tsx +10 -3
  3. package/Components/BaseFocusable/index.tsx +23 -12
  4. package/Components/Cell/__tests__/CellWIthFocusable.test.js +3 -2
  5. package/Components/Cell/index.js +1 -1
  6. package/Components/ComponentResolver/index.ts +1 -1
  7. package/Components/FeedLoader/FeedLoader.tsx +6 -15
  8. package/Components/FeedLoader/FeedLoaderHOC.tsx +21 -0
  9. package/Components/FeedLoader/index.js +2 -8
  10. package/Components/Focusable/FocusableiOS.tsx +1 -1
  11. package/Components/Focusable/Touchable.tsx +6 -3
  12. package/Components/Focusable/index.android.tsx +11 -4
  13. package/Components/Focusable/index.tsx +1 -1
  14. package/Components/FocusableList/FocusableItem.tsx +22 -3
  15. package/Components/FocusableList/FocusableListItemWrapper.tsx +2 -1
  16. package/Components/FocusableList/index.tsx +14 -7
  17. package/Components/FreezeWithCallback/__tests__/index.test.tsx +67 -43
  18. package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +42 -59
  19. package/Components/GeneralContentScreen/utils/useCurationAPI.ts +13 -10
  20. package/Components/Layout/TV/LayoutBackground.tsx +1 -1
  21. package/Components/Layout/TV/__tests__/index.test.tsx +0 -1
  22. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +2 -0
  23. package/Components/MasterCell/DefaultComponents/Button.tsx +1 -1
  24. package/Components/MasterCell/DefaultComponents/Image/hoc/withDimensions.tsx +1 -1
  25. package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +1 -1
  26. package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +10 -10
  27. package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +18 -18
  28. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/__tests__/index.test.tsx +10 -10
  29. package/Components/MasterCell/utils/behaviorProvider.ts +82 -14
  30. package/Components/MasterCell/utils/index.ts +11 -5
  31. package/Components/OfflineHandler/__tests__/index.test.tsx +26 -35
  32. package/Components/PlayerContainer/ErrorDisplay/index.ts +1 -1
  33. package/Components/PlayerContainer/ProgramInfo/index.tsx +1 -1
  34. package/Components/PlayerContainer/index.ts +1 -1
  35. package/Components/River/ComponentsMap/hooks/__tests__/useLoadingState.test.ts +378 -0
  36. package/Components/River/ComponentsMap/hooks/useLoadingState.ts +2 -2
  37. package/Components/River/RefreshControl.tsx +11 -17
  38. package/Components/River/TV/River.tsx +2 -17
  39. package/Components/River/TV/index.tsx +3 -1
  40. package/Components/River/TV/withPipesV1DataLoader.tsx +43 -0
  41. package/Components/River/TV/withRiverDataLoader.tsx +17 -0
  42. package/Components/River/__tests__/river.test.js +12 -26
  43. package/Components/River/index.tsx +1 -1
  44. package/Components/Screen/__tests__/Screen.test.tsx +28 -29
  45. package/Components/Tabs/Tabs.tsx +2 -3
  46. package/Components/Touchable/__tests__/touchable.test.tsx +12 -17
  47. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +3 -9
  48. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +24 -8
  49. package/Components/VideoModal/__tests__/PlayerDetails.test.tsx +5 -5
  50. package/Contexts/ConfigutaionContext/__tests__/ConfigurationProvider.test.tsx +3 -3
  51. package/Contexts/ScreenContext/index.tsx +46 -6
  52. package/Decorators/ConfigurationWrapper/__tests__/withConfigurationProvider.test.tsx +3 -3
  53. package/Decorators/RiverFeedLoader/__tests__/__snapshots__/riverFeedLoader.test.tsx.snap +221 -209
  54. package/Decorators/RiverFeedLoader/__tests__/riverFeedLoader.test.tsx +14 -16
  55. package/Decorators/RiverFeedLoader/__tests__/utils.test.ts +0 -20
  56. package/Decorators/RiverFeedLoader/index.tsx +22 -4
  57. package/Decorators/RiverFeedLoader/utils/index.ts +0 -18
  58. package/Decorators/RiverResolver/__tests__/riverResolver.test.tsx +3 -6
  59. package/Decorators/ZappPipesDataConnector/ResolverSelector.tsx +25 -0
  60. package/Decorators/ZappPipesDataConnector/__tests__/NullFeedResolver.test.tsx +78 -0
  61. package/Decorators/ZappPipesDataConnector/__tests__/ResolverSelector.test.tsx +205 -0
  62. package/Decorators/ZappPipesDataConnector/__tests__/StaticFeedResolver.test.tsx +251 -0
  63. package/Decorators/ZappPipesDataConnector/__tests__/UrlFeedResolver.test.tsx +368 -0
  64. package/Decorators/ZappPipesDataConnector/__tests__/utils.test.ts +39 -0
  65. package/Decorators/ZappPipesDataConnector/index.tsx +26 -293
  66. package/Decorators/ZappPipesDataConnector/resolvers/NullFeedResolver.tsx +25 -0
  67. package/Decorators/ZappPipesDataConnector/resolvers/StaticFeedResolver.tsx +87 -0
  68. package/Decorators/ZappPipesDataConnector/resolvers/UrlFeedResolver.tsx +266 -0
  69. package/Decorators/ZappPipesDataConnector/types.ts +29 -0
  70. package/Decorators/ZappPipesDataConnector/utils/mongoFilter.ts +738 -0
  71. package/Decorators/ZappPipesDataConnector/utils/useFilter.tsx +136 -0
  72. package/events/index.ts +1 -0
  73. package/package.json +5 -6
  74. package/Components/River/__tests__/__snapshots__/river.test.js.snap +0 -27
@@ -27,7 +27,7 @@ export function AudioPlayerMobileLayout({
27
27
  }: Props) {
28
28
  const fadeAnimation = useRef(new Animated.Value(0)).current;
29
29
 
30
- const mainContainerStyles = platformSelect({
30
+ const mainContainerStyles: ViewStyle = platformSelect({
31
31
  native: {
32
32
  backgroundColor: "transparent",
33
33
  overflow: "hidden",
@@ -27,13 +27,20 @@ const LTR = {
27
27
  justifyContent: "flex-start",
28
28
  textAlign: "left",
29
29
  alignItems: "flex-end",
30
- };
30
+ } as const;
31
31
 
32
32
  const RTL = {
33
33
  flexDirection: "row-reverse",
34
34
  justifyContent: "flex-end",
35
35
  textAlign: "right",
36
36
  alignItems: "flex-start",
37
- };
37
+ } as const;
38
38
 
39
- export const directionStyles = (isRTL) => (isRTL ? RTL : LTR);
39
+ export const directionStyles = (
40
+ isRTL: boolean
41
+ ): {
42
+ flexDirection: "row" | "row-reverse";
43
+ justifyContent: "flex-start" | "flex-end";
44
+ textAlign: "left" | "right";
45
+ alignItems: "flex-end" | "flex-start";
46
+ } => (isRTL ? RTL : LTR);
@@ -146,10 +146,14 @@ export class BaseFocusable<
146
146
  * @param {Object} scrollDirection
147
147
  * @returns {Promise}
148
148
  */
149
- onFocus: FocusManager.FocusEventCB = (focusable, scrollDirection) => {
149
+ onFocus: FocusManager.FocusEventCB = (
150
+ focusable,
151
+ scrollDirection,
152
+ context
153
+ ) => {
150
154
  const { onFocus = noop } = this.props;
151
155
  this.setFocusedState(true);
152
- onFocus(focusable, scrollDirection);
156
+ onFocus(focusable, scrollDirection, context);
153
157
  };
154
158
 
155
159
  /**
@@ -247,8 +251,8 @@ export class BaseFocusable<
247
251
  * @param {Object} scrollDirection
248
252
  * @returns {Promise}
249
253
  */
250
- focus(_, scrollDirection) {
251
- return this.onFocus(this, scrollDirection); // invokeComponentMethod(this, "onFocus", scrollDirection);
254
+ focus(_, scrollDirection, context?: FocusManager.FocusContext) {
255
+ return this.onFocus(this, scrollDirection, context); // invokeComponentMethod(this, "onFocus", scrollDirection, context);
252
256
  }
253
257
 
254
258
  /**
@@ -258,9 +262,10 @@ export class BaseFocusable<
258
262
  */
259
263
  blur(
260
264
  _,
261
- scrollDirection?: FocusManager.Web.Direction | FocusManager.IOS.Direction
265
+ scrollDirection?: FocusManager.Web.Direction | FocusManager.IOS.Direction,
266
+ context?: FocusManager.FocusContext
262
267
  ) {
263
- return this.onBlur(this, scrollDirection);
268
+ return this.onBlur(this, scrollDirection, context);
264
269
  }
265
270
 
266
271
  /**
@@ -272,7 +277,7 @@ export class BaseFocusable<
272
277
  * @param {string} scrollDirection string representation of the direction of the navigation which landed
273
278
  * to this item being focused
274
279
  */
275
- _executeFocusSequence(methodNames, scrollDirection) {
280
+ _executeFocusSequence(methodNames, scrollDirection, context) {
276
281
  return R.reduce(
277
282
  (sequence, methodName) => {
278
283
  const method = this[methodName]; // Access the method by name
@@ -284,7 +289,7 @@ export class BaseFocusable<
284
289
  }
285
290
 
286
291
  return sequence
287
- .then(() => method.call(this, scrollDirection))
292
+ .then(() => method.call(this, this, scrollDirection, context))
288
293
  .catch((e) => {
289
294
  throw e; // Re-throw for consistent error handling
290
295
  });
@@ -294,15 +299,21 @@ export class BaseFocusable<
294
299
  );
295
300
  }
296
301
 
297
- setFocus(scrollDirection) {
302
+ setFocus(
303
+ scrollDirection?: ScrollDirection,
304
+ context?: FocusManager.FocusContext
305
+ ) {
298
306
  const focusMethods = ["willReceiveFocus", "focus", "hasReceivedFocus"];
299
307
 
300
- return this._executeFocusSequence(focusMethods, scrollDirection);
308
+ return this._executeFocusSequence(focusMethods, scrollDirection, context);
301
309
  }
302
310
 
303
- setBlur(scrollDirection) {
311
+ setBlur(
312
+ scrollDirection?: ScrollDirection,
313
+ context?: FocusManager.FocusContext
314
+ ) {
304
315
  const blurMethods = ["willLoseFocus", "blur", "hasLostFocus"];
305
316
 
306
- return this._executeFocusSequence(blurMethods, scrollDirection);
317
+ return this._executeFocusSequence(blurMethods, scrollDirection, context);
307
318
  }
308
319
  }
@@ -1,12 +1,13 @@
1
1
  import { View } from "react-native";
2
2
  import React from "react";
3
- import { act, render } from "@testing-library/react-native";
3
+ import { act } from "@testing-library/react-native";
4
4
  import { CellWithFocusable } from "../CellWithFocusable.tsx";
5
5
 
6
6
  import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils/focusManager";
7
+ import { renderWithProviders } from "@applicaster/zapp-react-native-utils/testUtils/index.tsx";
7
8
 
8
9
  const renderWith = (props) => {
9
- return render(<CellWithFocusable {...props} />);
10
+ return renderWithProviders(<CellWithFocusable {...props} />);
10
11
  };
11
12
 
12
13
  describe("CellWithFocusable", () => {
@@ -1,6 +1,6 @@
1
1
  import * as R from "ramda";
2
2
 
3
- import { connectToStore } from "@applicaster/zapp-react-native-redux";
3
+ import { connectToStore } from "@applicaster/zapp-react-native-redux/utils/connectToStore";
4
4
  import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
5
5
 
6
6
  import {
@@ -1,6 +1,6 @@
1
1
  import * as R from "ramda";
2
2
 
3
- import { connectToStore } from "@applicaster/zapp-react-native-redux";
3
+ import { connectToStore } from "@applicaster/zapp-react-native-redux/utils/connectToStore";
4
4
 
5
5
  import { ComponentResolverComponent } from "./ComponentResolver";
6
6
 
@@ -1,25 +1,16 @@
1
1
  import React from "react";
2
2
  import * as R from "ramda";
3
+ import { selectZappPipes } from "@applicaster/zapp-react-native-redux";
3
4
 
4
5
  type Props = {
5
- zappPipes: ZappPipesData;
6
- loadPipesData: (
7
- feed: string,
8
- options?: Partial<{
9
- clearCache: boolean;
10
- meta: any;
11
- loadLocalFavorites: boolean;
12
- silentRefresh: boolean;
13
- parentFeed: ZappFeed;
14
- callback: () => void;
15
- bodyParams: any;
16
- riverId: string;
17
- }>
18
- ) => void;
6
+ zappPipes: ReturnType<typeof selectZappPipes>;
7
+ loadPipesData: ReturnType<
8
+ typeof import("@applicaster/zapp-react-native-utils/reactHooks/feed").useLoadPipesDataDispatch
9
+ >;
19
10
  feedUrl: string;
20
11
  children: (feed: ZappFeed) => React.ComponentType<any>;
21
12
  onFeedLoaded: (feed: ZappFeed) => {};
22
- onError: (feed: ZappFeed) => {};
13
+ onError: (error: ZappPipesData["error"]) => {};
23
14
  refreshing: boolean;
24
15
  refreshCallback: () => void;
25
16
  };
@@ -0,0 +1,21 @@
1
+ import React from "react";
2
+ import {
3
+ selectZappPipes,
4
+ useAppSelector,
5
+ } from "@applicaster/zapp-react-native-redux";
6
+ import { useLoadPipesDataDispatch } from "@applicaster/zapp-react-native-utils/reactHooks/feed";
7
+
8
+ export const FeedLoaderHOC = (_Component: any) => {
9
+ return function FeedLoaderHOC(props: any) {
10
+ const zappPipes = useAppSelector(selectZappPipes);
11
+ const loadPipesData = useLoadPipesDataDispatch();
12
+
13
+ return (
14
+ <_Component
15
+ {...props}
16
+ zappPipes={zappPipes}
17
+ loadPipesData={loadPipesData}
18
+ />
19
+ );
20
+ };
21
+ };
@@ -1,10 +1,4 @@
1
- import * as R from "ramda";
2
-
3
- import { connectToStore } from "@applicaster/zapp-react-native-redux";
4
- import { loadPipesData } from "@applicaster/zapp-react-native-redux/ZappPipes";
5
-
6
1
  import { FeedLoaderComponent } from "./FeedLoader";
2
+ import { FeedLoaderHOC } from "./FeedLoaderHOC";
7
3
 
8
- export const FeedLoader = connectToStore(R.pick(["zappPipes"]), {
9
- loadPipesData,
10
- })(FeedLoaderComponent);
4
+ export const FeedLoader = FeedLoaderHOC(FeedLoaderComponent);
@@ -2,7 +2,7 @@ import React from "react";
2
2
 
3
3
  type Props = {
4
4
  children: () => React.ReactNode;
5
- };
5
+ } & Record<string, any>;
6
6
 
7
7
  function FocusableiOSComponent({ children }: Props) {
8
8
  if (typeof children === "function") {
@@ -9,7 +9,8 @@ type Props = {
9
9
  onLongPress?: (ref: FocusManager.TouchableRef) => void;
10
10
  onFocus?: (
11
11
  ref: FocusManager.TouchableRef,
12
- options: FocusManager.Android.CallbackOptions
12
+ options: FocusManager.Android.CallbackOptions,
13
+ context: Option<FocusManager.FocusContext>
13
14
  ) => void;
14
15
  onBlur?: (
15
16
  ref: FocusManager.TouchableRef,
@@ -18,6 +19,7 @@ type Props = {
18
19
 
19
20
  disableFocus?: boolean;
20
21
  blockFocus?: boolean;
22
+ isSelected: (id?: string) => boolean;
21
23
  } & Partial<ParentFocus>;
22
24
 
23
25
  export class Touchable extends React.Component<Props> {
@@ -39,9 +41,10 @@ export class Touchable extends React.Component<Props> {
39
41
 
40
42
  onFocus(
41
43
  focusableRef: FocusManager.TouchableRef,
42
- options: FocusManager.Android.CallbackOptions
44
+ options: FocusManager.Android.CallbackOptions,
45
+ context: Option<FocusManager.FocusContext>
43
46
  ): void {
44
- this.props?.onFocus?.(focusableRef, options);
47
+ this.props?.onFocus?.(focusableRef, options, context);
45
48
  }
46
49
 
47
50
  onBlur(
@@ -22,7 +22,8 @@ type Props = {
22
22
  onPress?: (ref: FocusManager.FocusableRef) => void;
23
23
  onFocus?: (
24
24
  ref: FocusManager.FocusableRef,
25
- options: FocusManager.Android.CallbackOptions
25
+ options: FocusManager.Android.CallbackOptions,
26
+ context?: FocusManager.FocusContext
26
27
  ) => void;
27
28
  onBlur?: (
28
29
  ref: FocusManager.FocusableRef,
@@ -32,9 +33,11 @@ type Props = {
32
33
  onPressOut?: (ref: FocusManager.FocusableRef) => void;
33
34
  onLongPress?: (ref: FocusManager.FocusableRef) => void;
34
35
  onRegister?: () => void;
36
+ onUnRegister?: () => void;
35
37
  isFocusableCell?: boolean;
36
38
  /** only for FocusableScrollView */
37
39
  onSetIsFocusable?: (isFocusable: boolean) => void;
40
+ isSelected?: (id?: string) => boolean;
38
41
  } & ParentFocus;
39
42
 
40
43
  export const FocusableContext = React.createContext<
@@ -70,8 +73,10 @@ function FocusableComponent(props: Props, forwardedRef) {
70
73
  onPressOut,
71
74
  onLongPress,
72
75
  onRegister = noop,
76
+ onUnRegister = noop,
73
77
  isFocusableCell = true,
74
78
  onSetIsFocusable,
79
+ isSelected,
75
80
  } = props;
76
81
 
77
82
  const isRTL = useIsRTL();
@@ -113,9 +118,10 @@ function FocusableComponent(props: Props, forwardedRef) {
113
118
 
114
119
  return () => {
115
120
  unregister();
121
+ onUnRegister();
116
122
  };
117
123
  }
118
- }, [id, onRegister, isFocusableCell, parentFocusableId]);
124
+ }, [id, onRegister, onUnRegister, isFocusableCell, parentFocusableId]);
119
125
 
120
126
  if (R.isNil(id)) {
121
127
  // eslint-disable-next-line no-console
@@ -125,9 +131,9 @@ function FocusableComponent(props: Props, forwardedRef) {
125
131
  }
126
132
 
127
133
  const _onFocus = React.useCallback(
128
- (ref, options) => {
134
+ (ref, options, context) => {
129
135
  setFocused(true);
130
- onFocus?.(ref, options);
136
+ onFocus?.(ref, options, context);
131
137
  },
132
138
  [onFocus]
133
139
  );
@@ -183,6 +189,7 @@ function FocusableComponent(props: Props, forwardedRef) {
183
189
  blockFocus={blockFocus}
184
190
  onPressIn={onPressIn}
185
191
  onPressOut={onPressOut}
192
+ isSelected={isSelected}
186
193
  {...parentFocus}
187
194
  >
188
195
  <FocusableContext.Provider value={contextState}>
@@ -4,7 +4,7 @@ import { FocusableiOS } from "./FocusableiOS";
4
4
 
5
5
  import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
6
6
 
7
- export const Focusable = platformSelect({
7
+ export const Focusable: React.ComponentType<any> = platformSelect({
8
8
  tvos: FocusableTvOS,
9
9
  ios: FocusableiOS,
10
10
  default: FocusableDefault,
@@ -10,7 +10,8 @@ type FocusableItemComponentProps = {
10
10
  onFocus: (
11
11
  element: FocusManager.FocusableRef,
12
12
  renderArgs: { item: FocusableItemComponentProps["item"]; index: number },
13
- direction: FocusManager.Android.FocusNavigationDirections
13
+ direction: FocusManager.Android.FocusNavigationDirections,
14
+ context: Option<FocusManager.FocusContext>
14
15
  ) => void;
15
16
  onListElementFocus?: (any, RenderItemProps, Direction) => void;
16
17
  onListElementBlur?: (any, RenderItemProps, Direction) => void;
@@ -45,8 +46,8 @@ const FocusableItemComponent = ({
45
46
  const renderArgs = { item, index };
46
47
 
47
48
  const onFocusHandler = React.useCallback(
48
- (element, direction) => {
49
- onFocus?.(element, renderArgs, direction);
49
+ (element, direction, context) => {
50
+ onFocus?.(element, renderArgs, direction, context);
50
51
  },
51
52
  [item, onFocus]
52
53
  );
@@ -79,6 +80,23 @@ const FocusableItemComponent = ({
79
80
  [item, onListElementPressOut]
80
81
  );
81
82
 
83
+ const isSelected = React.useCallback(
84
+ (id_: Option<string>) => {
85
+ console.log("debug_2", "isSelected", {
86
+ item,
87
+ extraChildrenData,
88
+ id_,
89
+ });
90
+
91
+ if (id_) {
92
+ return id_ === item.id;
93
+ }
94
+
95
+ return item?.data?.target === extraChildrenData;
96
+ },
97
+ [item, extraChildrenData]
98
+ );
99
+
82
100
  return (
83
101
  <Focusable
84
102
  nextFocusDown={nextFocusDown}
@@ -91,6 +109,7 @@ const FocusableItemComponent = ({
91
109
  onLongPress={onLongPressHandler}
92
110
  onPressOut={onPressOutHandler}
93
111
  id={id}
112
+ isSelected={isSelected}
94
113
  {...focusableItemProps}
95
114
  >
96
115
  <FocusableChild
@@ -17,7 +17,8 @@ type Props = {
17
17
  onFocus: (
18
18
  element: FocusManager.FocusableRef,
19
19
  renderArgs: { item: Item; index: number },
20
- direction: FocusManager.Android.FocusNavigationDirections
20
+ direction: FocusManager.Android.FocusNavigationDirections,
21
+ context: FocusManager.FocusContext
21
22
  ) => void;
22
23
  onListElementBlur?: (any, RenderItemProps, Direction) => void;
23
24
  onListElementPress?: (any, RenderItemProps) => void;
@@ -30,17 +30,24 @@ export type IListRenderItem<ItemT> = (
30
30
  export const getFocusableId = (parentId, index) =>
31
31
  `${parentId}___index:${index}`;
32
32
 
33
+ type Item = ZappEntry | ZappUIComponent | any;
34
+
33
35
  export type Props<ItemT> = FlatListProps<ItemT> & {
34
36
  id?: number | string;
35
37
  horizontal?: boolean;
36
38
  loop?: boolean;
37
39
  numColumns?: number;
38
40
  data: ZappEntry[] | ZappUIComponent[] | any[];
39
- onListElementFocus?: (any, RenderItemProps, Direction) => void;
40
- onListElementBlur?: (any, RenderItemProps, Direction) => void;
41
- onListElementPress?: (any, RenderItemProps) => void;
42
- onListElementPressOut?: (any, RenderItemProps) => void;
43
- onListElementLongPress?: (any, RenderItemProps) => void;
41
+ onListElementFocus?: (
42
+ element: FocusManager.FocusableRef,
43
+ renderItemProps: { item: Item; index: number },
44
+ direction: FocusManager.Android.FocusNavigationDirections,
45
+ context: FocusManager.FocusContext
46
+ ) => void;
47
+ onListElementBlur?: (element, renderItemProps, direction) => void;
48
+ onListElementPress?: (element, renderItemProps) => void;
49
+ onListElementPressOut?: (element, renderItemProps) => void;
50
+ onListElementLongPress?: (element, renderItemProps) => void;
44
51
  focusableItemProps?: any;
45
52
  focused?: boolean;
46
53
  initialScrollIndex?: number;
@@ -138,11 +145,11 @@ function FocusableListComponent<ItemT>(props: Props<ItemT>, ref) {
138
145
  );
139
146
 
140
147
  const onFocus = React.useCallback(
141
- (element, renderArgs, direction) => {
148
+ (element, renderArgs, direction, context) => {
142
149
  const { index } = renderArgs;
143
150
 
144
151
  updateFocusedIndex?.(index);
145
- onListElementFocus?.(element, renderArgs, direction);
152
+ onListElementFocus?.(element, renderArgs, direction, context);
146
153
  },
147
154
  [onListElementFocus, updateFocusedIndex]
148
155
  );
@@ -1,19 +1,18 @@
1
1
  import React, { Dispatch, useEffect, useState } from "react";
2
- import {
3
- act,
4
- create,
5
- ReactTestRenderer,
6
- ReactTestRendererJSON,
7
- } from "react-test-renderer";
2
+ import { act, render } from "@testing-library/react-native";
3
+ import { View } from "react-native";
8
4
  import { FreezeWithCallback } from "../index";
9
5
 
10
- const SimpleContent = () => <div />;
6
+ const SimpleContent = () => <View testID="simple-content" />;
11
7
 
12
8
  interface InnerProps {
13
9
  value: number;
14
10
  }
11
+
15
12
  // eslint-disable-next-line unused-imports/no-unused-vars
16
- const Inner = ({ value }: InnerProps) => <div />;
13
+ const Inner = ({ value }: InnerProps) => (
14
+ <View testID="inner-component" data-value={value} />
15
+ );
17
16
 
18
17
  interface TestSubscriber {
19
18
  renderCount: number;
@@ -51,24 +50,20 @@ const Container = ({ freeze, children }: ContainerProps) => (
51
50
  );
52
51
 
53
52
  function setupTest(initialFreeze: boolean = false) {
54
- let testRenderer: ReactTestRenderer | undefined;
55
53
  const [Subscriber, subscriberState] = createSubscriberComponent();
56
54
 
57
- act(() => {
58
- testRenderer = create(
59
- <Container freeze={initialFreeze}>
60
- <Subscriber />
61
- </Container>
62
- );
63
- });
55
+ const renderResult = render(
56
+ <Container freeze={initialFreeze}>
57
+ <Subscriber />
58
+ </Container>
59
+ );
64
60
 
65
61
  return {
66
- testRenderer,
67
- testInstance: testRenderer?.root,
62
+ renderResult,
68
63
  subscriberState,
69
64
  updateFreeze: (freeze: boolean) => {
70
65
  act(() =>
71
- testRenderer?.update(
66
+ renderResult.rerender(
72
67
  <Container freeze={freeze}>
73
68
  <Subscriber />
74
69
  </Container>
@@ -80,91 +75,120 @@ function setupTest(initialFreeze: boolean = false) {
80
75
 
81
76
  describe("FreezeWithCallback", () => {
82
77
  test("Renders stuff not frozen", () => {
83
- const testRenderer = create(
78
+ const { getByTestId } = render(
84
79
  <Container freeze={false}>
85
80
  <SimpleContent />
86
81
  </Container>
87
82
  );
88
83
 
89
- expect(testRenderer.root.findByType(SimpleContent)).toBeTruthy();
84
+ expect(getByTestId("simple-content")).toBeTruthy();
90
85
  });
91
86
 
92
87
  test("Does not render stuff when frozen", () => {
93
- const testRenderer = create(
88
+ const { queryByTestId } = render(
94
89
  <Container freeze>
95
90
  <SimpleContent />
96
91
  </Container>
97
92
  );
98
93
 
99
- expect(testRenderer.root.findAllByType(SimpleContent)).toHaveLength(0);
94
+ expect(queryByTestId("simple-content")).toBe(null);
100
95
  });
101
96
 
102
97
  test("Stuff is gone after freeze", () => {
103
- const testRenderer = create(
98
+ const { toJSON, getByTestId, rerender } = render(
104
99
  <Container freeze={false}>
105
100
  <SimpleContent />
106
101
  </Container>
107
102
  );
108
103
 
109
- expect(testRenderer.root.findByType(SimpleContent)).toBeTruthy();
104
+ expect(getByTestId("simple-content")).toBeTruthy();
110
105
 
111
106
  act(() =>
112
- testRenderer.update(
107
+ rerender(
113
108
  <Container freeze>
114
109
  <SimpleContent />
115
110
  </Container>
116
111
  )
117
112
  );
118
113
 
119
- expect(testRenderer.toJSON()).toBe(null);
114
+ expect(toJSON()).toBe(null);
120
115
  });
121
116
 
122
117
  test("Updates work when not frozen", () => {
123
- const { testInstance, subscriberState } = setupTest();
118
+ const { renderResult, subscriberState } = setupTest();
119
+
120
+ expect(
121
+ renderResult.getByTestId("inner-component").props["data-value"]
122
+ ).toEqual(0);
124
123
 
125
- expect(testInstance?.findByType(Inner).props.value).toEqual(0);
126
124
  act(() => subscriberState.subscription(1));
127
- expect(testInstance?.findByType(Inner).props.value).toEqual(1);
125
+
126
+ expect(
127
+ renderResult.getByTestId("inner-component").props["data-value"]
128
+ ).toEqual(1);
129
+
128
130
  expect(subscriberState.renderCount).toBe(2);
129
131
  });
130
132
 
131
133
  test("Updates does not propagate when frozen", () => {
132
- const { testInstance, subscriberState, updateFreeze } = setupTest();
134
+ const { renderResult, subscriberState, updateFreeze } = setupTest();
135
+
136
+ expect(
137
+ renderResult.getByTestId("inner-component").props["data-value"]
138
+ ).toEqual(0);
133
139
 
134
- expect(testInstance?.findByType(Inner).props.value).toEqual(0);
135
140
  updateFreeze(true);
136
141
  act(() => subscriberState.subscription(1));
137
- expect(testInstance?.findByType(Inner).props.value).toEqual(0);
142
+
143
+ expect(
144
+ renderResult.getByTestId("inner-component").props["data-value"]
145
+ ).toEqual(0);
146
+
138
147
  expect(subscriberState.renderCount).toBe(1);
139
148
  });
140
149
 
141
150
  test("State persists after defrost", () => {
142
- const { testInstance, subscriberState, updateFreeze, testRenderer } =
143
- setupTest();
151
+ const { renderResult, subscriberState, updateFreeze } = setupTest();
152
+
153
+ expect(
154
+ renderResult.getByTestId("inner-component").props["data-value"]
155
+ ).toEqual(0);
144
156
 
145
- expect(testInstance?.findByType(Inner).props.value).toEqual(0);
146
157
  act(() => subscriberState.subscription(1));
147
- expect(testInstance?.findByType(Inner).props.value).toEqual(1);
158
+
159
+ expect(
160
+ renderResult.getByTestId("inner-component").props["data-value"]
161
+ ).toEqual(1);
148
162
 
149
163
  updateFreeze(true);
150
- expect(testRenderer?.toJSON()).toBe(null);
164
+ expect(renderResult.toJSON()).toBe(null);
151
165
 
152
166
  updateFreeze(false);
153
- expect((testRenderer?.toJSON() as ReactTestRendererJSON).type).toBe("div");
154
- expect(testInstance?.findByType(Inner).props.value).toEqual(1);
167
+ expect(renderResult.getByTestId("inner-component")).toBeTruthy();
168
+
169
+ expect(
170
+ renderResult.getByTestId("inner-component").props["data-value"]
171
+ ).toEqual(1);
155
172
  });
156
173
 
157
174
  test("Update propagate after defrost", () => {
158
- const { testInstance, subscriberState, updateFreeze } = setupTest();
175
+ const { renderResult, subscriberState, updateFreeze } = setupTest();
159
176
 
160
177
  updateFreeze(true);
161
178
  act(() => subscriberState.subscription(1));
162
179
  act(() => subscriberState.subscription(2));
163
180
  act(() => subscriberState.subscription(3));
164
- expect(testInstance?.findByType(Inner).props.value).toEqual(0);
181
+
182
+ expect(
183
+ renderResult.getByTestId("inner-component").props["data-value"]
184
+ ).toEqual(0);
165
185
 
166
186
  updateFreeze(false);
167
- expect(testInstance?.findByType(Inner).props.value).toEqual(3);
187
+
188
+ expect(
189
+ renderResult.getByTestId("inner-component").props["data-value"]
190
+ ).toEqual(3);
191
+
168
192
  expect(subscriberState.renderCount).toBe(2);
169
193
  });
170
194
  });